From a017ee1ef62b17d5d65074b9dc3c9123cc414935 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 13:55:58 +0000 Subject: [PATCH 01/11] Add ESP32-C3 single-core support with automatic core detection - Modified signalDecoder.cpp to check CONFIG_FREERTOS_UNICORE - Single-core ESP32 variants (ESP32-C3, ESP32-S2) run decoder on core 0 with priority 3 - Multi-core ESP32 variants run decoder on core 1 with priority 2 - Added documentation in README.md explaining the automatic detection Co-authored-by: NorthernMan54 <19808920+NorthernMan54@users.noreply.github.com> --- README.md | 13 +++++++++++++ src/signalDecoder.cpp | 9 +++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5233668..77f47a6 100644 --- a/README.md +++ b/README.md @@ -365,6 +365,19 @@ build_flags = For a complete example, see the `esp32_heltec_915` environment in [example/OOK_Receiver/platformio.ini](example/OOK_Receiver/platformio.ini#L163). +## ESP32 Platform Support + +### Single-Core ESP32 Variants (ESP32-C3, ESP32-S2) + +The library automatically detects and supports single-core ESP32 variants such as the ESP32-C3 and ESP32-S2. The decoder task's CPU core assignment and priority are automatically adjusted based on the `CONFIG_FREERTOS_UNICORE` configuration: + +* **Single-core processors** (ESP32-C3, ESP32-S2): Decoder task runs on core 0 with priority 3 +* **Multi-core processors** (ESP32, ESP32-S3): Decoder task runs on core 1 with priority 2 + +This configuration ensures compatibility with single-core ESP32 variants that only have core 0 available, preventing boot crashes that would occur if the task were pinned to the non-existent core 1. + +The `CONFIG_FREERTOS_UNICORE` flag is automatically set by the ESP-IDF/Arduino framework when compiling for single-core ESP32 variants, so no manual configuration is required. + ## Wiring and Building the Example Details are [here](example/OOK_Receiver/README.md) diff --git a/src/signalDecoder.cpp b/src/signalDecoder.cpp index 8545191..94f5a31 100644 --- a/src/signalDecoder.cpp +++ b/src/signalDecoder.cpp @@ -41,8 +41,13 @@ # endif #endif -#define rtl_433_Decoder_Priority 2 -#define rtl_433_Decoder_Core 1 +#ifdef CONFIG_FREERTOS_UNICORE +# define rtl_433_Decoder_Core 0 +# define rtl_433_Decoder_Priority 3 +#else +# define rtl_433_Decoder_Core 1 +# define rtl_433_Decoder_Priority 2 +#endif /*----------------------------- rtl_433_ESP Internals -----------------------------*/ From d24ebf7dd9922e698436fcb75aad7f5e97da4aa1 Mon Sep 17 00:00:00 2001 From: Mathieu Tournier Date: Thu, 19 Feb 2026 14:18:55 +0100 Subject: [PATCH 02/11] Change ReadMe --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77f47a6..a504b1f 100644 --- a/README.md +++ b/README.md @@ -367,9 +367,9 @@ For a complete example, see the `esp32_heltec_915` environment in [example/OOK_R ## ESP32 Platform Support -### Single-Core ESP32 Variants (ESP32-C3, ESP32-S2) +### Single-Core ESP32 Variants (ESP32-C3, ESP32-C5, ESP32-S2) -The library automatically detects and supports single-core ESP32 variants such as the ESP32-C3 and ESP32-S2. The decoder task's CPU core assignment and priority are automatically adjusted based on the `CONFIG_FREERTOS_UNICORE` configuration: +The library automatically detects and supports single-core ESP32 variants such as the ESP32-C3/5 and ESP32-S2. The decoder task's CPU core assignment and priority are automatically adjusted based on the `CONFIG_FREERTOS_UNICORE` configuration: * **Single-core processors** (ESP32-C3, ESP32-S2): Decoder task runs on core 0 with priority 3 * **Multi-core processors** (ESP32, ESP32-S3): Decoder task runs on core 1 with priority 2 From 553484712e964710548b720b1d398321644f5838 Mon Sep 17 00:00:00 2001 From: Mathieu Tournier Date: Thu, 19 Feb 2026 14:19:46 +0100 Subject: [PATCH 03/11] Add C5 to SPI init config --- src/rtl_433_ESP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtl_433_ESP.cpp b/src/rtl_433_ESP.cpp index d779268..ac3895d 100644 --- a/src/rtl_433_ESP.cpp +++ b/src/rtl_433_ESP.cpp @@ -32,7 +32,7 @@ #if defined(RF_MODULE_SCK) && defined(RF_MODULE_MISO) && \ defined(RF_MODULE_MOSI) && defined(RF_MODULE_CS) # include -# if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 +# if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C5 SPIClass newSPI(FSPI); # else SPIClass newSPI(VSPI); From b3ea9585e6deda43823324c1a5ddff747c075ca1 Mon Sep 17 00:00:00 2001 From: Mathieu Tournier Date: Thu, 19 Feb 2026 14:20:14 +0100 Subject: [PATCH 04/11] Add C5 config in ini file --- example/OOK_Receiver/platformio.ini | 48 +++++++++++++++++++++++ example/OOK_Receiver/update_link_flags.py | 11 ++++++ 2 files changed, 59 insertions(+) create mode 100644 example/OOK_Receiver/update_link_flags.py diff --git a/example/OOK_Receiver/platformio.ini b/example/OOK_Receiver/platformio.ini index 847a9f6..5072641 100644 --- a/example/OOK_Receiver/platformio.ini +++ b/example/OOK_Receiver/platformio.ini @@ -28,6 +28,7 @@ framework = arduino monitor_filters = esp32_exception_decoder ;platform = espressif32@3.5.0 platform = espressif32@6.1.0 +extra_scripts = pre:update_link_flags.py lib_ldf_mode = chain+ lib_deps = ${libraries.arduinolog} @@ -75,6 +76,53 @@ build_flags = upload_protocol = esptool monitor_speed = 921600 +[env:esp32c5_cc1101] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip +board = esp32-c5-devkitc-1 +framework = arduino +build_flags = + '-DCONFIG_ESP_CONSOLE_UART=1' ; settings for esp32c3 without uart + '-DARDUINO_USB_MODE=1' + '-DARDUINO_USB_CDC_ON_BOOT=1' + '-DLOG_LEVEL=LOG_LEVEL_TRACE' + '-DONBOARD_LED=27' ; LED_D4 +; *** rtl_433_ESP Options *** +; '-DRF_MODULE_FREQUENCY=915.00' + '-DOOK_MODULATION=true' ; False is FSK, True is OOK + '-DRTL_DEBUG=1' ; rtl_433 verbose mode +; '-DRTL_VERBOSE=58' ; LaCrosse TX141-Bv2, TX141TH-Bv2, TX141-Bv3, TX141W, TX145wsdth sensor +; '-DRAW_SIGNAL_DEBUG=true' ; display raw received messages +; '-DMEMORY_DEBUG=true' ; display memory usage information + '-DDEMOD_DEBUG=true' ; display signal debug info + #'-DMY_DEVICES=true' ; subset of devices +; '-DPUBLISH_UNPARSED=true' ; publish unparsed signal details + '-DMINRSSI=-88' + '-DRSSI_THRESHOLD=1' ; Apply a delta of 12 to average RSSI level +; '-DAVERAGE_RSSI=5000' ; Display RSSI floor ( Average of 5000 samples ) +; '-DSIGNAL_RSSI=true' ; Display during signal receive +; '-DOOK_MODULATION=false' ; False is FSK, True is OOK +; *** RF Module Options *** + '-DRF_CC1101="CC1101"' ; CC1101 Transceiver Module +; '-DRF_MODULE_CS=7' ; pin to be used as chip select + '-DRF_MODULE_GDO0=25' ; CC1101 pin GDO0 + '-DRF_MODULE_GDO2=5' ; CC1101 pin GDO2 + '-DRF_MODULE_CS=10' ; pin to be used as chip select + '-DRF_MODULE_MOSI=02' + '-DRF_MODULE_MISO=7' + '-DRF_MODULE_SCK=6' + '-DRF_MODULE_INIT_STATUS=true' ; Display transceiver config during startup +; *** RadioLib Options *** +; '-DRADIOLIB_DEBUG=true' +; '-DRADIOLIB_VERBOSE=true' +; *** FSK Setting Testing *** +; '-DsetBitrate' +; '-DsetFreqDev' +; '-DsetRxBW' + +upload_protocol = esptool +monitor_speed = 921600 + + [env:esp32_cc1101] board = esp32dev build_flags = diff --git a/example/OOK_Receiver/update_link_flags.py b/example/OOK_Receiver/update_link_flags.py new file mode 100644 index 0000000..104f0c3 --- /dev/null +++ b/example/OOK_Receiver/update_link_flags.py @@ -0,0 +1,11 @@ + +# Custom settings, as referred to as "extra_script" in platformio.ini +# +# See http://docs.platformio.org/en/latest/projectconf.html#extra-script + +from SCons.Script import DefaultEnvironment + +env = DefaultEnvironment() + +# General options that are passed to the C and C++ compilers +env.Append(CCFLAGS=["-Wno-implicit-function-declaration", "-Wno-error=implicit-function-declaration","-Wno-int-conversion"]) From b4522ac8e70ba40be6746417f109c6f822dbb357 Mon Sep 17 00:00:00 2001 From: Mathieu Tournier Date: Thu, 19 Feb 2026 14:20:36 +0100 Subject: [PATCH 05/11] remove duplicate file preventing compilation --- src/rtl_433/decoder_util.c | 278 ------------------------------------- 1 file changed, 278 deletions(-) delete mode 100644 src/rtl_433/decoder_util.c diff --git a/src/rtl_433/decoder_util.c b/src/rtl_433/decoder_util.c deleted file mode 100644 index 6f0be60..0000000 --- a/src/rtl_433/decoder_util.c +++ /dev/null @@ -1,278 +0,0 @@ -/** @file - High-level utility functions for decoders. - - Copyright (C) 2018 Christian Zuckschwerdt - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. -*/ - -#include "decoder_util.h" - -#include -#include - -#include "fatal.h" - -r_device* decoder_create(r_device const* dev_template, unsigned user_data_size) { - r_device* r_dev = calloc(1, sizeof(*r_dev)); - if (!r_dev) { - WARN_MALLOC("decoder_create()"); - return NULL; // NOTE: returns NULL on alloc failure. - } - if (dev_template) - *r_dev = *dev_template; // copy - - if (user_data_size) { - r_dev->decode_ctx = calloc(1, user_data_size); - if (!r_dev->decode_ctx) { - WARN_MALLOC("decoder_create()"); - free(r_dev); - return NULL; // NOTE: returns NULL on alloc failure. - } - } - - return r_dev; -} - -void* decoder_user_data(r_device* decoder) { - return decoder->decode_ctx; -} - -// output functions - -void decoder_output_log(r_device* decoder, int level, data_t* data) { - decoder->log_fn(decoder, level, data); -} - -void decoder_output_data(r_device* decoder, data_t* data) { - decoder->output_fn(decoder, data); -} - -// helper - -static char* bitrow_asprint_code(uint8_t const* bitrow, unsigned bit_len) { - char* row_code; - char row_bytes[BITBUF_ROWS * BITBUF_COLS * 2 + 1]; // TODO: this is a lot of stack - - row_bytes[0] = '\0'; - // print byte-wide - for (unsigned col = 0; col < (unsigned)(bit_len + 7) / 8; ++col) { - sprintf(&row_bytes[2 * col], "%02x", bitrow[col]); - } - // remove last nibble if needed - row_bytes[2 * (bit_len + 3) / 8] = '\0'; - - // print at least one '0' - if (bit_len == 0) { - snprintf(row_bytes, sizeof(row_bytes), "0"); - } - - // a simple bitrow representation - row_code = malloc(8 + bit_len / 4 + 1); // "{nnnn}..\0" - if (!row_code) { - WARN_MALLOC("decoder_output_bitbuffer()"); - return NULL; // NOTE: returns NULL on alloc failure. - } - sprintf(row_code, "{%u}%s", bit_len, row_bytes); - - return row_code; -} - -static char* bitrow_asprint_bits(uint8_t const* bitrow, unsigned bit_len) { - char *row_bits, *p; - - p = row_bits = malloc(bit_len + bit_len / 4 + 1); // "1..\0" (1 space per nibble) - if (!row_bits) { - WARN_MALLOC("bitrow_asprint_bits()"); - return NULL; // NOTE: returns NULL on alloc failure. - } - - // print bit-wide with a space every nibble - for (unsigned i = 0; i < bit_len; ++i) { - if (i > 0 && i % 4 == 0) { - *p++ = ' '; - } - if (bitrow[i / 8] & (0x80 >> (i % 8))) { - *p++ = '1'; - } else { - *p++ = '0'; - } - } - *p++ = '\0'; - - return row_bits; -} - -// variadic output functions - -int decoder_verbose(r_device* decoder) { - return decoder->verbose; -} - -void decoder_log(r_device* decoder, int level, char const* func, char const* msg) { - if (decoder->verbose >= level) { - // note that decoder levels start at LOG_WARNING - level += 4; - - /* clang-format off */ - data_t *data = data_make( - "src", "", DATA_STRING, func, - "lvl", "", DATA_INT, level, - "msg", "", DATA_STRING, msg, - NULL); - /* clang-format on */ - decoder_output_log(decoder, level, data); - } -} - -void decoder_logf(r_device* decoder, int level, char const* func, _Printf_format_string_ const char* format, ...) { - if (decoder->verbose >= level) { - char msg[60]; // fixed length limit - va_list ap; - va_start(ap, format); - vsnprintf(msg, sizeof(msg), format, ap); - va_end(ap); - - decoder_log(decoder, level, func, msg); - } -} - -void decoder_log_bitbuffer(r_device* decoder, int level, char const* func, const bitbuffer_t* bitbuffer, char const* msg) { - if (decoder->verbose >= level) { - // note that decoder levels start at LOG_WARNING - level += 4; - - char* row_codes[BITBUF_ROWS] = {0}; - char* row_bits[BITBUF_ROWS] = {0}; - - unsigned num_rows = bitbuffer->num_rows; - for (unsigned i = 0; i < num_rows; i++) { - row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); - - if (decoder->verbose_bits) { - row_bits[i] = bitrow_asprint_bits(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); - } - } - - /* clang-format off */ - data_t *data = data_make( - "src", "", DATA_STRING, func, - "lvl", "", DATA_INT, level, - "msg", "", DATA_STRING, msg, - "num_rows", "", DATA_INT, num_rows, - "codes", "", DATA_ARRAY, data_array(num_rows, DATA_STRING, row_codes), - NULL); - /* clang-format on */ - - if (decoder->verbose_bits) { - data = data_ary(data, "bits", "", NULL, data_array(num_rows, DATA_STRING, row_bits)); - } - - decoder_output_log(decoder, level, data); - - for (unsigned i = 0; i < num_rows; i++) { - free(row_codes[i]); - free(row_bits[i]); - } - } -} - -void decoder_logf_bitbuffer(r_device* decoder, int level, char const* func, const bitbuffer_t* bitbuffer, _Printf_format_string_ const char* format, ...) { - // TODO: pass to interested outputs - if (decoder->verbose >= level) { - char msg[60]; // fixed length limit - va_list ap; - va_start(ap, format); - vsnprintf(msg, sizeof(msg), format, ap); - va_end(ap); - - decoder_log_bitbuffer(decoder, level, func, bitbuffer, msg); - } -} - -void decoder_log_bitrow(r_device* decoder, int level, char const* func, uint8_t const* bitrow, unsigned bit_len, char const* msg) { - if (decoder->verbose >= level) { - // note that decoder levels start at LOG_WARNING - level += 4; - - char* row_code; - char* row_bits = NULL; - - row_code = bitrow_asprint_code(bitrow, bit_len); - - /* clang-format off */ - data_t *data = data_make( - "src", "", DATA_STRING, func, - "lvl", "", DATA_INT, level, - "msg", "", DATA_STRING, msg, - "codes", "", DATA_STRING, row_code, - NULL); - /* clang-format on */ - - if (decoder->verbose_bits) { - row_bits = bitrow_asprint_bits(bitrow, bit_len); - data = data_str(data, "bits", "", NULL, row_bits); - } - - decoder_output_log(decoder, level, data); - - free(row_code); - free(row_bits); - } -} - -void decoder_logf_bitrow(r_device* decoder, int level, char const* func, uint8_t const* bitrow, unsigned bit_len, _Printf_format_string_ const char* format, ...) { - if (decoder->verbose >= level) { - char msg[60]; // fixed length limit - va_list ap; - va_start(ap, format); - vsnprintf(msg, sizeof(msg), format, ap); - va_end(ap); - - decoder_log_bitrow(decoder, level, func, bitrow, bit_len, msg); - } -} - -/* TODO: maybe use as decoder_log function -void decoder_output_bitbuffer_array(r_device *decoder, bitbuffer_t const *bitbuffer, char const *msg) -{ - data_t *data; - data_t *row_data[BITBUF_ROWS]; - char *row_codes[BITBUF_ROWS]; - char row_bytes[BITBUF_ROWS * BITBUF_COLS * 2 + 1]; // TODO: this is a lot of stack - unsigned i; - - for (i = 0; i < bitbuffer->num_rows; i++) { - row_bytes[0] = '\0'; - // print byte-wide - for (unsigned col = 0; col < (unsigned)(bitbuffer->bits_per_row[i] + 7) / 8; ++col) { - sprintf(&row_bytes[2 * col], "%02x", bitbuffer->bb[i][col]); - } - // remove last nibble if needed - row_bytes[2 * (bitbuffer->bits_per_row[i] + 3) / 8] = '\0'; - - row_data[i] = data_make( - "len", "", DATA_INT, bitbuffer->bits_per_row[i], - "data", "", DATA_STRING, row_bytes, - NULL); - - // a simpler representation for csv output - row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); - } - - data = data_make( - "msg", "", DATA_STRING, msg, - "num_rows", "", DATA_INT, bitbuffer->num_rows, - "rows", "", DATA_ARRAY, data_array(bitbuffer->num_rows, DATA_DATA, row_data), - "codes", "", DATA_ARRAY, data_array(bitbuffer->num_rows, DATA_STRING, row_codes), - NULL); - decoder_output_data(decoder, data); - - for (i = 0; i < bitbuffer->num_rows; i++) { - free(row_codes[i]); - } -} -*/ From 557c6527775efe8606b538b7c06d8a5c41818b7c Mon Sep 17 00:00:00 2001 From: Mathieu Tournier Date: Fri, 20 Feb 2026 09:56:50 +0100 Subject: [PATCH 06/11] Revert "remove duplicate file preventing compilation" This reverts commit b4522ac8e70ba40be6746417f109c6f822dbb357. --- src/rtl_433/decoder_util.c | 278 +++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 src/rtl_433/decoder_util.c diff --git a/src/rtl_433/decoder_util.c b/src/rtl_433/decoder_util.c new file mode 100644 index 0000000..6f0be60 --- /dev/null +++ b/src/rtl_433/decoder_util.c @@ -0,0 +1,278 @@ +/** @file + High-level utility functions for decoders. + + Copyright (C) 2018 Christian Zuckschwerdt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "decoder_util.h" + +#include +#include + +#include "fatal.h" + +r_device* decoder_create(r_device const* dev_template, unsigned user_data_size) { + r_device* r_dev = calloc(1, sizeof(*r_dev)); + if (!r_dev) { + WARN_MALLOC("decoder_create()"); + return NULL; // NOTE: returns NULL on alloc failure. + } + if (dev_template) + *r_dev = *dev_template; // copy + + if (user_data_size) { + r_dev->decode_ctx = calloc(1, user_data_size); + if (!r_dev->decode_ctx) { + WARN_MALLOC("decoder_create()"); + free(r_dev); + return NULL; // NOTE: returns NULL on alloc failure. + } + } + + return r_dev; +} + +void* decoder_user_data(r_device* decoder) { + return decoder->decode_ctx; +} + +// output functions + +void decoder_output_log(r_device* decoder, int level, data_t* data) { + decoder->log_fn(decoder, level, data); +} + +void decoder_output_data(r_device* decoder, data_t* data) { + decoder->output_fn(decoder, data); +} + +// helper + +static char* bitrow_asprint_code(uint8_t const* bitrow, unsigned bit_len) { + char* row_code; + char row_bytes[BITBUF_ROWS * BITBUF_COLS * 2 + 1]; // TODO: this is a lot of stack + + row_bytes[0] = '\0'; + // print byte-wide + for (unsigned col = 0; col < (unsigned)(bit_len + 7) / 8; ++col) { + sprintf(&row_bytes[2 * col], "%02x", bitrow[col]); + } + // remove last nibble if needed + row_bytes[2 * (bit_len + 3) / 8] = '\0'; + + // print at least one '0' + if (bit_len == 0) { + snprintf(row_bytes, sizeof(row_bytes), "0"); + } + + // a simple bitrow representation + row_code = malloc(8 + bit_len / 4 + 1); // "{nnnn}..\0" + if (!row_code) { + WARN_MALLOC("decoder_output_bitbuffer()"); + return NULL; // NOTE: returns NULL on alloc failure. + } + sprintf(row_code, "{%u}%s", bit_len, row_bytes); + + return row_code; +} + +static char* bitrow_asprint_bits(uint8_t const* bitrow, unsigned bit_len) { + char *row_bits, *p; + + p = row_bits = malloc(bit_len + bit_len / 4 + 1); // "1..\0" (1 space per nibble) + if (!row_bits) { + WARN_MALLOC("bitrow_asprint_bits()"); + return NULL; // NOTE: returns NULL on alloc failure. + } + + // print bit-wide with a space every nibble + for (unsigned i = 0; i < bit_len; ++i) { + if (i > 0 && i % 4 == 0) { + *p++ = ' '; + } + if (bitrow[i / 8] & (0x80 >> (i % 8))) { + *p++ = '1'; + } else { + *p++ = '0'; + } + } + *p++ = '\0'; + + return row_bits; +} + +// variadic output functions + +int decoder_verbose(r_device* decoder) { + return decoder->verbose; +} + +void decoder_log(r_device* decoder, int level, char const* func, char const* msg) { + if (decoder->verbose >= level) { + // note that decoder levels start at LOG_WARNING + level += 4; + + /* clang-format off */ + data_t *data = data_make( + "src", "", DATA_STRING, func, + "lvl", "", DATA_INT, level, + "msg", "", DATA_STRING, msg, + NULL); + /* clang-format on */ + decoder_output_log(decoder, level, data); + } +} + +void decoder_logf(r_device* decoder, int level, char const* func, _Printf_format_string_ const char* format, ...) { + if (decoder->verbose >= level) { + char msg[60]; // fixed length limit + va_list ap; + va_start(ap, format); + vsnprintf(msg, sizeof(msg), format, ap); + va_end(ap); + + decoder_log(decoder, level, func, msg); + } +} + +void decoder_log_bitbuffer(r_device* decoder, int level, char const* func, const bitbuffer_t* bitbuffer, char const* msg) { + if (decoder->verbose >= level) { + // note that decoder levels start at LOG_WARNING + level += 4; + + char* row_codes[BITBUF_ROWS] = {0}; + char* row_bits[BITBUF_ROWS] = {0}; + + unsigned num_rows = bitbuffer->num_rows; + for (unsigned i = 0; i < num_rows; i++) { + row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); + + if (decoder->verbose_bits) { + row_bits[i] = bitrow_asprint_bits(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); + } + } + + /* clang-format off */ + data_t *data = data_make( + "src", "", DATA_STRING, func, + "lvl", "", DATA_INT, level, + "msg", "", DATA_STRING, msg, + "num_rows", "", DATA_INT, num_rows, + "codes", "", DATA_ARRAY, data_array(num_rows, DATA_STRING, row_codes), + NULL); + /* clang-format on */ + + if (decoder->verbose_bits) { + data = data_ary(data, "bits", "", NULL, data_array(num_rows, DATA_STRING, row_bits)); + } + + decoder_output_log(decoder, level, data); + + for (unsigned i = 0; i < num_rows; i++) { + free(row_codes[i]); + free(row_bits[i]); + } + } +} + +void decoder_logf_bitbuffer(r_device* decoder, int level, char const* func, const bitbuffer_t* bitbuffer, _Printf_format_string_ const char* format, ...) { + // TODO: pass to interested outputs + if (decoder->verbose >= level) { + char msg[60]; // fixed length limit + va_list ap; + va_start(ap, format); + vsnprintf(msg, sizeof(msg), format, ap); + va_end(ap); + + decoder_log_bitbuffer(decoder, level, func, bitbuffer, msg); + } +} + +void decoder_log_bitrow(r_device* decoder, int level, char const* func, uint8_t const* bitrow, unsigned bit_len, char const* msg) { + if (decoder->verbose >= level) { + // note that decoder levels start at LOG_WARNING + level += 4; + + char* row_code; + char* row_bits = NULL; + + row_code = bitrow_asprint_code(bitrow, bit_len); + + /* clang-format off */ + data_t *data = data_make( + "src", "", DATA_STRING, func, + "lvl", "", DATA_INT, level, + "msg", "", DATA_STRING, msg, + "codes", "", DATA_STRING, row_code, + NULL); + /* clang-format on */ + + if (decoder->verbose_bits) { + row_bits = bitrow_asprint_bits(bitrow, bit_len); + data = data_str(data, "bits", "", NULL, row_bits); + } + + decoder_output_log(decoder, level, data); + + free(row_code); + free(row_bits); + } +} + +void decoder_logf_bitrow(r_device* decoder, int level, char const* func, uint8_t const* bitrow, unsigned bit_len, _Printf_format_string_ const char* format, ...) { + if (decoder->verbose >= level) { + char msg[60]; // fixed length limit + va_list ap; + va_start(ap, format); + vsnprintf(msg, sizeof(msg), format, ap); + va_end(ap); + + decoder_log_bitrow(decoder, level, func, bitrow, bit_len, msg); + } +} + +/* TODO: maybe use as decoder_log function +void decoder_output_bitbuffer_array(r_device *decoder, bitbuffer_t const *bitbuffer, char const *msg) +{ + data_t *data; + data_t *row_data[BITBUF_ROWS]; + char *row_codes[BITBUF_ROWS]; + char row_bytes[BITBUF_ROWS * BITBUF_COLS * 2 + 1]; // TODO: this is a lot of stack + unsigned i; + + for (i = 0; i < bitbuffer->num_rows; i++) { + row_bytes[0] = '\0'; + // print byte-wide + for (unsigned col = 0; col < (unsigned)(bitbuffer->bits_per_row[i] + 7) / 8; ++col) { + sprintf(&row_bytes[2 * col], "%02x", bitbuffer->bb[i][col]); + } + // remove last nibble if needed + row_bytes[2 * (bitbuffer->bits_per_row[i] + 3) / 8] = '\0'; + + row_data[i] = data_make( + "len", "", DATA_INT, bitbuffer->bits_per_row[i], + "data", "", DATA_STRING, row_bytes, + NULL); + + // a simpler representation for csv output + row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); + } + + data = data_make( + "msg", "", DATA_STRING, msg, + "num_rows", "", DATA_INT, bitbuffer->num_rows, + "rows", "", DATA_ARRAY, data_array(bitbuffer->num_rows, DATA_DATA, row_data), + "codes", "", DATA_ARRAY, data_array(bitbuffer->num_rows, DATA_STRING, row_codes), + NULL); + decoder_output_data(decoder, data); + + for (i = 0; i < bitbuffer->num_rows; i++) { + free(row_codes[i]); + } +} +*/ From 2c2160bec53094ab13738bcf0003f84b7f1aba92 Mon Sep 17 00:00:00 2001 From: Mathieu Tournier Date: Fri, 20 Feb 2026 09:50:37 +0100 Subject: [PATCH 07/11] remove decoder_utils copy file that create linking duplicate with decoder_util file --- src/rtl_433/decoder_util copy.c | 292 -------------------------------- 1 file changed, 292 deletions(-) delete mode 100644 src/rtl_433/decoder_util copy.c diff --git a/src/rtl_433/decoder_util copy.c b/src/rtl_433/decoder_util copy.c deleted file mode 100644 index 49a3fab..0000000 --- a/src/rtl_433/decoder_util copy.c +++ /dev/null @@ -1,292 +0,0 @@ -/** @file - High-level utility functions for decoders. - - Copyright (C) 2018 Christian Zuckschwerdt - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. -*/ - -#include "decoder_util.h" -#include -#include -#include "fatal.h" - -// create decoder functions - -r_device *decoder_create(r_device const *dev_template, unsigned user_data_size) -{ - r_device *r_dev = calloc(1, sizeof (*r_dev)); - if (!r_dev) { - WARN_MALLOC("decoder_create()"); - return NULL; // NOTE: returns NULL on alloc failure. - } - if (dev_template) - *r_dev = *dev_template; // copy - - if (user_data_size) { - r_dev->decode_ctx = calloc(1, user_data_size); - if (!r_dev->decode_ctx) { - WARN_MALLOC("decoder_create()"); - free(r_dev); - return NULL; // NOTE: returns NULL on alloc failure. - } - } - - return r_dev; -} - -void *decoder_user_data(r_device *decoder) -{ - return decoder->decode_ctx; -} - -// output functions - -void decoder_output_log(r_device *decoder, int level, data_t *data) -{ - decoder->log_fn(decoder, level, data); -} - -void decoder_output_data(r_device *decoder, data_t *data) -{ - decoder->output_fn(decoder, data); -} - -// helper - -static char *bitrow_asprint_code(uint8_t const *bitrow, unsigned bit_len) -{ - char *row_code; - char row_bytes[BITBUF_ROWS * BITBUF_COLS * 2 + 1]; // TODO: this is a lot of stack - - row_bytes[0] = '\0'; - // print byte-wide - for (unsigned col = 0; col < (unsigned)(bit_len + 7) / 8; ++col) { - sprintf(&row_bytes[2 * col], "%02x", bitrow[col]); - } - // remove last nibble if needed - row_bytes[2 * (bit_len + 3) / 8] = '\0'; - - // print at least one '0' - if (bit_len == 0) { - snprintf(row_bytes, sizeof(row_bytes), "0"); - } - - // a simple bitrow representation - row_code = malloc(8 + bit_len / 4 + 1); // "{nnnn}..\0" - if (!row_code) { - WARN_MALLOC("decoder_output_bitbuffer()"); - return NULL; // NOTE: returns NULL on alloc failure. - } - sprintf(row_code, "{%u}%s", bit_len, row_bytes); - - return row_code; -} - -static char *bitrow_asprint_bits(uint8_t const *bitrow, unsigned bit_len) -{ - char *row_bits, *p; - - p = row_bits = malloc(bit_len + bit_len / 4 + 1); // "1..\0" (1 space per nibble) - if (!row_bits) { - WARN_MALLOC("bitrow_asprint_bits()"); - return NULL; // NOTE: returns NULL on alloc failure. - } - - // print bit-wide with a space every nibble - for (unsigned i = 0; i < bit_len; ++i) { - if (i > 0 && i % 4 == 0) { - *p++ = ' '; - } - if (bitrow[i / 8] & (0x80 >> (i % 8))) { - *p++ = '1'; - } - else { - *p++ = '0'; - } - } - *p++ = '\0'; - - return row_bits; -} - -// variadic output functions - -int decoder_verbose(r_device *decoder) -{ - return decoder->verbose; -} - -void decoder_log(r_device *decoder, int level, char const *func, char const *msg) -{ - if (decoder->verbose >= level) { - // note that decoder levels start at LOG_WARNING - level += 4; - - /* clang-format off */ - data_t *data = data_make( - "src", "", DATA_STRING, func, - "lvl", "", DATA_INT, level, - "msg", "", DATA_STRING, msg, - NULL); - /* clang-format on */ - decoder_output_log(decoder, level, data); - } -} - -void decoder_logf(r_device *decoder, int level, char const *func, _Printf_format_string_ const char *format, ...) -{ - if (decoder->verbose >= level) { - char msg[60]; // fixed length limit - va_list ap; - va_start(ap, format); - vsnprintf(msg, sizeof(msg), format, ap); - va_end(ap); - - decoder_log(decoder, level, func, msg); - } -} - -void decoder_log_bitbuffer(r_device *decoder, int level, char const *func, const bitbuffer_t *bitbuffer, char const *msg) -{ - if (decoder->verbose >= level) { - // note that decoder levels start at LOG_WARNING - level += 4; - - char *row_codes[BITBUF_ROWS] = {0}; - char *row_bits[BITBUF_ROWS] = {0}; - - unsigned num_rows = bitbuffer->num_rows; - for (unsigned i = 0; i < num_rows; i++) { - row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); - - if (decoder->verbose_bits) { - row_bits[i] = bitrow_asprint_bits(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); - } - } - - /* clang-format off */ - data_t *data = data_make( - "src", "", DATA_STRING, func, - "lvl", "", DATA_INT, level, - "msg", "", DATA_STRING, msg, - "num_rows", "", DATA_INT, num_rows, - "codes", "", DATA_ARRAY, data_array(num_rows, DATA_STRING, row_codes), - NULL); - /* clang-format on */ - - if (decoder->verbose_bits) { - data = data_ary(data, "bits", "", NULL, data_array(num_rows, DATA_STRING, row_bits)); - } - - decoder_output_log(decoder, level, data); - - for (unsigned i = 0; i < num_rows; i++) { - free(row_codes[i]); - free(row_bits[i]); - } - } -} - -void decoder_logf_bitbuffer(r_device *decoder, int level, char const *func, const bitbuffer_t *bitbuffer, _Printf_format_string_ const char *format, ...) -{ - // TODO: pass to interested outputs - if (decoder->verbose >= level) { - char msg[60]; // fixed length limit - va_list ap; - va_start(ap, format); - vsnprintf(msg, sizeof(msg), format, ap); - va_end(ap); - - decoder_log_bitbuffer(decoder, level, func, bitbuffer, msg); - } -} - -void decoder_log_bitrow(r_device *decoder, int level, char const *func, uint8_t const *bitrow, unsigned bit_len, char const *msg) -{ - if (decoder->verbose >= level) { - // note that decoder levels start at LOG_WARNING - level += 4; - - char *row_code; - char *row_bits = NULL; - - row_code = bitrow_asprint_code(bitrow, bit_len); - - /* clang-format off */ - data_t *data = data_make( - "src", "", DATA_STRING, func, - "lvl", "", DATA_INT, level, - "msg", "", DATA_STRING, msg, - "codes", "", DATA_STRING, row_code, - NULL); - /* clang-format on */ - - if (decoder->verbose_bits) { - row_bits = bitrow_asprint_bits(bitrow, bit_len); - data = data_str(data, "bits", "", NULL, row_bits); - } - - decoder_output_log(decoder, level, data); - - free(row_code); - free(row_bits); - } -} - -void decoder_logf_bitrow(r_device *decoder, int level, char const *func, uint8_t const *bitrow, unsigned bit_len, _Printf_format_string_ const char *format, ...) -{ - if (decoder->verbose >= level) { - char msg[60]; // fixed length limit - va_list ap; - va_start(ap, format); - vsnprintf(msg, sizeof(msg), format, ap); - va_end(ap); - - decoder_log_bitrow(decoder, level, func, bitrow, bit_len, msg); - } -} - -/* TODO: maybe use as decoder_log function -void decoder_output_bitbuffer_array(r_device *decoder, bitbuffer_t const *bitbuffer, char const *msg) -{ - data_t *data; - data_t *row_data[BITBUF_ROWS]; - char *row_codes[BITBUF_ROWS]; - char row_bytes[BITBUF_ROWS * BITBUF_COLS * 2 + 1]; // TODO: this is a lot of stack - unsigned i; - - for (i = 0; i < bitbuffer->num_rows; i++) { - row_bytes[0] = '\0'; - // print byte-wide - for (unsigned col = 0; col < (unsigned)(bitbuffer->bits_per_row[i] + 7) / 8; ++col) { - sprintf(&row_bytes[2 * col], "%02x", bitbuffer->bb[i][col]); - } - // remove last nibble if needed - row_bytes[2 * (bitbuffer->bits_per_row[i] + 3) / 8] = '\0'; - - row_data[i] = data_make( - "len", "", DATA_INT, bitbuffer->bits_per_row[i], - "data", "", DATA_STRING, row_bytes, - NULL); - - // a simpler representation for csv output - row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); - } - - data = data_make( - "msg", "", DATA_STRING, msg, - "num_rows", "", DATA_INT, bitbuffer->num_rows, - "rows", "", DATA_ARRAY, data_array(bitbuffer->num_rows, DATA_DATA, row_data), - "codes", "", DATA_ARRAY, data_array(bitbuffer->num_rows, DATA_STRING, row_codes), - NULL); - decoder_output_data(decoder, data); - - for (i = 0; i < bitbuffer->num_rows; i++) { - free(row_codes[i]); - } -} -*/ From c20e24189970f2940a378babf667c68a74615e97 Mon Sep 17 00:00:00 2001 From: Northern Man <19808920+NorthernMan54@users.noreply.github.com> Date: Mon, 2 Mar 2026 09:02:50 +0700 Subject: [PATCH 08/11] Update example/OOK_Receiver/platformio.ini Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- example/OOK_Receiver/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/OOK_Receiver/platformio.ini b/example/OOK_Receiver/platformio.ini index 5072641..09ccd8c 100644 --- a/example/OOK_Receiver/platformio.ini +++ b/example/OOK_Receiver/platformio.ini @@ -107,7 +107,7 @@ build_flags = '-DRF_MODULE_GDO0=25' ; CC1101 pin GDO0 '-DRF_MODULE_GDO2=5' ; CC1101 pin GDO2 '-DRF_MODULE_CS=10' ; pin to be used as chip select - '-DRF_MODULE_MOSI=02' + '-DRF_MODULE_MOSI=2' '-DRF_MODULE_MISO=7' '-DRF_MODULE_SCK=6' '-DRF_MODULE_INIT_STATUS=true' ; Display transceiver config during startup From fce824695fa62b30ff569e36e266f83e41f4760f Mon Sep 17 00:00:00 2001 From: Northern Man <19808920+NorthernMan54@users.noreply.github.com> Date: Mon, 2 Mar 2026 09:04:10 +0700 Subject: [PATCH 09/11] Update example/OOK_Receiver/platformio.ini Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- example/OOK_Receiver/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/OOK_Receiver/platformio.ini b/example/OOK_Receiver/platformio.ini index 09ccd8c..965d010 100644 --- a/example/OOK_Receiver/platformio.ini +++ b/example/OOK_Receiver/platformio.ini @@ -97,7 +97,7 @@ build_flags = #'-DMY_DEVICES=true' ; subset of devices ; '-DPUBLISH_UNPARSED=true' ; publish unparsed signal details '-DMINRSSI=-88' - '-DRSSI_THRESHOLD=1' ; Apply a delta of 12 to average RSSI level + '-DRSSI_THRESHOLD=1' ; Apply a delta of 1 to average RSSI level ; '-DAVERAGE_RSSI=5000' ; Display RSSI floor ( Average of 5000 samples ) ; '-DSIGNAL_RSSI=true' ; Display during signal receive ; '-DOOK_MODULATION=false' ; False is FSK, True is OOK From 6648e608ee91edd49910f414cc797f6031483c9c Mon Sep 17 00:00:00 2001 From: Northern Man <19808920+NorthernMan54@users.noreply.github.com> Date: Mon, 2 Mar 2026 09:04:52 +0700 Subject: [PATCH 10/11] Update example/OOK_Receiver/platformio.ini Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- example/OOK_Receiver/platformio.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/example/OOK_Receiver/platformio.ini b/example/OOK_Receiver/platformio.ini index 965d010..6ca0c96 100644 --- a/example/OOK_Receiver/platformio.ini +++ b/example/OOK_Receiver/platformio.ini @@ -77,6 +77,12 @@ upload_protocol = esptool monitor_speed = 921600 [env:esp32c5_cc1101] +; NOTE: This environment uses a custom platform URL to obtain early ESP32-C5 Arduino support in PlatformIO. +; Once the official Espressif32 platform includes stable ESP32-C5 support, replace this line with: +; platform = espressif32 +; and (optionally) pin to a minimum version, e.g.: +; platform = espressif32@^ +; Be sure to test builds for all environments before removing this custom platform. platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip board = esp32-c5-devkitc-1 framework = arduino From 141981900dd7af46238c055559ccbd2f0bdab45d Mon Sep 17 00:00:00 2001 From: Northern Man <19808920+NorthernMan54@users.noreply.github.com> Date: Mon, 2 Mar 2026 09:05:16 +0700 Subject: [PATCH 11/11] Update example/OOK_Receiver/platformio.ini Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- example/OOK_Receiver/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/OOK_Receiver/platformio.ini b/example/OOK_Receiver/platformio.ini index 6ca0c96..798acd8 100644 --- a/example/OOK_Receiver/platformio.ini +++ b/example/OOK_Receiver/platformio.ini @@ -87,7 +87,7 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/ board = esp32-c5-devkitc-1 framework = arduino build_flags = - '-DCONFIG_ESP_CONSOLE_UART=1' ; settings for esp32c3 without uart + '-DCONFIG_ESP_CONSOLE_UART=1' ; settings for single-core ESP32 variants without uart '-DARDUINO_USB_MODE=1' '-DARDUINO_USB_CDC_ON_BOOT=1' '-DLOG_LEVEL=LOG_LEVEL_TRACE'