From 8c4045e2a4bb8d76ddd7052f4aecf7e4f31dffff Mon Sep 17 00:00:00 2001 From: portersky <24420859+portersky@users.noreply.github.com> Date: Sun, 14 Jun 2026 21:55:15 +0200 Subject: [PATCH] feat: implement cel_crsf_param_write Fire-and-forget parameter write. Builds CRSF PARAM_WRITE frame and sends it over the serial port. --- celrs/crsf_param.c | 15 +++++++------- tests/CMakeLists.txt | 5 +++-- tests/test_crsf_param.c | 46 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/celrs/crsf_param.c b/celrs/crsf_param.c index babaf92..1f06107 100644 --- a/celrs/crsf_param.c +++ b/celrs/crsf_param.c @@ -27,13 +27,14 @@ int cel_crsf_param_read(cel_serial_port* port, uint8_t index, int cel_crsf_param_write(cel_serial_port* port, uint8_t index, uint8_t value) { - /* TODO: send param write frame. - * Use cel_crsf_build_param_write_frame() + cel_serial_write(). - * No response expected for write — fire and forget. */ - (void)port; - (void)index; - (void)value; - return -1; + if (port == NULL) return -1; + + uint8_t frame[16]; + size_t len = cel_crsf_build_param_write_frame(frame, index, value); + if (len == 0) return -1; + + size_t written = cel_serial_write(port, frame, len); + return (written == len) ? 0 : -1; } int cel_crsf_param_set_power(cel_serial_port* port, int mw, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c9d93b5..ee78372 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -55,11 +55,12 @@ target_compile_features(test_crsf_telemetry PRIVATE c_std_23) add_test(NAME test_crsf_telemetry COMMAND test_crsf_telemetry) list(APPEND TEST_TARGETS test_crsf_telemetry) -# CRSF param tests — pure functions (parse), no mock needed +# CRSF param tests — mocks serial for write/ping/read add_executable(test_crsf_param test_crsf_param.c) target_include_directories(test_crsf_param PRIVATE "${CMAKE_SOURCE_DIR}") -target_link_libraries(test_crsf_param PRIVATE celrs_crsf Unity::Unity) +target_link_libraries(test_crsf_param PRIVATE celrs_crsf celrs_serial Unity::Unity CMock::CMock) target_compile_features(test_crsf_param PRIVATE c_std_23) +cmock_generate_mock(test_crsf_param "${CMAKE_SOURCE_DIR}/celrs/platform/serial_internal.h") add_test(NAME test_crsf_param COMMAND test_crsf_param) list(APPEND TEST_TARGETS test_crsf_param) diff --git a/tests/test_crsf_param.c b/tests/test_crsf_param.c index a5c85ae..846ce39 100644 --- a/tests/test_crsf_param.c +++ b/tests/test_crsf_param.c @@ -1,9 +1,16 @@ #include "unity.h" #include "celrs/crsf_param.h" +#include "Mockserial_internal.h" #include -void setUp(void) {} -void tearDown(void) {} +void setUp(void) { + Mockserial_internal_Init(); +} + +void tearDown(void) { + Mockserial_internal_Verify(); + Mockserial_internal_Destroy(); +} /* cel_crsf_param_parse tests */ @@ -161,6 +168,38 @@ void test_param_parse_options_truncation(void) { TEST_ASSERT_EQUAL_UINT8(255, strlen(param.options)); /* truncated to 255 */ } +/* cel_crsf_param_write tests */ + +void test_param_write_null_port(void) { + TEST_ASSERT_EQUAL_INT(-1, cel_crsf_param_write(NULL, 0, 0)); +} + +void test_param_write_success(void) { + cel_serial_platform_open_ExpectAndReturn("COM3", 400000, + (cel_serial_platform_handle)42); + cel_serial_port* port = cel_serial_open("COM3", 400000); + TEST_ASSERT_NOT_NULL(port); + + cel_serial_platform_write_ExpectAnyArgsAndReturn(8); + TEST_ASSERT_EQUAL_INT(0, cel_crsf_param_write(port, 5, 3)); + + cel_serial_platform_close_Expect((cel_serial_platform_handle)42); + cel_serial_close(port); +} + +void test_param_write_partial_write(void) { + cel_serial_platform_open_ExpectAndReturn("COM3", 400000, + (cel_serial_platform_handle)42); + cel_serial_port* port = cel_serial_open("COM3", 400000); + TEST_ASSERT_NOT_NULL(port); + + cel_serial_platform_write_ExpectAnyArgsAndReturn(4); + TEST_ASSERT_EQUAL_INT(-1, cel_crsf_param_write(port, 5, 3)); + + cel_serial_platform_close_Expect((cel_serial_platform_handle)42); + cel_serial_close(port); +} + int main(void) { UNITY_BEGIN(); RUN_TEST(test_param_parse_null_args); @@ -172,5 +211,8 @@ int main(void) { RUN_TEST(test_param_parse_folder); RUN_TEST(test_param_parse_name_truncation); RUN_TEST(test_param_parse_options_truncation); + RUN_TEST(test_param_write_null_port); + RUN_TEST(test_param_write_success); + RUN_TEST(test_param_write_partial_write); return UNITY_END(); }