mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
fix(power): use XOSC standby to keep TCXO on through CAD→RX; add burst window
- cadWake() now sets standbyXOSC=true so RadioLib's internal standby() calls keep the TCXO powered continuously through the CAD scan and into startReceive, eliminating the freq-drift window that dropped ~50% of long packets - PS_RX_TIMEOUT_MS 1500→3000 to cover 256 B packets at SF8/BW62.5/CR5 (~1925 ms) - 500 ms burst window after each successful receive: skip inter-scan sleep so back-to-back messages are caught without waiting out the 65 ms cadence Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -41,14 +41,15 @@ public:
|
|||||||
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
|
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
|
||||||
|
|
||||||
// Warm sleep between CAD scans: ~1.5 µA vs ~600 µA in standby-RC.
|
// Warm sleep between CAD scans: ~1.5 µA vs ~600 µA in standby-RC.
|
||||||
// cadWake() delays 5 ms so the TCXO fully re-stabilises before the next scan
|
// cadWake() sets standbyXOSC=true so every subsequent internal standby() call
|
||||||
// (previous attempt without the delay corrupted long packets via freq drift).
|
// keeps the TCXO powered — no gap between CAD and startReceive, no freq drift.
|
||||||
|
// The chip's programmed TCXO timeout (set by begin()) handles stabilisation.
|
||||||
void cadSleep() override {
|
void cadSleep() override {
|
||||||
((CustomSX1262 *)_radio)->sleep(true); // warm sleep — config retained
|
((CustomSX1262 *)_radio)->sleep(true); // warm sleep — config retained
|
||||||
}
|
}
|
||||||
void cadWake() override {
|
void cadWake() override {
|
||||||
_radio->standby();
|
((SX126x *)_radio)->standbyXOSC = true; // all subsequent standby() → XOSC
|
||||||
delayMicroseconds(5000); // TCXO stabilisation after warm sleep
|
_radio->standby(); // wake into standby-XOSC, TCXO on
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRxBoostedGainMode(bool en) override {
|
void setRxBoostedGainMode(bool en) override {
|
||||||
|
|||||||
@@ -24,8 +24,13 @@
|
|||||||
// → 65 ms gives 2 guaranteed windows with margin. Revisit if SF/BW change.
|
// → 65 ms gives 2 guaranteed windows with margin. Revisit if SF/BW change.
|
||||||
#define PS_CAD_INTERVAL_MS 65
|
#define PS_CAD_INTERVAL_MS 65
|
||||||
// If CAD detects activity but no packet actually lands, fall back to scanning
|
// If CAD detects activity but no packet actually lands, fall back to scanning
|
||||||
// instead of sitting in continuous RX forever.
|
// instead of sitting in continuous RX forever. Must exceed the longest possible
|
||||||
#define PS_RX_TIMEOUT_MS 1500
|
// packet air-time: 256 B at SF8/BW62.5/CR5 ≈ 1925 ms from preamble start, so
|
||||||
|
// 3000 ms gives ~1 s margin for a false-detect case.
|
||||||
|
#define PS_RX_TIMEOUT_MS 3000
|
||||||
|
// After a successful receive, skip inter-scan sleep for this long so back-to-back
|
||||||
|
// messages are caught without waiting out the 65 ms window each time.
|
||||||
|
#define PS_BURST_WINDOW_MS 500
|
||||||
|
|
||||||
static volatile uint8_t state = STATE_IDLE;
|
static volatile uint8_t state = STATE_IDLE;
|
||||||
|
|
||||||
@@ -160,6 +165,10 @@ void RadioLibWrapper::armRecv() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RadioLibWrapper::enterCadSleep() {
|
void RadioLibWrapper::enterCadSleep() {
|
||||||
|
if ((int32_t)(millis() - _ps_burst_until) < 0) {
|
||||||
|
armRecv(); // burst window: skip sleep, scan again immediately
|
||||||
|
return;
|
||||||
|
}
|
||||||
cadSleep(); // warm sleep (SX126x) or standby fallback between scans
|
cadSleep(); // warm sleep (SX126x) or standby fallback between scans
|
||||||
_ps_phase = PS_SLEEPING;
|
_ps_phase = PS_SLEEPING;
|
||||||
_ps_timer = millis() + PS_CAD_INTERVAL_MS;
|
_ps_timer = millis() + PS_CAD_INTERVAL_MS;
|
||||||
@@ -228,6 +237,7 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) {
|
|||||||
} else {
|
} else {
|
||||||
// Serial.print(" readData() -> "); Serial.println(len);
|
// Serial.print(" readData() -> "); Serial.println(len);
|
||||||
n_recv++;
|
n_recv++;
|
||||||
|
_ps_burst_until = millis() + PS_BURST_WINDOW_MS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = STATE_IDLE; // need another startReceive()
|
state = STATE_IDLE; // need another startReceive()
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ protected:
|
|||||||
bool _power_save = false;
|
bool _power_save = false;
|
||||||
uint8_t _ps_phase = 0; // PS_* (see .cpp): scanning / sleeping / rxing
|
uint8_t _ps_phase = 0; // PS_* (see .cpp): scanning / sleeping / rxing
|
||||||
uint32_t _ps_timer = 0; // next-scan time, or RX false-detect deadline
|
uint32_t _ps_timer = 0; // next-scan time, or RX false-detect deadline
|
||||||
|
uint32_t _ps_burst_until = 0; // scan continuously until this time after RX
|
||||||
void armRecv(); // arm RX honouring power-save (CAD) or continuous
|
void armRecv(); // arm RX honouring power-save (CAD) or continuous
|
||||||
void powerSaveLoop();
|
void powerSaveLoop();
|
||||||
void enterCadSleep();
|
void enterCadSleep();
|
||||||
|
|||||||
Reference in New Issue
Block a user