Last active
May 5, 2025 01:16
-
-
Save oysstu/68072c44c02879a2abf94ef350d1c7c6 to your computer and use it in GitHub Desktop.
Implementation of crc16 (CRC-16-CCITT) in python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def crc16(data: bytes, poly=0x8408): | |
''' | |
CRC-16-CCITT Algorithm | |
''' | |
data = bytearray(data) | |
crc = 0xFFFF | |
for b in data: | |
cur_byte = 0xFF & b | |
for _ in range(0, 8): | |
if (crc & 0x0001) ^ (cur_byte & 0x0001): | |
crc = (crc >> 1) ^ poly | |
else: | |
crc >>= 1 | |
cur_byte >>= 1 | |
crc = (~crc & 0xFFFF) | |
crc = (crc << 8) | ((crc >> 8) & 0xFF) | |
return crc & 0xFFFF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@oysstu This line is incorrect::
This is incorrect because your code implements a bit-serial LFSR CRC calculator, but the INIT value of 0xFFFF comes from Ross Williams' Rocksoft^tm model, which is based on a table-driven calculation.
The Rocksoft model is described in Williams' crc_v3.txt, which you can find here
In the Rocksoft model, the initial value (0xFFFF) is loaded into the register, and the current contents of the register are XOR'd with the next incoming data bytes at the start of each iteration. You can see this in Williams' sample C code. Line 1635 in crc_v3.txt shows the INIT value being loaded into the register (p_cm->cm_reg), and line 1649 shows the data bytes being XOR'd into p_cm->cm_reg.
By preloading a serial LFSR with 0xFFFF, you're effectively prepending 0xFFFF to your block of data, which doesn't give the same result. What you actually want to do is XOR 0xFFFF with the first two bytes of data.
I recommend testing your algorithm against the calculator at sunshine2k.de. It gives correct results.