I have to define a communication protocol and I want to use a bitfield to store some logic values.
I'm working on the both systems: the sender: a device and a .Net software as receiver.
On the firmware side, I defined as usually a bitfield struct like:
struct __attribute__((__packed__)) BitsField
{
// Logic values
uint8_t vesselPresenceSw: 1;
uint8_t drawerPresenceSw: 1;
uint8_t pumpState: 1;
uint8_t waterValveState: 1;
uint8_t steamValveState: 1;
uint8_t motorDriverState: 1;
// Unused
uint8_t unused_0: 1;
uint8_t unused_1: 1;
};
How I can define a same structure on the software side that support a bytes deserialization to build the struct itself?
I'm afraid there is no direct C# equivalent to C-style bitfield structs.
C# is capable, to a limited extent, of approximating C-style unions by using FieldOffset attributes. These explicit layout attributes allow you to specify exact and potentially overlapping field offsets. Unfortunately, that doesn't even get you halfway there: the offsets must be specified in bytes rather than bits, and you cannot enforce a specific width when reading or writing overlapping fields.
The closest C# comes to natively supporting bitfields is probably flag-based enum types. You may find this sufficient, provided you don't need more than 64 bits. Start by declaring an enum based on the smallest unsigned type that will fit all your flags:
[Flags]
public enum BitFields : byte {
None = 0,
VesselPresenceSw = 1 << 0,
DrawerPresenceSw = 1 << 1,
PumpState = 1 << 2,
WaterValveState = 1 << 3,
SteamValveState = 1 << 4,
MotorDriverState = 1 << 5
}
The named items can have any value assigned to them that fits within the underlying type (byte in this case), so one item could represent multiple bits if you wanted it to. Note that if you want to interop directly with a C-style bitfield, your first value should start at the most significant bit rather than the least.
To use your flags, just declare a variable or field of your new type and perform whatever bitwise operations you need:
BitFields bits = BitFields.None;
bits |= BitFields.VesselPresenceSw | BitFields.PumpState;
bits &= ~BitFields.VesselPresenceSw;
// etc.
On the upside, enums declared with [Flags] are nicely formatted when displayed in the debugger or converted to strings. For example, if you were to print the expression BitFields.VesselPresenceSw | BitFields.PumpState, you would get the text DrawerPresenceSw, PumpState.
There is a caveat: the storage for an enum will accept any value that fits within the underlying type. It would be perfectly legal to write:
BitFields badBits = (BitFields)0xFF;
This sets all 8 bits of the byte-sized enumeration, but our named values only cover 6 bits. Depending on your requirements, you may want to declare a constant that encompasses only the 'legal' flags, which you could & against.
If you need anything richer than that, there is a framework-level 'bitfield' data structure called BitArray. However, BitArray is a reference type that uses a managed int[] for storage. It's not going to help you if want a struct that you could use for interop purposes or any kind of memory mapping.
Please see an example,
C code,
struct example_bit_field
{
unsigned char bit1 : 1;
unsigned char bit2 : 1;
unsigned char two_bits : 2;
unsigned char four_bits : 4;
}
and C# equivalent,
[BitFieldNumberOfBitsAttribute(8)]
struct ExampleBitField : IBitField
{
[BitFieldInfo(0, 1)]
public bool Bit1 { get; set; }
[BitFieldInfo(1, 1)]
public byte Bit2 { get; set; }
[BitFieldInfo(2, 2)]
public byte TwoBits { get; set; }
[BitFieldInfo(4, 4)]
public byte FourBits { get; set; }
}
Source :- https://www.codeproject.com/Articles/1095576/Bit-Field-in-Csharp-using-struct
You can try mimic such a struct. It seems, that you want to use it in the interop (say, C routine exchange data with C# program). Since you have logic values, let expose them as bool:
using System.Runtime.InteropServices;
...
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyBitsField {
private Byte m_Data; // We actually store Byte
public MyBitsField(Byte data) {
m_Data = data;
}
private bool GetBit(int index) {
return (m_Data & (1 << index)) != 0;
}
private void SetBit(int index, bool value) {
byte v = (byte)(1 << index);
if (value)
m_Data |= v;
else
m_Data = (byte) ((m_Data | v) ^ v);
}
public bool vesselPresenceSw {
get { return GetBit(0); }
set { SetBit(0, value); }
}
...
public bool motorDriverState {
get { return GetBit(5); }
set { SetBit(5, value); }
}
}
Usage:
var itemToSend = new MyBitsField() {
vesselPresenceSw = false,
motorDriverState = true,
};
In the meantime, I had a similar idea #Dmitry.
I found the following solution using FieldOffset attribute.
Working well without additional code. I think it's acceptable.
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct LiveDataBitField
{
// Where the values are effectively stored
public byte WholeField { get; private set; }
public bool VesselPresenceSw
{
get => (WholeField & 0x1) > 0;
set
{
if (value)
{
WholeField |= 1;
}
else
{
WholeField &= 0xfE;
}
}
}
public bool DrawerPresenceSw
{
get => (WholeField & 0x2) >> 1 > 0;
set
{
if (value)
{
WholeField |= (1 << 1);
}
else
{
WholeField &= 0xFD;
}
}
}
public bool PumpState
{
get => (WholeField & 0x4) >> 2 > 0;
set
{
if (value)
{
WholeField |= (1 << 2);
}
else
{
WholeField &= 0xFB;
}
}
}
public bool WaterValveState
{
get => (WholeField & 0x8) >> 3 > 0;
set
{
if (value)
{
WholeField |= (1 << 3);
}
else
{
WholeField &= 0xF7;
}
}
}
public bool SteamValveState
{
get => (WholeField & 0x10) >> 4 > 0;
set
{
if (value)
{
WholeField |= (1 << 4);
}
else
{
WholeField &= 0xEF;
}
}
}
public bool MotorDriverState
{
get => (WholeField & 0x20) >> 5 > 0;
set
{
if (value)
{
WholeField |= (1 << 5);
}
else
{
WholeField &= 0xDF;
}
}
}
}
To deserialize a byte array to struct you can use:
public static object ReadStruct(byte[] data, Type type)
{
var pinnedPacket = GCHandle.Alloc(data, GCHandleType.Pinned);
var obj = Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), type);
pinnedPacket.Free();
return obj;
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
In order to check hihest bit is on I use code:
byte data = 0x88 ;
bool is_on= ((data & 0x80) == 0x80);
How to do this in more elegant and C# way ?
public static bool Get(byte b, int position)
{
if (position > 7)
throw new ArgumentException();
return ((b & (byte)(1 << position)) != 0);
}
Since you're checking a bit, the only thing I might do is write out the literal so you can see the individual bits, like this:
int mask = 0b1000_0000;
byte data = 0x88 ;
bool is_on= ((data & mask) == mask);
I might further abstract this as a method:
public static bool MatchesMask(this int data, int mask)
{
return (data&mask)==mask;
}
So I could call it like this:
int mask = 0b1000_0000;
byte data = 0x88 ;
bool is_on = data.MatchesMask(mask);
If you are dealing with bit setting and getting consider some auxiliary classes to help you. Look at the Flag structure below
Usage
You initialize a Flag with a mask Flag flag = 0x20, or set a specific bit Flag flag = Flag.Bit(5).
You poll a bit with flag.Get(value) and you set a bit with value = flag.Set(value); to set to 1, and value = flag.Set(value, false); to set it 0.
Test Output
10110011 & 00100000 = True
10010011 & 00100000 = False
Code
public struct Flag
{
readonly byte mask;
public Flag(byte mask)
{
this.mask=mask;
}
public byte Mask => this.mask;
public static Flag Bit(int position)
=> new Flag((byte)(1<<position));
public static implicit operator byte(Flag bit) => bit.mask;
public static implicit operator Flag(byte mask) => new Flag(mask);
public bool Get(byte value) => (value & mask)!=0;
public byte Set(byte value, bool bit = true)
{
if (bit)
{
return (byte)(value | mask);
}
else
{
return (byte)(value & ~mask);
}
}
}
static class Program
{
public static string Bin(this byte data)
=> Convert.ToString(data, 2).PadLeft(8, '0');
static void Main(string[] args)
{
byte value = 0xB3;
Flag flag = 0x20;
// or alernativly
// var flag = Flag.Bit(6); // mask = 0b0010000
Console.WriteLine($"{Bin(value)} & {Bin(flag.Mask)} = {flag.Get(value)}");
// not set the bit to 0
value = flag.Set(value, false);
Console.WriteLine($"{Bin(value)} & {Bin(flag.Mask)} = {flag.Get(value)}");
}
}
References
Set a specific bit in an int
I have a byte that represents two values.
First bit represents represents the sequence number.
The rest of the bits represent the actual content.
In C, I could easily parse this out by the following:
typedef struct
{
byte seqNumber : 1;
byte content : 7;
}
MyPacket;
Then I can easily case the input to MyPacket:
char* inputByte = "U"; // binary 01010101
MyPacket * myPacket = (MyPacket*)inputByte;
Then
myPacket->seqNumber = 1
myPacket->content = 42
How can I do the same thing in C#?
Thank you
kab
I would just use properties. Make getters and setters for the two parts that modify the appropriate bits in the true representation.
class myPacket {
public byte packed = 0;
public int seqNumber {
get { return value >> 7; }
set { packed = value << 7 | packed & ~(1 << 7); }
}
public int content {
get { return value & ~(1 << 7); }
set { packed = packed & (1 << 7) | value & ~(1 << 7); }
}
}
C# likes to keep its types simple, so I am betting this is the closest you are getting. Obviously it does not net you the performance improvement in C, but it salvages the meanings.
Hey I want to write a struct like the XNA Color struct or the SurfaceFormat.Bgra4444 struct that holds 2 nibbles in a 8 bit byte.
This is what I have so far...
/// <summary>
/// Packed byte containing two 4bit values
/// </summary>
public struct Nibble2 : IEquatable<Nibble2>
{
private byte packedValue;
public byte X
{
get { return 0; }
set { }
}
public byte Y
{
get { return 0; }
set { }
}
/// <summary>
/// Creates an instance of this object.
/// </summary>
/// <param name="x">Initial value for the x component.</param>
/// <param name="y">Initial value for the y component.</param>
public Nibble2(float x, float y)
{
packedValue = 0;
}
/// <summary>
/// Creates an instance of this object.
/// </summary>
/// <param name="vector">Input value for both components.</param>
public Nibble2(Vector2 vector)
{
packedValue = 0;
}
public static bool operator ==(Nibble2 a, Nibble2 b) { return a.packedValue == b.packedValue; }
public static bool operator !=(Nibble2 a, Nibble2 b) { return a.packedValue != b.packedValue; }
public override string ToString()
{ return packedValue.ToString("X : " + X + " Y : " + Y, CultureInfo.InvariantCulture); }
public override int GetHashCode()
{return packedValue;}
public override bool Equals(object obj)
{
if (obj is Nibble2)
return Equals((Nibble2)obj);
return false;
}
public bool Equals(Nibble2 other)
{return packedValue == other.packedValue;}
}
As you can see my propertys and constructors are not implimented. As this is the part I am having trouble with.
Thanks for any help you can provide.
Basically, you just need to keep in mind what is the high and low nibbles. The low nibble can be obtained just by masking with binary 1111 (decimal 15). The high nibble can be obtained (since byte is unsigned) by right-shifting by 4. The rest is just bit-math.
// assume x is the low nibble
public byte X
{
get { return (byte)(packedValue & 15); }
set { packedValue = (packedValue & 240) | (value & 15); }
}
// assume y is the high nibble
public byte Y
{
get { return (byte) (packedValue >> 4); }
set { packedValue = (value << 4) | (packedValue & 15); }
}
I can't, however, help you with:
public Nibble2(float x, float y)
{
packedValue = 0;
}
because that is 64 bits, and you want to fit it into 8. You'd need to be a lot more specific about what you want to do with those values.
Consider the following byte value:
10101100
To read the high bits of a byte, you should shift the bytes to the right:
10101100 (original)
01010110 (shifted one bit)
00101011
00010101
00001010 (shifted four bits)
You can shift bytes by using return (byte)(packedValue >> 4);
To read just the low bits, you simply eliminate the top bits using an AND opertation:
10101100
00001111 AND
--------
00001100
You can perform this AND operation on a value by using return (byte)(packedValue & 0xf);
Setting these values can be performed by clearing the target nibble and then simply adding the input value (shifted left if setting the high nibble):
packedValue = (byte)((packedValue & 0xf0) + (lowNibble & 0xf));
packedValue = (byte)((packedValue & 0xf) + (highNibble << 4));
if you AND the input value with byte filled like this 00001111 which is 15 in dec. You keep the part that you want to save. Then you'll have to left shift the left part of your Nibble2 with 4 bytes to store in the packedValue byte.
private byte x = 0;
private byte y = 0;
public byte X
{
get { return x; }
set { x = value}
}
public byte Y
{
get { return y; }
set { y = value }
}
private byte packedValue
{
get { return (x & 15 << 4) | (y & 15); }
}
Mr. Ayende wrote in his latest blog post about an implementation of a queue. In the post he's using two magical files: BinaryWriterWith7BitEncoding & BinaryReaderWith7BitEncoding
BinaryWriterWith7BitEncoding can write both int and long? using the following method signatures: void WriteBitEncodedNullableInt64(long? value) & void Write7BitEncodedInt(int value)
and
BinaryReaderWith7BitEncoding can read the values written using the following method signatures: long? ReadBitEncodedNullableInt64() and int Read7BitEncodedInt()
So far I've only managed to find a way to read the 7BitEncodedInt:
protected int Read7BitEncodedInt()
{
int value = 0;
int byteval;
int shift = 0;
while(((byteval = ReadByte()) & 0x80) != 0)
{
value |= ((byteval & 0x7F) << shift);
shift += 7;
}
return (value | (byteval << shift));
}
I'm not too good with byte shifting - does anybody know how to read and write the 7BitEncoded long? and write the int ?
Here's something like the write:
static void Write7BitEncodedInt32(Stream dest, int value)
{
Write7BitEncodedUInt32(dest, (uint) value);
}
static void Write7BitEncodedUInt32(Stream dest, uint value)
{
if(value < 128) { dest.WriteByte((byte)value); return;}
while(value != 0)
{
byte b = (byte) (value & 0x7F);
value >>= 7; // since uint, we'll eventually run out of 1s
if (value != 0) b |= 0x80; // and there's more
dest.WriteByte(b);
}
}
Is there a built in Gray code datatype anywhere in the .NET framework? Or conversion utility between Gray and binary? I could do it myself, but if the wheel has already been invented...
Use this trick.
/*
The purpose of this function is to convert an unsigned
binary number to reflected binary Gray code.
*/
unsigned short binaryToGray(unsigned short num)
{
return (num>>1) ^ num;
}
A tricky Trick: for up to 2^n bits, you can convert Gray to binary by
performing (2^n) - 1 binary-to Gray conversions. All you need is the
function above and a 'for' loop.
/*
The purpose of this function is to convert a reflected binary
Gray code number to a binary number.
*/
unsigned short grayToBinary(unsigned short num)
{
unsigned short temp = num ^ (num>>8);
temp ^= (temp>>4);
temp ^= (temp>>2);
temp ^= (temp>>1);
return temp;
}
Here is a C# implementation that assumes you only want to do this on non-negative 32-bit integers:
static uint BinaryToGray(uint num)
{
return (num>>1) ^ num;
}
You might also like to read this blog post which provides methods for conversions in both directions, though the author chose to represent the code as an array of int containing either one or zero at each position. Personally I would think a BitArray might be a better choice.
Perhaps this collection of methods is useful
based on BitArray
both directions
int or just n Bits
just enjoy.
public static class GrayCode
{
public static byte BinaryToByte(BitArray binary)
{
if (binary.Length > 8)
throw new ArgumentException("bitarray too long for byte");
var array = new byte[1];
binary.CopyTo(array, 0);
return array[0];
}
public static int BinaryToInt(BitArray binary)
{
if (binary.Length > 32)
throw new ArgumentException("bitarray too long for int");
var array = new int[1];
binary.CopyTo(array, 0);
return array[0];
}
public static BitArray BinaryToGray(BitArray binary)
{
var len = binary.Length;
var gray = new BitArray(len);
gray[len - 1] = binary[len - 1]; // copy high-order bit
for (var i = len - 2; i >= 0; --i)
{
// remaining bits
gray[i] = binary[i] ^ binary[i + 1];
}
return gray;
}
public static BitArray GrayToBinary(BitArray gray)
{
var len = gray.Length;
var binary = new BitArray(len);
binary[len - 1] = gray[len - 1]; // copy high-order bit
for (var i = len - 2; i >= 0; --i)
{
// remaining bits
binary[i] = !gray[i] ^ !binary[i + 1];
}
return binary;
}
public static BitArray ByteToGray(byte value)
{
var bits = new BitArray(new[] { value });
return BinaryToGray(bits);
}
public static BitArray IntToGray(int value)
{
var bits = new BitArray(new[] { value });
return BinaryToGray(bits);
}
public static byte GrayToByte(BitArray gray)
{
var binary = GrayToBinary(gray);
return BinaryToByte(binary);
}
public static int GrayToInt(BitArray gray)
{
var binary = GrayToBinary(gray);
return BinaryToInt(binary);
}
/// <summary>
/// Returns the bits as string of '0' and '1' (LSB is right)
/// </summary>
/// <param name="bits"></param>
/// <returns></returns>
public static string AsString(this BitArray bits)
{
var sb = new StringBuilder(bits.Length);
for (var i = bits.Length - 1; i >= 0; i--)
{
sb.Append(bits[i] ? "1" : "0");
}
return sb.ToString();
}
public static IEnumerable<bool> Bits(this BitArray bits)
{
return bits.Cast<bool>();
}
public static bool[] AsBoolArr(this BitArray bits, int count)
{
return bits.Bits().Take(count).ToArray();
}
}
There is nothing built-in as far as Gray code in .NET.
Graphical Explanation about Gray code conversion - this can help a little