feat(repeater): suppress Adaptive Power Control while relaying

A repeater wants full, consistent TX power for relay reach, and APC's feedback
(own ACKs / own flood echoes) never fires on forwarded traffic — so leaving APC
on would relay at whatever reduced power it last trimmed to, or sit inert on a
dedicated repeater network. Force it off whenever client_repeat is on, mirroring
the power-save lock:

- apcActive() = tx_apc && !client_repeat gates every APC control site
  (sample/failure/track).
- applyApc() pins power to the tx_power_dbm ceiling; called at boot, on the
  on-device repeater toggle, and on the app's CMD_SET_RADIO_PARAMS.
- Settings "Auto pwr" shows "--" and blocks the toggle while repeating; the
  user's pref is preserved and restored when the repeater is switched off.

Also refreshes the FEATURES repeater entry (Hold-Enter reset, Errors row, schema
0x10, the radio-setting locks and status indicator).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-06-19 14:45:34 +02:00
co-authored by Claude Sonnet 4.6
parent 84a76adcf1
commit 885662beae
7 changed files with 36 additions and 16 deletions
@@ -260,6 +260,7 @@ public:
p->client_repeat ^= 1;
the_mesh.applyRepeaterRadio(); // switch to profile on enable / restore companion on disable
_task->applyPowerSave(); // duty-cycle RX is forced off while repeating
_task->applyApc(); // pin TX power to the ceiling while repeating (APC suppressed)
buildItems(p);
_dirty = true;
return true;
@@ -613,7 +613,9 @@ class SettingsScreen : public UIScreen {
} else if (item == TX_APC) {
display.print("Auto pwr");
display.setCursor(valCol(display), y);
display.print((p && p->tx_apc) ? "ON" : "OFF");
// Suppressed (and locked) while repeating — a repeater holds full TX power.
if (p && p->client_repeat) display.print("--");
else display.print((p && p->tx_apc) ? "ON" : "OFF");
#if AUTO_OFF_MILLIS > 0
} else if (item == AUTO_OFF) {
display.print("AutoOff");
@@ -1007,6 +1009,7 @@ public:
return true;
}
if (_selected == TX_APC && p && (left || right || enter)) {
if (p->client_repeat) { _task->showAlert("Off while repeating", 900); return true; }
p->tx_apc ^= 1;
_task->applyApc();
_dirty = true;