diff --git a/.github/workflows/run-unit-tests.yml b/.github/workflows/run-unit-tests.yml index 4543c9dea..a6810b340 100644 --- a/.github/workflows/run-unit-tests.yml +++ b/.github/workflows/run-unit-tests.yml @@ -579,6 +579,7 @@ jobs: python3 -B test/test_morse_hil_timing.py -v python3 -B test/test_morse_hil_production.py -v python3 -B test/test_morse_rx_squelch.py -v + python3 -B test/test_morse_rx_adaptive_quiet.py -v python3 -B test/test_morse_hil_squelch.py -v python3 -B test/test_morse_cli.py -v python3 -B test/test_morse_auth.py -v diff --git a/src/helpers/MorseRx.h b/src/helpers/MorseRx.h index d89a23c53..6a5ecb724 100644 --- a/src/helpers/MorseRx.h +++ b/src/helpers/MorseRx.h @@ -178,7 +178,7 @@ public: _last_sample_at = now; _max_sample_gap_ms = 0; _last_rssi = _minimum_rssi = _maximum_rssi = NAN; - _have_noise = _candidate_valid = _keyed = _floor_settled = false; + _have_noise = _candidate = _candidate_valid = _keyed = _floor_settled = false; _active = true; #if defined(MESH_MORSE_HIL) && MESH_MORSE_HIL if (_trace) _trace->clear(); @@ -255,7 +255,7 @@ public: } void sample(float rssi_dbm, uint32_t now) { - if (!service(now) || !isfinite(rssi_dbm) || rssi_dbm < -180.0f || rssi_dbm > 20.0f) return; + if (!service(now) || !(rssi_dbm >= -180.0f && rssi_dbm <= 20.0f)) return; _last_rssi = rssi_dbm; const uint32_t sample_gap = static_cast(now - _last_sample_at); const float filter_gap = sample_gap > 10U ? 10U : sample_gap; diff --git a/test/fixtures/morse_rx_adaptive_quiet.cpp b/test/fixtures/morse_rx_adaptive_quiet.cpp index e41e2793e..5a00df300 100644 --- a/test/fixtures/morse_rx_adaptive_quiet.cpp +++ b/test/fixtures/morse_rx_adaptive_quiet.cpp @@ -147,10 +147,34 @@ static void startup_outlier_spikes_and_late_arming_changes() { } } +static void invalid_power_never_enters_the_model() { + Receiver r; + r.level(-126, 520); + mesh::MorseRxDiagnostics before, after; + r.rx.diagnostics(before); + for (float invalid : {NAN, INFINITY, -INFINITY, -180.01f, 20.01f}) + r.level(invalid, 2); + r.rx.diagnostics(after); + assert(after.samples == before.samples && after.last_dbm == before.last_dbm); + assert(after.minimum_dbm == before.minimum_dbm && after.maximum_dbm == before.maximum_dbm); + assert(after.noise_dbm == before.noise_dbm && !r.rx.keyed()); + r.level(-119, 48); + r.level(-126, 400); + r.rx.stop(r.now); + assert(std::strcmp(r.rx.text(), "E ") == 0); + + Receiver bounds; + bounds.level(-180, 2); + bounds.level(20, 2); + bounds.rx.diagnostics(after); + assert(after.samples == 2 && after.minimum_dbm == -180 && after.maximum_dbm == 20); +} + int main() { learned_noise_cannot_prekey_a_real_dot(); recurrent_learned_excursions_stay_quiet_until_expiry(); weak_cw_is_relative_to_the_observed_environment(); startup_outlier_spikes_and_late_arming_changes(); + invalid_power_never_enters_the_model(); std::puts("actual adaptive quiet checks passed"); }