From a7bc7a4733cf6dd834ca8cdb046159ceeaeab8e2 Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Wed, 25 Mar 2026 20:17:42 +1100 Subject: [PATCH] t5s3 only lightsleep mode --- examples/companion_radio/ui-new/UITask.cpp | 43 ++++++++++++++++++++++ examples/companion_radio/ui-new/UITask.h | 7 ++++ src/helpers/ESP32Board.h | 16 ++++++-- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 992b183..2aa0abb 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -18,6 +18,9 @@ #if defined(WIFI_SSID) || defined(MECK_WIFI_COMPANION) #include #endif +#if defined(LilyGo_T5S3_EPaper_Pro) && !defined(BLE_PIN_CODE) && !defined(MECK_WIFI_COMPANION) + #include "esp_sleep.h" +#endif #ifndef AUTO_OFF_MILLIS #define AUTO_OFF_MILLIS 15000 // 15 seconds @@ -1937,6 +1940,42 @@ if (curr) curr->poll(); } #endif + // ── T5S3 standalone powersaving ────────────────────────────────────────── + // When locked with display off, enter ESP32 light sleep (~8 mA total). + // Radio stays in continuous RX — DIO1 going HIGH wakes the CPU instantly. + // Boot button (GPIO0 LOW) and a 30-min safety timer also wake. + // First sleep starts 60s after lock; subsequent cycles wake for 5s to let + // the mesh stack process/relay any received packet, then sleep again. +#if defined(LilyGo_T5S3_EPaper_Pro) && !defined(BLE_PIN_CODE) && !defined(MECK_WIFI_COMPANION) + if (_locked && _display != NULL && !_display->isOn()) { + unsigned long now = millis(); + if (now - _psLastActive >= _psNextSleepSecs * 1000UL) { + Serial.println("[POWERSAVE] Entering light sleep (locked+idle)"); + board.sleep(1800); // Light sleep up to 30 min + // ── CPU resumes here on wake ── + unsigned long wakeAt = millis(); + _psLastActive = wakeAt; + _psNextSleepSecs = 5; // Stay awake 5s for mesh processing + + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + if (cause == ESP_SLEEP_WAKEUP_GPIO) { + // Boot button pressed — unlock and return to normal use + Serial.println("[POWERSAVE] Woke by button — unlocking"); + unlockScreen(); + _psNextSleepSecs = 60; // Reset to long delay after user interaction + } else if (cause == ESP_SLEEP_WAKEUP_EXT1) { + Serial.println("[POWERSAVE] Woke by LoRa packet"); + } else if (cause == ESP_SLEEP_WAKEUP_TIMER) { + Serial.println("[POWERSAVE] Woke by timer"); + } + } + } else if (!_locked) { + // Not locked — keep powersaving timer reset so first sleep is 60s after lock + _psLastActive = millis(); + _psNextSleepSecs = 60; + } +#endif + #ifdef PIN_VIBRATION vibration.loop(); #endif @@ -2063,6 +2102,10 @@ void UITask::lockScreen() { _next_refresh = 0; // Draw lock screen immediately _auto_off = millis() + 60000; // 60s before display off while locked _lastLockRefresh = millis(); // Start 15-min clock refresh cycle +#if defined(LilyGo_T5S3_EPaper_Pro) && !defined(BLE_PIN_CODE) && !defined(MECK_WIFI_COMPANION) + _psLastActive = millis(); // Start powersaving countdown (60s to first sleep) + _psNextSleepSecs = 60; +#endif Serial.println("[UI] Screen locked — entering low-power mode"); } diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index 2e52aaf..e497321 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -113,6 +113,13 @@ class UITask : public AbstractUITask { bool _vkbActive = false; UIScreen* _screenBeforeVKB = nullptr; unsigned long _vkbOpenedAt = 0; + + // Powersaving: light sleep when locked + idle (standalone only — no BLE/WiFi) + // Wakes on LoRa packet (DIO1), boot button (GPIO0), or 30-min timer +#if !defined(BLE_PIN_CODE) && !defined(MECK_WIFI_COMPANION) + unsigned long _psLastActive = 0; // millis() at last wake or lock entry + unsigned long _psNextSleepSecs = 60; // Seconds before first sleep (60s), then 5s cycles +#endif #ifdef MECK_CARDKB bool _cardkbDetected = false; #endif diff --git a/src/helpers/ESP32Board.h b/src/helpers/ESP32Board.h index 01b4c98..c0c420d 100644 --- a/src/helpers/ESP32Board.h +++ b/src/helpers/ESP32Board.h @@ -10,6 +10,7 @@ #include #include "esp_wifi.h" #include "driver/rtc_io.h" +#include "driver/gpio.h" class ESP32Board : public mesh::MainBoard { protected: @@ -60,13 +61,20 @@ public: #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(P_LORA_DIO_1) // Supported ESP32 variants if (rtc_gpio_is_valid_gpio((gpio_num_t)P_LORA_DIO_1)) { // Only enter sleep mode if P_LORA_DIO_1 is RTC pin esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); - esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // To wake up when receiving a LoRa packet + esp_sleep_enable_ext1_wakeup((1ULL << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // Wake on LoRa packet + + // T5S3: Also wake on boot button press (GPIO0, active LOW). + // gpio_wakeup uses level trigger — works for light sleep only. +#if defined(LilyGo_T5S3_EPaper_Pro) && defined(PIN_USER_BTN) + gpio_wakeup_enable((gpio_num_t)PIN_USER_BTN, GPIO_INTR_LOW_LEVEL); + esp_sleep_enable_gpio_wakeup(); +#endif if (secs > 0) { - esp_sleep_enable_timer_wakeup(secs * 1000000); // To wake up every hour to do periodically jobs + esp_sleep_enable_timer_wakeup(secs * 1000000ULL); // Timer wake (microseconds) } - esp_light_sleep_start(); // CPU enters light sleep + esp_light_sleep_start(); // CPU halts here, resumes on wake } #endif } @@ -154,4 +162,4 @@ public: } }; -#endif +#endif \ No newline at end of file