#ifndef LIVOXPROTO1_PROTOCOL_H #define LIVOXPROTO1_PROTOCOL_H #include #include #include #include #include #include namespace livoxProto1 { namespace comms { // Endianness detection namespace endian { inline bool isLittleEndian() { union { uint32_t i; char c[4]; } test = {0x01020304}; return test.c[0] == 4; } } /** EXPLANATION: * Device types as defined in the Livox protocol specification */ enum class DeviceType : uint8_t { Hub = 0, Mid40 = 1, Tele15 = 2, Horizon = 3, Mid70 = 6, Avia = 7 }; /** EXPLANATION: * Protocol frame header structure. * All multi-byte fields are in little-endian format as per protocol spec. */ struct Header { uint8_t sof; // 0: Start of Frame (0xAA) uint8_t version; // 1: Protocol Version (1) uint16_t length; // 2-3: Frame Length (little-endian) uint8_t cmd_type; // 4: Command Type (0x02 = MSG for broadcast) uint16_t seq_num; // 5-6: Sequence Number (little-endian) uint16_t crc_16; // 7-8: Header Checksum (little-endian) void swapToHostEndianness(); bool sanityCheck() const; } __attribute__((packed)); /** EXPLANATION: * Protocol frame footer structure. * All multi-byte fields are in little-endian format as per protocol spec. */ struct Footer { uint32_t crc_32; // 0-3: Whole Frame Checksum (little-endian) void swapToHostEndianness(); bool sanityCheck() const; } __attribute__((packed)); /** EXPLANATION: * Complete wire format for Livox broadcast messages. * All multi-byte fields are in little-endian format as per protocol spec. */ struct BroadcastMessage { Header header; // 0-8: Protocol frame header uint8_t cmd_set; // 9: Command Set (0x00 = General) uint8_t cmd_id; // 10: Command ID (0x00 = Broadcast) uint8_t broadcast_code[16]; // 11-26: Device Broadcast Code (null-terminated string) uint8_t dev_type; // 27: Device Type uint16_t reserved; // 28-29: Reserved (little-endian) Footer footer; // 30-33: Protocol frame footer void swapToHostEndianness(); bool sanityCheck() const; } __attribute__((packed)); } // namespace comms } // namespace livoxProto1 #endif // LIVOXPROTO1_PROTOCOL_H