portersky cf02745b02
CI / macOS (push) Has been cancelled
CI / Windows / Clang (push) Has been cancelled
Inital commit
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00
2026-06-14 19:48:37 +02:00

celrs

A C23 project for interfacing with ELRS TX modules (e.g., BAYCK Nano Dual Band) via serial USB using the CRSF (Crossfire Serial) protocol.

Built on the same TDD foundation as ctdd using Unity and CMock.

All dependencies are fetched automatically via CMake FetchContent — no manual installation required beyond the tools listed below.

Requirements

Tool Purpose
CMake ≥ 3.21 Build system
Ninja Build backend
C23 compiler GCC 14+, Clang 18+
Ruby ≥ 3.0 CMock mock generation
gcovr ≥ 6.0 Coverage reports — optional (uv tool install gcovr)

Build

Configure:

cmake -S . -B build -G Ninja

Build:

ninja -C build

Test

Full Unity output with colors:

ninja -C build check

CTest summary only:

ninja -C build test

check builds all suites and runs CTest with --output-on-failure, so assertion-level detail appears on any failure without running binaries by hand.

Coverage

Configure with coverage instrumentation:

cmake -S . -B build-cov -G Ninja -DENABLE_COVERAGE=ON

Generate the HTML report:

ninja -C build-cov coverage

Open build-cov/coverage/index.html in a browser to view results.

Only celrs/ source files are measured. Unity, CMock, and generated mock files are excluded. Requires GCC or Clang with gcov support, and gcovr on PATH.

Windows note: requires GCC (e.g. scoop install gcc) or a Clang build that includes compiler-rt. A custom Clang without compiler-rt will fail at link time.

Run

Connect your ELRS TX module via USB, then run:

Windows:

./build/main.exe COM3

Linux / macOS:

./build/main /dev/ttyUSB0

Architecture

celrs/
  crsf.h / crsf.c      CRSF protocol: CRC8, frame parse/build
  serial.h / serial.c  Serial port abstraction (Win/POSIX)
  logger.h / logger.c  Level-filtering logger
  log_write.h/.c       stdout log sink
main.c                 Entry point — demo heartbeat + read
tests/
  test_crsf.c          CRSF CRC, parse, build tests
  test_serial.c        Serial open/close/stub tests
  test_logger.c        Logger level-filtering tests
deps/
  FindUnity.cmake      Fetches Unity v2.6.1 via ZIP
  FindCMock.cmake      Fetches CMock v2.6.0 via ZIP

CRSF Protocol

CRSF (Crossfire Serial Protocol) is the serial protocol used by ELRS for communication between ground station and TX/RX modules.

Frame format

+------+------+------+------+-------+-------+
| 0xC8 | dest | src  | type | size  | ...   |  CRC  |
+------+------+------+------+-------+-------+
  1 byte  1B     1B     1B     1B     N B     1 byte
  • Header: Always 0xC8
  • Destination: Target device address
  • Source: Sender device address
  • Type: Frame type (heartbeat, RC channels, telemetry, etc.)
  • Size: Payload length in bytes
  • Payload: Frame-specific data
  • CRC: CRC8-CCITT over dest+src+type+size+payload

Common device addresses

Address Device
0x00 FC Broadcast
0x10 Flight Controller
0x80 TBS Ground Station
0xEA Custom Module
0xDD RC Device

Common frame types

Type Name
0x01 RC Channels Packed
0x02 Packet Link Telemetry
0x03 Heartbeat
0x08 Device Info
0x09 Parameter List
0x17 MSP Read
0x18 MSP Write

Adding a new module (TDD workflow)

1. Write the header

// celrs/telemetry.h
#pragma once
#include <stdint.h>

typedef struct {
    int16_t rssi;
    uint8_t link_quality;
    int16_t tx_power;
} telemetry_data;

int telemetry_parse(telemetry_data* out, uint8_t const* buf, size_t len);

2. Write a failing test

// tests/test_telemetry.c
#include "unity.h"
#include "celrs/telemetry.h"

void setUp(void) {}
void tearDown(void) {}

void test_parse_rssi(void) {
    telemetry_data data;
    uint8_t buf[8] = { /* ... */ };
    TEST_ASSERT_EQUAL_INT(0, telemetry_parse(&data, buf, sizeof(buf)));
    TEST_ASSERT_EQUAL_INT16(-42, data.rssi);
}

int main(void) {
    UNITY_BEGIN();
    RUN_TEST(test_parse_rssi);
    return UNITY_END();
}

3. Register the test in tests/CMakeLists.txt

add_executable(test_telemetry test_telemetry.c)
target_include_directories(test_telemetry PRIVATE "${CMAKE_SOURCE_DIR}")
target_link_libraries(test_telemetry PRIVATE celrs_telemetry Unity::Unity)
target_compile_features(test_telemetry PRIVATE c_std_23)
add_test(NAME test_telemetry COMMAND test_telemetry)
list(APPEND TEST_TARGETS test_telemetry)

4. Add a stub, confirm RED, then implement GREEN

Stub celrs/telemetry.c with return -1;, run tests to see the failure, then implement the real logic and confirm they pass.

S
Description
C23 library and CLI tools for ELRS TX modules via CRSF
Readme MIT 257 KiB
Languages
C 93.3%
CMake 6.7%