Skip to content

Commit 9f98885

Browse files
committed
JP LBT: make busy-channel backoff non-blocking
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.
1 parent 247b894 commit 9f98885

2 files changed

Lines changed: 18 additions & 5 deletions

File tree

src/helpers/radiolib/RadioLibWrappers.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,17 +194,27 @@ int16_t RadioLibWrapper::performChannelScan() {
194194

195195
bool RadioLibWrapper::isChannelActive() {
196196
if (isAS923_1_JP()) {
197+
// Non-blocking backoff: if a prior busy detection armed a backoff wait,
198+
// report busy and let Dispatcher::checkSend() re-poll on the next loop()
199+
// pass instead of spin-waiting here (which used to block the Dispatcher
200+
// loop for up to 16s).
201+
if (_lbt_backoff_active) {
202+
if ((int32_t)(millis() - _lbt_deadline) < 0) {
203+
return true; // still waiting; re-checked next call
204+
}
205+
_lbt_backoff_active = false;
206+
return isChannelActive(); // backoff elapsed -- re-sense (bounded, single-level recursion)
207+
}
208+
197209
// ARIB STD-T108: 5ms continuous RSSI sensing, -80dBm absolute threshold
198210
uint32_t sense_start = millis();
199211
while (millis() - sense_start < 5) {
200212
if (getCurrentRSSI() > -80.0f) {
201213
_busy_count++;
202214
uint32_t base_ms = 2000;
203215
uint32_t max_backoff = min(base_ms * (1u << _busy_count), (uint32_t)16000);
204-
uint32_t backoff_until = millis() + random(max_backoff / 2, max_backoff);
205-
while (millis() < backoff_until) {
206-
YIELD_TASK();
207-
}
216+
_lbt_deadline = millis() + random(max_backoff / 2, max_backoff);
217+
_lbt_backoff_active = true;
208218
return true;
209219
}
210220
YIELD_TASK();

src/helpers/radiolib/RadioLibWrappers.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ class RadioLibWrapper : public mesh::Radio {
1515
int32_t _floor_sample_sum;
1616
uint8_t _preamble_sf;
1717

18+
bool _lbt_backoff_active; // non-blocking wait after RSSI busy detection (up to 16s)
19+
uint32_t _lbt_deadline;
20+
1821
void idle();
1922
void startRecv();
2023
float packetScoreInt(float snr, int sf, int packet_len);
2124
virtual bool isReceivingPacket() =0;
2225
virtual void doResetAGC();
2326

2427
public:
25-
RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board), _busy_count(0), _preamble_sf(0) { n_recv = n_sent = 0; }
28+
RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board), _busy_count(0), _preamble_sf(0), _lbt_backoff_active(false), _lbt_deadline(0) { n_recv = n_sent = 0; }
2629

2730
void begin() override;
2831
virtual void powerOff() { _radio->sleep(); }

0 commit comments

Comments
 (0)