user2701295
user2701295

Reputation: 53

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];

Upvotes: 2

Views: 3683

Answers (4)

Parax
Parax

Reputation: 11

to expand and clarify the reply by Carl Norum.

The (int) typecast is required because the source is a byte. The bitshift is performed on the source datatype before the result is saved into X. Therefore it must be cast to at least 16 bits (an int) in order to bitshift 8 bits and retain all the data before the OR operation is executed and the result saved.

What the code is not telling you is if this should be an unsigned int or if there is a sign in the bit data. I'd expect -ve data is possible with an Accelerometer.

Upvotes: 0

Lee Meador
Lee Meador

Reputation: 12985

The device result is in 6 bytes and the bytes need to be rearranged into 3 integers (having values that can only take up 10 bits at most).

So the first two bytes look like this:

00: xxxx xxxx <- binary value
01: ???? ??xx

The ??? part isn't part of the result because the xxx part comprise the 10 bits. I guess the hardware is built in such a way that the ??? part is all zero bits.

To get this into a single integer variable, we need all 8 of the low bits plus the upper-order 2 bits, shifted left by 8 position so they don't interfere with the low order 8 bits. The logical OR (| - vertical bar) will join those two parts into a single integer that looks like this:

x: ???? ??xx xxxx xxxx <- binary value of a single 16 bit integer

Actually it doesn't matter how big the 'int' is (in bits) as the remaining bits (beyond that 16) will be zero in this case.

Upvotes: 0

Carl Norum
Carl Norum

Reputation: 225072

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

Upvotes: 4

user529758
user529758

Reputation:

The value in slot 1 is being bit shifted 8 places to the left.(does this point to buff slot 0?)

Nah. Bitwise operators ain't pointer arithmetic, don't confuse the two. Shifting by N places to the left is (roughly) equivalent with multiplying by 2 to the Nth power (except some corner cases in C, but let's not talk about those yet).

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

No. | is not the logical OR operator (that would be ||) but the bitwise OR one. All the code does is combining the two bytes in buff[0] and buff[1] into a single 2-byte integer, where buff[1] denotes the MSB of the number.

Upvotes: 1

Related Questions