I have a protocol guide for a piece of hardware where I can extract 16 different kinds of data. To indicate I want all data, I would enter 65535 as the mask.
2^0 (1)
+ 2^1 (2)
+ 2^2 (4)
...
+ 2^15 (32768)
==============
65535
I now need to indicate I need options 9, 10, and 13. Presumably I simply need to use the following calculation:
2^9 (512)
+ 2^10 (1024)
+ 2^13 (8192)
==============
9728
(If I'm off-base here, or there is a programmatic way to do this, I'd be interested to know!)
What I would like to know is how I would in future extract all the numbers that were involved in the summation.
I had thought I would be able to check with (9728 & 9) == 9, (9728 & 10) == 10, and (9728 & 13) == 13, but all those return false.
bit 9 is 256; bit 10 is 512; bit 13 is 4096.
So:
if((val & 256) != 0) { /* bit 9 is set */ }
if((val & 512) != 0) { /* bit 10 is set */ }
if((val & 4096) != 0) { /* bit 13 is set */ }
You could also use an enum for convenience:
[Flags]
public enum MyFlags {
None = 0,
Foo = 1,
Bar = 2,
...
SomeFlag = 256,
AnotherFlag = 512,
...
}
then:
MyFlags flags = (MyFlags)val;
if((flags & MyFlags.SomeFlag) != 0) {/* SomeFlag is set */}
And likewise:
MyFlags thingsWeWant = MyFlags.Foo | MyFlags.SomeFlag | MyFlags.AnotherFlag;
int val = (int)thingsWeWant;
Did mean sth like this?
var value = 512 | 1024 | 8192;
var pos = 9;
var isSetNine = (value & (1 << pos)) != 0;
Related
I have a Byte scaleValue with the value 3 (0000.0011 binary)
Now I want to set the BIT 3 and 4 (Scale) of the Byte Config (see image) with help of my Byte scaleValue but it does not work.
Before: 0000.0000 (if configByte has the init value 0)
After: 0001.1000
Here is my code:
configByte = (byte) (configByte | (scaleValue << 3));
Byte Config:
If configByte is the entire 8-bit chunk, and scaleValue is the value (currently in bits 0/1) that you want to inject into bits 3/4, then fundamentally you need:
configByte = (byte)(configByte | (scaleValue << 3));
However, this assumes that:
bits 3/4 in configByte are currently zero
only bits 0/1 in scaleValue are set (or not)
If those two assumptions aren't true, then you need to mask out the issue with ... masks:
configByte = (byte)((configByte & 231) | ((scaleValue & 3) << 3));
The & 231 removes bits 3/4 in the old value. The & 3 enforces just bits 0/1 in the new value (before the shift)
You can use these extension methods:
public static bool GetBit(this byte data, byte position)
{
byte mask = (byte)(1 << position);
return (data & mask) != 0;
}
public static byte SetBit(this byte data, byte position, bool value)
{
byte mask = (byte)(1 << position);
if (value)
{
return (byte)(data | mask);
}
else
{
return (byte)( data & (~mask));
}
}
static void Main(string[] args)
{
byte data = 0b0000100;
if (data.GetBit(2))
{
}
data = data.SetBit(4, true);
data = data.SetBit(2, false);
}
I'm working on a dll that parses binary data I get from a Home Automation module.
But I need some advice on some code I have.
So I get a message with some bytes, and each bit indicates a certain condition in this case.
In the code I have at the moment each condition is an enum, I put the enums in an array and check if the corresponding bit is set.
private void ParseZoneConditionFlag1(int Flag1) // Flag1 = Hex represenation of byte
{
Zone_Status_ZoneConditionFlagEnum[] FlagArray = new Zone_Status_ZoneConditionFlagEnum[8];
FlagArray[0] = Zone_Status_ZoneConditionFlagEnum.Faulted;
FlagArray[1] = Zone_Status_ZoneConditionFlagEnum.Tampered;
FlagArray[2] = Zone_Status_ZoneConditionFlagEnum.Trouble;
FlagArray[3] = Zone_Status_ZoneConditionFlagEnum.Bypassed;
FlagArray[4] = Zone_Status_ZoneConditionFlagEnum.Inhibited;
FlagArray[5] = Zone_Status_ZoneConditionFlagEnum.Low_Battery;
FlagArray[6] = Zone_Status_ZoneConditionFlagEnum.Loss_Supervision;
FlagArray[7] = Zone_Status_ZoneConditionFlagEnum.Reserved;
base.CheckBitsSet(FlagArray, Flag1, ZoneConditionFlags_List);
}
private void ParseZoneConditionFlag2(int Flag2)
{
Zone_Status_ZoneConditionFlagEnum[] FlagArray = new Zone_Status_ZoneConditionFlagEnum[8];
FlagArray[0] = Zone_Status_ZoneConditionFlagEnum.Alarm_Memory;
FlagArray[1] = Zone_Status_ZoneConditionFlagEnum.Bypass_Memory;
FlagArray[2] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[3] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[4] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[5] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[6] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[7] = Zone_Status_ZoneConditionFlagEnum.Reserved;
base.CheckBitsSet(FlagArray, Flag2, ZoneConditionFlags_List);
}
And the method were I check the actual bits
protected void CheckBitsSet<T>(T[] ConstantArray, int HexValue, List<T> DestinationList)
{
byte b = (byte) HexValue;
for (int i = 0; i < Mask.Length; i++)
{
if(IsBitSet(b, i))
{
DestinationList.Add(ConstantArray[i]);
}
}
}
public bool IsBitSet(byte b, int pos)
{
return (b & (1 << pos)) != 0;
}
This works, but I wonder if there is a cleaner way to do this.
With cleaner I mean without having to add the right enums to an array each time.
How about just:
[Flags]
enum MyFlags : short
{
None = 0,
Faulted = 1 << 0,
Tampered = 1 << 1,
Trouble = 1 << 2,
Bypassed = 1 << 3,
Inhibited = 1 << 4,
LowBattery = 1 << 5,
LossOfSupervision = 1 << 6,
AlarmMemory = 1 << 8,
BypassMemory = 1 << 9
}
static bool IsSet(MyFlags value, MyFlags flag)
{
return ((value & flag) == flag);
}
and read the value as a 2-byte value (short, being careful about endianness), and then cast to MyFlags.
To check for any flag, just:
MyFlags value = ...
bool isAlarmMemory = IsSet(value, MyFlags.AlarmMemory);
It gets tricker when you talk about composite flags, i.e.
bool memoryProblem = IsSet(value, MyFlags.AlarmMemory | MyFlags.BypassMemory);
as you need to figure out whether you mean "is any of these flags set?" vs "are all of these flags set?"
It comes down to the test;
return ((value & flag) == flag); // means "are all set"
return ((value & flag) != 0); // means "is any set"
For reading:
// this is just some garbage that I'm pretending is a message from
// your module; I'm assuming the byte numbers in the image are
// zero-based, so the two that we want are: \/\/\/ (the 6,3)
byte[] data = { 12, 63, 113, 0, 13, 123, 14, 6, 3, 14, 15 };
// and I'm assuming "byte 7" and "byte 8" (image) are zero-based;
// MyFlags uses byte 7 *first*, so it is little-endian; we can get that
// via:
short flagsRaw = (short)(data[7] | (data[8] << 8));
MyFlags flags = (MyFlags)flagsRaw;
// flags has value Tampered | Trouble | AlarmMemory | BypassMemory,
// which is what we expect for {6,3}
Use this:
[Flags]
public enum MyEnum
{
Value1 = 1,
Value2 = 2,
Value3 = 4,
Value5 = 8
}
(...)
void Func(int flag)
{
MyEnum #enum = (MyEnum)flag;
// Testing, whether a flag is set
if ((#enum & MyEnum.Value1) != 0) // sth
}
I'm very new to C# (and C in general for that matter) I'm getting a byte value returned from an external source that represents the states of 8 input pins on the port of an IO device so I get a value of 0-255 representing the binary pattern present on the port.
How can I strip out the individual bits and set them as bool vars, so doing something like this:
if (inputBuffer[1] == 1)
{
IO.Input0 = true;
IO.Input1 = false;
IO.Input2 = false;
IO.Input3 = false;
IO.Input4 = false;
IO.Input5 = false;
IO.Input6 = false;
IO.Input7 = false;
}
I'm probably overexplaining what I'm trying to achieve but thought this gives the best example although highly impractical, how can I better achieve this to set the variables based on a byte value of 0-255.
Use a bitwise-and (&). Assuming Input0 represents the least significant bit:
IO.Input0 = (inputBuffer & 0x01) == 0x01;
IO.Input1 = (inputBuffer & 0x02) == 0x02;
IO.Input2 = (inputBuffer & 0x04) == 0x04;
IO.Input3 = (inputBuffer & 0x08) == 0x08;
IO.Input4 = (inputBuffer & 0x10) == 0x10;
IO.Input5 = (inputBuffer & 0x20) == 0x20;
IO.Input6 = (inputBuffer & 0x40) == 0x40;
IO.Input7 = (inputBuffer & 0x80) == 0x80;
You can also implement an extension method like the following:
public static bool IsBitSet(this byte b, int bit)
{
if(bit < 0 || bit > 7)
throw new ArgumentOutOfRangeException("bit must be between 0 and 7");
byte bitToCheck = (byte)(0x01 << bit);
return (b & bitToCheck) == bitToCheck;
}
Which you could then call like:
IO.Input4 = inputBuffer.IsBitSet(4);
Use a bitmask and the &-operator to figure this out
byte b = 100;
if(b&1 == 1) { } //bit 1 is set
if(b&2 == 2) { } //bit 2 is set
if(b&4 == 4) { } //bit 3 is set
...
I think a self written class can help. Class could contain the 8 bits and the constructor takes a byte. In the constructor you can calculate the single bits.
public class myByte
{
bool Input0 = false;
bool Input1 = false;
bool Input2 = false;
bool Input3 = false;
bool Input4 = false;
bool Input5 = false;
bool Input6 = false;
bool Input7 = false;
public myByte(byte b)
{
//written by Ic.
Input0 = b & 0x01 == 0x01;
Input1 = b & 0x02 == 0x02;
Input2 = b & 0x04 == 0x04;
Input3 = b & 0x08 == 0x08;
Input4 = b & 0x10 == 0x10;
Input5 = b & 0x20 == 0x20;
Input6 = b & 0x40 == 0x40;
Input7 = b & 0x80 == 0x80;
}
... //getter setter ...
}
You can do this.
int x= inputBuffer[1];
bit1 = ((x>>7)&1==1);
bit2 = ((x>>6)&1==1);
bit3 = ((x>>5)&1==1);
bit4 = ((x>>4)&1==1);
bit5 = ((x>>3)&1==1);
bit6 = ((x>>2)&1==1);
bit7 = ((x>>1)&1==1);
bit8 = (x&1==1);
To get 1st bit from say 11101110 value you need to right shift first bt 7 times and then doing AND operation with 1 will tell you whether the value is 1 or 0 and same solution applies for other bits as well.
You can use the BitArray class.
var bitArray = new BitArray(inputBuffer);
IO.Input1 = bitArray[byteIndex * 8 + 1];
Or
var bitArray = new BitArray(new byte[] { inputBuffer[1] });
IO.Input1 = bitArray[1];
You can also iterate it as a collection of Boolean values, and perform bitwise operation on the entire collection.
It's obviously not as performant as the other options offered here (cost of allocation) but it does provide a very neat API for bit calculations.
If the data is given to you in a Byte form and that each bit has been masked, then I would leave it as it is. Converting them to another type is unnecessary, it will be an extra work for no benefit. To get the correct bit, just use the bit mask pattern
private bool GetMaskedBit(var inputBuffer , int mask)
{
return ((inputBuffer & mask) != 0);
}
This way you parse the buffer and the required bit you wanted, this will return whether the bit has been set or not.
I'm making a tile based 2d platformer and every byte of memory is precious. I have one byte field that can hold values from 0 to 255, but what I need is two properties with values 0~15. How can I turn one byte field into two properties like that?
do you mean just use the lower 4 bits for one value and the upper 4 bits for the other?
to get two values from 1 byte use...
a = byte & 15;
b = byte / 16;
setting is just the reverse as
byte = a | b * 16;
Using the shift operator is better but the compiler optimizers usually do this for you nowadays.
byte = a | (b << 4);
To piggy back off of sradforth's answer, and to answer your question about properties:
private byte _myByte;
public byte LowerHalf
{
get
{
return (byte)(_myByte & 15);
}
set
{
_myByte = (byte)(value | UpperHalf * 16);
}
}
public byte UpperHalf
{
get
{
return (byte)(_myByte / 16);
}
set
{
_myByte = (byte)(LowerHalf | value * 16);
}
}
Below are some properties and some backing store, I've tried to write them in a way that makes the logic easy to follow.
private byte HiAndLo = 0;
private const byte LoMask = 15; // 00001111
private const byte HiMask = 240; // 11110000
public byte Lo
{
get
{
// ----&&&&
return (byte)(this.hiAndLo & LoMask);
}
set
{
if (value > LoMask) //
{
// Values over 15 are too high.
throw new OverflowException();
}
// &&&&0000
// 0000----
// ||||||||
this.hiAndLo = (byte)((this.hiAndLo & HiMask) | value);
}
}
public byte Hi
{
get
{
// &&&&XXXX >> 0000&&&&
return (byte)((this.hiAndLo & HiMask) >> 4);
}
set
{
if (value > LoMask)
{
// Values over 15 are too high.
throw new OverflowException();
}
// -------- << ----0000
// XXXX&&&&
// ||||||||
this.hiAndLo = (byte)((hiAndLo & LoMask) | (value << 4 ));
}
}
I have been looking around quite a bit to find some C# code to convert a network in CIDR notation (72.20.10.0/24) to an IP address range, without much luck. There are some threads about CIDR on stackoverlow, but none seems to have any C# code and cover exactly what I need. So I decided to cook it myself, and I did not want the code to rely on System.Net for any conversions in this version.
Perhaps it may be of help to someone.
References:
What's the best way to convert from network bitcount to netmask?
"Whatmask" C code from http://www.laffeycomputer.com/whatmask.html
Usage:
uint startIP, endIP;
Network2IpRange("72.20.10.0/24", out startIP, out endIP);
The code assumes 32 bits for everything.
static void Network2IpRange(string sNetwork, out uint startIP, out uint endIP)
{
uint ip, /* ip address */
mask, /* subnet mask */
broadcast, /* Broadcast address */
network; /* Network address */
int bits;
string[] elements = sNetwork.Split(new Char[] { '/' });
ip = IP2Int(elements[0]);
bits = Convert.ToInt32(elements[1]);
mask = ~(0xffffffff >> bits);
network = ip & mask;
broadcast = network + ~mask;
usableIps = (bits >30)?0:(broadcast - network - 1);
if (usableIps <= 0)
{
startIP = endIP = 0;
}
else
{
startIP = network + 1;
endIP = broadcast - 1;
}
}
public static uint IP2Int(string IPNumber)
{
uint ip = 0;
string[] elements = IPNumber.Split(new Char[] { '.' });
if (elements.Length==4)
{
ip = Convert.ToUInt32(elements[0])<<24;
ip += Convert.ToUInt32(elements[1])<<16;
ip += Convert.ToUInt32(elements[2])<<8;
ip += Convert.ToUInt32(elements[3]);
}
return ip;
}
Feel free to submit your improvements.
I recommend to use the C# IPNetwork class from Github.
string net = "192.168.168.100/24";
IPNetwork ipnetwork = IPNetwork.Parse(net);
Console.WriteLine("Network : {0}", ipnetwork.Network);
Console.WriteLine("Netmask : {0}", ipnetwork.Netmask);
Console.WriteLine("Broadcast : {0}", ipnetwork.Broadcast);
Console.WriteLine("FirstUsable : {0}", ipnetwork.FirstUsable);
Console.WriteLine("LastUsable : {0}", ipnetwork.LastUsable);
Console.WriteLine("Usable : {0}", ipnetwork.Usable);
Console.WriteLine("Cidr : {0}", ipnetwork.Cidr);
It will ouput
Network : 192.168.168.0
Netmask : 255.255.255.0
Broadcast : 192.168.168.255
FirstUsable : 192.168.168.1
LastUsable : 192.168.168.254
Usable : 254
Cidr : 24
Have fun.
Here is how you do it for your example 72.20.10.0/24,
Let Network be 72.20.10.0
Mask is ~((1 << (32-24)) - 1) // or
Mask is ~(0xFFFFFFFF >> 24)
which is 0xFFFFFF00
StartIP is -- (Network & Mask);
which is 72.20.10.0 & 0xFFFFFF00
EndIP is -- ((Network & Mask) | ~Mask);
which is (72.20.10.0 & 0xFFFFFF00) | 0x000000FF
This will be 72.20.10.0 -- 72.20.10.255.
The steps would go like this for a network/maskBits,
You compute the mask in one of these two ways,
mask = ~((1 << (32 - maskBits)) - 1) // or,
mask = ~(0xFFFFFFFF >> maskBits)
then the range is,
StartIP = network
EndIP = network | ~mask
More precisely,
StartIP = network & mask
EndIP = (network & mask) | ~mask
Where,
<< is bitwise left shift (without rollover)
& is bitwise AND,
| is bitwise OR, and
~ is bitwise INVERT.
Here's how to convert CIDR notation to a range in T-SQL, from my blog post :
First pre-create this function in SQL Server (from
http://www.stardeveloper.com).
CREATE FUNCTION [dbo].[ConvertIPToLong](#IP varchar(15))
RETURNS bigint
AS
BEGIN
DECLARE #Long bigint
SET #Long = CONVERT(bigint, PARSENAME(#IP, 4)) * 256 * 256 * 256 +
CONVERT(bigint, PARSENAME(#IP, 3)) * 256 * 256 +
CONVERT(bigint, PARSENAME(#IP, 2)) * 256 +
CONVERT(bigint, PARSENAME(#IP, 1))
RETURN (#Long)
END
This is a sample of T-SQL code I put together that will calculate the
low and high IP ranges from a CIDR address. It's messy and I had to
work around T-SQL's lack of bit shift operators.
Declare #CidrIP varchar(50)
Set #CidrIP = '10.100.60.55/28'
Select dbo.[ConvertIPToLong](left(#CidrIP, patindex('%/%' , #CidrIP) - 1)) & (cast(4294967295 as bigint) ^ (Power(2, 32 - Cast(substring(#CidrIP, patindex('%/%' , #CidrIP) + 1, 2) as int)) - 1)) as LowRange,
dbo.[ConvertIPToLong](left(#CidrIP, patindex('%/%' , #CidrIP) - 1)) & (cast(4294967295 as bigint) ^ (Power(2, 32 - Cast(substring(#CidrIP, patindex('%/%' , #CidrIP) + 1, 2) as int)) - 1)) + (Power(2, 32 - Cast(substring(#CidrIP, patindex('%/%' , #CidrIP) + 1, 2) as int)) - 1)