Root cause: SetRegulatorMode(DC-DC+LDO) in begin() kills LoRa RX on
boards without the DC-DC inductor (T-Beam Supreme, T-Watch Ultra).
TX still works, preamble/RSSI detection works, but RX_DONE never
fires — mimics hardware failure.
Three regressions from 033ddd6 fixed:
- Remove SetRegulatorMode(0x01) from begin() — these boards use
LDO-only, which is the SX1262 default after reset
- Restore receive() call in dcd() after false preamble timeout —
upstream fix (3ae8982) we had removed; just clearing IRQ flags
is insufficient to reset the demodulator chain
- Add lora_receive() after beacon_transmit() — radio was left in
STDBY after TX, never returning to RX mode
Also reverts getPacketType check in receive(), TCXO-before-calibration,
clear-device-errors, and TX fallback mode changes that were not needed
and caused intermittent RX failures during testing.
Verified: bidirectional LoRa RX between watch and T-Beam Supreme
with IFAC authentication at 868 MHz SF7 BW125K.
Root cause found via loop profiling: two functions called every loop
iteration on unprovisioned devices consumed 950ms:
1. beacon_update() called startRadio() every loop when GPS had fix
but device wasn't provisioned (hw_ready=false). startRadio() does
full radio init with SPI commands and delays (~600ms). Fix: gate
beacon_update() on hw_ready.
2. stopRadio() called LoRa->end() (SPI sleep + SPI.end()) every loop
in the !hw_ready path (~99ms). Fix: only call when radio_online
is true (stop once, not repeatedly).
Result: loop time 950ms → 0.3ms (3200x improvement).
Also added:
- Main loop profiling (radio/serial/display/pmu/gps/bt/imu timing)
- Build timestamp in metrics command for version verification
- Visible-tile-only label updates (GPS float formatting skipped
when GPS screen not shown)
- Reverted to hwcdc USB mode (TinyUSB adds ~900ms/loop overhead)
- USB MSC SD card code preserved but inactive (needs TinyUSB)
SharedSPI.h: FreeRTOS mutex protecting the shared SPI bus (pins
33/34/35) used by LoRa (SX1262), SD card, and future NFC.
sx126x.cpp: All 6 SPI transaction blocks wrapped with
shared_spi_mutex acquire/release. LoRa uses portMAX_DELAY
(always gets access, just delayed by SD if needed).
USBSD.h: USB MSC SD card access uses shared_spi_mutex with
200ms timeout. Deferred init (3s after boot) for SPI bus
readiness. Metrics: sd_ready, sd_reads, sd_fails counters.
IMULogger.h, Gui.h: SD card writes wrapped in shared_spi_mutex.
Status: SD card correctly reports 29.7GB via USB MSC. Reads
work intermittently (~50% success). Root cause: main loop
takes ~700ms per iteration, causing mutex timeout for MSC
callbacks. Needs loop time investigation to achieve reliable
USB mass storage.
The CO5300 display uses a separate SPI3 bus — not affected.
Standalone GPS beacon mode: when no KISS host is connected for 15s,
the RNode transmits position and battery telemetry over LoRa.
Two beacon paths:
- LXMF (recommended): encrypted per-packet messages with announces,
compatible with Sideband and any LXMF application. Supports IFAC
network authentication.
- Legacy JSON: plaintext or encrypted raw packets for simple collectors.
Key changes:
- GPS support for T-Beam Supreme S3 (L76K) and Heltec V4 (external)
- SX1262 radio fixes: IQ polarity, DCD preamble lockup, RX reliability
- LXMF identity management with NVS-backed Ed25519/X25519 keys
- IFAC authentication (CMD_IFAC_KEY 0x89) for private networks
- Per-channel serial isolation (USB, BLE, WiFi)
- GPS status page in OLED display rotation
- Provisioning via rnlog: provision-lxmf, provision-ifac
- Documentation in Documentation/BEACON.md
Work in progress
Status: Boots, display works on Xiao espansion base,
radio is recognized
Todo:
PMU
Firmware hash fails even if generated and then written
Radio testing
Buttons / LEDs
other?