fix: move FEAT_RX_POWERSAVE to Features.h; no extra [LOC] on "Stop after" change

- FEAT_RX_POWERSAVE lived in MyMesh.h, but SettingsScreen.h only pulls
  Features.h -- it saw the flag only via include order, and an undefined
  macro in `#if` silently reads as 0, which would split the build the day
  it's flipped to 1. Now defined in Features.h (the home of FEAT_* flags),
  which MyMesh.h includes; comment/doc pointers updated.
- Changing Live Share's "Stop after" restarted the whole session, forcing
  an immediate re-announce [LOC] although the position hadn't changed. It
  now restarts only the duration clock (restartLocShareClock()).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-09-24 15:50:37 +02:00
co-authored by Claude Opus 5.5
parent 299fcf2c13
commit 1620df6c10
10 changed files with 32 additions and 24 deletions
+17
View File
@@ -29,6 +29,23 @@
#define FEAT_FULL_REFRESH_SETTING 0
#endif
// Hardware RX duty-cycle ("Pwr save") is disabled: the SX126x's duty-cycle
// preamble detection needs the *actual transmitted* preamble to exactly match
// what we're configured to expect (confirmed hardware behaviour, see SX1262
// datasheet 6.1.3 and https://github.com/jgromes/RadioLib/issues/1597) --
// something we can't guarantee across a mesh with mixed firmware. A mismatch
// doesn't cost a little sensitivity, it silently drops every packet from that
// sender regardless of signal strength (2026-09-22 field report: near-total
// reception loss, unaffected by antenna). The real duty-cycle implementation
// (RadioLibWrapper::armRecv()/CustomSX1262Wrapper::startPowerSaveRecv()) is
// left in place for if a network-wide compatibility mechanism ever lands --
// flipping this back to 1 requires solving that first, not just re-adding the
// Settings toggle. See docs/development/roadmap.md for the full writeup.
// Lives here (not MyMesh.h) so every `#if FEAT_RX_POWERSAVE` user sees the
// same definition: an undefined macro in `#if` silently reads as 0, which
// would split the build the day this is flipped to 1.
#define FEAT_RX_POWERSAVE 0
namespace Features {
#if defined(EINK_DISPLAY_MODEL)
+3 -3
View File
@@ -288,7 +288,7 @@ bool MyMesh::getCADEnabled() const {
// (unlike simple_repeater's CommonCLI `cad` command) — it's wired and
// persisted for a future manual override, but always 0 today.
// rx_powersave is never actually applied to the radio while FEAT_RX_POWERSAVE
// is 0 (see MyMesh.h) -- don't let a stale persisted byte from before that
// is 0 (see Features.h) -- don't let a stale persisted byte from before that
// still auto-enable CAD here for a duty-cycle mode that isn't running.
#if FEAT_RX_POWERSAVE
return _prefs.cad_enabled || (_prefs.rx_powersave && !_prefs.client_repeat);
@@ -2001,7 +2001,7 @@ void MyMesh::begin(bool has_display) {
#if FEAT_RX_POWERSAVE
radio_driver.setPowerSaving(_prefs.rx_powersave && !_prefs.client_repeat); // duty-cycle RX off while repeating (must hear all traffic)
#else
radio_driver.setPowerSaving(false); // see MyMesh.h FEAT_RX_POWERSAVE -- ignore any stale persisted rx_powersave byte
radio_driver.setPowerSaving(false); // see Features.h FEAT_RX_POWERSAVE -- ignore any stale persisted rx_powersave byte
#endif
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
@@ -2496,7 +2496,7 @@ void MyMesh::handleCmdFrame(size_t len) {
#if FEAT_RX_POWERSAVE
radio_driver.setPowerSaving(_prefs.rx_powersave && !_prefs.client_repeat);
#else
radio_driver.setPowerSaving(false); // see MyMesh.h FEAT_RX_POWERSAVE -- ignore any stale persisted rx_powersave byte
radio_driver.setPowerSaving(false); // see Features.h FEAT_RX_POWERSAVE -- ignore any stale persisted rx_powersave byte
#endif
applyApc(); // pins power to the ceiling; apcActive() keeps it there while repeating
MESH_DEBUG_PRINTLN("OK: CMD_SET_RADIO_PARAMS: f=%d, bw=%d, sf=%d, cr=%d", freq, bw, (uint32_t)sf,
+1 -14
View File
@@ -4,6 +4,7 @@
#include <Mesh.h>
#include "AbstractUITask.h"
#include <helpers/ui/DisplayDriver.h>
#include "Features.h" // FEAT_RX_POWERSAVE, used by MyMesh.cpp
// Forward declaration for UITask
class UITask;
@@ -11,20 +12,6 @@ class UITask;
/*------------ Frame Protocol --------------*/
#define FIRMWARE_VER_CODE 13
// Hardware RX duty-cycle ("Pwr save") is disabled: the SX126x's duty-cycle
// preamble detection needs the *actual transmitted* preamble to exactly match
// what we're configured to expect (confirmed hardware behaviour, see SX1262
// datasheet 6.1.3 and https://github.com/jgromes/RadioLib/issues/1597) --
// something we can't guarantee across a mesh with mixed firmware. A mismatch
// doesn't cost a little sensitivity, it silently drops every packet from that
// sender regardless of signal strength (2026-09-22 field report: near-total
// reception loss, unaffected by antenna). The real duty-cycle implementation
// (RadioLibWrapper::armRecv()/CustomSX1262Wrapper::startPowerSaveRecv()) is
// left in place for if a network-wide compatibility mechanism ever lands --
// flipping this back to 1 requires solving that first, not just re-adding the
// Settings toggle. See docs/development/roadmap.md for the full writeup.
#define FEAT_RX_POWERSAVE 0
// Fallback only -- every real build (local or CI) goes through build.sh, which
// always injects its own FIRMWARE_BUILD_DATE (today's date at build time).
// __DATE__ is the compiler's own "Mmm dd yyyy" build-date macro, so a
@@ -133,7 +133,7 @@ public:
_dirty = true; break;
case K_DURATION:
_prefs->loc_share_duration_idx = (uint8_t)((_prefs->loc_share_duration_idx + (dir >= 0 ? 1 : NodePrefs::LOC_SHARE_DURATION_COUNT - 1)) % NodePrefs::LOC_SHARE_DURATION_COUNT);
_task->restartLocShareSession(); // a new length starts the session over
_task->restartLocShareClock(); // a new length starts the clock over (no extra [LOC] send)
_dirty = true; break;
case K_TARGET:
if (enter) { _task->pickLocShareTarget(); return; } // full chooser
+1 -1
View File
@@ -3856,7 +3856,7 @@ void UITask::applyPowerSave() {
// kept and restored when the repeater is switched off.
radio_driver.setPowerSaving(_node_prefs->rx_powersave && !_node_prefs->client_repeat);
#else
radio_driver.setPowerSaving(false); // see MyMesh.h FEAT_RX_POWERSAVE -- ignore any stale persisted rx_powersave byte
radio_driver.setPowerSaving(false); // see Features.h FEAT_RX_POWERSAVE -- ignore any stale persisted rx_powersave byte
#endif
}
+4
View File
@@ -340,6 +340,10 @@ public:
void gotoLiveShareScreen();
// Start the auto-share session clock afresh (next engine tick treats it as a new enable).
void restartLocShareSession() { _loc_share_was_enabled = false; }
// Restart only the session's duration clock -- unlike restartLocShareSession(),
// no re-announce. For a changed "Stop after" length, where position hasn't
// changed. No-op before the engine has started a session (it sets the clock then).
void restartLocShareClock() { if (_loc_share_was_enabled) _loc_share_session_ms = millis(); }
void gotoLocatorScreen();
// Re-arm the locator state machine so the next evaluation initialises
// silently (called by the Locator tool after the target/radius changes,