Hi,
I am working with an LSM303DLHC sensor that has all sorts of 2’s compliment data. I am trying without any success to turn the data into actual values that make sense. I am trying to use the invert ‘~’ operator to invert a number if it is supposed to be negative. This is what happens:
Say the number I have (xhm) is 255 (MSB is 1, so it is negative). When I use the operation:
if (xhm > 127)
{
xhm = ~xhm;
}
I get -256 for the number, not -1. What am I doing wrong?
Thanks,
Tom
mag[0] and mag[1] are the two x magnetometer registers and xh is the final magnetometer reading. Is there a simpler way to do this? Why does the ~ invert not work?
Thanks,
Tom
@ tommyvdp - What you need to do is called sign extension. Basically when you promote a signed number from a lower bit count to a higher bit count you need to extend the sign bit to fill the higher bit values. So in your case the you want to promote a 12 bit number to a 16 bit number so you need to extend the sign bit to fill the 4 additional bits.
Your 12 bit number 3087 is represented in binary as
110000001111
To put this into a short and have it be treated correctly you need extend the sign bit which would give the following bit pattern
1111110000001111
^^^^
These bits match the sign bit, if the sign bit had been a 0 ie. a positive number then these bits would have been all 0s.
So how do you sign extend the number, well here is some quick bit math (untested!!!)
short SignExtend(short value, signBit)
{
int signMask = 1 << signBit;
if ((value & singMask) != 0)
{
return (short)((short)(0xffff & ~(signMask - 1)) | value);
}
return value;
}
I hope that is right, but basically, we are checking if the sign bit is a 1 then we create an mask which will make all the high bits above the sign bit 1s and then we or the original value with the mask to get the sign extended value.
This code is a little naive, but I can’t think of a better way now. When I am at my dev PC I will see if my brain is working a little better. But hopefully this gets you going.
Good point, I should have been more explicit about that!
So here is my less naive solution, it leverages the fact that the compiler/CPU actually understands the concept of sign extension and will ensure that a signed value is correctly sign extended when you use the shift operators.
The first line determines the bit difference between the smaller and the larger type. Then the current value is shifted left by that difference, shifting the sign bit in the high bit position for the target type. To tell the compiler that we intend this to be a signed short, the value is explicitly cast to a short, now the compiler will ensure that any bit manipulations keep the sign intact. We can now shift right by 4 to restore the 12 bit value but keeping the sign extended through the bits that are now shifted away.