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;
|
_noise_floor = 0;
|
||||||
_threshold = 0;
|
_threshold = 0;
|
||||||
|
_busy_count = 0; // initialize exponential backoff counter
|
||||||
|
|
||||||
// start average out some samples
|
// start average out some samples
|
||||||
_num_floor_samples = 0;
|
_num_floor_samples = 0;
|
||||||
|
|
@ -183,39 +184,43 @@ bool RadioLibWrapper::isChannelActive() {
|
||||||
if (_threshold == 0) return false; // interference check is disabled
|
if (_threshold == 0) return false; // interference check is disabled
|
||||||
|
|
||||||
#ifdef JP_STRICT
|
#ifdef JP_STRICT
|
||||||
// ARIB STD-T108 compliant LBT: continuous RSSI sensing for >= 5ms
|
// 5ms continuous RSSI sensing
|
||||||
// Energy-based sensing required; LoRa CAD alone is not sufficient
|
|
||||||
uint32_t sense_start = millis();
|
uint32_t sense_start = millis();
|
||||||
uint32_t sense_duration_ms = 5;
|
while (millis() - sense_start < 5) {
|
||||||
while (millis() - sense_start < sense_duration_ms) {
|
|
||||||
if (getCurrentRSSI() > -80.0f) {
|
if (getCurrentRSSI() > -80.0f) {
|
||||||
// Channel busy detected during 5ms sensing window
|
// RSSI busy: backoff and return without CAD
|
||||||
uint32_t backoff_until = millis() + random(8000, 22000);
|
_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) {
|
while (millis() < backoff_until) {
|
||||||
vTaskDelay(1); // yield CPU to FreeRTOS tasks including BLE
|
vTaskDelay(1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
vTaskDelay(1); // yield CPU between RSSI samples
|
vTaskDelay(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// CAD
|
||||||
int16_t result = performChannelScan();
|
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;
|
state = STATE_IDLE;
|
||||||
startRecv();
|
startRecv();
|
||||||
|
|
||||||
if (result != RADIOLIB_CHANNEL_FREE) {
|
if (result != RADIOLIB_CHANNEL_FREE) {
|
||||||
// Random backoff to desynchronize retries between competing nodes
|
// CAD busy: backoff
|
||||||
uint32_t backoff_until = millis() + random(8000, 22000);
|
_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) {
|
while (millis() < backoff_until) {
|
||||||
vTaskDelay(1); // yield CPU to FreeRTOS tasks including BLE
|
vTaskDelay(1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_busy_count = 0;
|
||||||
|
|
||||||
// Small jitter even when channel is free to prevent simultaneous TX
|
// Small jitter even when channel is free to prevent simultaneous TX
|
||||||
// from two nodes that both detect a free channel at the same time
|
// from two nodes that both detect a free channel at the same time
|
||||||
uint32_t jitter_until = millis() + random(0, 500);
|
uint32_t jitter_until = millis() + random(0, 500);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ protected:
|
||||||
mesh::MainBoard* _board;
|
mesh::MainBoard* _board;
|
||||||
uint32_t n_recv, n_sent, n_recv_errors, _tx_start_ms;
|
uint32_t n_recv, n_sent, n_recv_errors, _tx_start_ms;
|
||||||
int16_t _noise_floor, _threshold;
|
int16_t _noise_floor, _threshold;
|
||||||
|
uint8_t _busy_count; // consecutive busy detections for exponential backoff
|
||||||
uint16_t _num_floor_samples;
|
uint16_t _num_floor_samples;
|
||||||
int32_t _floor_sample_sum;
|
int32_t _floor_sample_sum;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue