mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
Add exponential backoff for channel busy detection
Replace fixed random(8000-22000ms) backoff with exponential backoff: - 1st busy: 3-6s - 2nd busy: 6-12s - 3rd+ busy: 12-20s (capped) - Reset counter on channel free Results (48-byte simultaneous DM, JP SF12/BW125/CR4-5): - 3/3 success, delivered within 0:23-0:45 - Previous fixed backoff: 1:03-3:55
This commit is contained in:
parent
c5bacd7de9
commit
2d11d9fedb
2 changed files with 20 additions and 14 deletions
|
|
@ -34,6 +34,7 @@ void RadioLibWrapper::begin() {
|
|||
|
||||
_noise_floor = 0;
|
||||
_threshold = 0;
|
||||
_busy_count = 0; // initialize exponential backoff counter
|
||||
|
||||
// start average out some samples
|
||||
_num_floor_samples = 0;
|
||||
|
|
@ -183,39 +184,43 @@ bool RadioLibWrapper::isChannelActive() {
|
|||
if (_threshold == 0) return false; // interference check is disabled
|
||||
|
||||
#ifdef JP_STRICT
|
||||
// ARIB STD-T108 compliant LBT: continuous RSSI sensing for >= 5ms
|
||||
// Energy-based sensing required; LoRa CAD alone is not sufficient
|
||||
// 5ms continuous RSSI sensing
|
||||
uint32_t sense_start = millis();
|
||||
uint32_t sense_duration_ms = 5;
|
||||
while (millis() - sense_start < sense_duration_ms) {
|
||||
while (millis() - sense_start < 5) {
|
||||
if (getCurrentRSSI() > -80.0f) {
|
||||
// Channel busy detected during 5ms sensing window
|
||||
uint32_t backoff_until = millis() + random(8000, 22000);
|
||||
// RSSI busy: backoff and return without CAD
|
||||
_busy_count++;
|
||||
uint32_t base_ms = 3000;
|
||||
uint32_t max_backoff = min(base_ms * (1u << _busy_count), (uint32_t)20000);
|
||||
uint32_t backoff_until = millis() + random(max_backoff / 2, max_backoff);
|
||||
while (millis() < backoff_until) {
|
||||
vTaskDelay(1); // yield CPU to FreeRTOS tasks including BLE
|
||||
vTaskDelay(1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
vTaskDelay(1); // yield CPU between RSSI samples
|
||||
vTaskDelay(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// CAD
|
||||
int16_t result = performChannelScan();
|
||||
// scanChannel() triggers DIO interrupt (CAD done) which sets STATE_INT_READY
|
||||
// via setFlag() ISR. Clear it before restarting RX so recvRaw() doesn't
|
||||
// try to read a non-existent packet and count a spurious recv error.
|
||||
state = STATE_IDLE;
|
||||
startRecv();
|
||||
|
||||
if (result != RADIOLIB_CHANNEL_FREE) {
|
||||
// Random backoff to desynchronize retries between competing nodes
|
||||
uint32_t backoff_until = millis() + random(8000, 22000);
|
||||
// CAD busy: backoff
|
||||
_busy_count++;
|
||||
uint32_t base_ms = 3000;
|
||||
uint32_t max_backoff = min(base_ms * (1u << _busy_count), (uint32_t)20000);
|
||||
uint32_t backoff_until = millis() + random(max_backoff / 2, max_backoff);
|
||||
while (millis() < backoff_until) {
|
||||
vTaskDelay(1); // yield CPU to FreeRTOS tasks including BLE
|
||||
vTaskDelay(1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_busy_count = 0;
|
||||
|
||||
// Small jitter even when channel is free to prevent simultaneous TX
|
||||
// from two nodes that both detect a free channel at the same time
|
||||
uint32_t jitter_until = millis() + random(0, 500);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ protected:
|
|||
mesh::MainBoard* _board;
|
||||
uint32_t n_recv, n_sent, n_recv_errors, _tx_start_ms;
|
||||
int16_t _noise_floor, _threshold;
|
||||
uint8_t _busy_count; // consecutive busy detections for exponential backoff
|
||||
uint16_t _num_floor_samples;
|
||||
int32_t _floor_sample_sum;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue