Archive for November 23rd, 2009

Arduino: Bit Fields Start Low

The first bit in an Arduino bit field is the lowest-order bit.

Set up a bit field to hold, oh, say, the data bits from the WWVB radio time code:

struct WWVB_bits_ {
 unsigned char Minute_10:3;
 unsigned char Minute_1:4;
 unsigned char Hour_10:2;
 unsigned char Hour_1:4;
 unsigned char DOY_100:2;
 unsigned char DOY_10:4;
 unsigned char DOY_1:4;
// unsigned char UT1_SIGN:3;
// unsigned char UT1_CORR:4;
// unsigned char Year_10:4;
// unsigned char Year_1:4;
 unsigned char LY:1;
 unsigned char LS:1;
 unsigned char DST57:1;
 unsigned char DST58:1;
};

[Update: Remember, that struct is bass-ackwards. You want the most-significant fields on the bottom, rather than the top, so the bits fill them in properly. This is how I found out that’s true…]

Coerce the bits into an unnatural union with an unsigned long int and create a variable:

union WWVB_code_ {
 uint32_t WWVB_ul;
 struct WWVB_bits_ WWVB_bits;
};

union WWVB_code_ ReceivedBits;

Then set a few bits to find out how the compiler arranges things:

 ReceivedBits.WWVB_bits.DST57 = 1;
 ReceivedBits.WWVB_bits.DST58 = 1;
 ReceivedBits.WWVB_bits.Hour_1 = 9;
 ReceivedBits.WWVB_bits.Minute_1 = 4;

 sprintf(PrintBuffer,"Bit field: %08lX",ReceivedBits.WWVB_ul);
 Serial.println(PrintBuffer);

Which produces this informative line:

Bit field: 03001220

Soooo, rats, the DST bits are on the left and the Minute bits are on the right. That doesn’t tell you how they’re actually laid out in memory, but if you’re doing the interrupt handler in C, then you just stuff the incoming MSB-first bits from the radio directly into the right side of the int and let them slide leftward.

If you count ‘em up, you’ll find that the commented-out bits allow the remainder to fit into an unsigned long int, which is all of 32 bits on the Arduino. You can actually use an unsigned long long int to get 64 bits, but it seems Arduino bit fields can’t extend beyond 32 bits.

There are ways around that, particularly seeing as how I’m using a simpleminded interpreter to parse the incoming bits, but I’ll doodle about that later.

Insert the usual caveats about portability and interoperability and maintainability and … well, you know why bits fields are such a bad idea.

Leave a comment