Browse Source

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.
pull/2218/head
jirogit 2 weeks ago
committed by me
parent
commit
25f65735df
  1. 18
      src/helpers/radiolib/RadioLibWrappers.cpp
  2. 5
      src/helpers/radiolib/RadioLibWrappers.h

18
src/helpers/radiolib/RadioLibWrappers.cpp

@ -194,6 +194,18 @@ int16_t RadioLibWrapper::performChannelScan() {
bool RadioLibWrapper::isChannelActive() { bool RadioLibWrapper::isChannelActive() {
if (isAS923_1_JP()) { if (isAS923_1_JP()) {
// Non-blocking backoff: if a prior busy detection armed a backoff wait,
// report busy and let Dispatcher::checkSend() re-poll on the next loop()
// pass instead of spin-waiting here (which used to block the Dispatcher
// loop for up to 16s).
if (_lbt_backoff_active) {
if ((int32_t)(millis() - _lbt_deadline) < 0) {
return true; // still waiting; re-checked next call
}
_lbt_backoff_active = false;
return isChannelActive(); // backoff elapsed -- re-sense (bounded, single-level recursion)
}
// ARIB STD-T108: 5ms continuous RSSI sensing, -80dBm absolute threshold // ARIB STD-T108: 5ms continuous RSSI sensing, -80dBm absolute threshold
uint32_t sense_start = millis(); uint32_t sense_start = millis();
while (millis() - sense_start < 5) { while (millis() - sense_start < 5) {
@ -201,10 +213,8 @@ bool RadioLibWrapper::isChannelActive() {
_busy_count++; _busy_count++;
uint32_t base_ms = 2000; uint32_t base_ms = 2000;
uint32_t max_backoff = min(base_ms * (1u << _busy_count), (uint32_t)16000); uint32_t max_backoff = min(base_ms * (1u << _busy_count), (uint32_t)16000);
uint32_t backoff_until = millis() + random(max_backoff / 2, max_backoff); _lbt_deadline = millis() + random(max_backoff / 2, max_backoff);
while (millis() < backoff_until) { _lbt_backoff_active = true;
YIELD_TASK();
}
return true; return true;
} }
YIELD_TASK(); YIELD_TASK();

5
src/helpers/radiolib/RadioLibWrappers.h

@ -20,6 +20,9 @@ protected:
int32_t _floor_sample_sum; int32_t _floor_sample_sum;
uint8_t _preamble_sf; uint8_t _preamble_sf;
bool _lbt_backoff_active; // non-blocking wait after RSSI busy detection (up to 16s)
uint32_t _lbt_deadline;
void idle(); void idle();
void startRecv(); void startRecv();
float packetScoreInt(float snr, int sf, int packet_len); float packetScoreInt(float snr, int sf, int packet_len);
@ -27,7 +30,7 @@ protected:
virtual void doResetAGC(); virtual void doResetAGC();
public: public:
RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board), _busy_count(0), _preamble_sf(0) { n_recv = n_sent = 0; } 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; }
void begin() override; void begin() override;
virtual void powerOff() { _radio->sleep(); } virtual void powerOff() { _radio->sleep(); }

Loading…
Cancel
Save