From a1622e652dff728a90b15c78418bd1d490d30045 Mon Sep 17 00:00:00 2001 From: cjkas Date: Mon, 19 Oct 2026 22:05:12 +0200 Subject: [PATCH 1/5] build: move to pioarduino 55.03.312 (Arduino 3.3.12, ESP-IDF 5.5) IDF 4.4 gets no more security fixes, and the planned RMT radio needs IDF 5's RMT driver. See docs/adr/0003-pioarduino-idf55.md. - Every env on one pinned pioarduino release. C6 drops its own library list and flags but stays a debug build on huge_app. - Release envs build at CORE_DEBUG_LEVEL=2 so the ESP32 image fits its 1.5 MB OTA slot (17 KB free); debug envs stay at 3. - Drop the C3: its image is 76.5 KB over the OTA slot on IDF 5.5. - CI installs pioarduino's Core and checks firmware.bin against the app partition, failing under 8 KB free. PlatformIO's "Flash:" figure reads ~45 KB low and passed a C3 image that doesn't fit. - esp_task_wdt_reconfigure(): on 3.x the core already starts the watchdog and esp_task_wdt_init() fails, so the C6 build kept the 5 s default. - An updated firmware is kept only once it has run 60 s with the network up; a reset before then rolls back to the previous one. - ETH.begin() takes the 3.x argument order; Arduino 2.x branches gone. Co-Authored-By: Claude Opus 5.5 --- .github/size_check.py | 52 +++++++++++++++++++++++++++++++ .github/workflows/build.yaml | 20 ++++++------ AGENTS.md | 4 +++ README.md | 3 ++ docs/SECURITY_PLAN.md | 1 + docs/adr/0003-pioarduino-idf55.md | 18 +++++++++++ platformio.ini | 40 ++++++++++-------------- src/ESPNetwork.cpp | 2 +- src/LogLock.cpp | 12 ++----- src/SomfyController.ino | 34 ++++++++++++-------- src/Utils.cpp | 3 ++ src/Utils.h | 4 +++ test/test_utils/test_utils.cpp | 18 +++++++++++ 13 files changed, 152 insertions(+), 59 deletions(-) create mode 100644 .github/size_check.py create mode 100644 docs/adr/0003-pioarduino-idf55.md diff --git a/.github/size_check.py b/.github/size_check.py new file mode 100644 index 0000000..a10d402 --- /dev/null +++ b/.github/size_check.py @@ -0,0 +1,52 @@ +"""Fail the build when the firmware leaves too little room in its app slot. + +PlatformIO only fails once the firmware no longer fits. Releases are built at +CORE_DEBUG_LEVEL=2 because the ESP32 image barely fits its 1.5 MB OTA slot, so +this warns while there is still room to act. + +Usage: python .github/size_check.py [min free KB] +Writes a line to $GITHUB_STEP_SUMMARY when it is set. +""" +import os +import struct +import sys + +ENTRY = struct.Struct(" 3 else 8 * 1024 + used = os.path.getsize(os.path.join(build_dir, "firmware.bin")) + slot = app_slot_size(os.path.join(build_dir, "partitions.bin")) + free = slot - used + ok = free >= min_free + line = (f"| {name} | {used:,} | {slot:,} | {free / 1024:.1f} KB | " + f"{'OK' if ok else f'FAIL: under {min_free // 1024} KB free'} |") + print(line) + summary = os.environ.get("GITHUB_STEP_SUMMARY") + if summary: + with open(summary, "a", encoding="utf-8") as f: + f.write("| Env | Firmware | App slot | Free | |\n|---|---|---|---|---|\n") + f.write(line + "\n") + return 0 if ok else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index bbc23e1..b94857f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -21,8 +21,9 @@ jobs: with: python-version: "3.12" + # pioarduino's fork of PlatformIO Core, which the pioarduino platform needs. - name: Install PlatformIO - run: pip install platformio + run: pip install pioarduino - name: Run native unit tests run: pio test -e native @@ -40,7 +41,9 @@ jobs: # fwname: firmware-only binary for OTA updates # obname: onboard image (bootloader + partitions + firmware + littlefs merged) # for flashing a new chip via USB/serial - # addr_bootloader: chip-dependent (ESP32: 0x1000, C3/S3/C6: 0x0) + # addr_bootloader: chip-dependent (ESP32: 0x1000, S3/C6: 0x0) + # No C3: on ESP-IDF 5.5 its image no longer fits the 1.5 MB OTA slot + # (docs/adr/0003-pioarduino-idf55.md). C3 boards stay on 3.0.x. # addr_fs: must match spiffs/littlefs offset in esp32_3MB.csv include: - env: esp32dev @@ -51,14 +54,6 @@ jobs: fwname: SomfyController.ino.esp32.bin fsname: SomfyController.littlefs.esp32.bin obname: SomfyController.onboard.esp32.bin - - env: esp32c3 - name: ESP32-C3 - chip: ESP32-C3 - addr_bootloader: "0x0" - addr_fs: "0x310000" - fwname: SomfyController.ino.esp32c3.bin - fsname: SomfyController.littlefs.esp32c3.bin - obname: SomfyController.onboard.esp32c3.bin - env: esp32s3 name: ESP32-S3 chip: ESP32-S3 @@ -112,7 +107,7 @@ jobs: python-version: "3.12" - name: Install PlatformIO and esptool - run: pip install platformio esptool + run: pip install pioarduino esptool - name: Build LittleFS image run: pio run -e ${{ matrix.env }} -t buildfs @@ -123,6 +118,9 @@ jobs: - name: Build firmware run: pio run -e ${{ matrix.env }} + - name: Check firmware size + run: python .github/size_check.py .pio/build/${{ matrix.env }} ${{ matrix.env }} 8 + - name: Restore LittleFS image run: cp littlefs.bin .pio/build/${{ matrix.env }}/littlefs.bin diff --git a/AGENTS.md b/AGENTS.md index b902d5b..c4089ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,3 +2,7 @@ - Fix any test or type errors until the whole suite is green. - Add or update tests for the code you change, even if nobody asked. - to test run `pio test -e native` + +## Building +- Firmware builds need pioarduino's Core (`pip install pioarduino`, or the pioarduino IDE extension). Stock PlatformIO Core refuses the pinned platform, see [ADR 0003](docs/adr/0003-pioarduino-idf55.md). +- The platform installs its Python packages into `~/.platformio/penv` and fails on Windows while `pio.exe` from that env is running. Run builds as `python -m platformio` from that env's Python. diff --git a/README.md b/README.md index 19c5a85..47f6043 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ * Backup does no longer use LITTLEFS. Only RAM is used. Storage should not wear out so quick. * Added uptime info in web UI +## Building +The firmware builds on [pioarduino](https://github.com/pioarduino/platform-espressif32) (Arduino 3.x on ESP-IDF 5.5), not the stock PlatformIO platform. In VS Code use the **pioarduino IDE** extension instead of PlatformIO IDE. On the command line, `pip install pioarduino` gives you `pio`. Run the unit tests with `pio test -e native`. [ADR 0003](docs/adr/0003-pioarduino-idf55.md) explains why. + ## There is a partition layout modification it's just better to perform full ESP32 wipeout. Perform backup then wipeout the firmware and restore from the bkp. * fwname: firmware-only binary for OTA updates * obname: onboard image (bootloader + partitions + firmware + littlefs merged) for flashing a new chip via USB/serial diff --git a/docs/SECURITY_PLAN.md b/docs/SECURITY_PLAN.md index 970c729..cd5576b 100644 --- a/docs/SECURITY_PLAN.md +++ b/docs/SECURITY_PLAN.md @@ -107,5 +107,6 @@ Everything else is checked with the `esp32devdbg` build, plus curl and websocket ## Not in this plan - TLS. +- Checking GitHub's certificate in `GitOTA`. It calls `setInsecure()`, so anyone who can intercept the update download can serve their own firmware. ESP-IDF 5.5 ([ADR 0003](adr/0003-pioarduino-idf55.md)) ships a certificate bundle, so this is possible now. It needs its own change: the full bundle costs more flash than the ESP32 build has spare, and pinning GitHub's root certificates might fit. - Session tokens with expiry. - Contents of the binary backup file (it holds no passwords, but it does hold rolling codes; `/backup` becomes a config route). diff --git a/docs/adr/0003-pioarduino-idf55.md b/docs/adr/0003-pioarduino-idf55.md new file mode 100644 index 0000000..3a6baf0 --- /dev/null +++ b/docs/adr/0003-pioarduino-idf55.md @@ -0,0 +1,18 @@ +# Firmware builds on pioarduino (Arduino 3.x, ESP-IDF 5.5), pinned to one release + +We moved every firmware env from `espressif32 @ 6.13.0` (Arduino 2.0.17 on ESP-IDF 4.4.7) to pioarduino's `55.03.312` (Arduino 3.3.12 on ESP-IDF 5.5). IDF 4.4 no longer gets security fixes for Wi-Fi, lwIP and mbedTLS, and the planned RMT radio needs IDF 5's RMT driver. The official PlatformIO platform never shipped Arduino 3.x, so pioarduino, a community fork, is the only way to get it in PlatformIO. We pin one release URL rather than `stable`, so a framework upgrade is always its own PR with its own size check and hardware test. + +## Considered Options + +- **Stay on IDF 4.4.** Rejected: no more security fixes, and no new RMT driver. +- **Rebuild the IDF libraries with `custom_sdkconfig`** to leave out PPP, NAT and provisioning (about 20 KB the firmware never uses). Deferred: it makes builds much slower, and log level 2 already makes the ESP32 build fit. +- **Grow the app slots in the partition table.** Rejected: an OTA update can't change the partition table, so every existing device would need a USB flash. + +## Consequences + +- **Firmware size.** The ESP32 image grows from 1,382,640 bytes (v3.0.14) to 1,555,472 at `CORE_DEBUG_LEVEL=2`, leaving 17 KB of the 1.5 MB OTA slot. At level 3 it doesn't fit, so release envs build at level 2 (warnings and errors) and debug envs stay at 3. PlatformIO's "Flash:" figure counts ELF sections, not the image, and reads about 45 KB low, so CI checks `firmware.bin` against the app partition and fails under 8 KB free (`.github/size_check.py`). +- **No more C3 builds.** Its image grows by 214 KB to 1,651,216 bytes, 76.5 KB over the OTA slot even at level 2. C3 boards stay on the 3.0.x releases. +- **Ethernet PHY ids are ours.** Arduino 3.x renumbered `eth_phy_type_t` (`ETH_PHY_GENERIC` is 0). NVS, backups and the web UI keep the Arduino 2.x numbers as `eth_phy_id_t` (`src/EthPhy.h`), translated by name when Ethernet starts. Never cast a stored id to the framework enum. +- **Ethernet only on the original ESP32.** Arduino 3.x has the RMII MAC API only where `CONFIG_ETH_USE_ESP32_EMAC` is set. S3 and C6 build without Ethernet. +- **Updates roll back until proven.** We override the core's `verifyRollbackLater()` hook to return true, and `loop()` marks the new firmware valid once it has run 60 s and the network is up. A reset before then boots the previous firmware. The LittleFS image an update wrote stays, so the old firmware runs with the new web UI. +- **Tooling.** pioarduino needs its own Core fork (`pip install pioarduino`, the pioarduino IDE extension in VS Code), which it installs into `~/.platformio/penv` in place of PlatformIO Core. diff --git a/platformio.ini b/platformio.ini index 12645b4..6ddfc27 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,7 +15,9 @@ src_dir = src ; Shared by every firmware env (they extend it). Kept out of [env] so the ; native test env doesn't inherit the Arduino framework and ESP32 libraries. [esp32] -platform = espressif32 @ 6.13.0 +; pioarduino: Arduino 3.3.12 on ESP-IDF 5.5. Pinned to a release so an +; upgrade is its own PR (docs/adr/0003-pioarduino-idf55.md). +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.312/platform-espressif32.zip framework = arduino ; Unit tests only run on the PC: pio test -e native test_ignore = * @@ -30,8 +32,9 @@ extra_scripts = pre:minify.py post:archive_elf.py board_build.filesystem = littlefs -build_flags = - -DCORE_DEBUG_LEVEL=3 +; Each env adds a CORE_DEBUG_LEVEL: 2 (warnings) for release builds, which +; only fit the 1.5 MB OTA slot without the info logs, 3 for debug builds. +build_flags = -DCONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=1 -DCONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=1 -DCONFIG_ESP_COREDUMP_CHECKSUM_CRC32=1 @@ -57,7 +60,9 @@ build_flags = extends = esp32 board = esp32dev board_build.partitions = esp32_3MB.csv -build_flags = ${dualcore.build_flags} +build_flags = + ${dualcore.build_flags} + -DCORE_DEBUG_LEVEL=2 [env:esp32devdbg] extends = esp32 @@ -73,39 +78,26 @@ board_build.partitions = esp32_huge_app.csv ; KBs of flash per file, so treat every file as large. build_flags = ${dualcore.build_flags} + -DCORE_DEBUG_LEVEL=3 --param=large-unit-insns=1000 -[env:esp32c3] -extends = esp32 -board = esp32-c3-devkitm-1 -board_build.partitions = esp32_3MB.csv - [env:esp32s3] extends = esp32 board = esp32-s3-devkitc-1 -build_flags = ${dualcore.build_flags} +build_flags = + ${dualcore.build_flags} + -DCORE_DEBUG_LEVEL=2 +; Released as a debug build with one 3 MB app slot, so C6 boards update over +; USB, not OTA. [env:esp32c6] extends = esp32 -platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip board = seeed_xiao_esp32c6 build_type = debug board_build.partitions = esp32_huge_app.csv build_flags = ${esp32.build_flags} - -DCONFIG_FREERTOS_HZ=1000 - -include "driver/gpio.h" -lib_deps = - ; Low-Level libs, frameowrks and drivers - ESP32Async/AsyncTCP - https://github.com/Viproz/SmartRC-CC1101-Driver-Lib.git - ; Commmunication Protocol - links2004/WebSockets - https://github.com/hmueller01/pubsubclient3.git - ; Data-Parsing - bblanchon/ArduinoJson - ; High-level wrappers/servers - ESP32Async/ESPAsyncWebServer + -DCORE_DEBUG_LEVEL=3 ; Host-side unit tests: pio test -e native (needs gcc/g++ on PATH). ; Only the sources the tests cover are built; test/stubs stands in for Arduino.h. diff --git a/src/ESPNetwork.cpp b/src/ESPNetwork.cpp index 5125a9c..6a51e58 100644 --- a/src/ESPNetwork.cpp +++ b/src/ESPNetwork.cpp @@ -396,7 +396,7 @@ bool ESPNetwork::connectWired() { if(!ethPhyType(settings.Ethernet.phyType, phyType)) ESP_LOGE(TAG, "Ethernet PHY type %u is not supported", (unsigned int)settings.Ethernet.phyType); else - begun = ETH.begin(settings.Ethernet.phyAddress, settings.Ethernet.PWRPin, settings.Ethernet.MDCPin, settings.Ethernet.MDIOPin, phyType, settings.Ethernet.CLKMode); + begun = ETH.begin(phyType, settings.Ethernet.phyAddress, settings.Ethernet.MDCPin, settings.Ethernet.MDIOPin, settings.Ethernet.PWRPin, settings.Ethernet.CLKMode); if(!begun) { ESP_LOGE(TAG, "Ethernet Begin failed"); this->ethStarted = false; diff --git a/src/LogLock.cpp b/src/LogLock.cpp index 8c68d63..0d131f6 100644 --- a/src/LogLock.cpp +++ b/src/LogLock.cpp @@ -18,7 +18,6 @@ // progress (see LogLockPolicy.h). #include #include -#include "esp_idf_version.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/task.h" @@ -41,19 +40,12 @@ static volatile TaskHandle_t logOwner = nullptr; // line takes about 20ms at 115200 baud. #define LOG_LOCK_WAIT_MS 20 -#if ESP_IDF_VERSION_MAJOR >= 5 -#define taskOnCore(core) xTaskGetCurrentTaskHandleForCore(core) -#define taskCore(task) xTaskGetCoreID(task) -#else -#define taskOnCore(core) xTaskGetCurrentTaskHandleForCPU(core) -#define taskCore(task) xTaskGetAffinity(task) -#endif static LogHolder logHolder(TaskHandle_t owner) { if(!owner) return LogHolder::unknown; for(BaseType_t core = 0; core < portNUM_PROCESSORS; core++) - if(taskOnCore(core) == owner) return LogHolder::running; + if(xTaskGetCurrentTaskHandleForCore(core) == owner) return LogHolder::running; // A task pinned elsewhere only runs once whatever preempted it there is done. - const BaseType_t core = taskCore(owner); + const BaseType_t core = xTaskGetCoreID(owner); if(core == tskNO_AFFINITY || core == xPortGetCoreID()) return LogHolder::preemptedHere; return LogHolder::preemptedElsewhere; } diff --git a/src/SomfyController.ino b/src/SomfyController.ino index fb1dbc2..0d7d973 100644 --- a/src/SomfyController.ino +++ b/src/SomfyController.ino @@ -16,18 +16,20 @@ #include "GitOTA.h" #include "esp_core_dump.h" #include "esp_system.h" -#include "esp_idf_version.h" -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) #include "esp_app_desc.h" -#define getRunningElfSha esp_app_get_elf_sha256 -#else #include "esp_ota_ops.h" -#define getRunningElfSha esp_ota_get_app_elf_sha256 -#endif #include "Timing.h" static const char *TAG = "Main"; #define LOOP_SLOW_MS 100 +// How long an updated firmware has to run, and then have the network up, before +// it is kept. A reset before then rolls back to the previous firmware. +#define OTA_PROVEN_MS 60000 + +// Overrides the core's weak hook so it leaves an updated firmware unverified +// at boot. loop() confirms it once otaProven(). +extern "C" bool verifyRollbackLater() { return true; } +static bool otaPending = false; ConfigSettings settings; Web webServer; @@ -101,7 +103,7 @@ void setup() { static_assert(sizeof(crashedSha) <= sizeof(summary.app_elf_sha256), "copy would read past app_elf_sha256"); SETCHARPROP(crashedSha, (const char *)summary.app_elf_sha256, sizeof(crashedSha)); char runningSha[APP_ELF_SHA256_SZ] = {0}; - getRunningElfSha(runningSha, sizeof(runningSha)); + esp_app_get_elf_sha256(runningSha, sizeof(runningSha)); if(strcmp(crashedSha, runningSha) == 0) CRASH_LOG(" Build: %s (running %s, same build)", crashedSha, runningSha); else @@ -129,14 +131,15 @@ void setup() { net.setup(); somfy.begin(); //git.checkForUpdate(); -#if ESP_ARDUINO_VERSION_MAJOR >= 3 + // The core starts the watchdog with a 5s timeout before setup(), so + // esp_task_wdt_init() would fail and keep that. const esp_task_wdt_config_t wdt_config = { .timeout_ms = 15000, .idle_core_mask = 1, .trigger_panic = true }; - esp_task_wdt_init(&wdt_config); -#else - esp_task_wdt_init(15, true); //enable panic so ESP32 restarts -#endif + esp_task_wdt_reconfigure(&wdt_config); esp_task_wdt_add(NULL); //add current thread to WDT watch - + esp_ota_img_states_t otaState; + otaPending = esp_ota_get_state_partition(esp_ota_get_running_partition(), &otaState) == ESP_OK && + otaState == ESP_OTA_IMG_PENDING_VERIFY; + if(otaPending) ESP_LOGW(TAG, "Updated firmware, keeping it once it has run %ds with the network up", OTA_PROVEN_MS / 1000); } void loop() { @@ -183,6 +186,11 @@ void loop() { net.end(); ESP.restart(); } + if(otaPending && otaProven(net.connected(), millis(), OTA_PROVEN_MS)) { + otaPending = false; + if(esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) ESP_LOGI(TAG, "Updated firmware confirmed, rollback cancelled"); + else ESP_LOGE(TAG, "Unable to confirm the updated firmware"); + } esp_task_wdt_reset(); loopStats.record(pass.us()); } diff --git a/src/Utils.cpp b/src/Utils.cpp index f329951..75c77f0 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -147,6 +147,9 @@ void RssiBroadcast::sent(bool broadcast, int rssi, int channel, uint32_t now) { bool worthRoaming(bool connected, int currentRssi, int apRssi, int minGain) { return !connected || apRssi >= currentRssi + minGain; } +bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs) { + return networkUp && uptimeMs >= minUptimeMs; +} const char *wifiAuthModeName(uint8_t authMode) { switch(authMode) { case 0: return "OPEN"; diff --git a/src/Utils.h b/src/Utils.h index e182535..27c9ba9 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -82,6 +82,10 @@ enum class heap_emit_t : uint8_t { none, client, broadcast, room }; // num is the socket client asked for, 255 for everyone. A broadcast goes out // every intervalMs; in between only the clients in room 0 get one. heap_emit_t heapEmitTarget(uint8_t num, uint32_t sinceLastMs, uint32_t intervalMs, bool roomHasClients); +// Whether a firmware the bootloader is holding for verification after an +// update has proven itself: it has run for minUptimeMs and the network is +// up. Until then a reset rolls back to the previous firmware. +bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs); // How well loop() keeps up: the passes it made per second and its longest // pass, over the window since the last memStatus broadcast. Only the loop // task calls record(), rate(), maxUs() and publish(). publish() closes the diff --git a/test/test_utils/test_utils.cpp b/test/test_utils/test_utils.cpp index f3c2c2c..b17d0e0 100644 --- a/test/test_utils/test_utils.cpp +++ b/test/test_utils/test_utils.cpp @@ -257,6 +257,21 @@ static void test_worthRoaming_any_ap_while_disconnected() { TEST_ASSERT_TRUE(worthRoaming(false, 0, -90, 6)); } +/********************************************************************* + * otaProven + ********************************************************************/ +static void test_otaProven_after_the_minimum_uptime_with_network() { + TEST_ASSERT_TRUE(otaProven(true, 60000, 60000)); + TEST_ASSERT_TRUE(otaProven(true, 3600000, 60000)); +} +static void test_otaProven_not_before_the_minimum_uptime() { + TEST_ASSERT_FALSE(otaProven(true, 59999, 60000)); +} +static void test_otaProven_not_without_network() { + // A firmware that can't connect would leave the device unreachable. + TEST_ASSERT_FALSE(otaProven(false, 3600000, 60000)); +} + /********************************************************************* * wifiAuthModeName ********************************************************************/ @@ -384,6 +399,9 @@ int main(int argc, char **argv) { RUN_TEST(test_worthRoaming_needs_the_full_gain); RUN_TEST(test_worthRoaming_never_to_a_weaker_ap); RUN_TEST(test_worthRoaming_any_ap_while_disconnected); + RUN_TEST(test_otaProven_after_the_minimum_uptime_with_network); + RUN_TEST(test_otaProven_not_before_the_minimum_uptime); + RUN_TEST(test_otaProven_not_without_network); RUN_TEST(test_wifiAuthModeName_matches_the_idf_enum); RUN_TEST(test_wifiAuthModeName_unknown_past_the_shared_values); RUN_TEST(test_heapEmitTarget_one_client_always_gets_it); From ab7eae3d94ec15037517c597fc65097719224074 Mon Sep 17 00:00:00 2001 From: cjkas Date: Tue, 20 Oct 2026 20:43:00 +0200 Subject: [PATCH 2/5] fix: download the per-chip LittleFS image in online updates Releases publish SomfyController.littlefs..bin, but the updater asked for SomfyController.littlefs.bin. The download 404'd and the device rebooted into the new firmware with the old web UI. Also: hasFS now matches per-chip images, C6 picks its own firmware file, and recoverFilesystem() points at cjkas instead of rstrouse. Co-Authored-By: Claude Opus 5.5 --- data-src/index.js | 2 +- src/GitOTA.cpp | 30 ++++++++++++------------------ src/GitOTA.h | 1 - src/Utils.cpp | 8 ++++++++ src/Utils.h | 6 ++++++ test/test_utils/test_utils.cpp | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 20 deletions(-) diff --git a/data-src/index.js b/data-src/index.js index 6dd60fd..2055e5e 100644 --- a/data-src/index.js +++ b/data-src/index.js @@ -4849,7 +4849,7 @@ class Firmware { let div = this.createFileUploader('/updateApplication'); general.reloadApp = true; let inst = div.querySelector('div[id=divInstText]'); - inst.innerHTML = '
Select a binary file [SomfyController.littlefs.bin] containing the littlefs data for the application then press the Upload File button.
'; + inst.innerHTML = '
Select a binary file [SomfyController.littlefs.<chip>.bin, e.g. SomfyController.littlefs.esp32.bin] containing the littlefs data for the application then press the Upload File button.
'; if (this.isMobile()) { inst.innerHTML += `
WARNING
`; inst.innerHTML += '
This browser does not support automatic backups. It is highly recommended that you back up your configuration using the backup button before proceeding.
'; diff --git a/src/GitOTA.cpp b/src/GitOTA.cpp index 9b13d9c..9391624 100644 --- a/src/GitOTA.cpp +++ b/src/GitOTA.cpp @@ -43,7 +43,7 @@ void GitRelease::setReleaseProperty(const char *key, const char *val) { void GitRelease::setAssetProperty(const char *key, const char *val) { if(strcmp(key, "name") == 0) { //Serial.println(val); - if(strstr(val, "littlefs.bin")) this->hasFS = true; + if(isFsAsset(val)) this->hasFS = true; else if(strstr(val, "ino.esp32.bin")) { if(strlen(this->hwVersions)) strcat(this->hwVersions, ","); strcat(this->hwVersions, "32"); @@ -353,22 +353,16 @@ void GitUpdater::emitDownloadProgress(uint8_t num, size_t total, size_t loaded, sockEmit.loop(); webServer.loop(); } -void GitUpdater::setFirmwareFile() { +// The chip part of this board's release asset names. +static const char *chipName() { esp_chip_info_t ci; esp_chip_info(&ci); switch(ci.model) { - case esp_chip_model_t::CHIP_ESP32S3: - strcpy(this->currentFile, "SomfyController.ino.esp32s3.bin"); - break; - case esp_chip_model_t::CHIP_ESP32S2: - strcpy(this->currentFile, "SomfyController.ino.esp32s2.bin"); - break; - case esp_chip_model_t::CHIP_ESP32C3: - strcpy(this->currentFile, "SomfyController.ino.esp32c3.bin"); - break; - default: - strcpy(this->currentFile, "SomfyController.ino.esp32.bin"); - break; + case esp_chip_model_t::CHIP_ESP32S3: return "esp32s3"; + case esp_chip_model_t::CHIP_ESP32S2: return "esp32s2"; + case esp_chip_model_t::CHIP_ESP32C3: return "esp32c3"; + case esp_chip_model_t::CHIP_ESP32C6: return "esp32c6"; + default: return "esp32"; } } @@ -379,14 +373,14 @@ bool GitUpdater::beginUpdate(const char *version) { strcpy(this->targetRelease, version); this->emitUpdateCheck(); - this->setFirmwareFile(); + releaseAssetName(this->currentFile, sizeof(this->currentFile), "ino", chipName()); this->partition = U_FLASH; this->lockFS = this->cancelled = false; this->error = 0; this->error = this->downloadFile(); if(this->error == 0 && !this->cancelled) { somfy.commit(); - strcpy(this->currentFile, "SomfyController.littlefs.bin"); + releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", chipName()); this->partition = U_SPIFFS; this->lockFS = true; this->error = this->downloadFile(); @@ -405,8 +399,8 @@ bool GitUpdater::beginUpdate(const char *version) { return true; } bool GitUpdater::recoverFilesystem() { - sprintf(this->baseUrl, "https://github.com/rstrouse/ESPSomfy-RTS/releases/download/%s/", settings.fwVersion.name); - strcpy(this->currentFile, "SomfyController.littlefs.bin"); + sprintf(this->baseUrl, "https://github.com/cjkas/ESPSomfy-RTS/releases/download/%s/", settings.fwVersion.name); + releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", chipName()); this->status = GIT_UPDATING; this->partition = U_SPIFFS; this->lockFS = true; diff --git a/src/GitOTA.h b/src/GitOTA.h index 6996f83..7a02112 100644 --- a/src/GitOTA.h +++ b/src/GitOTA.h @@ -55,7 +55,6 @@ class GitUpdater { bool beginUpdate(const char *release); bool endUpdate(); int8_t downloadFile(); - void setFirmwareFile(); void setCurrentRelease(GitRepo &repo); void loop(); diff --git a/src/Utils.cpp b/src/Utils.cpp index 75c77f0..2651f2a 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -150,6 +150,14 @@ bool worthRoaming(bool connected, int currentRssi, int apRssi, int minGain) { bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs) { return networkUp && uptimeMs >= minUptimeMs; } +bool releaseAssetName(char *buf, size_t size, const char *kind, const char *chip) { + int n = snprintf(buf, size, "SomfyController.%s.%s.bin", kind, chip); + return n >= 0 && (size_t)n < size; +} +bool isFsAsset(const char *name) { + size_t len = strlen(name); + return strstr(name, ".littlefs.") && len >= 4 && strcmp(name + len - 4, ".bin") == 0; +} const char *wifiAuthModeName(uint8_t authMode) { switch(authMode) { case 0: return "OPEN"; diff --git a/src/Utils.h b/src/Utils.h index 27c9ba9..723d9d5 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -86,6 +86,12 @@ heap_emit_t heapEmitTarget(uint8_t num, uint32_t sinceLastMs, uint32_t intervalM // update has proven itself: it has run for minUptimeMs and the network is // up. Until then a reset rolls back to the previous firmware. bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs); +// A release asset's name: "SomfyController...bin", kind "ino" for +// the firmware or "littlefs" for the web UI image, chip e.g. "esp32s3". False +// when it doesn't fit in size. +bool releaseAssetName(char *buf, size_t size, const char *kind, const char *chip); +// Whether a release asset is a LittleFS image, for any chip. +bool isFsAsset(const char *name); // How well loop() keeps up: the passes it made per second and its longest // pass, over the window since the last memStatus broadcast. Only the loop // task calls record(), rate(), maxUs() and publish(). publish() closes the diff --git a/test/test_utils/test_utils.cpp b/test/test_utils/test_utils.cpp index b17d0e0..2e5db6e 100644 --- a/test/test_utils/test_utils.cpp +++ b/test/test_utils/test_utils.cpp @@ -272,6 +272,34 @@ static void test_otaProven_not_without_network() { TEST_ASSERT_FALSE(otaProven(false, 3600000, 60000)); } +/********************************************************************* + * releaseAssetName / isFsAsset + ********************************************************************/ +static void test_releaseAssetName_matches_the_release_workflow() { + // .github/workflows/build.yaml fwname and fsname. + char buf[64]; + TEST_ASSERT_TRUE(releaseAssetName(buf, sizeof(buf), "ino", "esp32")); + TEST_ASSERT_EQUAL_STRING("SomfyController.ino.esp32.bin", buf); + TEST_ASSERT_TRUE(releaseAssetName(buf, sizeof(buf), "littlefs", "esp32s3")); + TEST_ASSERT_EQUAL_STRING("SomfyController.littlefs.esp32s3.bin", buf); +} +static void test_releaseAssetName_too_small_buffer() { + char buf[16]; + TEST_ASSERT_FALSE(releaseAssetName(buf, sizeof(buf), "littlefs", "esp32c6")); + TEST_ASSERT_EQUAL(sizeof(buf) - 1, strlen(buf)); +} +static void test_isFsAsset_per_chip_images() { + TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.esp32.bin")); + TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.esp32c6.bin")); + TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.bin")); +} +static void test_isFsAsset_not_the_other_assets() { + TEST_ASSERT_FALSE(isFsAsset("SomfyController.ino.esp32.bin")); + TEST_ASSERT_FALSE(isFsAsset("SomfyController.onboard.esp32.bin.zip")); + TEST_ASSERT_FALSE(isFsAsset("SomfyController.littlefs.bin.sha256")); + TEST_ASSERT_FALSE(isFsAsset("")); +} + /********************************************************************* * wifiAuthModeName ********************************************************************/ @@ -402,6 +430,10 @@ int main(int argc, char **argv) { RUN_TEST(test_otaProven_after_the_minimum_uptime_with_network); RUN_TEST(test_otaProven_not_before_the_minimum_uptime); RUN_TEST(test_otaProven_not_without_network); + RUN_TEST(test_releaseAssetName_matches_the_release_workflow); + RUN_TEST(test_releaseAssetName_too_small_buffer); + RUN_TEST(test_isFsAsset_per_chip_images); + RUN_TEST(test_isFsAsset_not_the_other_assets); RUN_TEST(test_wifiAuthModeName_matches_the_idf_enum); RUN_TEST(test_wifiAuthModeName_unknown_past_the_shared_values); RUN_TEST(test_heapEmitTarget_one_client_always_gets_it); From 8196bd20e6fe355a1b24ed737c55d55e9b3b04ec Mon Sep 17 00:00:00 2001 From: cjkas Date: Tue, 20 Oct 2026 21:34:16 +0200 Subject: [PATCH 3/5] refactor: name release assets from the board's chip model Review follow-up for #72. - releaseAssetName() takes ConfigSettings::chipModel ("", "s3", "c3", "c6"), so GitOTA no longer keeps its own chip switch. C3 keeps its name for when the build comes back. - hasFS is set only when this board's own LittleFS image is in the release. isFsAsset() is gone; it also matched the old unsuffixed littlefs.bin, which the updater no longer asks for. - releaseAssetName() returns void: no caller checked the result and every name fits currentFile. - Both manual-upload hints name this board's file. - KNOWN_ISSUES: the "Main" install can't work, the repo holds no .bin files. Co-Authored-By: Claude Opus 5.5 --- data-src/index.js | 6 ++++-- docs/KNOWN_ISSUES.md | 7 +++++++ src/GitOTA.cpp | 24 ++++++------------------ src/Utils.cpp | 9 ++------- src/Utils.h | 10 ++++------ test/test_utils/test_utils.cpp | 34 ++++++++++++---------------------- 6 files changed, 35 insertions(+), 55 deletions(-) diff --git a/data-src/index.js b/data-src/index.js index 2055e5e..06a09ec 100644 --- a/data-src/index.js +++ b/data-src/index.js @@ -4834,7 +4834,8 @@ class Firmware { updateFirmware() { let div = this.createFileUploader('/updateFirmware'); let inst = div.querySelector('div[id=divInstText]'); - let html = '
Select a binary file [SomfyController.ino.esp32.bin] containing the device firmware then press the Upload File button.
'; + let chip = document.getElementById('divContainer').getAttribute('data-chipmodel') || ''; + let html = `
Select a binary file [SomfyController.ino.esp32${chip}.bin] containing the device firmware then press the Upload File button.
`; if (this.isMobile()) { html += `
WARNING
`; html += '
This browser does not support automatic backups. It is highly recommended that you back up your configuration using the backup button before proceeding.
'; @@ -4849,7 +4850,8 @@ class Firmware { let div = this.createFileUploader('/updateApplication'); general.reloadApp = true; let inst = div.querySelector('div[id=divInstText]'); - inst.innerHTML = '
Select a binary file [SomfyController.littlefs.<chip>.bin, e.g. SomfyController.littlefs.esp32.bin] containing the littlefs data for the application then press the Upload File button.
'; + let chip = document.getElementById('divContainer').getAttribute('data-chipmodel') || ''; + inst.innerHTML = `
Select a binary file [SomfyController.littlefs.esp32${chip}.bin] containing the littlefs data for the application then press the Upload File button.
`; if (this.isMobile()) { inst.innerHTML += `
WARNING
`; inst.innerHTML += '
This browser does not support automatic backups. It is highly recommended that you back up your configuration using the backup button before proceeding.
'; diff --git a/docs/KNOWN_ISSUES.md b/docs/KNOWN_ISSUES.md index 402fe61..ed15935 100644 --- a/docs/KNOWN_ISSUES.md +++ b/docs/KNOWN_ISSUES.md @@ -267,3 +267,10 @@ On 2026-10-19 the log shows `web GET /controller from 192.168.1.197 total took 2 - **Fixed: a command for an unknown shade left no trace.** `handleShadeCommand`, `handleTiltCommand` and `handleGroupCommand` in [src/entryPoints/Web.cpp](../src/entryPoints/Web.cpp) now log a `not found` warning. On 2026-10-18 Home Assistant sent 10 commands to a device that had no shades yet, and the log showed only the response times. - **Fixed: `last ping 0ms ago` meant the client never pinged.** The disconnect line in [src/outputs/SocketEmitter.cpp](../src/outputs/SocketEmitter.cpp) now says `never pinged`. Browsers don't ping, so they always showed it. - **Open: `.gz does not exist` errors are noise.** `serveStatic` tries `.gz` first. For files stored without one (`appversion`, `icon.png`), LittleFS logs an `E`-level `does not exist, no permits for creation` line on every request. The fix would be for `minify.py` to gzip the plain files too. `setTryGzipFirst(false)` doesn't help: the error comes from `exists()` probing the missing variant, so it would only move the noise to the gzip-only files. + +## Installing "Main" from the update dialog always fails + +**Status:** open. Found 2026-10-20 while reviewing PR #72. +**Location:** `GitUpdater::beginUpdate` in [src/GitOTA.cpp](../src/GitOTA.cpp). + +The update dialog offers a "Main" entry next to the releases. For it, the updater downloads from `https://raw.githubusercontent.com/cjkas/ESPSomfy-RTS/master/`, but the repository holds no `.bin` files, so the firmware download 404s. Nothing is written and the device keeps running, so it does no harm, but the option can't work. Either drop the entry or point it at a build that publishes per-chip images. diff --git a/src/GitOTA.cpp b/src/GitOTA.cpp index 9391624..2c09b9f 100644 --- a/src/GitOTA.cpp +++ b/src/GitOTA.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "esp_log.h" #include "ConfigSettings.h" #include "GitOTA.h" @@ -43,7 +42,9 @@ void GitRelease::setReleaseProperty(const char *key, const char *val) { void GitRelease::setAssetProperty(const char *key, const char *val) { if(strcmp(key, "name") == 0) { //Serial.println(val); - if(isFsAsset(val)) this->hasFS = true; + char fsFile[64]; + releaseAssetName(fsFile, sizeof(fsFile), "littlefs", settings.chipModel); + if(strcmp(val, fsFile) == 0) this->hasFS = true; else if(strstr(val, "ino.esp32.bin")) { if(strlen(this->hwVersions)) strcat(this->hwVersions, ","); strcat(this->hwVersions, "32"); @@ -353,19 +354,6 @@ void GitUpdater::emitDownloadProgress(uint8_t num, size_t total, size_t loaded, sockEmit.loop(); webServer.loop(); } -// The chip part of this board's release asset names. -static const char *chipName() { - esp_chip_info_t ci; - esp_chip_info(&ci); - switch(ci.model) { - case esp_chip_model_t::CHIP_ESP32S3: return "esp32s3"; - case esp_chip_model_t::CHIP_ESP32S2: return "esp32s2"; - case esp_chip_model_t::CHIP_ESP32C3: return "esp32c3"; - case esp_chip_model_t::CHIP_ESP32C6: return "esp32c6"; - default: return "esp32"; - } -} - bool GitUpdater::beginUpdate(const char *version) { ESP_LOGI(TAG, "Begin update called..."); if(strcmp(version, "Main") == 0) strcpy(this->baseUrl, "https://raw.githubusercontent.com/cjkas/ESPSomfy-RTS/master/"); @@ -373,14 +361,14 @@ bool GitUpdater::beginUpdate(const char *version) { strcpy(this->targetRelease, version); this->emitUpdateCheck(); - releaseAssetName(this->currentFile, sizeof(this->currentFile), "ino", chipName()); + releaseAssetName(this->currentFile, sizeof(this->currentFile), "ino", settings.chipModel); this->partition = U_FLASH; this->lockFS = this->cancelled = false; this->error = 0; this->error = this->downloadFile(); if(this->error == 0 && !this->cancelled) { somfy.commit(); - releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", chipName()); + releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", settings.chipModel); this->partition = U_SPIFFS; this->lockFS = true; this->error = this->downloadFile(); @@ -400,7 +388,7 @@ bool GitUpdater::beginUpdate(const char *version) { } bool GitUpdater::recoverFilesystem() { sprintf(this->baseUrl, "https://github.com/cjkas/ESPSomfy-RTS/releases/download/%s/", settings.fwVersion.name); - releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", chipName()); + releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", settings.chipModel); this->status = GIT_UPDATING; this->partition = U_SPIFFS; this->lockFS = true; diff --git a/src/Utils.cpp b/src/Utils.cpp index 2651f2a..0fc4a0a 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -150,13 +150,8 @@ bool worthRoaming(bool connected, int currentRssi, int apRssi, int minGain) { bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs) { return networkUp && uptimeMs >= minUptimeMs; } -bool releaseAssetName(char *buf, size_t size, const char *kind, const char *chip) { - int n = snprintf(buf, size, "SomfyController.%s.%s.bin", kind, chip); - return n >= 0 && (size_t)n < size; -} -bool isFsAsset(const char *name) { - size_t len = strlen(name); - return strstr(name, ".littlefs.") && len >= 4 && strcmp(name + len - 4, ".bin") == 0; +void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel) { + snprintf(buf, size, "SomfyController.%s.esp32%s.bin", kind, chipModel); } const char *wifiAuthModeName(uint8_t authMode) { switch(authMode) { diff --git a/src/Utils.h b/src/Utils.h index 723d9d5..7dfbb31 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -86,12 +86,10 @@ heap_emit_t heapEmitTarget(uint8_t num, uint32_t sinceLastMs, uint32_t intervalM // update has proven itself: it has run for minUptimeMs and the network is // up. Until then a reset rolls back to the previous firmware. bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs); -// A release asset's name: "SomfyController...bin", kind "ino" for -// the firmware or "littlefs" for the web UI image, chip e.g. "esp32s3". False -// when it doesn't fit in size. -bool releaseAssetName(char *buf, size_t size, const char *kind, const char *chip); -// Whether a release asset is a LittleFS image, for any chip. -bool isFsAsset(const char *name); +// A release asset's name: "SomfyController..esp32.bin", kind +// "ino" for the firmware or "littlefs" for the web UI image, chipModel as in +// ConfigSettings ("" for the ESP32, "s3", "c3", "c6"). +void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel); // How well loop() keeps up: the passes it made per second and its longest // pass, over the window since the last memStatus broadcast. Only the loop // task calls record(), rate(), maxUs() and publish(). publish() closes the diff --git a/test/test_utils/test_utils.cpp b/test/test_utils/test_utils.cpp index 2e5db6e..e549f73 100644 --- a/test/test_utils/test_utils.cpp +++ b/test/test_utils/test_utils.cpp @@ -273,31 +273,23 @@ static void test_otaProven_not_without_network() { } /********************************************************************* - * releaseAssetName / isFsAsset + * releaseAssetName ********************************************************************/ static void test_releaseAssetName_matches_the_release_workflow() { - // .github/workflows/build.yaml fwname and fsname. + // .github/workflows/build.yaml fwname and fsname, from ConfigSettings::chipModel. char buf[64]; - TEST_ASSERT_TRUE(releaseAssetName(buf, sizeof(buf), "ino", "esp32")); + releaseAssetName(buf, sizeof(buf), "ino", ""); TEST_ASSERT_EQUAL_STRING("SomfyController.ino.esp32.bin", buf); - TEST_ASSERT_TRUE(releaseAssetName(buf, sizeof(buf), "littlefs", "esp32s3")); + releaseAssetName(buf, sizeof(buf), "littlefs", "s3"); TEST_ASSERT_EQUAL_STRING("SomfyController.littlefs.esp32s3.bin", buf); + releaseAssetName(buf, sizeof(buf), "littlefs", "c6"); + TEST_ASSERT_EQUAL_STRING("SomfyController.littlefs.esp32c6.bin", buf); } -static void test_releaseAssetName_too_small_buffer() { - char buf[16]; - TEST_ASSERT_FALSE(releaseAssetName(buf, sizeof(buf), "littlefs", "esp32c6")); - TEST_ASSERT_EQUAL(sizeof(buf) - 1, strlen(buf)); -} -static void test_isFsAsset_per_chip_images() { - TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.esp32.bin")); - TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.esp32c6.bin")); - TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.bin")); -} -static void test_isFsAsset_not_the_other_assets() { - TEST_ASSERT_FALSE(isFsAsset("SomfyController.ino.esp32.bin")); - TEST_ASSERT_FALSE(isFsAsset("SomfyController.onboard.esp32.bin.zip")); - TEST_ASSERT_FALSE(isFsAsset("SomfyController.littlefs.bin.sha256")); - TEST_ASSERT_FALSE(isFsAsset("")); +static void test_releaseAssetName_keeps_c3() { + // C3 is out of the IDF 5.5 builds for now (ADR 0003) but is coming back. + char buf[64]; + releaseAssetName(buf, sizeof(buf), "ino", "c3"); + TEST_ASSERT_EQUAL_STRING("SomfyController.ino.esp32c3.bin", buf); } /********************************************************************* @@ -431,9 +423,7 @@ int main(int argc, char **argv) { RUN_TEST(test_otaProven_not_before_the_minimum_uptime); RUN_TEST(test_otaProven_not_without_network); RUN_TEST(test_releaseAssetName_matches_the_release_workflow); - RUN_TEST(test_releaseAssetName_too_small_buffer); - RUN_TEST(test_isFsAsset_per_chip_images); - RUN_TEST(test_isFsAsset_not_the_other_assets); + RUN_TEST(test_releaseAssetName_keeps_c3); RUN_TEST(test_wifiAuthModeName_matches_the_idf_enum); RUN_TEST(test_wifiAuthModeName_unknown_past_the_shared_values); RUN_TEST(test_heapEmitTarget_one_client_always_gets_it); From 108b2960c71f20978bd7675433e76851de924919 Mon Sep 17 00:00:00 2001 From: cjkas Date: Wed, 21 Oct 2026 12:08:42 +0200 Subject: [PATCH 4/5] build: vendor SmartRC-CC1101-Driver-Lib 2.5.7 unchanged Copied from the registry package lsatan/SmartRC-CC1101-Driver-Lib@2.5.7 (upstream unmaintained since 2021) so it can be fixed for Arduino 3.x in the next commit. This commit is the untouched copy, so that diff shows every change. Licence: LICENSE.txt ("permission to modify and publish"). Co-Authored-By: Claude Opus 5.5 --- .../ELECHOUSE_CC1101_SRC_DRV.cpp | 1307 +++++++++++++++++ .../ELECHOUSE_CC1101_SRC_DRV.h | 194 +++ lib/SmartRC-CC1101-Driver-Lib/LICENSE.txt | 22 + lib/SmartRC-CC1101-Driver-Lib/README.md | 641 ++++++++ lib/SmartRC-CC1101-Driver-Lib/library.json | 19 + platformio.ini | 1 - 6 files changed, 2183 insertions(+), 1 deletion(-) create mode 100644 lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.cpp create mode 100644 lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.h create mode 100644 lib/SmartRC-CC1101-Driver-Lib/LICENSE.txt create mode 100644 lib/SmartRC-CC1101-Driver-Lib/README.md create mode 100644 lib/SmartRC-CC1101-Driver-Lib/library.json diff --git a/lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.cpp b/lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.cpp new file mode 100644 index 0000000..6aa722b --- /dev/null +++ b/lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.cpp @@ -0,0 +1,1307 @@ +/* + ELECHOUSE_CC1101.cpp - CC1101 module library + Copyright (c) 2010 Michael. + Author: Michael, + Version: November 12, 2010 + + This library is designed to use CC1101/CC1100 module on Arduino platform. + CC1101/CC1100 module is an useful wireless module.Using the functions of the + library, you can easily send and receive data by the CC1101/CC1100 module. + Just have fun! + For the details, please refer to the datasheet of CC1100/CC1101. +---------------------------------------------------------------------------------------------------------------- +cc1101 Driver for RC Switch. Mod by Little Satan. With permission to modify and publish Wilson Shen (ELECHOUSE). +---------------------------------------------------------------------------------------------------------------- +*/ +#include +#include "ELECHOUSE_CC1101_SRC_DRV.h" +#include + +/****************************************************************/ +#define WRITE_BURST 0x40 //write burst +#define READ_SINGLE 0x80 //read single +#define READ_BURST 0xC0 //read burst +#define BYTES_IN_RXFIFO 0x7F //byte number in RXfifo +#define max_modul 6 + +byte modulation = 2; +byte frend0; +byte chan = 0; +int pa = 12; +byte last_pa; +byte SCK_PIN; +byte MISO_PIN; +byte MOSI_PIN; +byte SS_PIN; +byte GDO0; +byte GDO2; +byte SCK_PIN_M[max_modul]; +byte MISO_PIN_M[max_modul]; +byte MOSI_PIN_M[max_modul]; +byte SS_PIN_M[max_modul]; +byte GDO0_M[max_modul]; +byte GDO2_M[max_modul]; +byte gdo_set=0; +bool spi = 0; +bool ccmode = 0; +float MHz = 433.92; +byte m4RxBw = 0; +byte m4DaRa; +byte m2DCOFF; +byte m2MODFM; +byte m2MANCH; +byte m2SYNCM; +byte m1FEC; +byte m1PRE; +byte m1CHSP; +byte pc1PQT; +byte pc1CRC_AF; +byte pc1APP_ST; +byte pc1ADRCHK; +byte pc0WDATA; +byte pc0PktForm; +byte pc0CRC_EN; +byte pc0LenConf; +byte trxstate = 0; +byte clb1[2]= {24,28}; +byte clb2[2]= {31,38}; +byte clb3[2]= {65,76}; +byte clb4[2]= {77,79}; + +/****************************************************************/ +uint8_t PA_TABLE[8] {0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00}; +// -30 -20 -15 -10 0 5 7 10 +uint8_t PA_TABLE_315[8] {0x12,0x0D,0x1C,0x34,0x51,0x85,0xCB,0xC2,}; //300 - 348 +uint8_t PA_TABLE_433[8] {0x12,0x0E,0x1D,0x34,0x60,0x84,0xC8,0xC0,}; //387 - 464 +// -30 -20 -15 -10 -6 0 5 7 10 12 +uint8_t PA_TABLE_868[10] {0x03,0x17,0x1D,0x26,0x37,0x50,0x86,0xCD,0xC5,0xC0,}; //779 - 899.99 +// -30 -20 -15 -10 -6 0 5 7 10 11 +uint8_t PA_TABLE_915[10] {0x03,0x0E,0x1E,0x27,0x38,0x8E,0x84,0xCC,0xC3,0xC0,}; //900 - 928 +/**************************************************************** +*FUNCTION NAME:SpiStart +*FUNCTION :spi communication start +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiStart(void) +{ + // initialize the SPI pins + pinMode(SCK_PIN, OUTPUT); + pinMode(MOSI_PIN, OUTPUT); + pinMode(MISO_PIN, INPUT); + pinMode(SS_PIN, OUTPUT); + + // enable SPI + #ifdef ESP32 + SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, SS_PIN); + #else + SPI.begin(); + #endif +} +/**************************************************************** +*FUNCTION NAME:SpiEnd +*FUNCTION :spi communication disable +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiEnd(void) +{ + // disable SPI + SPI.endTransaction(); + SPI.end(); +} +/**************************************************************** +*FUNCTION NAME: GDO_Set() +*FUNCTION : set GDO0,GDO2 pin for serial pinmode. +*INPUT : none +*OUTPUT : none +****************************************************************/ +void ELECHOUSE_CC1101::GDO_Set (void) +{ + pinMode(GDO0, OUTPUT); + pinMode(GDO2, INPUT); +} +/**************************************************************** +*FUNCTION NAME: GDO_Set() +*FUNCTION : set GDO0 for internal transmission mode. +*INPUT : none +*OUTPUT : none +****************************************************************/ +void ELECHOUSE_CC1101::GDO0_Set (void) +{ + pinMode(GDO0, INPUT); +} +/**************************************************************** +*FUNCTION NAME:Reset +*FUNCTION :CC1101 reset //details refer datasheet of CC1101/CC1100// +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Reset (void) +{ + digitalWrite(SS_PIN, LOW); + delay(1); + digitalWrite(SS_PIN, HIGH); + delay(1); + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + SPI.transfer(CC1101_SRES); + while(digitalRead(MISO_PIN)); + digitalWrite(SS_PIN, HIGH); +} +/**************************************************************** +*FUNCTION NAME:Init +*FUNCTION :CC1101 initialization +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Init(void) +{ + setSpi(); + SpiStart(); //spi initialization + digitalWrite(SS_PIN, HIGH); + digitalWrite(SCK_PIN, HIGH); + digitalWrite(MOSI_PIN, LOW); + Reset(); //CC1101 reset + RegConfigSettings(); //CC1101 register config + SpiEnd(); +} +/**************************************************************** +*FUNCTION NAME:SpiWriteReg +*FUNCTION :CC1101 write data to register +*INPUT :addr: register address; value: register value +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiWriteReg(byte addr, byte value) +{ + SpiStart(); + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + SPI.transfer(addr); + SPI.transfer(value); + digitalWrite(SS_PIN, HIGH); + SpiEnd(); +} +/**************************************************************** +*FUNCTION NAME:SpiWriteBurstReg +*FUNCTION :CC1101 write burst data to register +*INPUT :addr: register address; buffer:register value array; num:number to write +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiWriteBurstReg(byte addr, byte *buffer, byte num) +{ + byte i, temp; + SpiStart(); + temp = addr | WRITE_BURST; + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + SPI.transfer(temp); + for (i = 0; i < num; i++) + { + SPI.transfer(buffer[i]); + } + digitalWrite(SS_PIN, HIGH); + SpiEnd(); +} +/**************************************************************** +*FUNCTION NAME:SpiStrobe +*FUNCTION :CC1101 Strobe +*INPUT :strobe: command; //refer define in CC1101.h// +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiStrobe(byte strobe) +{ + SpiStart(); + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + SPI.transfer(strobe); + digitalWrite(SS_PIN, HIGH); + SpiEnd(); +} +/**************************************************************** +*FUNCTION NAME:SpiReadReg +*FUNCTION :CC1101 read data from register +*INPUT :addr: register address +*OUTPUT :register value +****************************************************************/ +byte ELECHOUSE_CC1101::SpiReadReg(byte addr) +{ + byte temp, value; + SpiStart(); + temp = addr| READ_SINGLE; + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + SPI.transfer(temp); + value=SPI.transfer(0); + digitalWrite(SS_PIN, HIGH); + SpiEnd(); + return value; +} + +/**************************************************************** +*FUNCTION NAME:SpiReadBurstReg +*FUNCTION :CC1101 read burst data from register +*INPUT :addr: register address; buffer:array to store register value; num: number to read +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiReadBurstReg(byte addr, byte *buffer, byte num) +{ + byte i,temp; + SpiStart(); + temp = addr | READ_BURST; + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + SPI.transfer(temp); + for(i=0;i4){m=4;} +modulation = m; +Split_MDMCFG2(); +switch (m) +{ +case 0: m2MODFM=0x00; frend0=0x10; break; // 2-FSK +case 1: m2MODFM=0x10; frend0=0x10; break; // GFSK +case 2: m2MODFM=0x30; frend0=0x11; break; // ASK +case 3: m2MODFM=0x40; frend0=0x10; break; // 4-FSK +case 4: m2MODFM=0x70; frend0=0x10; break; // MSK +} +SpiWriteReg(CC1101_MDMCFG2, m2DCOFF+m2MODFM+m2MANCH+m2SYNCM); +SpiWriteReg(CC1101_FREND0, frend0); +setPA(pa); +} +/**************************************************************** +*FUNCTION NAME:PA Power +*FUNCTION :set CC1101 PA Power +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPA(int p) +{ +int a; +pa = p; + +if (MHz >= 300 && MHz <= 348){ +if (pa <= -30){a = PA_TABLE_315[0];} +else if (pa > -30 && pa <= -20){a = PA_TABLE_315[1];} +else if (pa > -20 && pa <= -15){a = PA_TABLE_315[2];} +else if (pa > -15 && pa <= -10){a = PA_TABLE_315[3];} +else if (pa > -10 && pa <= 0){a = PA_TABLE_315[4];} +else if (pa > 0 && pa <= 5){a = PA_TABLE_315[5];} +else if (pa > 5 && pa <= 7){a = PA_TABLE_315[6];} +else if (pa > 7){a = PA_TABLE_315[7];} +last_pa = 1; +} +else if (MHz >= 378 && MHz <= 464){ +if (pa <= -30){a = PA_TABLE_433[0];} +else if (pa > -30 && pa <= -20){a = PA_TABLE_433[1];} +else if (pa > -20 && pa <= -15){a = PA_TABLE_433[2];} +else if (pa > -15 && pa <= -10){a = PA_TABLE_433[3];} +else if (pa > -10 && pa <= 0){a = PA_TABLE_433[4];} +else if (pa > 0 && pa <= 5){a = PA_TABLE_433[5];} +else if (pa > 5 && pa <= 7){a = PA_TABLE_433[6];} +else if (pa > 7){a = PA_TABLE_433[7];} +last_pa = 2; +} +else if (MHz >= 779 && MHz <= 899.99){ +if (pa <= -30){a = PA_TABLE_868[0];} +else if (pa > -30 && pa <= -20){a = PA_TABLE_868[1];} +else if (pa > -20 && pa <= -15){a = PA_TABLE_868[2];} +else if (pa > -15 && pa <= -10){a = PA_TABLE_868[3];} +else if (pa > -10 && pa <= -6){a = PA_TABLE_868[4];} +else if (pa > -6 && pa <= 0){a = PA_TABLE_868[5];} +else if (pa > 0 && pa <= 5){a = PA_TABLE_868[6];} +else if (pa > 5 && pa <= 7){a = PA_TABLE_868[7];} +else if (pa > 7 && pa <= 10){a = PA_TABLE_868[8];} +else if (pa > 10){a = PA_TABLE_868[9];} +last_pa = 3; +} +else if (MHz >= 900 && MHz <= 928){ +if (pa <= -30){a = PA_TABLE_915[0];} +else if (pa > -30 && pa <= -20){a = PA_TABLE_915[1];} +else if (pa > -20 && pa <= -15){a = PA_TABLE_915[2];} +else if (pa > -15 && pa <= -10){a = PA_TABLE_915[3];} +else if (pa > -10 && pa <= -6){a = PA_TABLE_915[4];} +else if (pa > -6 && pa <= 0){a = PA_TABLE_915[5];} +else if (pa > 0 && pa <= 5){a = PA_TABLE_915[6];} +else if (pa > 5 && pa <= 7){a = PA_TABLE_915[7];} +else if (pa > 7 && pa <= 10){a = PA_TABLE_915[8];} +else if (pa > 10){a = PA_TABLE_915[9];} +last_pa = 4; +} +if (modulation == 2){ +PA_TABLE[0] = 0; +PA_TABLE[1] = a; +}else{ +PA_TABLE[0] = a; +PA_TABLE[1] = 0; +} +SpiWriteBurstReg(CC1101_PATABLE,PA_TABLE,8); +} +/**************************************************************** +*FUNCTION NAME:Frequency Calculator +*FUNCTION :Calculate the basic frequency. +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setMHZ(float mhz){ +byte freq2 = 0; +byte freq1 = 0; +byte freq0 = 0; + +MHz = mhz; + +for (bool i = 0; i==0;){ +if (mhz >= 26){ +mhz-=26; +freq2+=1; +} +else if (mhz >= 0.1015625){ +mhz-=0.1015625; +freq1+=1; +} +else if (mhz >= 0.00039675){ +mhz-=0.00039675; +freq0+=1; +} +else{i=1;} +} +if (freq0 > 255){freq1+=1;freq0-=256;} + +SpiWriteReg(CC1101_FREQ2, freq2); +SpiWriteReg(CC1101_FREQ1, freq1); +SpiWriteReg(CC1101_FREQ0, freq0); + +Calibrate(); +} +/**************************************************************** +*FUNCTION NAME:Calibrate +*FUNCTION :Calibrate frequency +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Calibrate(void){ + +if (MHz >= 300 && MHz <= 348){ +SpiWriteReg(CC1101_FSCTRL0, map(MHz, 300, 348, clb1[0], clb1[1])); +if (MHz < 322.88){SpiWriteReg(CC1101_TEST0,0x0B);} +else{ +SpiWriteReg(CC1101_TEST0,0x09); +int s = ELECHOUSE_cc1101.SpiReadStatus(CC1101_FSCAL2); +if (s<32){SpiWriteReg(CC1101_FSCAL2, s+32);} +if (last_pa != 1){setPA(pa);} +} +} +else if (MHz >= 378 && MHz <= 464){ +SpiWriteReg(CC1101_FSCTRL0, map(MHz, 378, 464, clb2[0], clb2[1])); +if (MHz < 430.5){SpiWriteReg(CC1101_TEST0,0x0B);} +else{ +SpiWriteReg(CC1101_TEST0,0x09); +int s = ELECHOUSE_cc1101.SpiReadStatus(CC1101_FSCAL2); +if (s<32){SpiWriteReg(CC1101_FSCAL2, s+32);} +if (last_pa != 2){setPA(pa);} +} +} +else if (MHz >= 779 && MHz <= 899.99){ +SpiWriteReg(CC1101_FSCTRL0, map(MHz, 779, 899, clb3[0], clb3[1])); +if (MHz < 861){SpiWriteReg(CC1101_TEST0,0x0B);} +else{ +SpiWriteReg(CC1101_TEST0,0x09); +int s = ELECHOUSE_cc1101.SpiReadStatus(CC1101_FSCAL2); +if (s<32){SpiWriteReg(CC1101_FSCAL2, s+32);} +if (last_pa != 3){setPA(pa);} +} +} +else if (MHz >= 900 && MHz <= 928){ +SpiWriteReg(CC1101_FSCTRL0, map(MHz, 900, 928, clb4[0], clb4[1])); +SpiWriteReg(CC1101_TEST0,0x09); +int s = ELECHOUSE_cc1101.SpiReadStatus(CC1101_FSCAL2); +if (s<32){SpiWriteReg(CC1101_FSCAL2, s+32);} +if (last_pa != 4){setPA(pa);} +} +} +/**************************************************************** +*FUNCTION NAME:Calibration offset +*FUNCTION :Set calibration offset +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setClb(byte b, byte s, byte e){ +if (b == 1){ +clb1[0]=s; +clb1[1]=e; +} +else if (b == 2){ +clb2[0]=s; +clb2[1]=e; +} +else if (b == 3){ +clb3[0]=s; +clb3[1]=e; +} +else if (b == 4){ +clb4[0]=s; +clb4[1]=e; +} +} +/**************************************************************** +*FUNCTION NAME:getCC1101 +*FUNCTION :Test Spi connection and return 1 when true. +*INPUT :none +*OUTPUT :none +****************************************************************/ +bool ELECHOUSE_CC1101::getCC1101(void){ +setSpi(); +if (SpiReadStatus(0x31)>0){ +return 1; +}else{ +return 0; +} +} +/**************************************************************** +*FUNCTION NAME:getMode +*FUNCTION :Return the Mode. Sidle = 0, TX = 1, Rx = 2. +*INPUT :none +*OUTPUT :none +****************************************************************/ +byte ELECHOUSE_CC1101::getMode(void){ +return trxstate; +} +/**************************************************************** +*FUNCTION NAME:Set Sync_Word +*FUNCTION :Sync Word +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setSyncWord(byte sh, byte sl){ +SpiWriteReg(CC1101_SYNC1, sh); +SpiWriteReg(CC1101_SYNC0, sl); +} +/**************************************************************** +*FUNCTION NAME:Set ADDR +*FUNCTION :Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setAddr(byte v){ +SpiWriteReg(CC1101_ADDR, v); +} +/**************************************************************** +*FUNCTION NAME:Set PQT +*FUNCTION :Preamble quality estimator threshold +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPQT(byte v){ +Split_PKTCTRL1(); +pc1PQT = 0; +if (v>7){v=7;} +pc1PQT = v*32; +SpiWriteReg(CC1101_PKTCTRL1, pc1PQT+pc1CRC_AF+pc1APP_ST+pc1ADRCHK); +} +/**************************************************************** +*FUNCTION NAME:Set CRC_AUTOFLUSH +*FUNCTION :Enable automatic flush of RX FIFO when CRC is not OK +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setCRC_AF(bool v){ +Split_PKTCTRL1(); +pc1CRC_AF = 0; +if (v==1){pc1CRC_AF=8;} +SpiWriteReg(CC1101_PKTCTRL1, pc1PQT+pc1CRC_AF+pc1APP_ST+pc1ADRCHK); +} +/**************************************************************** +*FUNCTION NAME:Set APPEND_STATUS +*FUNCTION :When enabled, two status bytes will be appended to the payload of the packet +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setAppendStatus(bool v){ +Split_PKTCTRL1(); +pc1APP_ST = 0; +if (v==1){pc1APP_ST=4;} +SpiWriteReg(CC1101_PKTCTRL1, pc1PQT+pc1CRC_AF+pc1APP_ST+pc1ADRCHK); +} +/**************************************************************** +*FUNCTION NAME:Set ADR_CHK +*FUNCTION :Controls address check configuration of received packages +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setAdrChk(byte v){ +Split_PKTCTRL1(); +pc1ADRCHK = 0; +if (v>3){v=3;} +pc1ADRCHK = v; +SpiWriteReg(CC1101_PKTCTRL1, pc1PQT+pc1CRC_AF+pc1APP_ST+pc1ADRCHK); +} +/**************************************************************** +*FUNCTION NAME:Set WHITE_DATA +*FUNCTION :Turn data whitening on / off. +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setWhiteData(bool v){ +Split_PKTCTRL0(); +pc0WDATA = 0; +if (v == 1){pc0WDATA=64;} +SpiWriteReg(CC1101_PKTCTRL0, pc0WDATA+pc0PktForm+pc0CRC_EN+pc0LenConf); +} +/**************************************************************** +*FUNCTION NAME:Set PKT_FORMAT +*FUNCTION :Format of RX and TX data +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPktFormat(byte v){ +Split_PKTCTRL0(); +pc0PktForm = 0; +if (v>3){v=3;} +pc0PktForm = v*16; +SpiWriteReg(CC1101_PKTCTRL0, pc0WDATA+pc0PktForm+pc0CRC_EN+pc0LenConf); +} +/**************************************************************** +*FUNCTION NAME:Set CRC +*FUNCTION :CRC calculation in TX and CRC check in RX +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setCrc(bool v){ +Split_PKTCTRL0(); +pc0CRC_EN = 0; +if (v==1){pc0CRC_EN=4;} +SpiWriteReg(CC1101_PKTCTRL0, pc0WDATA+pc0PktForm+pc0CRC_EN+pc0LenConf); +} +/**************************************************************** +*FUNCTION NAME:Set LENGTH_CONFIG +*FUNCTION :Configure the packet length +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setLengthConfig(byte v){ +Split_PKTCTRL0(); +pc0LenConf = 0; +if (v>3){v=3;} +pc0LenConf = v; +SpiWriteReg(CC1101_PKTCTRL0, pc0WDATA+pc0PktForm+pc0CRC_EN+pc0LenConf); +} +/**************************************************************** +*FUNCTION NAME:Set PACKET_LENGTH +*FUNCTION :Indicates the packet length +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPacketLength(byte v){ +SpiWriteReg(CC1101_PKTLEN, v); +} +/**************************************************************** +*FUNCTION NAME:Set DCFILT_OFF +*FUNCTION :Disable digital DC blocking filter before demodulator +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setDcFilterOff(bool v){ +Split_MDMCFG2(); +m2DCOFF = 0; +if (v==1){m2DCOFF=128;} +SpiWriteReg(CC1101_MDMCFG2, m2DCOFF+m2MODFM+m2MANCH+m2SYNCM); +} +/**************************************************************** +*FUNCTION NAME:Set MANCHESTER +*FUNCTION :Enables Manchester encoding/decoding +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setManchester(bool v){ +Split_MDMCFG2(); +m2MANCH = 0; +if (v==1){m2MANCH=8;} +SpiWriteReg(CC1101_MDMCFG2, m2DCOFF+m2MODFM+m2MANCH+m2SYNCM); +} +/**************************************************************** +*FUNCTION NAME:Set SYNC_MODE +*FUNCTION :Combined sync-word qualifier mode +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setSyncMode(byte v){ +Split_MDMCFG2(); +m2SYNCM = 0; +if (v>7){v=7;} +m2SYNCM=v; +SpiWriteReg(CC1101_MDMCFG2, m2DCOFF+m2MODFM+m2MANCH+m2SYNCM); +} +/**************************************************************** +*FUNCTION NAME:Set FEC +*FUNCTION :Enable Forward Error Correction (FEC) +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setFEC(bool v){ +Split_MDMCFG1(); +m1FEC=0; +if (v==1){m1FEC=128;} +SpiWriteReg(CC1101_MDMCFG1, m1FEC+m1PRE+m1CHSP); +} +/**************************************************************** +*FUNCTION NAME:Set PRE +*FUNCTION :Sets the minimum number of preamble bytes to be transmitted. +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPRE(byte v){ +Split_MDMCFG1(); +m1PRE=0; +if (v>7){v=7;} +m1PRE = v*16; +SpiWriteReg(CC1101_MDMCFG1, m1FEC+m1PRE+m1CHSP); +} +/**************************************************************** +*FUNCTION NAME:Set Channel +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setChannel(byte ch){ +chan = ch; +SpiWriteReg(CC1101_CHANNR, chan); +} +/**************************************************************** +*FUNCTION NAME:Set Channel spacing +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setChsp(float f){ +Split_MDMCFG1(); +byte MDMCFG0 = 0; +m1CHSP = 0; +if (f > 405.456543){f = 405.456543;} +if (f < 25.390625){f = 25.390625;} +for (int i = 0; i<5; i++){ +if (f <= 50.682068){ +f -= 25.390625; +f /= 0.0991825; +MDMCFG0 = f; +float s1 = (f - MDMCFG0) *10; +if (s1 >= 5){MDMCFG0++;} +i = 5; +}else{ +m1CHSP++; +f/=2; +} +} +SpiWriteReg(19,m1CHSP+m1FEC+m1PRE); +SpiWriteReg(20,MDMCFG0); +} +/**************************************************************** +*FUNCTION NAME:Set Receive bandwidth +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setRxBW(float f){ +Split_MDMCFG4(); +int s1 = 3; +int s2 = 3; +for (int i = 0; i<3; i++){ +if (f > 101.5625){f/=2; s1--;} +else{i=3;} +} +for (int i = 0; i<3; i++){ +if (f > 58.1){f/=1.25; s2--;} +else{i=3;} +} +s1 *= 64; +s2 *= 16; +m4RxBw = s1 + s2; +SpiWriteReg(16,m4RxBw+m4DaRa); +} +/**************************************************************** +*FUNCTION NAME:Set Data Rate +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setDRate(float d){ +Split_MDMCFG4(); +float c = d; +byte MDMCFG3 = 0; +if (c > 1621.83){c = 1621.83;} +if (c < 0.0247955){c = 0.0247955;} +m4DaRa = 0; +for (int i = 0; i<20; i++){ +if (c <= 0.0494942){ +c = c - 0.0247955; +c = c / 0.00009685; +MDMCFG3 = c; +float s1 = (c - MDMCFG3) *10; +if (s1 >= 5){MDMCFG3++;} +i = 20; +}else{ +m4DaRa++; +c = c/2; +} +} +SpiWriteReg(16, m4RxBw+m4DaRa); +SpiWriteReg(17, MDMCFG3); +} +/**************************************************************** +*FUNCTION NAME:Set Devitation +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setDeviation(float d){ +float f = 1.586914; +float v = 0.19836425; +int c = 0; +if (d > 380.859375){d = 380.859375;} +if (d < 1.586914){d = 1.586914;} +for (int i = 0; i<255; i++){ +f+=v; +if (c==7){v*=2;c=-1;i+=8;} +if (f>=d){c=i;i=255;} +c++; +} +SpiWriteReg(21,c); +} +/**************************************************************** +*FUNCTION NAME:Split PKTCTRL0 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_PKTCTRL1(void){ +int calc = SpiReadStatus(7); +pc1PQT = 0; +pc1CRC_AF = 0; +pc1APP_ST = 0; +pc1ADRCHK = 0; +for (bool i = 0; i==0;){ +if (calc >= 32){calc-=32; pc1PQT+=32;} +else if (calc >= 8){calc-=8; pc1CRC_AF+=8;} +else if (calc >= 4){calc-=4; pc1APP_ST+=4;} +else {pc1ADRCHK = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:Split PKTCTRL0 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_PKTCTRL0(void){ +int calc = SpiReadStatus(8); +pc0WDATA = 0; +pc0PktForm = 0; +pc0CRC_EN = 0; +pc0LenConf = 0; +for (bool i = 0; i==0;){ +if (calc >= 64){calc-=64; pc0WDATA+=64;} +else if (calc >= 16){calc-=16; pc0PktForm+=16;} +else if (calc >= 4){calc-=4; pc0CRC_EN+=4;} +else {pc0LenConf = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:Split MDMCFG1 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_MDMCFG1(void){ +int calc = SpiReadStatus(19); +m1FEC = 0; +m1PRE = 0; +m1CHSP = 0; +int s2 = 0; +for (bool i = 0; i==0;){ +if (calc >= 128){calc-=128; m1FEC+=128;} +else if (calc >= 16){calc-=16; m1PRE+=16;} +else {m1CHSP = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:Split MDMCFG2 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_MDMCFG2(void){ +int calc = SpiReadStatus(18); +m2DCOFF = 0; +m2MODFM = 0; +m2MANCH = 0; +m2SYNCM = 0; +for (bool i = 0; i==0;){ +if (calc >= 128){calc-=128; m2DCOFF+=128;} +else if (calc >= 16){calc-=16; m2MODFM+=16;} +else if (calc >= 8){calc-=8; m2MANCH+=8;} +else{m2SYNCM = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:Split MDMCFG4 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_MDMCFG4(void){ +int calc = SpiReadStatus(16); +m4RxBw = 0; +m4DaRa = 0; +for (bool i = 0; i==0;){ +if (calc >= 64){calc-=64; m4RxBw+=64;} +else if (calc >= 16){calc -= 16; m4RxBw+=16;} +else{m4DaRa = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:RegConfigSettings +*FUNCTION :CC1101 register config //details refer datasheet of CC1101/CC1100// +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::RegConfigSettings(void) +{ + SpiWriteReg(CC1101_FSCTRL1, 0x06); + + setCCMode(ccmode); + setMHZ(MHz); + + SpiWriteReg(CC1101_MDMCFG1, 0x02); + SpiWriteReg(CC1101_MDMCFG0, 0xF8); + SpiWriteReg(CC1101_CHANNR, chan); + SpiWriteReg(CC1101_DEVIATN, 0x47); + SpiWriteReg(CC1101_FREND1, 0x56); + SpiWriteReg(CC1101_MCSM0 , 0x18); + SpiWriteReg(CC1101_FOCCFG, 0x16); + SpiWriteReg(CC1101_BSCFG, 0x1C); + SpiWriteReg(CC1101_AGCCTRL2, 0xC7); + SpiWriteReg(CC1101_AGCCTRL1, 0x00); + SpiWriteReg(CC1101_AGCCTRL0, 0xB2); + SpiWriteReg(CC1101_FSCAL3, 0xE9); + SpiWriteReg(CC1101_FSCAL2, 0x2A); + SpiWriteReg(CC1101_FSCAL1, 0x00); + SpiWriteReg(CC1101_FSCAL0, 0x1F); + SpiWriteReg(CC1101_FSTEST, 0x59); + SpiWriteReg(CC1101_TEST2, 0x81); + SpiWriteReg(CC1101_TEST1, 0x35); + SpiWriteReg(CC1101_TEST0, 0x09); + SpiWriteReg(CC1101_PKTCTRL1, 0x04); + SpiWriteReg(CC1101_ADDR, 0x00); + SpiWriteReg(CC1101_PKTLEN, 0x00); +} +/**************************************************************** +*FUNCTION NAME:SetTx +*FUNCTION :set CC1101 send data +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SetTx(void) +{ + SpiStrobe(CC1101_SIDLE); + SpiStrobe(CC1101_STX); //start send + trxstate=1; +} +/**************************************************************** +*FUNCTION NAME:SetRx +*FUNCTION :set CC1101 to receive state +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SetRx(void) +{ + SpiStrobe(CC1101_SIDLE); + SpiStrobe(CC1101_SRX); //start receive + trxstate=2; +} +/**************************************************************** +*FUNCTION NAME:SetTx +*FUNCTION :set CC1101 send data and change frequency +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SetTx(float mhz) +{ + SpiStrobe(CC1101_SIDLE); + setMHZ(mhz); + SpiStrobe(CC1101_STX); //start send + trxstate=1; +} +/**************************************************************** +*FUNCTION NAME:SetRx +*FUNCTION :set CC1101 to receive state and change frequency +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SetRx(float mhz) +{ + SpiStrobe(CC1101_SIDLE); + setMHZ(mhz); + SpiStrobe(CC1101_SRX); //start receive + trxstate=2; +} +/**************************************************************** +*FUNCTION NAME:RSSI Level +*FUNCTION :Calculating the RSSI Level +*INPUT :none +*OUTPUT :none +****************************************************************/ +int ELECHOUSE_CC1101::getRssi(void) +{ +int rssi; +rssi=SpiReadStatus(CC1101_RSSI); +if (rssi >= 128){rssi = (rssi-256)/2-74;} +else{rssi = (rssi/2)-74;} +return rssi; +} +/**************************************************************** +*FUNCTION NAME:LQI Level +*FUNCTION :get Lqi state +*INPUT :none +*OUTPUT :none +****************************************************************/ +byte ELECHOUSE_CC1101::getLqi(void) +{ +byte lqi; +lqi=SpiReadStatus(CC1101_LQI); +return lqi; +} +/**************************************************************** +*FUNCTION NAME:SetSres +*FUNCTION :Reset CC1101 +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setSres(void) +{ + SpiStrobe(CC1101_SRES); + trxstate=0; +} +/**************************************************************** +*FUNCTION NAME:setSidle +*FUNCTION :set Rx / TX Off +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setSidle(void) +{ + SpiStrobe(CC1101_SIDLE); + trxstate=0; +} +/**************************************************************** +*FUNCTION NAME:goSleep +*FUNCTION :set cc1101 Sleep on +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::goSleep(void){ + trxstate=0; + SpiStrobe(0x36);//Exit RX / TX, turn off frequency synthesizer and exit + SpiStrobe(0x39);//Enter power down mode when CSn goes high. +} +/**************************************************************** +*FUNCTION NAME:Char direct SendData +*FUNCTION :use CC1101 send data +*INPUT :txBuffer: data array to send; size: number of data to send, no more than 61 +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SendData(char *txchar) +{ +int len = strlen(txchar); +byte chartobyte[len]; +for (int i = 0; i sync transmitted + while (digitalRead(GDO0)); // Wait for GDO0 to be cleared -> end of packet + SpiStrobe(CC1101_SFTX); //flush TXfifo + trxstate=1; +} +/**************************************************************** +*FUNCTION NAME:Char direct SendData +*FUNCTION :use CC1101 send data without GDO +*INPUT :txBuffer: data array to send; size: number of data to send, no more than 61 +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SendData(char *txchar,int t) +{ +int len = strlen(txchar); +byte chartobyte[len]; +for (int i = 0; i + Version: November 12, 2010 + + This library is designed to use CC1101/CC1100 module on Arduino platform. + CC1101/CC1100 module is an useful wireless module.Using the functions of the + library, you can easily send and receive data by the CC1101/CC1100 module. + Just have fun! + For the details, please refer to the datasheet of CC1100/CC1101. +---------------------------------------------------------------------------------------------------------------- +cc1101 Driver for RC Switch. Mod by Little Satan. With permission to modify and publish Wilson Shen (ELECHOUSE). +---------------------------------------------------------------------------------------------------------------- +*/ +#ifndef ELECHOUSE_CC1101_SRC_DRV_h +#define ELECHOUSE_CC1101_SRC_DRV_h + +#include + +//***************************************CC1101 define**************************************************// +// CC1101 CONFIG REGSITER +#define CC1101_IOCFG2 0x00 // GDO2 output pin configuration +#define CC1101_IOCFG1 0x01 // GDO1 output pin configuration +#define CC1101_IOCFG0 0x02 // GDO0 output pin configuration +#define CC1101_FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds +#define CC1101_SYNC1 0x04 // Sync word, high INT8U +#define CC1101_SYNC0 0x05 // Sync word, low INT8U +#define CC1101_PKTLEN 0x06 // Packet length +#define CC1101_PKTCTRL1 0x07 // Packet automation control +#define CC1101_PKTCTRL0 0x08 // Packet automation control +#define CC1101_ADDR 0x09 // Device address +#define CC1101_CHANNR 0x0A // Channel number +#define CC1101_FSCTRL1 0x0B // Frequency synthesizer control +#define CC1101_FSCTRL0 0x0C // Frequency synthesizer control +#define CC1101_FREQ2 0x0D // Frequency control word, high INT8U +#define CC1101_FREQ1 0x0E // Frequency control word, middle INT8U +#define CC1101_FREQ0 0x0F // Frequency control word, low INT8U +#define CC1101_MDMCFG4 0x10 // Modem configuration +#define CC1101_MDMCFG3 0x11 // Modem configuration +#define CC1101_MDMCFG2 0x12 // Modem configuration +#define CC1101_MDMCFG1 0x13 // Modem configuration +#define CC1101_MDMCFG0 0x14 // Modem configuration +#define CC1101_DEVIATN 0x15 // Modem deviation setting +#define CC1101_MCSM2 0x16 // Main Radio Control State Machine configuration +#define CC1101_MCSM1 0x17 // Main Radio Control State Machine configuration +#define CC1101_MCSM0 0x18 // Main Radio Control State Machine configuration +#define CC1101_FOCCFG 0x19 // Frequency Offset Compensation configuration +#define CC1101_BSCFG 0x1A // Bit Synchronization configuration +#define CC1101_AGCCTRL2 0x1B // AGC control +#define CC1101_AGCCTRL1 0x1C // AGC control +#define CC1101_AGCCTRL0 0x1D // AGC control +#define CC1101_WOREVT1 0x1E // High INT8U Event 0 timeout +#define CC1101_WOREVT0 0x1F // Low INT8U Event 0 timeout +#define CC1101_WORCTRL 0x20 // Wake On Radio control +#define CC1101_FREND1 0x21 // Front end RX configuration +#define CC1101_FREND0 0x22 // Front end TX configuration +#define CC1101_FSCAL3 0x23 // Frequency synthesizer calibration +#define CC1101_FSCAL2 0x24 // Frequency synthesizer calibration +#define CC1101_FSCAL1 0x25 // Frequency synthesizer calibration +#define CC1101_FSCAL0 0x26 // Frequency synthesizer calibration +#define CC1101_RCCTRL1 0x27 // RC oscillator configuration +#define CC1101_RCCTRL0 0x28 // RC oscillator configuration +#define CC1101_FSTEST 0x29 // Frequency synthesizer calibration control +#define CC1101_PTEST 0x2A // Production test +#define CC1101_AGCTEST 0x2B // AGC test +#define CC1101_TEST2 0x2C // Various test settings +#define CC1101_TEST1 0x2D // Various test settings +#define CC1101_TEST0 0x2E // Various test settings + +//CC1101 Strobe commands +#define CC1101_SRES 0x30 // Reset chip. +#define CC1101_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). + // If in RX/TX: Go to a wait state where only the synthesizer is + // running (for quick RX / TX turnaround). +#define CC1101_SXOFF 0x32 // Turn off crystal oscillator. +#define CC1101_SCAL 0x33 // Calibrate frequency synthesizer and turn it off + // (enables quick start). +#define CC1101_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and + // MCSM0.FS_AUTOCAL=1. +#define CC1101_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if + // MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled: + // Only go to TX if channel is clear. +#define CC1101_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit + // Wake-On-Radio mode if applicable. +#define CC1101_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer +#define CC1101_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio) +#define CC1101_SPWD 0x39 // Enter power down mode when CSn goes high. +#define CC1101_SFRX 0x3A // Flush the RX FIFO buffer. +#define CC1101_SFTX 0x3B // Flush the TX FIFO buffer. +#define CC1101_SWORRST 0x3C // Reset real time clock. +#define CC1101_SNOP 0x3D // No operation. May be used to pad strobe commands to two + // INT8Us for simpler software. +//CC1101 STATUS REGSITER +#define CC1101_PARTNUM 0x30 +#define CC1101_VERSION 0x31 +#define CC1101_FREQEST 0x32 +#define CC1101_LQI 0x33 +#define CC1101_RSSI 0x34 +#define CC1101_MARCSTATE 0x35 +#define CC1101_WORTIME1 0x36 +#define CC1101_WORTIME0 0x37 +#define CC1101_PKTSTATUS 0x38 +#define CC1101_VCO_VC_DAC 0x39 +#define CC1101_TXBYTES 0x3A +#define CC1101_RXBYTES 0x3B + +//CC1101 PATABLE,TXFIFO,RXFIFO +#define CC1101_PATABLE 0x3E +#define CC1101_TXFIFO 0x3F +#define CC1101_RXFIFO 0x3F + +//************************************* class **************************************************// +class ELECHOUSE_CC1101 +{ +private: + void SpiStart(void); + void SpiEnd(void); + void GDO_Set (void); + void GDO0_Set (void); + void Reset (void); + void setSpi(void); + void RegConfigSettings(void); + void Calibrate(void); + void Split_PKTCTRL0(void); + void Split_PKTCTRL1(void); + void Split_MDMCFG1(void); + void Split_MDMCFG2(void); + void Split_MDMCFG4(void); +public: + void Init(void); + byte SpiReadStatus(byte addr); + void setSpiPin(byte sck, byte miso, byte mosi, byte ss); + void addSpiPin(byte sck, byte miso, byte mosi, byte ss, byte modul); + void setGDO(byte gdo0, byte gdo2); + void setGDO0(byte gdo0); + void addGDO(byte gdo0, byte gdo2, byte modul); + void addGDO0(byte gdo0, byte modul); + void setModul(byte modul); + void setCCMode(bool s); + void setModulation(byte m); + void setPA(int p); + void setMHZ(float mhz); + void setChannel(byte chnl); + void setChsp(float f); + void setRxBW(float f); + void setDRate(float d); + void setDeviation(float d); + void SetTx(void); + void SetRx(void); + void SetTx(float mhz); + void SetRx(float mhz); + int getRssi(void); + byte getLqi(void); + void setSres(void); + void setSidle(void); + void goSleep(void); + void SendData(byte *txBuffer, byte size); + void SendData(char *txchar); + void SendData(byte *txBuffer, byte size, int t); + void SendData(char *txchar, int t); + byte CheckReceiveFlag(void); + byte ReceiveData(byte *rxBuffer); + bool CheckCRC(void); + void SpiStrobe(byte strobe); + void SpiWriteReg(byte addr, byte value); + void SpiWriteBurstReg(byte addr, byte *buffer, byte num); + byte SpiReadReg(byte addr); + void SpiReadBurstReg(byte addr, byte *buffer, byte num); + void setClb(byte b, byte s, byte e); + bool getCC1101(void); + byte getMode(void); + void setSyncWord(byte sh, byte sl); + void setAddr(byte v); + void setWhiteData(bool v); + void setPktFormat(byte v); + void setCrc(bool v); + void setLengthConfig(byte v); + void setPacketLength(byte v); + void setDcFilterOff(bool v); + void setManchester(bool v); + void setSyncMode(byte v); + void setFEC(bool v); + void setPRE(byte v); + void setPQT(byte v); + void setCRC_AF(bool v); + void setAppendStatus(bool v); + void setAdrChk(byte v); + bool CheckRxFifo(int t); +}; + +extern ELECHOUSE_CC1101 ELECHOUSE_cc1101; + +#endif diff --git a/lib/SmartRC-CC1101-Driver-Lib/LICENSE.txt b/lib/SmartRC-CC1101-Driver-Lib/LICENSE.txt new file mode 100644 index 0000000..8b4631b --- /dev/null +++ b/lib/SmartRC-CC1101-Driver-Lib/LICENSE.txt @@ -0,0 +1,22 @@ +---------------------------------------------------------------------------------------------------------------- +cc1101 Driver for RC Switch. Mod by Little Satan. With permission to modify and publish Wilson Shen (ELECHOUSE). +---------------------------------------------------------------------------------------------------------------- + + + ELECHOUSE_CC1101.cpp - CC1101 module library + Copyright (c) 2010 Michael. + Author: Michael, + Version: November 12, 2010 + + This library is designed to use CC1101/CC1100 module on Arduino platform. + CC1101/CC1100 module is an useful wireless module.Using the functions of the + library, you can easily send and receive data by the CC1101/CC1100 module. + Just have fun! + For the details, please refer to the datasheet of CC1100/CC1101. + +notes: The whole stuff that is not directly related to Rc_Switch, + NewRemoteSwitch or Elechouse_cc1101 Lib is Copyright (c) 2018 - 2020 by Little Satan. + Example calculator codes in the driver lib. + And so on... + You can freely use, edit or distribute it with reference to the source. + For everything else, the rights of the respective owners apply! \ No newline at end of file diff --git a/lib/SmartRC-CC1101-Driver-Lib/README.md b/lib/SmartRC-CC1101-Driver-Lib/README.md new file mode 100644 index 0000000..0e90dff --- /dev/null +++ b/lib/SmartRC-CC1101-Driver-Lib/README.md @@ -0,0 +1,641 @@ +# SmartRC-CC1101-Driver-Lib_V2.5.7 + +![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/LSatan/SmartRC-CC1101-Driver-Lib) + +Note: Find out about the laws in your country. +Use at your own risk. + +Attention! in version 2.5.7 there are changes for the internal transfer functions regarding the gdo pin assignment! + +--------------------------------------------- +Announcements / other +--------------------------------------------- + +attention: currently i can only answer questions very belatedly. +try to scour existing problems for a solution if possible. +Problems that have not yet been closed are mostly already solved! +thanks for your understanding + +For debug and advanced functions: https://github.com/LSatan/CC1101-Debug-Service-Tool + +new library Simu_Remote: https://github.com/LSatan/Simu_Remote_CC1101 + +--------------------------------------------- +Install: +--------------------------------------------- + +Can be downloaded directly from the Arduino library manager. Just search for cc1101. + +--------------------------------------------- +Foreword: +--------------------------------------------- +First of all, thanks to Elechouse that I can make the modified library accessible to everyone. + +Link: http://www.elechouse.com/elechouse/ + + + +The library has been redesigned and some improvements have been made. + +Among other things, you can now also use the internal send / receive function. + +I would be happy to receive your suggestions for further examples from other libraries. + +All examples included are listed in the next field. + +--------------------------------------------- +Containing examples: +--------------------------------------------- +1.Elechouse CC1101: +- +Description: CC1101 Internal send / receive examples. Supported modulations 2-FSK, GFSK, ASK/OOK, 4-FSK, MSK. + +2.Rc-Switch: +- +

Description: Arduino lib to operate 433/315Mhz devices like power outlet sockets.

+

Link: https://github.com/sui77/rc-switch

+ +3.NewRemoteswitch: +- +

Description: This library provides an easy class for Arduino, to send and receive signals used by some common "new style" 433MHz remote control switches.

+

Link: https://github.com/1technophile/NewRemoteSwitch

+ +4.RemoteSensor library: +- +

Description: This library provides an easy class for Arduino, to send and receive signals used by some common weather stations using -remote 433MHz sensors.

+

Link: https://github.com/mattwire/arduino-dev/tree/master/libraries/RemoteSensor

+ +5.ESPiLight: +- +

Description:This Arduino library is a port of the pilight 433.92MHz protocols to the Arduino platform. It was tested with a ESP8266. The aim is to transmit, receive and parse many 433.92MHz protocols, by providing a simple Arduino friendly API. This should help to implement IoT bridges between the 434MHz-RF band and internet protocols.

+

Link:https://github.com/puuu/ESPiLight

+ +--------------------------------------------- +Instructions / Description: +--------------------------------------------- +This driver library can be used for many libraries that use a simple RF ASK module, +with the advantages of the cc1101 module.It offers many direct setting options as in +SmartRF Studio and calculates settings such as MHz directly. + +The most important functions at a glance: + +ELECHOUSE_cc1101.Init(); //Initialize the cc1101. Must be set first! + +ELECHOUSE_cc1101.setPA(PA); //Set transmission power. + +ELECHOUSE_cc1101.setMHZ(MHZ); //Set the basic frequency. + +ELECHOUSE_cc1101.SetTx(); //Set transmit on. + +ELECHOUSE_cc1101.SetTx(MHZ); //Sets transmit on and changes the frequency. + +ELECHOUSE_cc1101.SetRX(); //Set receive on. + +ELECHOUSE_cc1101.SetRx(MHZ); //Sets receive on and changes the frequency. + +ELECHOUSE_cc1101.setRxBW(RXBW); //Set Receive filter bandwidth + +ELECHOUSE_cc1101.setGDO(GDO0, GDO2); //Set Gdo0 (tx) and Gdo2 (rx) for serial transmission function. + + +ELECHOUSE_cc1101.setSpiPin(SCK, MISO, MOSI, CSN); //custom SPI pins. Set your own Spi Pins.Or to switch between multiple cc1101. Must be set before init and before changing the cc1101. + +ELECHOUSE_cc1101.setChannel(chnl); //Set Channel from 0 to 255. default = 0(basic frequency). + +ELECHOUSE_cc1101.setClb(fband, cal1, cal2); //Optionally enter Offset Callibration. Requirements: Sketch Calibrate_frequency.ino below [CC1101-Debug-Service-Tool](https://github.com/LSatan/CC1101-Debug-Service-Tool/tree/master/Calibrate_frequency).A SDR receiver and SDR software. + +New in V2.5.7 + +ELECHOUSE_cc1101.setGDO0(GDO0); //Sets Gdo0 for internal transfer function. + +ELECHOUSE_cc1101.addGDO0(GDO0, Modul); //Adds Gdo0 for internal transfer function (multiple cc1101). + +ELECHOUSE_cc1101.addGDO(GDO0, GDO2, Modul); //Adds Gdo0 (tx) and Gdo2 (rx) for serial transmission function (multiple cc1101). + +ELECHOUSE_cc1101.addSpiPin(SCK, MISO, MOSI, CSN, Modul); //Adds Spi Pins for multiple cc1101. + +ELECHOUSE_cc1101.setModul(Modul); //Switches between modules. from 0 to 5. So a maximum of 6. + + +The new features are not final and can be changed at any time. + +All can also be used in a loop and are applied directly. + +--------------------------------------------- +Wiring: +--------------------------------------------- + +Notes: A logic level converter is recommended for arduino. It also works well without. Use at your own risk. + + + + + + + + + + + + + +--------------------------------------------- +Donation +--------------------------------------------- + +If you like the library, I would be happy about a star. + +you can support me with a donation. + +https://www.paypal.me/LittleSatan666 + +Thank You! + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.5.7 +--------------------------------------------- +13.07.2021 + +Driver Library :Fixed a bug when initalizing multiple cc1101 + +Driver Library :new commandos for easy handling of multiple cc1101 + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.5.6 +--------------------------------------------- +06.04.2021 + +Driver Library :Add NUM_PREAMBLE. Sets the minimum number of preamble bytes to be transmitted. + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.5.5 +--------------------------------------------- +23.01.2021 + +Driver Library :Error correction for CheckRxFifo and CheckReceiveFlag (reception internal CC1101 function). + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.5.4 +--------------------------------------------- +23.01.2021 + +Driver Library :No big frequency jumps over SetRx(freq); Possible. Fixed! Big thanks to NorthernMan54 for testing! + +Driver Library :double-initaliesing option from V2.5.3 has been removed. Necessary for SetRx(freq); to use. + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.5.3 +--------------------------------------------- +22.01.2021 + +Driver Library :Putting rx tx has no effect if they are already in mode. Prevents unnecessary double-initaliesing. + +Driver Library :new command added: ELECHOUSE_cc1101.goSleep(); //Enter power down mode. For wakeup set RX or TX. + +Driver Library :new command added: ELECHOUSE_cc1101.getMode(); //Return the Mode. Sidle = 0, TX = 1, Rx = 2. + +Driver Library :new command added: ELECHOUSE_cc1101.setSidle(); //Set Rx / Tx Off. + +Driver Library :new command added: ELECHOUSE_cc1101.getCC1101(); //Test Spi connection and return 1 when true. + +Examples :RcSwitch Repeater_cc1101.ino has been shortened. + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.5.2 +--------------------------------------------- +01.10.2020 + +Driver Library :SpiWriteReg, SpiReadReg, SpiWriteBurstReg and SpiReadBurstReg change to public. Allows additional modifications from sketch. + +Driver Library :Setrx no longer has to be set to receive.(internal transmission methods) + +Driver Library :Gdo pins are now set to input / output with set gdo instead of Init. + +Driver Library :Added new sending method. Allows sending without a gdo0 pin. + +notes :The new internal send and receive methods now work completely without an additional gdo pin. + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.5.1 +--------------------------------------------- +18.08.2020 + +Driver Library :When changing from receiving to sending, the program freezes (internal send functions). fixed! + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.5.0 +--------------------------------------------- +16.08.2020 + +Driver Library :Rssi was calculated incorrectly.Fixed Thanks to zapquiyou! + +Driver Library :New receiving method for internal examples added. Allows several actions to be carried out in the loop. + +Driver Library :Internal Crc check added for internal examples. + +Driver Library :Simplification to send char added for internal transfer examples. + +Driver Library :A lot of new settings added for internal transmission examples. Everything can be set as in SmartRF Studio and is calculated automatically. An overview: setDeviation, setChsp, setRxBW, setDRate, setSyncMode, setSyncWord, setAdrChk, setAddr, setWhiteData, setPktFormat, setLengthConfig, setPacketLength, setCrc, setCRC_AF, setDcFilterOff, setManchester, setFEC, setPQT, setAppendStatus. description in the examples! + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.4.0 +--------------------------------------------- +07.05.2020 + +Driver Library :frequency calculator has been simplified. error-free calculations and less variables. + +Driver Library :Added frequency calibration option. + +Driver Library :Certain frequencies could not be set. Fixed! Big thanks to gusgorman402! + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.3.5 +--------------------------------------------- +14.04.2020 + +Driver Library :setChsp has been removed to save space. This function is available in the Service / Debug Tool as an extended function. + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.3.4 +--------------------------------------------- +01.04.2020 + +Driver Library :set AGCCTRL2 from 0x07 to 0xC7. Reception is significantly improved! + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.3.3 +--------------------------------------------- +01.04.2020 + +Driver Library :set FSCTRL1 from 0x08 to 0x06. for better receive. + +Driver Library :set SpiWriteReg to public. Make it fit for debug tool! + +Driver Library :set SpiStrobe to public. Make it fit for debug tool! + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.3.2 +--------------------------------------------- +24.03.2020 + +Driver Library :Set gdo2 from input to output. Errors in libraries that use the pins directly. + +examples :Set gdo2 from setting 2 to 0 in default examples. Gdo2 is not required for these examples. + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.3.1 +--------------------------------------------- +18.03.2020 + +Driver Library :ESP8266/32 core panik. Fixed! The cc1101 must be initialized before setting options! + +examples :all examples have been adapted. + +examples :internal cc1101 examples have been adapted for esp8266/32. + +examples :ESPiLight examples added. + +--------------------------------------------- +Changelog: SmartRC-CC1101-Driver-Lib_V2.3 +--------------------------------------------- +18.03.2020 + +Driver Library :"RcSwitch-cc1101-driver-lib" becomes "SmartRC-cc1101-driver-lib". + +Pull request :#20 Removed unnecessary initializations when setting Tx or Rx mode. Agreed / accepted improves speed when changing rx / tx. Special thanks to fleibede. + +Pull request :#19 Added spi state after SPI pins have been set for default pins. The problem was solved differently. Special thanks to fleibede. + +Pull request :#18 Updated AVR types conditional defines. Agreed / accepted. Special thanks to fleibede. + +Driver Library :Frequency calculator certain frequencies were calculated incorrectly. fixed! + +Driver Library :Intelligent Pa Table system added. When changing the band The corresponding table is set via setTx / Rx and the frequency set to basic calibrated. All module internal transmission powers can now be set according to the band. + +Driver Library :Newly calibrated base frequency on chan 0 according to the SmartRF Studio. + +Driver Library :Channel spacing calculator can enter directly the spacing area in khz. + +Driver Library :Modulation setting added for internal transmission methods + +Driver Library :ESP32 reception improvements. + +Driver Library :Direct conversion of the RSSI level in the library. + +Driver Library :Correction of version numbering. + +examples :New examples added "RemoteSensor library". + +examples :New examples added "Elechouse CC1101 default examples" + +examples :Remote Fusion has been removed and given an extra library. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V2.2.1 +--------------------------------------------- +[Download Release V2.2.1](https://drive.google.com/file/d/1YHFpp2GQC96-GKcg67Tym9wt1E4CBdFc/view?usp=sharing) + +20.01.2019 + +Driver Library :Spi options have been removed. (Problems with ESP32) FIXED! + +notes :everything was checked again. D-SUN module on esp8266 / 32 and so on. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V2.2 +--------------------------------------------- +17.01.2019 + +Version notes :Spi was reconfigured for fix some issuses. + +Driver Library :HotFix for cc1101 module with "8pins"(example DSun). Transmitting on Esp8266 based bords not work. FIXED! + +Driver Library :Change "SpiReadStatus" to public. Now can read RSSI Level! + +Driver Library :Spi transfer rate was limited to cc1101 max transfer rate (10mhz). + +Driver Library :After using Spi, it will now be disabled. (receive data from serial monitor and rx pin was not working on Esp 8266/32) FIXED! + +Add Examples :ReceiveDemo_Simple_with_RSSI_cc1101.ino (Shows reception strength) + +Add Examples :Frequency_Scanner_cc1101.ino (Scans Transmitting frequency of your remotes. No good results with cc1101-DSun) + +Add Examples :ProtocolAnalyzeDemo_cc1101.ino (for scan unknown protokolls. Requires: link is in sketch!) + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V2.1 +--------------------------------------------- +3.1.2019 + +Driver Library :Spi corrections for esp32. Spi Pin changes did not work on esp32. FIXED! + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V2.0 +--------------------------------------------- +18.12.2018 + +Driver Library :Own Spi pin settings possible. Allows the use of other microcontrollers. Allows you to use multiple CC1101s. More information in the commands.txt + +Add TXT :driver lib commands and examples.txt + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.9.3 +--------------------------------------------- +27.11.2018 + +Driver Library :setESP8266 has been removed. Pins are set automatically with the init command. + +Driver Library :Arduino mega SPI pins added. + +Driver Library :Added setGDO pins (For libraries that directly address the GDO pins).Like this https://github.com/EinfachArne/Somfy_Remote . + Example ELECHOUSE_CC1101.setGDO(2, 4); // (pin2 = GDO0, pin4 = GDO2). + +Add Wiring TXT :WIRING MEGA.txt + +Add Wiring JPG :WIRING MEGA.jpg + +LICENSE :LICENSE.txt Update. + +notes :setGDO is not compatible with RC_Switch / NewRemotSwitch. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.9.2 +--------------------------------------------- +16.11.2018 + +Fixes Remotes Fusion :Receive mode and Repeater mode frequency, changes to the transmitter frequency after pressing on a transmitter. (RemotesFusion.ino)Fixed! + +NewRemoteSwitch :LearnCode_cc1101.ino (corrections). + +Added :Keywords.txt added. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.9.1 +--------------------------------------------- +07.11.2018 + +New Sketch :Clear_EEPROM.ino (if there are problems with the access point password or if you want to use your ESP for other projects). + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.9 +--------------------------------------------- +18.10.2018 + +New Sketch :RemotesFusion.ino. + +New Apk´s :RemotesFusion_V1_en.apk / RemotesFusion_V1_de.apk. + +Add Docs :Docs and manuals for RemotesFusion. + +Changes :channel spacing and channel set was removed from the examples. unnecessary because exact frequency can be set. + +notes :RemotesFusion is an application with which Rc-Switch and NewRemoteSwitch can be controlled at the same time. + A universal remote control APP with many possibilities. Only for Esp 8266/32 modules! For more information, watch the docs. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.8 +--------------------------------------------- +[Download Release V1.8](https://drive.google.com/file/d/1ADKOmW0SrUoomeoDskFrm0J2SdwCLB_O/view?usp=sharing) + +02.09.2018 + +Driver Library :Added pin settings for esp32. + +Examples :Added pin settings for esp32 examples. + +Add Wiring JPG :Add Wiring JPG esp32. + +Add Wiring TXT :Add Wiring TXT esp32. + +Add Wiring JPG :Add Wiring JPG esp32 for Receive_Send_Decimal_Demo_Simple.ino. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.7.2 +--------------------------------------------- +[Download Release V1.7.2](https://drive.google.com/file/d/1sfMvQw2JaGARTaYXZevOjB20BFOMS0tw/view?usp=sharing) + +16.08.2018 + +Examples :All NewRemoteSwitch examples are compatible with ESP. Exception Retransmitter_cc1101.ino. + +Driver Library :Frequency calculator calibrated. Difference -0.01 MHz. (Fixed!) Frequency is now accurate. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.7.1 +--------------------------------------------- +[Download Release V1.7.1](https://drive.google.com/file/d/1PXa1k0AIDY8bTMxFyyQMbOljijhIn1ke/view?usp=sharing) + +10.08.2018 + +Driver Library :Now you can Switch the frequency in loop. Examples: ELECHOUSE_cc1101.SetTx(433.92); and ELECHOUSE_cc1101.SetRx(433.92);. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.7 +--------------------------------------------- +[Download Release V1.7](https://drive.google.com/file/d/1uxACfe1ZUrkL4S3_NPVN0DmUfzbxt6oQ/view?usp=sharing) + +09.08.2018 + +Driver Library :Now you can enter your base frequency directly.The library calculates the settings automatically. example(433.92) + +Driver Library :Remove freq2, freq1 and freq0 Settings. + +Driver Library :Removed unnecessary entries. the library shrank from 32,8kb(.cpp) and 9,38kb(.h) to 17,0kb(.cpp) and 7,87kb(.h). + +New Example :(NewRemoteSwitch Library) NewRemoteRepeater.ino. Repeat the Received signal 1to1. Best thanks to Roman for write it. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.6.1 +--------------------------------------------- +[Download Release V1.6.1](https://drive.google.com/file/d/1q8FV5kDnhAj1SMZf6DS0wDcm5xo4E-5-/view?usp=sharing) + +05.08.2018 + +Examples Fix (rc-switch):Fix auto receive pulse. Received pulse don´t transmit. Fixed!(Repeater.ino and Receive_Send_Decimal_Demo_Simple.ino). + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.6 +--------------------------------------------- +[Download Release V1.6](https://drive.google.com/file/d/1p_iAxh7ZWlNWhFoqMM_tlLTLdyGK07-a/view?usp=sharing) + +03.08.2018 + +Esp8266 :Compatibility for all RC switch examples. + +Driver Library :Add the GDO2 pin for Receive. Change GDO0 to send. + +Wiring changes :Description in jpg's and txt's. + +Examples :All examples have been adjusted. + +Examples :Esp and Arduino are set automatically. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.5 +--------------------------------------------- +[Download Release V1.5](https://drive.google.com/file/d/1XcGPbvI5v2PcpnVBbjtOFwtuJtx3jMK4/view?usp=sharing) + +31.07.2018 + +New :Supportet NewRemoteSwitch Library. For wireless sockets by trust smart home, Smappee, DI-O Chacon, Intertechno and others. + You want to use it? Then you need that https://github.com/1technophile/NewRemoteSwitch + +Add Examples :NewRemoteSwitch Compatible examples. + +Driver Library :You can now switch directly from Tx to Rx in the loop. Without resetting the cc1101. + +Add Examples :New Repeater Example for Rc-switch. For example, to increase the range of your remote control. + +Example changes :Receive_Send_Decimal_Demo_Simple.ino (remove unnecessary commands). + +Examples Fix :Rc-Switch examples fix TypeA, TypeB and TypeD (missing from semicolon to SetTx). + +Notes :NewRemoteSwitch examples Retransmitter_cc1101.ino and LightShow_cc1101.ino only Arduino!!! + +Notes :Rc-switch example Repeater_cc1101.ino only Arduino!!! + +Notes :Rc-switch example Receive_Send_Decimal_Demo_Simple.ino only Arduino!!! + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.4 +--------------------------------------------- +[Download Release V1.4](https://drive.google.com/file/d/1nAPGeQSutfskirJsng44adB4sXU1YU6A/view?usp=sharing) + +26.07.2018 + +Driver Library :esp8266 Compatibility (Tested with Wemos d1 mini). + +Driver Library :Change default Receive filter bandwidth to 812khz (max). + +Driver Library :Change default Tx Power to PA10 (max). + +Examples :Add set esp command and pin settings. + +Examples :Diskription change. + +Demo Example :Add auto Recive and Send pulse length. (Receive_Send_Decimal_Demo_Simple.ino) + +Add Wiring JPG :Add Wiring JPG esp8266. + +Add Wiring TXT :Add Wiring TXT esp8266. + +Notes :esp8266 pin D4 don´t work with receive, Transmit and receive is set to D2. + +Notes :esp8266 don´t work with Receive_Send_Decimal_Demo_Simple.ino (freezes when reset cc1101). + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.3.1 +--------------------------------------------- +[Download Release V1.3.1](https://drive.google.com/file/d/1iKmagldd14O1Boa9Z_PDpXbHRECYUPdt/view?usp=sharing) + +30.03.2018: + +Driver Library Fix :no effect set by transmission power. + +Driver Library :Transmitting power can be adjusted via frequency(example in the sketches). + +Examples :Command Tx Power cleared. + +Examples Fix :set Receive filter bandwidth (command incomplete) Fixed. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.3 +--------------------------------------------- +[Download Release V1.3](https://drive.google.com/file/d/1q56Qewk8-Aquv1epss1gd7Gc05q4GrbO/view?usp=sharing) + +25.03.2018: + +Driver Library :Add Channel List. Now you can set channel numbers 0-255. + +Driver Library :Add bandwidth can be adjusted + +Driver Library :transmission power can be adjusted + +Driver Library :can set your own frequency settings (freq2, freq1, freq0) + +Driver Library :Channel spacing can be set. + +Examples :Add set new commands + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.2 +--------------------------------------------- +[Download Release V1.2](https://drive.google.com/file/d/1KLJt8ygszj9rqcttiEMt5zCnJKHc_qe3/view?usp=sharing) + +20.03.2018: + +Driver Library :Add 315Mhz Support. + +Driver Library :Add Channel command for finetune (80khz steps) from 420mhz - 440mhz / 302mhz - 322mhz. + +Examples :Add set channel command in examples. + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.1 +--------------------------------------------- +[Download Release V1.1](https://drive.google.com/file/d/1uZzcY4uoduiUjFZzXdxA-ucLoA_TtC1f/view?usp=sharing) + +19.03.2018: + +Driver Library Fix :Calibrated Frequency from 433.86 to 433.92 - 433.93 Mhz. + +Driver Library :cc1101 reset command added (allows switching between send and receive.) + +New Demo Example :Receive_Send_Decimal_Demo_Simple.ino (Sends last received decimal code) + To illustrate the change between RX and TX (press button = send / do not press button = receive) + +Add Wiring JPG :Wiring for Receive_Send_Decimal_Demo_Simple.ino + +Add Wiring JPG :Wiring for Nano / Uno + + +--------------------------------------------- +Changelog: RCSwitch-CC1101-Driver-Lib_V1.0 +--------------------------------------------- +[Download Release V1.0](https://drive.google.com/file/d/14538RtiEakZ_8yioXJT32XneheSjDqxi/view?usp=sharing) + +18.03.2018: + +cc1101 Compatibility for RC-Switch. + +cc1101 RC-Switch Compatible examples. diff --git a/lib/SmartRC-CC1101-Driver-Lib/library.json b/lib/SmartRC-CC1101-Driver-Lib/library.json new file mode 100644 index 0000000..63ef3b0 --- /dev/null +++ b/lib/SmartRC-CC1101-Driver-Lib/library.json @@ -0,0 +1,19 @@ +{ + "name": "SmartRC-CC1101-Driver-Lib", + "description": "This driver library can be used for many libraries that use a simple RF ASK module, with the advantages of the cc1101 module.It offers many direct setting options as in SmartRF Studio and calculates settings such as MHz directly.", + "keywords": "rf, radio, wireless, cc1101", + "authors": + { + "name": "Little Satan" + }, + "repository": + { + "type": "git", + "url": "https://github.com/LSatan/SmartRC-CC1101-Driver-Lib" + }, + "version": "2.5.7", + "frameworks": [ + "arduino" + ], + "platforms": "*" +} diff --git a/platformio.ini b/platformio.ini index 6ddfc27..c4e1bfa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,7 +23,6 @@ framework = arduino test_ignore = * lib_deps = bblanchon/ArduinoJson@^7.2.2 - lsatan/SmartRC-CC1101-Driver-Lib@^2.5.7 knolleary/PubSubClient@^2.8 esp32async/ESPAsyncWebServer@^3.12.1 esp32async/AsyncTCP@^3.5.0 From 9c1ec17e1a1422ba1eb10300b75110629053d039 Mon Sep 17 00:00:00 2001 From: cjkas Date: Wed, 21 Oct 2026 12:18:37 +0200 Subject: [PATCH 5/5] fix: stop the CC1101 driver's "IO is not set as GPIO" log spam Arduino 3.x tracks which peripheral owns each pin and logs when a pin the SPI bus owns is used through digitalRead()/digitalWrite(). The vendored SmartRC-CC1101 driver does both: - Every register access waits for CHIP_RDYn with digitalRead(MISO): one "IO 19 is not set as GPIO" warning per access, about one every 4 s from the RSSI read in decodeFrame(). It now reads the pad with gpio_get_level(), which returns the same level without the ownership check. - Init() set SCK and MOSI with digitalWrite() after SpiStart(), which the core refused with an error each boot. The writes are gone; the bus idles them. The MISO wait also had no bound, so a missing or dead module hung the caller. It now gives up after 10 ms. No native test: the driver only builds for the ESP32. To check on hardware: the serial log should have no "is not set as GPIO" lines, and frames should still decode with an RSSI. Co-Authored-By: Claude Opus 5.5 --- .../ELECHOUSE_CC1101_SRC_DRV.cpp | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.cpp b/lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.cpp index 6aa722b..c5f014d 100644 --- a/lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.cpp +++ b/lib/SmartRC-CC1101-Driver-Lib/ELECHOUSE_CC1101_SRC_DRV.cpp @@ -16,6 +16,24 @@ cc1101 Driver for RC Switch. Mod by Little Satan. With permission to modify and #include #include "ELECHOUSE_CC1101_SRC_DRV.h" #include +#ifdef ESP32 +#include +#endif + +// ESPSomfy-RTS: waits for the CC1101 to pull MISO low (CHIP_RDYn) before an +// SPI access. MISO belongs to the SPI bus by then, and Arduino 3.x logs a +// warning on every digitalRead() of a pin another peripheral owns, so on the +// ESP32 read the pad directly. Gives up after 10 ms so a missing or dead +// module can't hang the caller; the chip is ready within a few hundred us. +static void waitMisoLow(byte pin) +{ + uint32_t start = micros(); + #ifdef ESP32 + while(gpio_get_level((gpio_num_t)pin) && micros() - start < 10000); + #else + while(digitalRead(pin) && micros() - start < 10000); + #endif +} /****************************************************************/ #define WRITE_BURST 0x40 //write burst @@ -144,9 +162,9 @@ void ELECHOUSE_CC1101::Reset (void) digitalWrite(SS_PIN, HIGH); delay(1); digitalWrite(SS_PIN, LOW); - while(digitalRead(MISO_PIN)); + waitMisoLow(MISO_PIN); SPI.transfer(CC1101_SRES); - while(digitalRead(MISO_PIN)); + waitMisoLow(MISO_PIN); digitalWrite(SS_PIN, HIGH); } /**************************************************************** @@ -160,8 +178,9 @@ void ELECHOUSE_CC1101::Init(void) setSpi(); SpiStart(); //spi initialization digitalWrite(SS_PIN, HIGH); - digitalWrite(SCK_PIN, HIGH); - digitalWrite(MOSI_PIN, LOW); + // ESPSomfy-RTS: no digitalWrite() on SCK and MOSI here. SpiStart() has + // handed them to the SPI bus, so Arduino 3.x refused the writes and logged + // an error; the bus already idles SCK and MOSI. Reset(); //CC1101 reset RegConfigSettings(); //CC1101 register config SpiEnd(); @@ -176,7 +195,7 @@ void ELECHOUSE_CC1101::SpiWriteReg(byte addr, byte value) { SpiStart(); digitalWrite(SS_PIN, LOW); - while(digitalRead(MISO_PIN)); + waitMisoLow(MISO_PIN); SPI.transfer(addr); SPI.transfer(value); digitalWrite(SS_PIN, HIGH); @@ -194,7 +213,7 @@ void ELECHOUSE_CC1101::SpiWriteBurstReg(byte addr, byte *buffer, byte num) SpiStart(); temp = addr | WRITE_BURST; digitalWrite(SS_PIN, LOW); - while(digitalRead(MISO_PIN)); + waitMisoLow(MISO_PIN); SPI.transfer(temp); for (i = 0; i < num; i++) { @@ -213,7 +232,7 @@ void ELECHOUSE_CC1101::SpiStrobe(byte strobe) { SpiStart(); digitalWrite(SS_PIN, LOW); - while(digitalRead(MISO_PIN)); + waitMisoLow(MISO_PIN); SPI.transfer(strobe); digitalWrite(SS_PIN, HIGH); SpiEnd(); @@ -230,7 +249,7 @@ byte ELECHOUSE_CC1101::SpiReadReg(byte addr) SpiStart(); temp = addr| READ_SINGLE; digitalWrite(SS_PIN, LOW); - while(digitalRead(MISO_PIN)); + waitMisoLow(MISO_PIN); SPI.transfer(temp); value=SPI.transfer(0); digitalWrite(SS_PIN, HIGH); @@ -250,7 +269,7 @@ void ELECHOUSE_CC1101::SpiReadBurstReg(byte addr, byte *buffer, byte num) SpiStart(); temp = addr | READ_BURST; digitalWrite(SS_PIN, LOW); - while(digitalRead(MISO_PIN)); + waitMisoLow(MISO_PIN); SPI.transfer(temp); for(i=0;i