Reject standby RSSI during noise calibration
This commit is contained in:
1 parent
2b66e8284c
commit
0ed8167d02
3 files changed
+59
-4
No files matched your search
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user