diff --git a/src/utility/Power_Class.cpp b/src/utility/Power_Class.cpp index 2189340..e929077 100644 --- a/src/utility/Power_Class.cpp +++ b/src/utility/Power_Class.cpp @@ -1264,6 +1264,12 @@ namespace m5 void Power_Class::deepSleep(std::uint64_t micro_seconds, bool touch_wakeup) { + if (micro_seconds == 0) + { // A wakeup time of zero means "do not sleep". + // ( This check comes before the display is put to sleep. ) + M5_LOGW("deepSleep: micro_seconds is 0. not sleeping. ( use Power.sleep_no_timer to sleep without a timer wakeup )"); + return; + } M5.Display.sleep(); M5.Display.waitDisplay(); #if defined (M5UNIFIED_PC_BUILD) @@ -1287,32 +1293,52 @@ namespace m5 { wpin = GPIO_NUM_4; } + bool pin_wakeup_enabled = false; if (touch_wakeup && wpin < GPIO_NUM_MAX) { #if SOC_PM_SUPPORT_EXT0_WAKEUP - esp_sleep_enable_ext0_wakeup((gpio_num_t)wpin, false); + pin_wakeup_enabled = (ESP_OK == esp_sleep_enable_ext0_wakeup((gpio_num_t)wpin, false)); #elif SOC_PM_SUPPORT_EXT1_WAKEUP && SOC_RTCIO_PIN_COUNT > 0 - const uint64_t ext_wakeup_pin_1_mask = 1ULL << _wakeupPin; - ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup_io(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ANY_LOW)); + if (rtc_gpio_is_valid_gpio((gpio_num_t)wpin)) + { + const uint64_t ext_wakeup_pin_1_mask = 1ULL << wpin; + pin_wakeup_enabled = (ESP_OK == esp_sleep_enable_ext1_wakeup_io(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ANY_LOW)); #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED - ESP_ERROR_CHECK(rtc_gpio_pullup_dis((gpio_num_t)_wakeupPin)); - ESP_ERROR_CHECK(rtc_gpio_pulldown_en((gpio_num_t)_wakeupPin)); + if (pin_wakeup_enabled) + { + rtc_gpio_pullup_dis((gpio_num_t)wpin); + rtc_gpio_pulldown_en((gpio_num_t)wpin); + } #endif + } #endif - while (m5gfx::gpio_in(wpin) == false) + if (pin_wakeup_enabled) { - // Issue #91, ( M5Paper wakes too soon from deep sleep when touch wakeup is enabled - with solution ) - M5.update(); - m5gfx::delay(10); + while (m5gfx::gpio_in(wpin) == false) + { + // Issue #91, ( M5Paper wakes too soon from deep sleep when touch wakeup is enabled - with solution ) + M5.update(); + m5gfx::delay(10); + } + } + else + { // The wakeup pin is not an RTC IO. ( ex. M5PaperS3 touch INT = GPIO48 ) + // Such a pin can wake up from light sleep, but not from deep sleep. + M5_LOGW("deepSleep: GPIO%d cannot be used as a deep sleep wakeup source.", (int)wpin); } } - if (micro_seconds > 0) + if (micro_seconds != sleep_no_timer) { esp_sleep_enable_timer_wakeup(micro_seconds); } else { esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); + if (!pin_wakeup_enabled) + { // Neither a timer nor a wakeup pin was configured by this call. + // Unless another wakeup source has been set up, the device will not wake up until it is reset. + M5_LOGW("deepSleep: no timer or pin wakeup source is enabled."); + } } #endif esp_deep_sleep_start(); @@ -1321,6 +1347,11 @@ namespace m5 void Power_Class::lightSleep(std::uint64_t micro_seconds, bool touch_wakeup) { + if (micro_seconds == 0) + { // A wakeup time of zero means "do not sleep". + M5_LOGW("lightSleep: micro_seconds is 0. not sleeping. ( use Power.sleep_no_timer to sleep without a timer wakeup )"); + return; + } #if defined (M5UNIFIED_PC_BUILD) (void)micro_seconds; (void)touch_wakeup; @@ -1342,31 +1373,43 @@ namespace m5 { wpin = GPIO_NUM_4; } + bool pin_wakeup_enabled = false; if (touch_wakeup && wpin < GPIO_NUM_MAX) { if (M5.getBoard() == board_t::board_M5PaperS3) { // M5PaperS3 touch interrupt pin (GPIO48) is not RTC IO // and therefore not supported in EXT0 wakeup - gpio_wakeup_enable((gpio_num_t)wpin, gpio_int_type_t::GPIO_INTR_LOW_LEVEL); - esp_sleep_enable_gpio_wakeup(); + pin_wakeup_enabled = (ESP_OK == gpio_wakeup_enable((gpio_num_t)wpin, gpio_int_type_t::GPIO_INTR_LOW_LEVEL)) + && (ESP_OK == esp_sleep_enable_gpio_wakeup()); } else { #if SOC_PM_SUPPORT_EXT0_WAKEUP - esp_sleep_enable_ext0_wakeup((gpio_num_t)wpin, false); + pin_wakeup_enabled = (ESP_OK == esp_sleep_enable_ext0_wakeup((gpio_num_t)wpin, false)); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO); #endif } - while (m5gfx::gpio_in(wpin) == false) + if (pin_wakeup_enabled) + { + while (m5gfx::gpio_in(wpin) == false) + { + m5gfx::delay(10); + } + } + else { - m5gfx::delay(10); + M5_LOGW("lightSleep: wakeup by GPIO%d is not enabled.", (int)wpin); } } - if (micro_seconds > 0){ + if (micro_seconds != sleep_no_timer){ esp_sleep_enable_timer_wakeup(micro_seconds); }else{ esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); + if (!pin_wakeup_enabled) + { // Neither a timer nor a wakeup pin was configured by this call. + M5_LOGW("lightSleep: no timer or pin wakeup source is enabled."); + } } esp_light_sleep_start(); if (M5.getBoard() == board_t::board_M5PaperS3) diff --git a/src/utility/Power_Class.hpp b/src/utility/Power_Class.hpp index 9b91e58..f443165 100644 --- a/src/utility/Power_Class.hpp +++ b/src/utility/Power_Class.hpp @@ -136,13 +136,20 @@ namespace m5 /// @attention CoreInk と M5Paper は USB接続中はRTCタイマー起動が出来ない。; void timerSleep(const rtc_date_t& date, const rtc_time_t& time); + /// Value for micro_seconds of deepSleep / lightSleep, meaning "sleep without a timer wakeup". + /// The device sleeps until a wakeup pin or another wakeup source is triggered. + static constexpr std::uint64_t sleep_no_timer = ~0ull; + /// ESP32 deepsleep - /// @param micro_seconds Number of micro seconds to wakeup. - void deepSleep(std::uint64_t micro_seconds = 0, bool touch_wakeup = true); + /// @param micro_seconds Number of micro seconds to wakeup. 0 = do not sleep. sleep_no_timer = no timer wakeup. + /// @param touch_wakeup Enable wakeup by the wakeup pin of the device, if it has one. + /// @attention Waking up from deep sleep restarts the program from the beginning. + void deepSleep(std::uint64_t micro_seconds = sleep_no_timer, bool touch_wakeup = true); /// ESP32 lightsleep - /// @param micro_seconds Number of micro seconds to wakeup. - void lightSleep(std::uint64_t micro_seconds = 0, bool touch_wakeup = true); + /// @param micro_seconds Number of micro seconds to wakeup. 0 = do not sleep. sleep_no_timer = no timer wakeup. + /// @param touch_wakeup Enable wakeup by the wakeup pin of the device, if it has one. + void lightSleep(std::uint64_t micro_seconds = sleep_no_timer, bool touch_wakeup = true); /// Get the remaining battery power. /// @return 0-100 level diff --git a/src/utility/RTC_Class.cpp b/src/utility/RTC_Class.cpp index 297ad66..f6e4376 100644 --- a/src/utility/RTC_Class.cpp +++ b/src/utility/RTC_Class.cpp @@ -69,7 +69,7 @@ namespace m5 if (instance == nullptr) { - instance.reset(new PCF8563_Class(PCF8563_Class::DEFAULT_ADDRESS, 400000)); + instance.reset(new PCF8563_Class(PCF8563_Class::DEFAULT_ADDRESS, 400000, i2c)); } if (instance->begin())