1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/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()