Search code examples
cbluetoothbitbyte-shifting

Binary operations to pack mutliple values


Ive been playing around with a Bluetooth module for sending over data. The data contains of 3 rotations (0-360) and 3 buttons states (bits (0 or 1)).

I tried mapping this into a string (ie: 360_52_265_010% : x_y_z_bbb% where % is a mark for ending a stream of data) but sending this actually takes up to 16 bytes (more or less) because every little letter is a char (8bits)...

This is unacceptable. I have a small delay which I can not tolerate, so I came up with this idea:

  • One rotation axis = 9 bits of data because the maxvalue is 360, which takes up a max of 9 bits
  • We need 3 rotations + 3 bits for button states, so that adds up to 30 bits.
  • Searched the interwebs for the best datatype, and google gave me a float (32bit)

Now I'm thinking about mapping all of these values into a single float, because 4 bytes beats 17 bytes by far through a Bluetooth connection (I think)

For better interpretation, I made this beautiful representation of what I think should work: enter image description here

Now, I have 0 experience with bitshifting. Well I know the main concept, but I can't seem to get this working. I looked at a few other posts here and here but the masks confuse me.

So I just went for it, and tried this little piece of code:

    int xx = 270, yy = 5, zz = 26;
    //3 buttons; left, right, and trigger. I used a byte cause I actually have no idea how I could store just one bit
    byte ll = 0, rr = 0, tt = 1;
    //in here I tried to bitshift the values. Hence the word tried :(
    float packed = (float)(xx << 22 | yy << 13 | zz << 4 | rr << 3 | ll << 2 | tt << 1);

This spits out a float value of 67113578 (EDIT THIS IS WRONG, this value got converted from chars to a string due to printing it to my console)

So I was wondering if someone could help me a hand on packing those values into one float and back to my original data.

Thanks for helping!


Solution

  • Use unsigned long instead of float, or whatever unsigned integer type you know is 4 bytes wide in your machine. All your shifts are off by one. It should be:

    (xx << 21 | yy << 12 | zz << 3 | rr << 2 | ll << 1 | tt);