From fe1925e589b6c7769942c6f07dcd0b53cb341540 Mon Sep 17 00:00:00 2001 From: Wessel Nieboer Date: Thu, 23 Jul 2026 11:27:34 +0200 Subject: [PATCH] Reduce probe interval on less busy channels --- src/helpers/radiolib/RadioLibWrappers.cpp | 19 +++++++++++++------ src/helpers/radiolib/RadioLibWrappers.h | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/helpers/radiolib/RadioLibWrappers.cpp b/src/helpers/radiolib/RadioLibWrappers.cpp index 62d836a5..0feb6875 100644 --- a/src/helpers/radiolib/RadioLibWrappers.cpp +++ b/src/helpers/radiolib/RadioLibWrappers.cpp @@ -14,10 +14,11 @@ // ambient CAD auto-calibration: probe CAD periodically while idle, and raise/lower detPeak // so ambient activity (sub-decode-threshold distant traffic, interference) stops tripping LBT #define CAD_PROBE_INTERVAL 4000 // millis between ambient CAD probes -#define CAD_PROBE_WINDOW 32 // probes per evaluation window -#define CAD_PROBE_RAISE_HITS 10 // >= ~30% ambient detect rate -> desensitize -#define CAD_PROBE_LOWER_HITS 3 // <= ~10% ambient detect rate -> re-sensitize -#define CAD_PEAK_OFFSET_MAX 10 +#define CAD_PROBE_INTERVAL_QUIET 16000 // slower probing while offset is 0 and channel is clean +#define CAD_PROBE_WINDOW 16 // probes per evaluation window +#define CAD_PROBE_RAISE_HITS 5 // >= ~30% ambient detect rate -> desensitize +#define CAD_PROBE_LOWER_HITS 2 // <= ~12% ambient detect rate -> re-sensitize +#define CAD_PEAK_OFFSET_MAX 6 static volatile uint8_t state = STATE_IDLE; @@ -49,6 +50,7 @@ void RadioLibWrapper::begin() { _cad_probe_count = _cad_probe_hits = 0; _cad_last_count = _cad_last_hits = 0; _last_cad_probe = 0; + _cad_probe_interval = CAD_PROBE_INTERVAL; // start average out some samples _num_floor_samples = 0; @@ -116,7 +118,7 @@ void RadioLibWrapper::loop() { } if (_cad_enabled && state == STATE_RX && getCADDetPeakBase() > 0 - && millis() - _last_cad_probe >= CAD_PROBE_INTERVAL) { + && millis() - _last_cad_probe >= _cad_probe_interval) { _last_cad_probe = millis(); if (!isReceivingPacket()) { int16_t result = performChannelScan(); @@ -130,6 +132,7 @@ void RadioLibWrapper::loop() { } else if (result == RADIOLIB_LORA_DETECTED || result == RADIOLIB_PREAMBLE_DETECTED) { _cad_probe_count++; _cad_probe_hits++; + _cad_probe_interval = CAD_PROBE_INTERVAL; // activity -> resume fast probing } // else: scan error, don't count the sample @@ -143,10 +146,14 @@ void RadioLibWrapper::loop() { _cad_probe_count = _cad_probe_hits = 0; } else if (_cad_probe_count >= CAD_PROBE_WINDOW) { if (_cad_probe_hits <= CAD_PROBE_LOWER_HITS && _cad_peak_offset > 0) { - _cad_peak_offset--; + // step down twice as fast when the window was completely clean + _cad_peak_offset -= (_cad_probe_hits == 0 && _cad_peak_offset >= 2) ? 2 : 1; MESH_DEBUG_PRINTLN("RadioLibWrapper: CAD ambient %d/%d, detPeak offset -> %d", (int)_cad_probe_hits, (int)_cad_probe_count, (int)_cad_peak_offset); } + if (_cad_probe_hits == 0 && _cad_peak_offset == 0) { + _cad_probe_interval = CAD_PROBE_INTERVAL_QUIET; // idle channel, probe less often + } _cad_last_hits = _cad_probe_hits; _cad_last_count = _cad_probe_count; _cad_probe_count = _cad_probe_hits = 0; } diff --git a/src/helpers/radiolib/RadioLibWrappers.h b/src/helpers/radiolib/RadioLibWrappers.h index e2363a82..7530d110 100644 --- a/src/helpers/radiolib/RadioLibWrappers.h +++ b/src/helpers/radiolib/RadioLibWrappers.h @@ -21,6 +21,7 @@ protected: uint8_t _cad_peak_offset; uint8_t _cad_probe_count, _cad_probe_hits; uint8_t _cad_last_count, _cad_last_hits; + uint16_t _cad_probe_interval; unsigned long _last_cad_probe; void idle();