19 Commits

Author SHA1 Message Date
portersky 974b33e827 chore: rename targets and add ENABLE_TESTING option
Rename library targets from celrs_* to cel* (celcrsf, celserial,
cellogger, cellog) and add cel:: namespace aliases. Add cel::cel
umbrella target that links all core libraries.

Add ENABLE_TESTING option (default ON) to gate Unity/CMock fetch
and test targets for downstream consumers.
2026-06-15 00:39:25 +02:00
portersky f58eb0d976 fix: send RC channels with correct CRSF type
cel_crsf_build_rc_frame tagged RC channel frames with 0x01,
which is not a valid CRSF frame type. The TX module's CRSF
parser never recognized these as channel updates, so it had
no RC data to forward over RF and the receiver could never
report link quality.

Use CEL_CRSF_TYPE_RC_CHANNELS (0x16), the spec-correct RC
Channels Packed type. Drop the bogus 0x01 enum value.
2026-06-15 00:16:50 +02:00
portersky d67d9b29d2 fix: parse CRSF battery as big-endian per protocol spec
CRSF battery frame is big-endian: voltage(u16 BE 0.1V),
current(u16 BE 0.1A), capacity(u24 BE mAh), remaining(u8 %).

Previous code read little-endian with wrong byte count (7 vs 8)
and wrong scaling (/1000 vs /10), producing 9.98V for a 1S battery.
2026-06-14 23:34:12 +02:00
portersky 97c83aa460 feat: implement cel_crsf_param_set_power
Enumerate parameters until TX Power entry is found, match
requested mW against TEXT_SELECT options, and write the
selected option index.

Added:
- str_contains_ci() for case-insensitive substring matching
- is_power_param() to detect power-related parameters
- match_power_option() to find mW in option strings
- 4 new tests: null port, frame roundtrip, success, not found
2026-06-14 22:40:26 +02:00
portersky 7b3905084e feat: implement cel_crsf_param_ping and cel_crsf_param_read
Ping sends DEVICE_PING frame and waits for DEVICE_INFO response.
Read sends PARAM_READ frame and waits for matching PARAM_ENTRY.
Both use cel_crsf_stream_feed() with a clock-based timeout loop.
2026-06-14 22:08:51 +02:00
portersky 8c4045e2a4 feat: implement cel_crsf_param_write
Fire-and-forget parameter write. Builds CRSF PARAM_WRITE frame
and sends it over the serial port.
2026-06-14 21:55:15 +02:00
portersky 5d18258330 feat: implement cel_crsf_param_parse
Parse PARAM_ENTRY payload into cel_crsf_param struct. Handles
TEXT_SELECT with options string and UINT8/INT8 with min/max/default/
value fields. Respects hidden flag (bit 7 of type byte). Truncates
name and options to buffer limits.
2026-06-14 21:50:12 +02:00
portersky eaaaf710a2 feat: implement port find/probe and add platform description
Implement cel_serial_find_elrs_port() which enumerates serial ports
and matches descriptions against ELRS-related keywords (CP210, CH340,
FTDI, etc.). Implement cel_serial_open_probe() to try multiple baud
rates in order.

Add cel_serial_platform_get_description() for Windows (SetupAPI)
and POSIX (sysfs fallback). Wire setupapi into the Windows build.
Update serial tests with CMock expectations for the new functions.
2026-06-14 21:39:18 +02:00
portersky 34dd25fecb feat: implement telemetry parser
cel_crsf_telemetry_parse() decodes link stats, battery, heartbeat,
and airspeed frames. Updated cel_telem_battery and cel_telem_airspeed
structs to use uint16_t values matching CRSF protocol format.
2026-06-14 21:02:23 +02:00
portersky b97a7c5b3a feat: implement frame builders
cel_crsf_build_rc_frame() packs 16 channels (11-bit) into 22 bytes.
cel_crsf_build_ping_frame() builds device ping (0x28).
cel_crsf_build_param_read_frame() and cel_crsf_build_param_write_frame()
build parameter protocol frames (0x2C/0x2D).
2026-06-14 20:58:16 +02:00
portersky 8b181d0fcd feat: implement channel helpers
cel_crsf_channel_us_to_val() and cel_crsf_channel_val_to_us()
convert between microseconds (988-2012) and 11-bit values (172-1811)
with rounding. cel_crsf_channel_default() fills safe/disarmed values.
2026-06-14 20:54:56 +02:00
portersky a846b063f9 feat: implement frame parse and streaming reader
cel_crsf_frame_parse() parses ELRS USB format frames:
  [addr][length][type][payload...][crc]

cel_crsf_stream_* provides incremental parsing from a byte
stream: skips invalid sync bytes, discards bad CRC frames,
buffers partial frames across feed calls.
2026-06-14 20:51:57 +02:00
portersky dde27ab566 refactor: remove unused legacy frame format code
The old [0xC8][dest][src][type][size][payload][crc] format was never
used with real hardware. Remove cel_crsf_frame_legacy, *_legacy()
functions, and update tests/tools accordingly.
2026-06-14 20:49:45 +02:00
portersky df3d399610 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.
2026-06-14 20:47:56 +02:00
portersky 794ee9989a feat: implement Windows serial platform backend
Add cel_serial_platform_open/close/read/write/flush for
Windows using CreateFileA, DCB for baud/8N1, and
SetCommTimeouts for non-blocking reads.

serial.c now delegates all operations to the platform
backend via a cel_serial_platform_handle, and
test_serial.c mocks that backend with CMock.
2026-06-14 20:37:38 +02:00
portersky a1ea02771c refactor: make cel_serial_read non-blocking
Drop timeout_ms; read now returns immediately with whatever
data is available (0 if none), so callers don't block the rest
of their loop waiting on serial I/O.

telemetry's poll loop now sleeps interval_ms itself between
empty reads via a small sleep_ms helper.
2026-06-14 20:29:47 +02:00
portersky 2761bcb16c refactor: mock serial platform backend in test_serial
test_serial mocked log_write.h, which serial.c never calls.
Split celrs_serial into celrs_serial (platform-agnostic logic)
and celrs_serial_platform (real Win/POSIX backend), matching
the celrs_logger/celrs_log_write split.

test_serial now mocks celrs/platform/serial_internal.h and
links only celrs_serial, so the list-ports tests verify the
max_ports clamping and pass-through logic without hitting the
real registry or /dev.
2026-06-14 20:18:17 +02:00
portersky a0868cd3b7 feat: add serial port listing and CLI flags
Implement cel_serial_list_ports/cel_serial_free_ports with
platform backends: Windows reads HKLM\HARDWARE\DEVICEMAP\
SERIALCOMM (fast, single registry read), POSIX scans /dev for
ttyUSB*/ttyACM*.

telemetry tool gains --list, --port, and --baudrate flags;
baud rate was previously hardcoded to 400000. Rename the
tool_telemetry CMake target to telemetry.

Fix test_free_ports_zero_count, which passed a stack array to
cel_serial_free_ports (which calls free() on it), corrupting
the heap.
2026-06-14 20:13:57 +02:00
portersky cd7d411332 Inital commit
CI / macOS (push) Has been cancelled
CI / Windows / Clang (push) Has been cancelled
2026-06-14 19:50:16 +02:00