The `set freq <mhz>` handler saved the new frequency to prefs, then
reverted _prefs->freq to the old value in RAM to keep the running radio
on the old params until reboot. But _prefs is the source of truth for
every savePrefs(), so:
- `get freq` / `get radio` reported the old value right after a
successful `set freq`;
- the next savePrefs() from any other `set` command (e.g. `set rxduty`)
rewrote the old freq back over the persisted new one, losing the
change on reboot.
Mirror the `set radio` handler: keep _prefs->freq = f and freeze the
running radio on the old freq via freezeRadioParams() instead of
reverting the pref. Semantics unchanged (applies at reboot; the live
radio stays on the old freq until then); _prefs now correctly retains
the new value so `get` reflects it and later saves can't clobber it.
freezeRadioParams() is implemented for the Repeater and Room Server
roles; the CommonCLI base default is a no-op, so other roles are
unaffected.
Verified on Seeed XIAO MG24 + Wio-SX1262 (Repeater role, built from
release v20260704.220543 + this patch): `set freq 903.0` is retained by
`get freq` immediately and survives an intervening `set rxduty` + reboot.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a board-aware battery SOC system replacing the two independent
linear approximations that existed in the UI helpers.
New helpers/battery_curve.{h,c}: a 21-point (5% step) OCV lookup table
with integer linear interpolation. The default generic LiPo curve is a
weak symbol — any board can override it by dropping a battery_curve.c
into its board directory. CMakeLists.txt selects the board-specific file
when present, falling back to the generic.
Board.h gains getBattPercent() (default 0); ZephyrBoard implements it
via battery_curve_lookup().
Board-specific curves added for boards with measured cell data:
t1000_e, rak_wismesh_tag, thinknode_m6, sensecap_solar, wio_tracker_l1.
ADC multiplier corrections applied across all nRF52840 boards:
- Boards using a correctly-derived 3600×ratio formula get +0.5% to
compensate for nRF SAADC gain error (7200→7236, 6300→6332, etc.)
- rak_wismesh_tag, rak3401_1watt, gat562_30s had multipliers copied
from Arduino's 3.0V AREF formula; corrected to 3600×1.73×1.005=6259
- xiao_nrf52840 (10911) left unchanged — empirically calibrated value
above the theoretical, assumed already correct for that hardware
get adc.multiplier now reports current mV reading and the board's
curve 100% target, making field calibration self-guiding.
- track real RTC sync source on the joystick Time screen
- gate joystick-only UI helpers behind stub headers so non-joystick builds skip the extra code without #ifdef at every call site.