Search code examples
arduinobit-manipulationaccelerometermicrocontrollerbit-shift

bit-shift operation in accelerometer code


I'm programming my Arduino micro controller and I found some code for accepting accelerometer sensor data for later use. I can understand all but the following code. I'd like to have some intuition as to what is happening but after all my searching and reading I can't wrap my head around what is going on and truly understand.

I have taken a class in C++ and we did very little with bitwise operations or bit shifting or whatever you'd like to call it. Let me try to explain what I think I understand and you can correct me where it is needed.

So:

  1. I think we are storing a value in x, pretty sure in fact.
  2. It appears that the data in array "buff", slot number 1, is being set to the datatype of integer.
  3. The value in slot 1 is being bit shifted 8 places to the left.(does this point to buff slot 0?)

This new value is being compared to the data in buff slot 0 and if either bits are true then the bit in the data stored in x will also be true so, 0 and 1 = 1, 0 and 0 = 0 and 1 and 0 = 1 in the end stored value.

The code does this for all three axis: x, y, z but I'm not sure why...I need help. I want full understanding before I progress.

//each axis reading comes in 10 bit resolution, ie 2 bytes.  
// Least Significant Byte first!!
//thus we are converting both bytes in to one int
x = (((int)buff[1]) << 8) | buff[0];   
y = (((int)buff[3]) << 8) | buff[2];
z = (((int)buff[5]) << 8) | buff[4];

Solution

  • This code is being used to convert the raw accelerometer data (in an array of 6 bytes) into three 10-bit integer values. As the comment says, the data is LSB first. That is:

    buff[0] // least significant 8 bits of x data
    buff[1] // most significant 2 bits of x data 
    buff[2] // least significant 8 bits of y data
    buff[3] // most significant 2 bits of y data 
    buff[4] // least significant 8 bits of z data
    buff[5] // most significant 2 bits of z data 
    

    It's using bitwise operators two put the two parts together into a single variable. The (int) typecasts are unnecessary and (IMHO) confusing. This simplified expression:

    x = (buff[1] << 8) | buff[0];
    

    Takes the data in buff[1], and shifts it left 8 bits, and then puts the 8 bits from buff[0] in the space so created. Let's label the 10 bits a through j for example's sake:

    buff[0] = cdefghij
    buff[1] = 000000ab
    

    Then:

    buff[1] << 8 = ab00000000
    

    And:

    buff[1] << 8 | buff[0] = abcdefghij