Python: How to Convert 32-bit Signed Long to 7-bit ints

600 Views Asked by At

What is the best way (in Python) to convert 32-bit signed longs to 7-bit ints, in order to transmit them via Firmata/serial link? Converting into 8-bit is not a problem, just (long_val).to_bytes(4, 'little'). The final sequence should be like this:

No 1, bits 0-6
No 2, bits 7-13
No 3, bits 14-20
No 4, bits 21-27
No 5, bits 28-32

A backward conversion from a 5-item sequence of 7-bit ints into 32 bit signed longs would also be very helpful.

s = bin(pos)[2:].zfill(32)
cmd = bytearray([acc.ACCELSTEPPER_TO, dev_no,
int(s[28:32], 2), int(s[21:28], 2), int(s[14:21], 2),
int(s[7:14], 2), int(s[0:7], 2)])
brd.send_sysex(acc.ACCELSTEPPER_DATA, cmd)

My methods unfortunately produced wrong result, so I would like to discard them completely and restart from scratch. Thanks in advance for any suggestion(s).

2

There are 2 best solutions below

0
CL. On BEST ANSWER

Just do the conversions 7 bits at a time:

bytes = []
for i in range(5):
    bytes.append(long_value & 0x7f)
    long_value >>= 7
long_value = 0
for i in reversed(range(5)):
    long_value <<= 7
    long_value |= bytes[i]
3
Tobias On

It is not exactly 7 bits as such, but it sounds like a job for base64 coding. If all you need is to transmit the data over a 7-bit channel, then base64 should work just fine for you. Of course, your data stream will be slightly longer, i.e. 6 bytes instead of 5.

Here is how you might write it in Python:

import base64

def encode_number(n):
    """Takes an int and returns a bytes object in base64 encoding."""
    return base64.b64encode(n.to_bytes(4, byteorder='little'))

def decode_number(b):
    """Takes a bytes object in base64 encoding and returns an int."""
    return int.from_bytes(base64.b64decode(b), byteorder='little')

And if ever you need more than 32-bit numbers, just change the 4 in line 5 here.