Skip to content

fix: stop the CC1101 driver's "IO is not set as GPIO" log spam - #75

Merged
cjkas merged 2 commits into
feat/idf55from
fix/cc1101-spi-pins
Oct 21, 2026
Merged

cjkas merged 2 commits into
feat/idf55from
fix/cc1101-spi-pins

Conversation

@cjkas

@cjkas cjkas commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Summary

On Arduino 3.3 (#71) the serial log fills with:

[1503][E] __digitalWrite(): IO 18 is not set as GPIO. Execute digitalMode(18, OUTPUT) first.   ← once per boot
[1514][E] __digitalWrite(): IO 23 is not set as GPIO. Execute digitalMode(23, OUTPUT) first.   ← once per boot
[1526][W] __digitalRead():  IO 19 is not set as GPIO. digitalRead() may return an inconsistent value.   ← ~every 4 s

The Arduino 3.x core tracks which peripheral owns each pin and logs when an SPI pin is used through digitalRead()/digitalWrite(). The CC1101 driver does both. Its registry package (lsatan/SmartRC-CC1101-Driver-Lib 2.5.7) has been unmaintained since 2021, so it now lives in lib/:

 lib/
+└── SmartRC-CC1101-Driver-Lib/      # 2.5.7, first commit unchanged
 platformio.ini
-  lsatan/SmartRC-CC1101-Driver-Lib@^2.5.7
 ELECHOUSE_CC1101::SpiWriteReg / SpiReadReg / SpiStrobe / ... / Reset   (8 places)
   digitalWrite(SS_PIN, LOW)
-  while(digitalRead(MISO_PIN));                 # warns on every register access
+  waitMisoLow(MISO_PIN)                          # gpio_get_level(), gives up after 10 ms
   SPI.transfer(...)

 ELECHOUSE_CC1101::Init
   SpiStart()                                    # SPI.begin() takes SCK, MISO, MOSI
   digitalWrite(SS_PIN, HIGH)
-  digitalWrite(SCK_PIN, HIGH)                   # refused by the core: pin owned by SPI
-  digitalWrite(MOSI_PIN, LOW)                   # refused by the core: pin owned by SPI
   Reset()

gpio_get_level() reads the same pad without the ownership check. The writes in Init() already did nothing under 3.3, and the bus idles SCK and MOSI anyway. The MISO wait had no bound, so a missing or dead module hung the caller; it now gives up after 10 ms (the chip is ready within a few hundred µs). The changes are marked ESPSomfy-RTS: in the source. The repeating warning comes from the RSSI read in decodeFrame(), one per received frame.

Evidence

  • Before: 290 IO 19 is not set as GPIO warnings in 20 minutes of a release build's serial log, plus the IO 18 and IO 23 errors at every boot.
    After: the release build compiles against the copy in lib/ (.pio/build/esp32dev/libd34/SmartRC-CC1101-Driver-Lib).

pio test -e native: 415/415 passed. esp32dev builds, with 21,648 bytes free in the OTA slot. There's no native test because the driver only builds for the ESP32.

Hold before merge: not yet run on hardware. Flash esp32dev and check that the serial log has no is not set as GPIO lines and that received frames still show an RSSI.

Merge Danger

Door: two-way

Revert both commits to go back to the registry package.

Blast Radius: radio

Every CC1101 register access goes through the new wait. If the module isn't ready within 10 ms, the access now goes ahead instead of hanging. That doesn't make a missing module visible: getCC1101() only checks that the version register reads above 0, and a floating MISO usually reads 0xFF. Later driver updates have to be merged into lib/ by hand, but upstream hasn't released since 2021.

🤖 Generated with Claude Code

cjkas and others added 2 commits October 21, 2026 12:08
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
@cjkas
cjkas merged commit 2835f54 into feat/idf55 Oct 21, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant