I have two bitfields: (1) one to handle the frame (header), (2) the other to handle a subframe within a frame (identityFieldO2M).
union header
{
unsigned char arr[16]; // 128 bytes allocated
BitFieldMember<0, 1> SOF;
BitFieldMember<1, 11> BID;
BitFieldMember<12, 1> SRR;
BitFieldMember<13, 1> IDE;
BitFieldMember<14, 18> IDEX;
BitFieldMember<32, 1> RTR;
BitFieldMember<33, 1> r1;
BitFieldMember<34, 1> r0;
BitFieldMember<35, 4> DLC;
BitFieldMember<39, 8> DataField1;
BitFieldMember<47, 15> CRC;
BitFieldMember<62, 1> CRCDelim;
BitFieldMember<63, 1> ACKSlot;
BitFieldMember<64, 1> ACKdelim;
BitFieldMember<65, 7> eof;
};
union identityFieldO2M
{
unsigned char arr[5]; // 3 bytes allocated though only need 29 bits
BitFieldMember<0, 2> RCI;
BitFieldMember<2, 14> DOC;
BitFieldMember<16, 1> PVT;
BitFieldMember<17, 1> LCL;
BitFieldMember<18, 1> FSB;
BitFieldMember<19, 7> SourceFID;
BitFieldMember<26, 3> LCC;
};
I need to process first the first bitfield and from there I am combining two members of this bitfield and then running their combined output into another bitfield to determine subframes. The issue I have it, however, is when I do the bitwise function to combine the two bitfields, I am not able to pass this data back into the bitfield.
I think I am doing something "duh" wrong but I am not able to figure this out. Below is my implementation:
int main()
{
header a;
memset(a.arr, 0, sizeof(a.arr));
a = {0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0}; // 1010 0000
cout << hex << a.SOF << endl; // 1 -> 1
cout << hex << a.BID << endl; // 010 0000 1010 -> 20a
cout << hex << a.SRR << endl; // 0 -> 0
cout << hex << a.IDE << endl; // 0 -> 0
cout << hex << a.IDEX << endl; // 00 1010 0000 1010 0000 -> a0a0
cout << hex << a.RTR << endl; // 1 -> 1
cout << hex << a.r1 << endl; // 0 -> 0
cout << hex << a.r0 << endl; // 1 -> 1
cout << hex << a.DLC << endl; // 0 000 -> 0
cout << hex << a.DataField1 << endl; // 0 1010 000 -> 50
cout << hex << a.CRC << endl; // 0 1010 0000 1010 00 -> 2828
cout << hex << a.CRCDelim << endl; // 0 -> 0
cout << hex << a.ACKSlot << endl; // 0 -> 0
cout << hex << a.ACKdelim << endl; // 1 -> 1
cout << hex << a.eof << endl; // 010 0000 -> 20
int BID = a.BID;
int IDEX = a.IDEX;
int result = (BID<<18) | IDEX; // concatenate BID and IDEX together to get 29 bit header
cout << "test" << endl;
cout << "BID: " << hex << BID << endl; //-> 20a -> 010 0000 1010
cout << "IDEX: " << hex << IDEX << endl; //-> a0a0-> 00 1010 0000 1010 0000
cout << "Identifier Field: " << hex << result << endl; //-> 828a0a0 -> 01 0000 0101 0001 01 0 0 0 0010100 000
cout << "Size of Bitfield header: " << sizeof(a) << endl;
identityFieldO2M b;
b = result; // **error: no match for 'operator=' (operand types are 'identityFieldO2M' and 'int')**
memset(b.arr,0,sizeof(b.arr));
cout << hex << b.RCI << endl; // 01 -> 0x01
cout << hex << b.DOC << endl; // 0000 0101 0001 01 -> 0x145
cout << hex << b.PVT << endl; // 0 -> 0x00
cout << hex << b.LCL << endl; // 0 -> 0x00
cout << hex << b.FSB << endl; // 0 -> 0x00
cout << hex << b.SourceFID << endl; // 0010100 -> 0x14
cout << hex << b.LCC << endl; // 000 -> 0 -> 0x00
sleep(100);
return 0;
}
where the error happens when I am setting the result of concatenate BID and IDEX to struct b:
identityFieldO2M b;
b = result; // **error: no match for 'operator=' (operand types are 'identityFieldO2M' and 'int')**
memset(b.arr,0,sizeof(b.arr));
For the BitFieldMember template I am using this very helpful template here: https://codereview.stackexchange.com/questions/54342/template-for-endianness-free-code-data-always-packed-as-big-endian
Looking through the definition of the BitFieldMember template, here is the operand = to assign values into the field, where I suspect this issue may lay?
/* used to assign a value into the field */
inline self_t& operator=(unsigned m)
{
uchar *arr = selfArray();
m &= mask;
unsigned wmask = ~(mask << (7 - (lastBit & 7)));
m <<= (7 - (lastBit & 7));
uchar *p = arr + lastBit / 8;
int i = (lastBit & 7) + 1;
(*p &= wmask) |= m;
while (i < bitSize)
{
m >>= 8;
wmask >>= 8;
(*(--p) &= wmask) |= m;
i += 8;
}
return *this;
}