feat(repeater): dedicated Tools screen + optional radio profile

Move the repeater controls out of Settings > Radio (where the indented sub-item
labels collided with the value column on a 128px OLED) onto their own full-width
Tools > Repeater screen, holding the toggle, the five flood-politeness filters,
and live forwarding stats (Forwarded / Pool free / Queue) together. Toggle text
standardised to ON/OFF throughout.

Adds an optional dedicated radio profile (Network: Current/Custom): enabling the
repeater can switch the radio to a preset/manual freq/bw/sf/cr and disabling
restores the companion's params (revert-on-disable). A profile equal to the
companion = same network; a different one = drop onto a separate repeater
network. MyMesh::applyRepeaterRadio() is the single decision point (boot + every
toggle/edit), gated by repeaterProfileValid(); the profile re-applies after a
reboot left with the repeater on. Persisted behind schema 0xC0DE0010, cleared to
off when an upgraded file yields an invalid config.

Docs updated (settings_screen, tools_screen, README, FEATURES).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-06-19 09:20:16 +02:00
co-authored by Claude Sonnet 4.6
parent 22ad46257f
commit 0da487729d
13 changed files with 449 additions and 112 deletions
+13
View File
@@ -228,6 +228,19 @@ public:
DataStore* getDataStore() const { return _store; }
void applyApc(); // (re)initialise Adaptive Power Control from prefs
// True when the optional repeater radio profile is a valid LoRa config.
bool repeaterProfileValid() const {
return _prefs.repeater_freq >= 100.0f && _prefs.repeater_freq <= 960.0f
&& _prefs.repeater_sf >= 5 && _prefs.repeater_sf <= 12
&& _prefs.repeater_cr >= 5 && _prefs.repeater_cr <= 8
&& _prefs.repeater_bw >= 7.0f && _prefs.repeater_bw <= 510.0f;
}
// Load the radio with the correct params for the current mode: the repeater
// profile when relaying with a valid dedicated profile, otherwise the
// companion's own params. Single source of truth, used at boot and whenever
// the repeater toggle / network / profile changes.
void applyRepeaterRadio();
bool isAckPending(uint32_t expected_ack) const {
for (int i = 0; i < EXPECTED_ACK_TABLE_SIZE; i++)
if (expected_ack_table[i].ack == expected_ack) return true;