The Problem
I have a integer array of 16 'options', the data for which stored in an array of 10 bytes. That means that each option takes up a certain number of bits and some options share bytes with others.
B, T, P, I, 2, 3, e, S, p, O, t, E, U, V, m and M are the options. The Xs are unused bits. The lower and upper case represent separate options. It is structured like this:
Byte 00: BBBB BTTT
Byte 01: TPPP PPII
Byte 02: III2 2222
Byte 03: 2333 333e
Byte 04: eeee eSSS
Byte 05: SSSS Sxpp
Byte 06: ppOO OOOx
Byte 07: tttE EEEE
Byte 08: EEUU VVVm
Byte 09: mmmM Mxxx
My aim is to read those 10 bytes and get the values for those 16 options from the data stored across the bytes. The values of the bytes, in hexadecimal, are as follows:
D6
27
AD
B6
9B
10
0A
58
0C
00
My attempts at solving it
I've tried two methods so far to retrieve the desired values. The first was bit shifting, for example:
option[0] = optionByte[00] >> 3;
option[2] = (optionByte[01] << 1) >> 2;
option[11] = optionByte[07] >> 5;
This worked for the options which are only stored within a single byte and gave me the desired values, which were:
Option 0: 26
Option 2: 9
Option 11: 2
I didn't think this would be possible for options which are split across more than one byte, so instead, I tried creating a bit array from the byte array, translating it into a string of binary numbers representing the bits, then reading the string by the number of bits the option takes up, to create the binary number and convert it to decimal. Here is the function I wrote to perform this action:
public byte[] headerBytes = new byte[10];
public int[] headerSettings = new int[16];
public void readHeader()
{
int bits = 0;
int sIndex = 0; // Starting point to read from
string hBinary = string.Empty;
BitArray headerBits = new BitArray(headerBytes);
// Translate bit array to string of Binary digits
foreach (var bit in headerBits)
{
hBinary += Convert.ToInt16(bit).ToString();
}
// Convert option values to decimal from Binary values
for (int i = 0; i < 16; i++)
{
string hBinarySplit = string.Empty;
switch (i) // Set the number of bits to read depending on the option/loop iteration
{
case 0: bits = 5; break;
case 1: bits = 4; break;
case 2: bits = 5; break;
case 3: bits = 5; break;
case 4: bits = 6; break;
case 5: bits = 6; break;
case 6: bits = 6; break;
case 7: bits = 8; break;
case 8: bits = 5; break;
case 9: bits = 5; break;
case 10: bits = 3; break;
case 11: bits = 7; break;
case 12: bits = 2; break;
case 13: bits = 3; break;
case 14: bits = 4; break;
case 15: bits = 2; break;
};
if (i == 8 || i == 10)
sIndex += 1; // Ignore unused bits in bytes 5 and 6
// Create binary sub-value for option
hBinarySplit += hBinary.Substring(sIndex, bits);
// Advance point in main string to read from
sIndex += bits;
// Set option value to decimal from Binary sub-value
headerSettings[i] = Convert.ToInt16(hBinarySplit, 2);
}
}
This function ran error-free, but returned incorrect option values. The values I was expecting in decimal, are:
B: 26
T: 12
P: 09
I: 29
2: 27
3: 27
e: 19
S: 98
p: 00
O: 05
t: 02
E: 96
U: 00
V: 03
m: 00
M: 00
The function returned the following values to the integer array:
B (int 00) : 13
T (int 01) : 07
P (int 02) : 25
I (int 03) : 05
2 (int 04) : 42
3 (int 05) : 54
e (int 06) : 59
S (int 07) : 33
p (int 08) : 02
O (int 09) : 16
t (int 10) : 01
E (int 11) : 81
U (int 12) : 02
V (int 13) : 00
m (int 14) : 00
M (int 15) : 00
Summary
I have a feeling there may be something missing from the function which was the reason for the wrong values being returned.
Please could anyone advise a fix for the function, or if the initial bit-shifting method I tried is more efficient, how to do it when the bits are spread across multiple bytes?