# bit shifting, unsigned long and int convertions

Hello guys,

I’ve been trying to pack 3 rotations (ranging from 0 - 360) and 3 button states into a unsigned long variable. This worked great, and to make it more clear, here is a visual representation:

bits stored in a 32 bit unsigned long. I mapped the bits with square brackets, and from right to left:

• 3 bits for 3 button states, 1 is on, 0 is off
• 9 bits for Z axis (0-360 degrees), and 2 other groups for Y and X

00[000000 000][00000 0000][0000 00000][000]

I used this code to map those values:

where x, y and z are int values, and packedInfo is an unsigned long value

``````       x = (ypr[0] * 180 / M_PI);
if( x < 0) x += 360;

y = (ypr[1] * 180 / M_PI);
if( y < 0) y += 360;

z = (ypr[2] * 180 / M_PI);
if( z < 0) z += 360;

packedInfo = (x << 21UL |
y << 12UL |
z << 3 |
(digitalRead(5) == LOW ? 1 : 0) << 2 |
(digitalRead(6) == LOW ? 1 : 0) << 1 |
(digitalRead(7) == LOW ? 1 : 0));
``````

Now I want to unpack those values, and this is where everything goes wrong. First I had problems assigning the x and y values by bitshifting, but this was due to a problem with 21 and 12 (bitshift values for x and y) being normal integers but those are 16 bit, while I want to assign it to a 32 bit unsigned long, so the data got lost. I think I fixed this by converting the number to a unsigned long by adding ‘UL’ to it, altho I’m not 100% sure this works.

So, to unpack these values, I tried this piece of code:

``````        unsigned long mask = 511;

Serial.print("x1: ");
Serial.print(x);

Serial.print(" y1: ");
Serial.print(y);

Serial.print(" z1: ");
Serial.print(z);

Serial.println("");

Serial.print("x: ");
int xResult = packedInfo >> 21UL;
Serial.print((unsigned long)xResult);

Serial.print(" y: ");
int yResult = packedInfo >> 12UL & mask;
Serial.print((unsigned long)yResult);

Serial.print(" z: ");
int zResult = packedInfo >> 3 & mask;
Serial.print((unsigned long)zResult);
Serial.println("");
``````

Which works perfectly for my button states, and Z axis, but y and x (which are the bits packed at the most elft side of the unsigned long) are number bigger than 360. X mostly is around 2047 and y around 511.

I think this has something to do with converting datatypes, from unsigned to signed ? Would be nice if someone could explain my struggle here!

Thanks a lot

``````   packedInfo = ((uint32_t)x << 21 |
(uint32_t)y << 12 |
(uint32_t)z << 3 |
(digitalRead(5) == LOW ? 1 : 0) << 2 |
(digitalRead(6) == LOW ? 1 : 0) << 1 |
(digitalRead(7) == LOW ? 1 : 0));
``````

Yes, this works!

Could you explain why this works with an unsigned int, but not with an unsigned long?

uint32_t is "unsigned long".