| 61 | } |
| 62 | |
| 63 | void HalPowerManager::startDeepSleep(HalGPIO& gpio) const { |
| 64 | // Ensure that the power button has been released to avoid immediately turning back on if you're holding it |
| 65 | while (gpio.isPressed(HalGPIO::BTN_POWER)) { |
| 66 | delay(50); |
| 67 | gpio.update(); |
| 68 | } |
| 69 | |
| 70 | #ifdef ENABLE_SERIAL_LOG |
| 71 | // Tear down HWCDC so the host sees a clean disconnect and the peripheral |
| 72 | // doesn't hold power domains that interfere with USB-powered GPIO wake. |
| 73 | // logSerial is the raw HWCDC reference; Serial is the MySerialImpl proxy |
| 74 | // (which doesn't expose end()). |
| 75 | logSerial.end(); |
| 76 | #endif |
| 77 | |
| 78 | // Pre-sleep routines from the original firmware |
| 79 | // GPIO13 is connected to battery latch MOSFET, we need to make sure it's low during sleep |
| 80 | // Note that this means the MCU will be completely powered off during sleep, including RTC |
| 81 | constexpr gpio_num_t GPIO_SPIWP = GPIO_NUM_13; |
| 82 | gpio_set_direction(GPIO_SPIWP, GPIO_MODE_OUTPUT); |
| 83 | gpio_set_level(GPIO_SPIWP, 0); |
| 84 | esp_sleep_config_gpio_isolate(); |
| 85 | gpio_deep_sleep_hold_en(); |
| 86 | gpio_hold_en(GPIO_SPIWP); |
| 87 | pinMode(InputManager::POWER_BUTTON_PIN, INPUT_PULLUP); |
| 88 | // Arm the wakeup trigger *after* the button is released |
| 89 | // Note: this is only useful for waking up on USB power. On battery, the MCU will be completely powered off, so the |
| 90 | // power button is hard-wired to briefly provide power to the MCU, waking it up regardless of the wakeup source |
| 91 | // configuration |
| 92 | esp_deep_sleep_enable_gpio_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_GPIO_WAKEUP_GPIO_LOW); |
| 93 | // Enter Deep Sleep |
| 94 | esp_deep_sleep_start(); |
| 95 | } |
| 96 | |
| 97 | uint16_t HalPowerManager::getBatteryPercentage() const { |
| 98 | if (_batteryUseI2C) { |