diff --git a/README.md b/README.md index 52336681..a504b1f2 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-C5, ESP32-S2) + +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 + +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/example/OOK_Receiver/platformio.ini b/example/OOK_Receiver/platformio.ini index 847a9f65..798acd88 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,59 @@ build_flags = 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 +build_flags = + '-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' + '-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 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 +; *** 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=2' + '-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 00000000..104f0c33 --- /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"]) diff --git a/src/rtl_433/decoder_util copy.c b/src/rtl_433/decoder_util copy.c deleted file mode 100644 index 49a3fabf..00000000 --- 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]); - } -} -*/ diff --git a/src/rtl_433_ESP.cpp b/src/rtl_433_ESP.cpp index d7792682..ac3895d8 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); diff --git a/src/signalDecoder.cpp b/src/signalDecoder.cpp index 85451915..94f5a313 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 -----------------------------*/