feat: adopt ELRS USB CRSF frame format, add skeleton modules
Switch CRC from CCITT (0x07) to DVB-S2 (0xD5) to match ELRS. Adopt ELRS USB frame format: [addr][length][type][payload][crc]. Update frame type constants to match current ELRS protocol values. New skeleton modules (stub implementations with TODO comments): - crsf_telemetry.h/.c: telemetry decoders (GPS, battery, link..) - crsf_stream.h/.c: incremental streaming frame reader - crsf_param.h/.c: parameter protocol (read/write/set_power) Retained old frame format as *_legacy functions for backward compatibility with existing telemetry tool and tests. Add cel_serial_find_elrs_port() and cel_serial_open_probe() stubs to serial module for port auto-detection and baud probing.
This commit is contained in:
+104
-39
@@ -13,32 +13,106 @@
|
||||
#define CEL_CRSF_ADDRESS_RC_DEVICE 0xDD
|
||||
#define CEL_CRSF_ADDRESS_GPS 0xEC
|
||||
#define CEL_CRSF_ADDRESS_FLIGHT_CONTROLLER 0xED
|
||||
#define CEL_CRSF_ADDRESS_MODULE 0xEE
|
||||
#define CEL_CRSF_ADDRESS_LUA 0xEF
|
||||
|
||||
/* CRSF frame types */
|
||||
/* CRSF frame types (ELRS) */
|
||||
typedef enum {
|
||||
CEL_CRSF_FRAMETYPE_PACKET_LINK_TELEMETRY = 0x02,
|
||||
CEL_CRSF_FRAMETYPE_RC_CHANNELS_PACKED = 0x01,
|
||||
CEL_CRSF_FRAMETYPE_GPS = 0x02,
|
||||
CEL_CRSF_FRAMETYPE_HEARTBEAT = 0x03,
|
||||
CEL_CRSF_FRAMETYPE_VERSION = 0x04,
|
||||
CEL_CRSF_FRAMETYPE_PARAMETER_SETTINGS_ENTRY = 0x05,
|
||||
CEL_CRSF_FRAMETYPE_PARAMETER_READ = 0x06,
|
||||
CEL_CRSF_FRAMETYPE_PARAMETER_WRITE = 0x07,
|
||||
CEL_CRSF_FRAMETYPE_DEVICE_INFO = 0x08,
|
||||
CEL_CRSF_FRAMETYPE_PARAMETER_LIST = 0x09,
|
||||
CEL_CRSF_FRAMETYPE_RC_CHANNELS_RAW = 0x16,
|
||||
CEL_CRSF_FRAMETYPE_MSP_READ = 0x17,
|
||||
CEL_CRSF_FRAMETYPE_MSP_WRITE = 0x18,
|
||||
CEL_CRSF_FRAMETYPE_CURR_VOLTAGE_TEMP = 0x1E,
|
||||
CEL_CRSF_FRAMETYPE_BATTERY_SENSOR = 0x1F,
|
||||
CEL_CRSF_FRAMETYPE_COMPRESSED_SENSORS = 0x28,
|
||||
CEL_CRSF_FRAMETYPE_ARM = 0x0D,
|
||||
CEL_CRSF_FRAMETYPE_SETTING = 0x9E,
|
||||
CEL_CRSF_FRAMETYPE_SUPERBOX = 0xA0,
|
||||
CEL_CRSF_FRAMETYPE_DEVICE_SUPERBOX = 0xA1,
|
||||
} cel_crsf_frame_type;
|
||||
CEL_CRSF_TYPE_RC_CHANNELS_PACKED = 0x01,
|
||||
CEL_CRSF_TYPE_GPS = 0x02,
|
||||
CEL_CRSF_TYPE_VARIO = 0x07,
|
||||
CEL_CRSF_TYPE_BATTERY = 0x08,
|
||||
CEL_CRSF_TYPE_BARO_ALT = 0x09,
|
||||
CEL_CRSF_TYPE_AIRSPEED = 0x0A,
|
||||
CEL_CRSF_TYPE_HEARTBEAT = 0x0B,
|
||||
CEL_CRSF_TYPE_RPM = 0x0C,
|
||||
CEL_CRSF_TYPE_TEMP = 0x0D,
|
||||
CEL_CRSF_TYPE_VOLTAGES = 0x0E,
|
||||
CEL_CRSF_TYPE_ESC_SENSOR = 0x10,
|
||||
CEL_CRSF_TYPE_LINK_STATS = 0x14,
|
||||
CEL_CRSF_TYPE_RC_CHANNELS = 0x16,
|
||||
CEL_CRSF_TYPE_ATTITUDE = 0x1E,
|
||||
CEL_CRSF_TYPE_FLIGHT_MODE = 0x21,
|
||||
CEL_CRSF_TYPE_DEVICE_PING = 0x28,
|
||||
CEL_CRSF_TYPE_DEVICE_INFO = 0x29,
|
||||
CEL_CRSF_TYPE_PARAM_ENTRY = 0x2B,
|
||||
CEL_CRSF_TYPE_PARAM_READ = 0x2C,
|
||||
CEL_CRSF_TYPE_PARAM_WRITE = 0x2D,
|
||||
CEL_CRSF_TYPE_ELRS_STATUS = 0x2E,
|
||||
} cel_crsf_type;
|
||||
|
||||
/* Parsed CRSF frame */
|
||||
/* ELRS parameter types */
|
||||
typedef enum {
|
||||
CEL_PARAM_UINT8 = 0,
|
||||
CEL_PARAM_INT8 = 1,
|
||||
CEL_PARAM_UINT16 = 2,
|
||||
CEL_PARAM_INT16 = 3,
|
||||
CEL_PARAM_UINT32 = 4,
|
||||
CEL_PARAM_INT32 = 5,
|
||||
CEL_PARAM_FLOAT = 8,
|
||||
CEL_PARAM_TEXT_SELECT = 9,
|
||||
CEL_PARAM_STRING = 10,
|
||||
CEL_PARAM_FOLDER = 11,
|
||||
CEL_PARAM_INFO = 12,
|
||||
CEL_PARAM_COMMAND = 13,
|
||||
} cel_param_type;
|
||||
|
||||
/* Channel value mapping (11-bit) */
|
||||
#define CEL_CRSF_CH_MIN 172 /* 988 us */
|
||||
#define CEL_CRSF_CH_MID 992 /* 1500 us */
|
||||
#define CEL_CRSF_CH_MAX 1811 /* 2012 us */
|
||||
|
||||
/* Parsed CRSF frame (ELRS USB format: [addr][length][type][payload][crc]) */
|
||||
typedef struct {
|
||||
uint8_t addr;
|
||||
uint8_t length;
|
||||
uint8_t type;
|
||||
uint8_t payload[255];
|
||||
uint8_t payload_len;
|
||||
uint8_t crc;
|
||||
} cel_crsf_frame;
|
||||
|
||||
/* CRC8/DVB-S2 (poly 0xD5, init 0x00) */
|
||||
uint8_t cel_crsf_crc(uint8_t const* data, size_t len);
|
||||
|
||||
/* Build an RC channels frame (16 channels, 11-bit each).
|
||||
Returns total bytes written into dst (min 28 bytes needed). */
|
||||
size_t cel_crsf_build_rc_frame(uint8_t* dst, int16_t const channels[16]);
|
||||
|
||||
/* Build a device ping frame. Returns bytes written (min 7 bytes needed). */
|
||||
size_t cel_crsf_build_ping_frame(uint8_t* dst);
|
||||
|
||||
/* Build a parameter read frame. Returns bytes written (min 9 bytes needed). */
|
||||
size_t cel_crsf_build_param_read_frame(uint8_t* dst, uint8_t index,
|
||||
uint8_t chunk);
|
||||
|
||||
/* Build a parameter write frame. Returns bytes written (min 9 bytes needed). */
|
||||
size_t cel_crsf_build_param_write_frame(uint8_t* dst, uint8_t index,
|
||||
uint8_t value);
|
||||
|
||||
/* Parse a single CRSF frame from buf. Returns 0 on success, -1 on error.
|
||||
buf should start with the address byte (0xC8, 0xEE, etc.). */
|
||||
int cel_crsf_frame_parse(cel_crsf_frame* frame, uint8_t const* buf,
|
||||
size_t len);
|
||||
|
||||
/* Channel helpers */
|
||||
int16_t cel_crsf_channel_clamp(int16_t value);
|
||||
int16_t cel_crsf_channel_us_to_val(uint16_t us);
|
||||
uint16_t cel_crsf_channel_val_to_us(int16_t value);
|
||||
void cel_crsf_channel_default(int16_t channels[16]);
|
||||
|
||||
/* Telemetry parsing — see crsf_telemetry.h */
|
||||
#include "celrs/crsf_telemetry.h"
|
||||
|
||||
/* Streaming reader — see crsf_stream.h */
|
||||
#include "celrs/crsf_stream.h"
|
||||
|
||||
/* Parameter protocol — see crsf_param.h */
|
||||
#include "celrs/crsf_param.h"
|
||||
|
||||
/* --- Deprecated (old frame format: [0xC8][dest][src][type][size][payload][crc]) --- */
|
||||
|
||||
/* Deprecated frame structure (old format). Use cel_crsf_frame instead. */
|
||||
typedef struct {
|
||||
uint8_t destination;
|
||||
uint8_t source;
|
||||
@@ -46,20 +120,11 @@ typedef struct {
|
||||
uint8_t size;
|
||||
uint8_t payload[255];
|
||||
uint8_t crc;
|
||||
} cel_crsf_frame;
|
||||
} cel_crsf_frame_legacy;
|
||||
|
||||
/* CRC8 calculation over CRSF frame data (CCITT poly 0x07) */
|
||||
uint8_t cel_crsf_crc(uint8_t const* data, size_t len);
|
||||
|
||||
/* Validate CRC of a CRSF frame (header already stripped, starts at dest addr) */
|
||||
int cel_crsf_frame_validate(cel_crsf_frame const* frame);
|
||||
|
||||
/* Parse a raw buffer into a cel_crsf_frame. Returns 0 on success, -1 on error.
|
||||
buf should start with 0xC8 header. */
|
||||
int cel_crsf_frame_parse(cel_crsf_frame* frame, uint8_t const* buf, size_t len);
|
||||
|
||||
/* Build a CRSF frame into dst buffer. Returns total bytes written.
|
||||
dst must have space for at least 5 + size bytes (header, addr, src, type,
|
||||
size byte, payload, crc). */
|
||||
size_t cel_crsf_frame_build(uint8_t* dst, uint8_t destination, uint8_t source,
|
||||
uint8_t type, uint8_t const* payload, uint8_t size);
|
||||
int cel_crsf_frame_validate(cel_crsf_frame_legacy const* frame);
|
||||
int cel_crsf_frame_parse_legacy(cel_crsf_frame_legacy* frame, uint8_t const* buf,
|
||||
size_t len);
|
||||
size_t cel_crsf_frame_build_legacy(uint8_t* dst, uint8_t destination,
|
||||
uint8_t source, uint8_t type,
|
||||
uint8_t const* payload, uint8_t size);
|
||||
|
||||
Reference in New Issue
Block a user