fix: Align CRC calculation with ETSI EN 300 706 standard
All checks were successful
Build Linux / Build Linux (push) Successful in 1m29s
Build Windows / Build Windows (push) Successful in 4m45s

This commit is contained in:
2026-02-07 14:27:37 +01:00
parent de296b4711
commit 9b846970b8

View File

@@ -78,11 +78,12 @@ class Page:
def calculate_crc(self) -> int:
"""
Calculates the CRC-16 (CCITT) checksum for the page.
Covers Rows 0 to 23.
Row 0: Skips first 8 bytes (Header/Control). Uses bytes 8-39.
Rows 1-23: Uses all 40 bytes.
Data is 7-bit (stripped parity).
Initial value: 0 (ETSI EN 300 706 9.4.1.2).
According to ETSI EN 300 706 (Section 9.4.1.2 & Figure 13):
- Covers Row 0 columns 8-31 (Bytes 14-37 in packet, excluding header and clock).
- Covers Rows 1-25 columns 0-39 (Bytes 6-45 in packet).
- Total 1024 bytes (8192 bits).
- Data is 7-bit (stripped parity).
- Initial value: 0.
"""
crc = 0
poly = 0x1021
@@ -104,18 +105,27 @@ class Page:
for p in self.packets:
rows[p.row] = p
for r in range(24): # 0 to 23
for r in range(26): # 0 to 25
# Determine column range
if r == 0:
start_col, end_col = 8, 32 # Cols 8-31 (24 bytes)
else:
start_col, end_col = 0, 40 # Cols 0-39 (40 bytes)
if r in rows:
data = rows[r].data
start_col = 8 if r == 0 else 0
# Ensure data is long enough (should be 40)
d_len = len(data)
for i in range(start_col, 40):
byte_val = data[i] & 0x7F # Strip parity
for i in range(start_col, end_col):
if i < d_len:
byte_val = data[i] & 0x7F # Strip parity
else:
byte_val = 0x20 # Pad with space if short
crc = update_crc(crc, byte_val)
else:
# Missing row? Usually treated as spaces (0x20)
start_col = 8 if r == 0 else 0
for i in range(start_col, 40):
# Missing row treated as spaces
for i in range(start_col, end_col):
crc = update_crc(crc, 0x20)
return crc