isChannelActive() previously spin-waited (with YIELD_TASK()) for up to
16s after detecting RSSI busy, blocking Dispatcher::loop() from
servicing incoming packets for the duration of the backoff.
Replace the blocking wait with a state machine (_lbt_backoff_active /
_lbt_deadline): on busy detection, arm a deadline and return true
(busy) immediately. Dispatcher::checkSend()'s existing retry mechanism
(getCADFailRetryDelay()) re-polls isChannelActive() on the next
loop() pass; once the deadline has elapsed, re-sense (bounded,
single-level recursion) instead of assuming still-busy.
The initial 5ms RSSI sense and the post-clear jitter wait remain
blocking, as both are short (<=5ms and <=~1s respectively) relative
to the up-to-16s backoff this change targets.
Hardware-tested (LilyGo T3S3 sx1262 / Wio Tracker L1 Pro) in both quiet and
electrically noisy environments; confirmed both bidirectional and
unidirectional message delivery under legitimate busy-channel
conditions.
Add getMaxTextLen() and getMaxGroupTextLen() virtual to mesh::Radio
(default 160 bytes). BaseChatMesh uses these instead of the hardcoded
MAX_TEXT_LEN macro for limit checks in composeMsgPacket(),
sendCommandData(), and sendGroupMessage(). Stack buffers remain sized
to MAX_TEXT_LEN as a safe upper bound.
Enables isJapanMode() and getMaxTextLen() to work on SX1262-based targets
(WisMesh Tag, T-Echo Lite, T114, XIAO nRF52, etc.).
codingRate accessed as SX1262 base class member +4 (same pattern as LR1110).
getCodingRate() returns codingRate+4 (RadioLib stores 1-4 internally,
expose as CR4/5-8 matching the rest of the codebase).
CustomLR1110Wrapper overrides both getCodingRate() and getFreqMHz() so
isJapanMode() and getMaxTextLen() work correctly on T1000-E.
Add isJapanMode() virtual to mesh::Radio (default false) so Dispatcher
can query frequency context without depending on RadioLibWrapper.
Dispatcher::getCADFailMaxDuration() returns UINT32_MAX for JP nodes,
eliminating the 4-second forced-TX that would violate ARIB STD-T108.
Non-JP nodes retain the original 4-second safety timeout unchanged.
In JP 920MHz band (CH25-27): 5ms continuous RSSI sensing at -80dBm
absolute threshold, exponential backoff (2000-16000ms) on busy, jitter
(0-500ms) on free, then falls through to CAD if enabled.
Non-JP path: existing relative-RSSI threshold + CAD unchanged.
Add YIELD_TASK() macro and _busy_count field for backoff tracking.
Add getCodingRate() and getFreqMHz() virtual methods to RadioLibWrapper
base class, enabling subclasses to report their operating frequency.
isJapanMode() detects JP 920MHz band (CH25-27) for ARIB STD-T108 compliance.
getMaxTextLen() and getMaxGroupTextLen() enforce 4-second airtime limits
per SF12/BW125 measurements.
Compile fails due to user_btn not declared in board target.
Fixes:
- Add MomentaryButton declaration for user_btn in variants/xiao_nrf52/target.cpp
- Add momentary button helper include in variants/xiao_nrf52/target.h
- Add extern linkage for MomentaryButton -> user_btn in variants/xiao_nrf52/target.h
SerialEthernetInterface.cpp is compiled for every nRF52 target because
PlatformIO builds all .cpp files under src/. It includes
SerialEthernetInterface.h, which unconditionally pulls in
<RAK13800_W5100S.h> -- a library only present in the RAK4631 Ethernet
env's lib_deps. As a result any other nRF52 board (e.g. Heltec T114)
fails to build with 'RAK13800_W5100S.h: No such file or directory'.
Wrap the contents of both files in '#ifdef ETHERNET_ENABLED' so they
compile to empty translation units on non-Ethernet builds. RAK4631
Ethernet envs define ETHERNET_ENABLED and are unaffected.
Fixes#2985
Improvements:
- Add condition to only turn off display if on (avoids wedging the shutdown on some displays)
- Reset LoRa radio before calling radio_driver.powerOff() to ensure it is in a known good state (and will accept the command)
- Ensure SPI is started so LoRa radio commands can be sent (some shutdowns can happen before this)
- Add gate for P_LORA_NSS pin defined before writing to the pin