diff --git a/packets.py b/packets.py new file mode 100644 index 0000000..8effc5b --- /dev/null +++ b/packets.py @@ -0,0 +1,96 @@ +class Packet: + """Represents an 8-byte I2C packet.""" + LENGTH = 8 + + def __init__(self, data=None): + if data is None: + data = [0] * self.LENGTH + if len(data) != self.LENGTH: + raise ValueError(f"Packet must be {self.LENGTH} bytes") + self.bytes = data + + @classmethod + def from_bytes(cls, byte_list): + """Create Packet from list of bytes.""" + return cls(byte_list[:cls.LENGTH]) + + def __getitem__(self, idx): + return self.bytes[idx] + + def __setitem__(self, idx, value): + self.bytes[idx] = value + + def __repr__(self): + fields = [f"Byte {i}: 0x{b:02X}" for i, b in enumerate(self.bytes)] + return "\n".join(fields) + + def as_list(self): + return self.bytes + + def is_valid(self): + """Verify checksum (XOR of bytes 0-6 equals byte 7).""" + cs = 0 + for b in self.bytes[:-1]: + cs ^= b + return cs == self.bytes[-1] + +def create_motor_state_packet(fl=None, fr=None, bl=None, br=None): + """ + Create an 8-byte packet to set motor states for I2C transfer. + Packet format: + [0x01, 0x00, FL, FR, BL, BR, 0x00, checksum] + - 0x01: Command for Motor State Packet + - 0x00: Target/channel (set as needed) + - FL, FR, BL, BR: Motor states (0x00 = off, 0x01 = forward, 0x02 = backward) + - checksum: XOR of bytes 0-6 + """ + def getByteForState(state): + if state: + return 0x01 + elif not state: + return 0x02 + else: + return 0x00 + + packet = [0x01, 0x00, getByteForState(fl), getByteForState(fr), getByteForState(bl), getByteForState(br), 0x00] + checksum = 0 + for b in packet: + checksum ^= b + packet.append(checksum) + return Packet.from_bytes(bytes(packet)) + +def create_tail_wagging_packet(wagging=False): + """ + Create an 8-byte packet to set wagging for I2C transfer. + Packet format: + [0x02, 0x00, Wagging, 0x00, 0x00, 0x00, 0x00, checksum] + - 0x02: Command for Wagging Packet + - 0x00: Target/channel (set as needed) + - Wagging: 0x00 = false, 0x01 = true + - checksum: XOR of bytes 0-6 + """ + packet = [0x02, 0x00, 0x01 if wagging else 0x00, 0x00, 0x00, 0x00, 0x00] + checksum = 0 + for b in packet: + checksum ^= b + packet.append(checksum) + return Packet.from_bytes(bytes(packet)) + +def create_set_led_mode(mode=0): + """ + Create an 8-byte packet to set led mode for I2C transfer. + Packet format: + [0x02, 0x00, Mode, 0x00, 0x00, 0x00, 0x00, checksum] + - 0x02: Command for led mode + - 0x00: Target/channel (set as needed) + - Wagging: 0x00 = standard, 0x01 = rot, 0x02 = rainbow + - checksum: XOR of bytes 0-6 + """ + packet = [0x02, 0x00, mode & 0xFF, 0x00, 0x00, 0x00, 0x00] + checksum = 0 + for b in packet: + checksum ^= b + packet.append(checksum) + return Packet.from_bytes(bytes(packet)) + +