Unblock LR2021 retunes and add saved crystal calibration

Repeated preamble/header activity can keep a requested primary or TempRadio
change busy indefinitely. Bound unfinished-RX admission for accepted LR2021
changes while preserving completed packets, TX, BUSY and exclusive owners.
Ordinary scans and CAD keep their existing admission rules. Expose the failing
stage and native status through get radio.apply.

Add saved radio.xtrim capacitor calibration and measured radio.freqerror in
signed Hz from the last valid LoRa packet. Preserve native trim by default,
restore explicit calibration after resets/Morse, verify saves before applying,
wait two seconds for the acknowledgement, and roll back failed changes.

Calibration motivation and prior upstream work:
https://github.com/meshcore-dev/MeshCore/issues/3365
https://github.com/recrof/MeshCore/tree/lr2021-trim
Packet-status format follows Semtech's LR20xx driver and RadioLib staging.

Tests execute production activity/admission and transaction paths with noisy
RX, completion races, protected owners, failed setters, RX restart and save
rollback. Physical W12 retuning and RF calibration still require confirmation.
This commit is contained in:
mikecarper committed 2026-10-26 15:55:36 -07:00
1 parent b00d346df7
commit 8a8c80ee6a
32 files changed
+1913 -34

No files matched your search

+8
View File
@@ -1427,8 +1427,10 @@ bool SensorMesh::applySavedRadioParams() {
#endif
// A busy radio can accept the tuple before deferring TX power. Recovery
// is complete only after both saved settings have been accepted.
#if !defined(USE_LR2021)
if (radio_driver.supportsRxBoostedGainMode()
&& !radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain)) return false;
#endif
uint32_t timings[2] = {_prefs.rx_ps_rx_us, _prefs.rx_ps_sleep_us};
const uint32_t* applied_timings = _prefs.rx_powersaving_enabled
&& radio_driver.supportsRxPowerSaving() ? timings : NULL;
@@ -1438,6 +1440,12 @@ bool SensorMesh::applySavedRadioParams() {
return false;
}
active_cr = _prefs.cr;
#if defined(USE_LR2021)
// Primary admission owns the bounded unfinished-RX handoff. Applying gain
// first could keep that accepted command from ever reaching admission.
if (radio_driver.supportsRxBoostedGainMode()
&& !radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain)) return false;
#endif
#if defined(USE_LR2021)
if (side_detectors_allowed
&& !radio_driver.configSideDetectors(_prefs.extra_sf, extra_sf_count, _prefs.bw)) return false;