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:
+42
-38
@@ -5,7 +5,7 @@
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
|
||||
/* CRC tests */
|
||||
/* CRC tests — CRC8/DVB-S2 (poly 0xD5) */
|
||||
void test_crc_empty(void) {
|
||||
uint8_t data[1] = {0};
|
||||
TEST_ASSERT_EQUAL_UINT8(0x00, cel_crsf_crc(data, 0));
|
||||
@@ -18,45 +18,47 @@ void test_crc_single_byte(void) {
|
||||
}
|
||||
|
||||
void test_crc_known_value(void) {
|
||||
/* CRSF heartbeat frame data (dest+src+type+size+payload):
|
||||
* {0x10, 0x80, 0x03, 0x02, 0x80, 0x01}
|
||||
* Known CRC for this sequence */
|
||||
/* Verify CRC is deterministic */
|
||||
uint8_t data[6] = {0x10, 0x80, 0x03, 0x02, 0x80, 0x01};
|
||||
uint8_t crc = cel_crsf_crc(data, 6);
|
||||
TEST_ASSERT_TRUE(crc != 0);
|
||||
/* Verify idempotency */
|
||||
uint8_t crc2 = cel_crsf_crc(data, 6);
|
||||
TEST_ASSERT_EQUAL_UINT8(crc, crc2);
|
||||
}
|
||||
|
||||
/* Frame parse tests */
|
||||
void test_parse_invalid_header(void) {
|
||||
cel_crsf_frame frame;
|
||||
/* TODO: rewrite parse/build tests for new ELRS frame format.
|
||||
* New format: [addr][length][type][payload...][crc]
|
||||
* Old tests below use legacy functions for backward compat. */
|
||||
|
||||
/* Frame parse tests (legacy format) */
|
||||
void test_parse_legacy_invalid_header(void) {
|
||||
cel_crsf_frame_legacy frame;
|
||||
uint8_t buf[8] = {0x00, 0x10, 0x80, 0x03, 0x02, 0x80, 0x01, 0x00};
|
||||
TEST_ASSERT_EQUAL_INT(-1, cel_crsf_frame_parse(&frame, buf, 8));
|
||||
TEST_ASSERT_EQUAL_INT(-1, cel_crsf_frame_parse_legacy(&frame, buf, 8));
|
||||
}
|
||||
|
||||
void test_parse_too_short(void) {
|
||||
cel_crsf_frame frame;
|
||||
void test_parse_legacy_too_short(void) {
|
||||
cel_crsf_frame_legacy frame;
|
||||
uint8_t buf[2] = {0xC8, 0x10};
|
||||
TEST_ASSERT_EQUAL_INT(-1, cel_crsf_frame_parse(&frame, buf, 2));
|
||||
TEST_ASSERT_EQUAL_INT(-1, cel_crsf_frame_parse_legacy(&frame, buf, 2));
|
||||
}
|
||||
|
||||
void test_parse_null_frame(void) {
|
||||
void test_parse_legacy_null_frame(void) {
|
||||
uint8_t buf[8] = {0xC8, 0x10, 0x80, 0x03, 0x02, 0x80, 0x01, 0x00};
|
||||
TEST_ASSERT_EQUAL_INT(-1, cel_crsf_frame_parse(NULL, buf, 8));
|
||||
TEST_ASSERT_EQUAL_INT(-1, cel_crsf_frame_parse_legacy(NULL, buf, 8));
|
||||
}
|
||||
|
||||
void test_parse_null_buf(void) {
|
||||
cel_crsf_frame frame;
|
||||
TEST_ASSERT_EQUAL_INT(-1, cel_crsf_frame_parse(&frame, NULL, 8));
|
||||
void test_parse_legacy_null_buf(void) {
|
||||
cel_crsf_frame_legacy frame;
|
||||
TEST_ASSERT_EQUAL_INT(-1, cel_crsf_frame_parse_legacy(&frame, NULL, 8));
|
||||
}
|
||||
|
||||
/* Frame build tests */
|
||||
void test_build_heartbeat(void) {
|
||||
/* Frame build tests (legacy format) */
|
||||
void test_build_legacy_heartbeat(void) {
|
||||
uint8_t dst[256];
|
||||
uint8_t payload[2] = {0x80, 0x01};
|
||||
size_t len = cel_crsf_frame_build(dst, 0x00, 0x80, 0x03, payload, 2);
|
||||
size_t len = cel_crsf_frame_build_legacy(dst, 0x00, 0x80, 0x03,
|
||||
payload, 2);
|
||||
|
||||
TEST_ASSERT_GREATER_THAN(0, len);
|
||||
TEST_ASSERT_EQUAL_UINT8(CEL_CRSF_FRAME_HEADER, dst[0]);
|
||||
@@ -68,14 +70,15 @@ void test_build_heartbeat(void) {
|
||||
TEST_ASSERT_EQUAL_UINT8(0x01, dst[6]); /* payload[1] */
|
||||
}
|
||||
|
||||
void test_build_roundtrip(void) {
|
||||
void test_build_legacy_roundtrip(void) {
|
||||
uint8_t dst[256];
|
||||
uint8_t payload[4] = {0xAA, 0xBB, 0xCC, 0xDD};
|
||||
size_t len = cel_crsf_frame_build(dst, 0x10, 0x80, 0x01, payload, 4);
|
||||
size_t len = cel_crsf_frame_build_legacy(dst, 0x10, 0x80, 0x01,
|
||||
payload, 4);
|
||||
|
||||
/* Parse the built frame back */
|
||||
cel_crsf_frame frame;
|
||||
TEST_ASSERT_EQUAL_INT(0, cel_crsf_frame_parse(&frame, dst, len));
|
||||
cel_crsf_frame_legacy frame;
|
||||
TEST_ASSERT_EQUAL_INT(0, cel_crsf_frame_parse_legacy(&frame, dst, len));
|
||||
TEST_ASSERT_EQUAL_UINT8(0x10, frame.destination);
|
||||
TEST_ASSERT_EQUAL_UINT8(0x80, frame.source);
|
||||
TEST_ASSERT_EQUAL_UINT8(0x01, frame.type);
|
||||
@@ -84,18 +87,19 @@ void test_build_roundtrip(void) {
|
||||
TEST_ASSERT_EQUAL_UINT8(0xDD, frame.payload[3]);
|
||||
}
|
||||
|
||||
void test_build_null_dst(void) {
|
||||
void test_build_legacy_null_dst(void) {
|
||||
uint8_t payload[2] = {0x01, 0x02};
|
||||
TEST_ASSERT_EQUAL_UINT(0, cel_crsf_frame_build(NULL, 0x00, 0x80, 0x03, payload, 2));
|
||||
TEST_ASSERT_EQUAL_UINT(0, cel_crsf_frame_build_legacy(NULL, 0x00, 0x80,
|
||||
0x03, payload, 2));
|
||||
}
|
||||
|
||||
void test_build_null_payload(void) {
|
||||
void test_build_legacy_null_payload(void) {
|
||||
uint8_t dst[256];
|
||||
size_t len = cel_crsf_frame_build(dst, 0x10, 0x80, 0x03, NULL, 0);
|
||||
size_t len = cel_crsf_frame_build_legacy(dst, 0x10, 0x80, 0x03, NULL, 0);
|
||||
TEST_ASSERT_GREATER_THAN(0, len);
|
||||
/* Should still have valid CRC for empty payload */
|
||||
cel_crsf_frame frame;
|
||||
TEST_ASSERT_EQUAL_INT(0, cel_crsf_frame_parse(&frame, dst, len));
|
||||
cel_crsf_frame_legacy frame;
|
||||
TEST_ASSERT_EQUAL_INT(0, cel_crsf_frame_parse_legacy(&frame, dst, len));
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -103,13 +107,13 @@ int main(void) {
|
||||
RUN_TEST(test_crc_empty);
|
||||
RUN_TEST(test_crc_single_byte);
|
||||
RUN_TEST(test_crc_known_value);
|
||||
RUN_TEST(test_parse_invalid_header);
|
||||
RUN_TEST(test_parse_too_short);
|
||||
RUN_TEST(test_parse_null_frame);
|
||||
RUN_TEST(test_parse_null_buf);
|
||||
RUN_TEST(test_build_heartbeat);
|
||||
RUN_TEST(test_build_roundtrip);
|
||||
RUN_TEST(test_build_null_dst);
|
||||
RUN_TEST(test_build_null_payload);
|
||||
RUN_TEST(test_parse_legacy_invalid_header);
|
||||
RUN_TEST(test_parse_legacy_too_short);
|
||||
RUN_TEST(test_parse_legacy_null_frame);
|
||||
RUN_TEST(test_parse_legacy_null_buf);
|
||||
RUN_TEST(test_build_legacy_heartbeat);
|
||||
RUN_TEST(test_build_legacy_roundtrip);
|
||||
RUN_TEST(test_build_legacy_null_dst);
|
||||
RUN_TEST(test_build_legacy_null_payload);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user