0

I've been searching a lot about this topic and I hope finally get the answer here.

I want to use a structure for specific hardware and I want to implement this in C; this is the packet I want:

typedef struct {
    quint8 startByte        :8;
    quint16 ch1             :11;
    quint16 ch2             :11;
    quint16 ch3             :11;
    quint16 ch4             :11;
    quint16 ch5             :11;
    quint16 ch6             :11;
    quint16 ch7             :11;
    quint16 ch8             :11;
    quint16 ch9             :11;
    quint16 ch10            :11;
    quint16 ch11            :11;
    quint16 ch12            :11;
    quint16 ch13            :11;
    quint16 ch14            :11;
    quint16 ch15            :11;
    quint16 ch16            :11;
    quint8 endByte1         :8;
    quint8 endByte          :8;
}packet;

If you calculate the size it is 25 bytes. but when I use sizeof(packet) I get 46. Right now I'm using Qt 5.5 and I also want to use this code in Atmel studio 7 with AVR. By the way I also have used #pragma pack(1) and also __attribute__((__packed__)) and got the sizeof(packet) equal to 35.

frogatto
  • 28,539
  • 11
  • 83
  • 129
a.tabatabaei
  • 304
  • 3
  • 16
  • 2
    The standard does not specify a particular bitfield implementation, so it is possible that it varies accross platforms. You can always do it manually: http://stackoverflow.com/questions/11815894/how-to-read-write-arbitrary-bits-in-c-c/27592777#27592777 – dtech Feb 29 '16 at 18:16
  • nice. thanks for the quick reply. i'll check it – a.tabatabaei Feb 29 '16 at 18:30
  • @ddriver can you explain the process a little more – a.tabatabaei Feb 29 '16 at 19:50
  • I have expanded my answer, however I will not write the code for you, it will be most rewarding for you to do it yourself, this way you will really understand working with bits and bitwise operators. Don't worry if you don't get it right away - it is somewhat complex. – dtech Feb 29 '16 at 20:42

1 Answers1

2

You have 16 shorts * 2 bytes = 32 bytes + the start byte + the two end bytes - if it is packed that makes for a total of 35 bytes. Since you use 16bit datatype for 11 bit fields you are left with only 5 bytes - you cannot fit an 11bit field into 5 bits, so those 5 bits are essentially wasted.

0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
| field 1 |xxxxx| field 2 |xxxxx| field 3 |xxxxx

If I understand correctly, what you want to achieve is more like this:

0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
| field  1 | field  2 | field  3 | field  4 |...

I am not sure if the compiler can generate such a layout for you, but as already mentioned in the comment, you can do it manually. The compiler is not doing it because it would be inefficient - in order to read a field that crosses a boundary you have to do two reads, mask, shift and compose the final result together.

The answer I have linked explains bit manipulation in detail, the only thing different here is that you will have crossing of boundaries.

| byte1 | byte2 | byte3 | byte4 |
0123456701234567012345670123456701
| field  1 | field  2 | field  3 |

For example you want to read field 2 - it's index is 1, so 1 * 11 = 11 - that's the bit offset of the field. 11 / 8 = 1 with remainder of 3. This means its value begins after the 3-rd bit of the second byte and occupies 8 - 3 = 5 bits of it, and 11 - 5 = 6 bits of the next byte. Let's say the field value is 00100110111.

| byte1 | byte2 | byte3 | byte4 |
0123456701234567012345670123456701
| field  1 | field  2 | field  3 |
        xxx00100110111xx

The value will be contained within two bytes xxx00100 and 110111xx, and it can be reconstructed by shifting and composing the two like this:

xxx00100          << 8 AND
        110111xx
xxx00100110111xx

Then shift it left by 3 to cut off the first 3 bits from the previous field, then shift it right by 3 + 2 to cut off the last 2 bits from the next field and you are left with 0000000100110111 which is the value of the field in a short.

For writing the field the process is similar, however, make sure you don't corrupt the bits from the adjacent fields - you need to save and then properly restore those when you write the bytes for the target field.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • you understood me correctly but I need the data to be shifted somehow in that 5 wasted bits and this process continue to the end and finally bring a 25 byte structure. – a.tabatabaei Feb 29 '16 at 18:37
  • 1
    Well, as I said - do it manually. Have a 25 element byte array instead of all those fields, then for each field calculate its position, how it crosses the boundaries, and extract and compose the data using the bitwise operators. – dtech Feb 29 '16 at 18:39