First, apply a mask to ignore the high bits, like bytes[6] & 0x0F
. Next, JavaScript’s bitwise operators always assume two’s complement, when handling 32 bits. But, as you’re ignoring the high bits, some sign extension for the 3 or 4 bits that you’re ignoring is still needed… Something like, very much untested:
// LSB, and bits 28-31 reserved for future use. Sign-extend to handle
// negative values; 0b00001000 = 0x08 and 0b11110000 = 0xF0:
var lat = bytes[3] | bytes[4]<<8 | bytes[5]<<16
| (bytes[6] & 0x0F | (bytes[6] & 0x08 ? 0xF0 : 0x00))<<24;
// LSB, and bits 29-31 used for accuracy. Sign-extend to handle
// negative values; 0b00010000 = 0x10 and 0b11100000 = 0xE0:
var lng = bytes[7] | bytes[8]<<8 | bytes[9]<<16
| (bytes[10] & 0x1F | (bytes[10] & 0x10 ? 0xE0 : 0x00))<<24;
var accuracy = bytes[10]>>5;
Probably easier to shift 4 and 3 bytes too far to the left, and shift it back, as the bitwise operator >>
is the sign-propagating right shift:
// LSB, ignoring the 4 and 3 high bits, and sign-extending to 32 bits
// to support negative values, by shifting 4 or 3 bytes too far to
// the left (discarding those bits, as only 32 bits are preserved),
// followed by a sign-propagating right shift:
var lat = bytes[3] | bytes[4]<<8 | bytes[5]<<16 | bytes[6]<<28>>4;
var lng = bytes[7] | bytes[8]<<8 | bytes[9]<<16 | bytes[10]<<27>>3;
To parse a few bits from a single byte, see:
…which you can use for:
var voltage = (25 + bits(byte[1], 0, 3)) / 10;
var capacity = 100 * (bits(byte[1], 4, 7) / 15);
var accuracy = bits(byte[10], 5, 7);