Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/gps/GPS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,10 @@ bool GPS::setup()
}

notifyDeepSleepObserver.observe(&notifyDeepSleep);
#ifdef ARCH_ESP32
notifyLightSleepObserver.observe(&notifyLightSleep);
notifyLightSleepEndObserver.observe(&notifyLightSleepEnd);
#endif

return true;
}
Expand All @@ -827,6 +831,10 @@ GPS::~GPS()
{
// we really should unregister our sleep observer
notifyDeepSleepObserver.unobserve(&notifyDeepSleep);
#ifdef ARCH_ESP32
notifyLightSleepObserver.unobserve(&notifyLightSleep);
notifyLightSleepEndObserver.unobserve(&notifyLightSleepEnd);
#endif
}

// Put the GPS hardware into a specified state
Expand Down Expand Up @@ -1246,6 +1254,29 @@ int GPS::prepareDeepSleep(void *unused)
return 0;
}

#ifdef ARCH_ESP32
// Light-sleep is short and the GPS state machine survives across it; soft-sleep
// the receiver instead of disabling so we don't pay re-init / re-acquire cost
// on every cycle. Without this the GPS keeps drawing ~25 mA the whole time the
// MCU is asleep — the dominant drain on most non-router devices.
int GPS::prepareLightSleep(void *unused)
{
preLightSleepState = powerState;
if (powerState == GPS_ACTIVE) {
setPowerState(GPS_SOFTSLEEP);
}
return 0;
}

int GPS::endLightSleep(esp_sleep_wakeup_cause_t cause)
{
if (preLightSleepState == GPS_ACTIVE && powerState != GPS_ACTIVE) {
setPowerState(GPS_ACTIVE);
}
return 0;
}
#endif

static const char *PROBE_MESSAGE = "Trying %s (%s)...";
static const char *DETECTED_MESSAGE = "%s detected";

Expand Down
13 changes: 13 additions & 0 deletions src/gps/GPS.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,13 @@ class GPS : private concurrency::OSThread

CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);

#ifdef ARCH_ESP32
GPSPowerState preLightSleepState = GPS_OFF;
CallbackObserver<GPS, void *> notifyLightSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareLightSleep);
CallbackObserver<GPS, esp_sleep_wakeup_cause_t> notifyLightSleepEndObserver =
CallbackObserver<GPS, esp_sleep_wakeup_cause_t>(this, &GPS::endLightSleep);
Comment on lines +201 to +205
#endif

/** If !NULL we will use this serial port to construct our GPS */
#if defined(ARCH_RP2040)
static SerialUART *_serial_gps;
Expand Down Expand Up @@ -226,6 +233,12 @@ class GPS : private concurrency::OSThread
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);

#ifdef ARCH_ESP32
/// Drop the GPS into a low-power state for the duration of CPU light-sleep, and restore on wake.
int prepareLightSleep(void *unused);
int endLightSleep(esp_sleep_wakeup_cause_t cause);
#endif

/** Set power with EN pin, if relevant
*/
void writePinEN(bool on);
Expand Down
Loading