#!/usr/bin/env python3
|
"""
|
CRC16-CCITT Calculator
|
Based on the provided C implementation
|
"""
|
|
def calculate_crc16(data):
|
"""
|
Calculate CRC16-CCITT
|
|
Args:
|
data: bytes or bytearray
|
|
Returns:
|
uint16 CRC value
|
"""
|
crc = 0xFFFF
|
polynomial = 0x1021
|
|
for byte in data:
|
crc ^= (byte << 8)
|
for _ in range(8):
|
if crc & 0x8000:
|
crc = (crc << 1) ^ polynomial
|
else:
|
crc <<= 1
|
crc &= 0xFFFF # Keep it 16-bit
|
|
return crc & 0xFFFF
|
|
|
def main():
|
print("=" * 60)
|
print("CRC16-CCITT Calculator")
|
print("=" * 60)
|
print("Enter hex string (space-separated or continuous)")
|
print("Example: AA 55 03 09 00 67 00 00 0A 00 00")
|
print("Or: AA5503090067000000A0000")
|
print("Enter 'q' to quit")
|
print("=" * 60)
|
|
while True:
|
user_input = input("\nHex data: ").strip()
|
|
if user_input.lower() == 'q':
|
print("Goodbye!")
|
break
|
|
if not user_input:
|
continue
|
|
try:
|
# Remove spaces and convert to bytes
|
hex_string = user_input.replace(" ", "").replace("0x", "")
|
|
# Validate hex string length (must be even)
|
if len(hex_string) % 2 != 0:
|
print(f"Error: Hex string length must be even (got {len(hex_string)})")
|
continue
|
|
# Convert to bytes
|
data = bytes.fromhex(hex_string)
|
|
# Calculate CRC
|
crc = calculate_crc16(data)
|
|
# Display results
|
print(f"\nInput data ({len(data)} bytes):")
|
print(" ".join(f"{b:02X}" for b in data))
|
print(f"\nCRC16 Result:")
|
print(f" Hex: 0x{crc:04X}")
|
print(f" Dec: {crc}")
|
print(f" Bytes (Big Endian): {crc >> 8:02X} {crc & 0xFF:02X}")
|
print(f" Bytes (Little Endian): {crc & 0xFF:02X} {crc >> 8:02X}")
|
|
except ValueError as e:
|
print(f"Error: Invalid hex string - {e}")
|
except Exception as e:
|
print(f"Error: {e}")
|
|
|
def test_examples():
|
"""Test with known examples from the log"""
|
print("\n" + "=" * 60)
|
print("Testing with examples from log:")
|
print("=" * 60)
|
|
examples = [
|
# Frame 1: Speed 10
|
("AA 55 03 09 00 67 00 00 0A 00 00", "9E3C", "Full frame (11 bytes)"),
|
("09 00 67 00 00 0A 00 00", None, "From DataLen (8 bytes)"),
|
("67 00 00 0A 00 00", None, "From SeqNum (6 bytes)"),
|
|
# User's original example from protocol doc
|
("AA 55 03 09 00 01 00 00 32 00 00", "C37B", "User example (11 bytes)"),
|
]
|
|
for hex_data, expected_crc, description in examples:
|
data = bytes.fromhex(hex_data.replace(" ", ""))
|
crc = calculate_crc16(data)
|
|
print(f"\n{description}:")
|
print(f" Data: {hex_data}")
|
print(f" Calculated CRC: 0x{crc:04X}")
|
if expected_crc:
|
print(f" Expected CRC: 0x{expected_crc}")
|
match = (crc == int(expected_crc, 16))
|
print(f" Match: {'✓ YES' if match else '✗ NO'}")
|
|
|
if __name__ == "__main__":
|
# Run tests first
|
test_examples()
|
|
# Then start interactive mode
|
print("\n")
|
main()
|