Reject standby RSSI during noise calibration

This commit is contained in:
mikecarper committed 2026-09-10 14:17:51 -07:00
1 parent 2b66e8284c
commit 0ed8167d02
3 files changed
+59 -4

No files matched your search

+6
View File
@@ -34,6 +34,12 @@ without publishing. Longer collection spends more time in continuous RX when
RXPS is enabled. A quiet minimum is about 3.2 seconds; real completion time
also depends on packet activity and main-loop scheduling.
On radios with a mode probe, each eligible RSSI sample first checks that the
chip has not silently left RX. Confirmed standby/non-RX discards the partial
block without changing the published floor. Rejected attempts are also spaced
50 ms apart. BUSY and packet ownership block sampling; families without a mode
probe retain their existing RSSI path.
CAD has a bounded wait, stops RX duty cycling before scanning, and re-arms the
configured receive mode on success, busy detection, or error. A completed or
currently receiving packet owns the radio and blocks CAD. A packet interrupt
+14 -2
View File
@@ -528,10 +528,22 @@ void RadioLibWrapper::loop() {
if (!_rx_ps_armed
&& _floor_estimator.ready(static_cast<uint32_t>(now))
&& !(_nf_sample_from != 0 && (long)(now - _nf_sample_from) < 0)
&& !isReceivingPacket()) {
&& !isChipBusy() && !isPacketPendingOrReceiving()) {
// Silent RX loss can leave software in STATE_RX while standby RSSI is
// meaningless. Reject that observation before it can lower the floor.
// Space rejected attempts too; an empty block must not hammer SPI.
_nf_sample_from = now + NoiseFloorEstimator::SAMPLE_INTERVAL_MS;
if (readReceiveMode() == 0) {
_floor_estimator.reset(true);
return;
}
// Admission is independent of the old floor, allowing upward recovery.
// A mode probe is unavailable on some radio families; keep their existing
// RSSI path. Preserve a packet IRQ arriving during the status transaction.
// The estimator enforces 50 ms spacing and rejects invalid radio readings.
_floor_estimator.add(getCurrentRSSI(), static_cast<uint32_t>(now));
if (!isPacketPendingOrReceiving()) {
_floor_estimator.add(getCurrentRSSI(), static_cast<uint32_t>(now));
}
}
}
}
+39 -2
View File
@@ -71,13 +71,18 @@ struct RadioLibWrapper {
int32_t _noise_floor_centi_dbm = -10500;
int arm_result = 0, chip_mode = 1;
float rssi = -100;
unsigned arms = 0, stops = 0, soft = 0, hard = 0, reads = 0;
unsigned arms = 0, stops = 0, soft = 0, hard = 0, reads = 0, mode_reads = 0;
bool inject_mode_irq = false;
NoiseFloorEstimator _floor_estimator;
RadioLibWrapper() { state = STATE_RX; now_ms = 100; }
bool isChipBusy() { return busy; }
bool isReceivingPacket() { return packet; }
float getCurrentRSSI() { ++reads; return rssi; }
int8_t readReceiveMode() { return chip_mode; }
int8_t readReceiveMode() {
++mode_reads;
if (inject_mode_irq) state |= STATE_INT_READY;
return chip_mode;
}
bool recoverRadio(bool use_hard) { use_hard ? ++hard : ++soft; return true; }
void rxPsWatchdogCheck() {}
unsigned long getEstAirtimeFor(int) { return 10; }
@@ -188,6 +193,38 @@ int main() {
}
assert(w._noise_floor_centi_dbm == -10125);
}
// Hardware standby RSSI is not background noise, even if software says RX.
{
RadioLibWrapper w;
w._floor_estimator.add(-100, 0);
w.chip_mode = 0;
w.rssi = -127;
for (; now_ms < 4100; ++now_ms) w.loop();
assert(w._noise_floor_centi_dbm == -10500);
assert(w._floor_estimator.count() == 0 && w.reads == 0);
assert(w.mode_reads == 80); // rejected samples are also limited to 20 Hz
w.chip_mode = 1;
w.rssi = -100;
for (; now_ms < 8100; ++now_ms) w.loop();
assert(w.reads == 64 && !w._nf_refresh_requested);
assert(w._noise_floor_centi_dbm == -10125);
}
// A BUSY chip or a packet arriving during the mode probe must block RSSI I/O.
for (bool busy : {false, true}) {
RadioLibWrapper w;
w.busy = busy;
w.inject_mode_irq = !busy;
w.loop();
assert(w.reads == 0);
assert(w.mode_reads == (busy ? 0U : 1U));
}
// Families without a mode probe retain the existing RSSI sampling path.
{
RadioLibWrapper w;
w.chip_mode = -1;
w.loop();
assert(w.reads == 1);
}
// Busy continuous RX times out without changing the published floor.
{
RadioLibWrapper w;