Chris Barry Chris Barry - 14 days ago 9
Python Question

Calculating a checksum, using the most and least significant bits differently

I'm trying to calculate a checksum, and I have to admit my binary manipulation knowlege is failing me.

If anyone could help with the below (and improve the title of this question) I'd be most grateful.

(I've tried quite a lot of things, but I think I'm just not going about it correctly)

A previous question I asked is here, but the technique is different, I think - How to build byte array frame and calculate checksum

Documentation below:



To avoid the checksum coinciding with any of the control bytes (0x02 and 0x03), the checksum is divided into two bytes. In the first byte the four least significant bits are introduced, and the four most significant ones in the second.

Example:

Checksum calculation of the following command:

STX 0x02
Filler1 0x30
Filler2 0x30
Address 0x81
Type 0x56 “V”
Tray 0x8B
Belt 0x82
Checksum1 0xF6
Checksum2 0x4F
ETX 0x03


Add the values of every byte previous to the checksum. The result is obtained as an
unsigned char
.

Checksum = 0x02+0x30+0x30+0x81+0x56+0x8B+0x82 = 0x46


Set the four most significant bits to “1” using OR operator, forming
Checksum1
, where the four least significant bits of
Checksum
are stored.

Checksum1 = Checksum | 0xF0 = 0x46 | 0xF0 = 0xF6


Change the four least significant bits to “1” using OR operator, forming
Checksum1
, where the four most significant bits of Checksum are stored.

Checksum2 = Checksum | 0x0F = 0x46 | 0x0F = 0x4F


Additional



def print_bytes(bytes):
print("\n" + " ".join("\\x%02X" % v for v in bytes))

frame = bytearray([0x02,0x30,0x30,0x81,0x56,0x8B,0x82])

print_bytes(sum(frame).to_bytes(2, "little"))

\x46 \x02

Answer

The result is obtained as an unsigned char.

This means that you must only use the 8 least significant bits to calculate.

>>> (0x02 + 0x30 + 0x30 + 0x81 + 0x56 + 0x8b + 0x82)
582
>>> (0x02 + 0x30 + 0x30 + 0x81 + 0x56 + 0x8b + 0x82) & 0xff
70

And then within those 8 bits you need to set the 4 most and least significant bits.

>>> 70 | 0xf0
246
>>> 70 | 0x0f
79

This then results in 0xf6 and 0x4f as shown in the checksum bytes.