132 lines
5.2 KiB
C++
132 lines
5.2 KiB
C++
#pragma once
|
|
#include <Arduino.h>
|
|
|
|
// ============================================================================
|
|
// Protocol Constants
|
|
// ============================================================================
|
|
|
|
// Sync bytes (distinguishable from Feetech 0xFF 0xFF)
|
|
constexpr uint8_t SYNC0 = 0xA5;
|
|
constexpr uint8_t SYNC1 = 0x5A;
|
|
|
|
// Packet structure:
|
|
// [SYNC0][SYNC1][TAG 4 bytes][LENGTH 2 bytes][SEQ 2 bytes][PAYLOAD...][CRC16 2 bytes]
|
|
// Total overhead: 12 bytes
|
|
|
|
constexpr uint16_t MAX_PAYLOAD_SIZE = 6000;
|
|
constexpr uint16_t PACKET_HEADER_SIZE = 10; // sync(2) + tag(4) + len(2) + seq(2)
|
|
constexpr uint16_t PACKET_CRC_SIZE = 2;
|
|
|
|
// ============================================================================
|
|
// Packet Tags (4 bytes each, human-readable)
|
|
// ============================================================================
|
|
|
|
namespace Tag {
|
|
// Identity & Config
|
|
constexpr char IDENT[4] = {'I','D','N','T'}; // Identity request/response
|
|
constexpr char CONFG[4] = {'C','O','N','F'}; // Config update
|
|
|
|
// File Operations
|
|
constexpr char FLIST[4] = {'F','L','S','T'}; // File list
|
|
constexpr char FLOAD[4] = {'F','L','O','D'}; // File load
|
|
constexpr char FSAVE[4] = {'F','S','A','V'}; // File save
|
|
constexpr char FDELE[4] = {'F','D','E','L'}; // File delete
|
|
constexpr char FPLAY[4] = {'F','P','L','Y'}; // Play animation file
|
|
constexpr char FSTP[4] = {'F','S','T','P'}; // Stop animation
|
|
|
|
// Motor Control
|
|
constexpr char MSET[4] = {'M','S','E','T'}; // Set motor positions
|
|
constexpr char MPOS[4] = {'M','P','O','S'}; // Motor position stream
|
|
constexpr char MSCAN[4] = {'M','S','C','N'}; // Scan for motors
|
|
constexpr char MWRIT[4] = {'M','W','R','T'}; // Write motor register
|
|
constexpr char MSTRM[4] = {'M','S','T','M'}; // Motor stream control
|
|
|
|
// Sensors
|
|
constexpr char IMU[4] = {'I','M','U','0'}; // ADXL acceleration data (x,y,z)
|
|
constexpr char RADAR[4] = {'R','D','A','R'}; // Radar targets
|
|
constexpr char FRAME[4] = {'F','R','M','E'}; // Animation frame events (frame, mode, status)
|
|
|
|
// Behaviors
|
|
constexpr char BHVR[4] = {'B','H','V','R'}; // Behavior control (activate/deactivate)
|
|
constexpr char BLST[4] = {'B','L','S','T'}; // Behavior list (list all behaviors and their states)
|
|
|
|
// Visemes
|
|
constexpr char VLST[4] = {'V','L','S','T'}; // List all visemes
|
|
constexpr char VADD[4] = {'V','A','D','D'}; // Add a new viseme
|
|
constexpr char VDEL[4] = {'V','D','E','L'}; // Delete a viseme
|
|
constexpr char VSET[4] = {'V','S','E','T'}; // Set viseme motor positions
|
|
constexpr char VSME[4] = {'V','S','M','E'}; // Trigger a viseme by ID
|
|
|
|
// System
|
|
constexpr char STATE[4] = {'S','T','A','T'}; // System state/heartbeat
|
|
constexpr char MSGE[4] = {'M','S','G','E'}; // Log/debug message
|
|
constexpr char BOOT[4] = {'B','O','O','T'}; // Enter bootloader
|
|
constexpr char ACK[4] = {'A','C','K','!'}; // Acknowledge
|
|
constexpr char NACK[4] = {'N','A','C','K'}; // Negative acknowledge
|
|
}
|
|
|
|
// ============================================================================
|
|
// Play Modes (for FPLAY command)
|
|
// ============================================================================
|
|
|
|
enum PlayMode : uint8_t {
|
|
PLAY_IDLE = 0x00,
|
|
PLAY_ONCE = 0x01,
|
|
PLAY_LOOP = 0x02,
|
|
PLAY_REPEAT = 0x03
|
|
};
|
|
|
|
// ============================================================================
|
|
// Packet Buffer
|
|
// ============================================================================
|
|
|
|
extern uint8_t g_rxBuffer[MAX_PAYLOAD_SIZE + PACKET_HEADER_SIZE + PACKET_CRC_SIZE];
|
|
extern uint16_t g_rxBufferLen;
|
|
|
|
// ============================================================================
|
|
// CRC16-CCITT
|
|
// ============================================================================
|
|
|
|
uint16_t crc16Update(uint16_t crc, const uint8_t* data, uint16_t len);
|
|
uint16_t crc16Compute(const uint8_t* data, uint16_t len);
|
|
|
|
// ============================================================================
|
|
// Packet Sending
|
|
// ============================================================================
|
|
|
|
// Send a tagged packet with auto-incrementing sequence number
|
|
void sendPacket(const char tag[4], const uint8_t* payload, uint16_t len);
|
|
|
|
// Convenience: send string as MSGE packet
|
|
void sendMessage(const String& msg);
|
|
|
|
// Convenience: send ACK/NACK
|
|
void sendAck(const char originalTag[4]);
|
|
void sendNack(const char originalTag[4], const String& reason = "");
|
|
|
|
// ============================================================================
|
|
// Packet Receiving
|
|
// ============================================================================
|
|
|
|
// Packet receive state machine - call from loop()
|
|
// Returns true when a complete valid packet is ready
|
|
bool receivePacket();
|
|
|
|
// Get received packet info (valid after receivePacket returns true)
|
|
const char* getReceivedTag();
|
|
const uint8_t* getReceivedPayload();
|
|
uint16_t getReceivedPayloadLen();
|
|
uint16_t getReceivedSeq();
|
|
|
|
// Check if received tag matches
|
|
bool tagMatches(const char* received, const char expected[4]);
|
|
|
|
// ============================================================================
|
|
// Utility
|
|
// ============================================================================
|
|
|
|
// Compare tags
|
|
inline bool tagsEqual(const char a[4], const char b[4]) {
|
|
return memcmp(a, b, 4) == 0;
|
|
}
|