platform for developing on SQFMI's Watchy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

129 lines
3.7 KiB

#include "watchos.h"
#include "Module_Power.h"
void Module_Power::start()
{
// TODO: Fetch input module to poll for button presses
m_last_tick = 0;
m_light_sleep_accumulator = 0;
m_deep_sleep_accumulator = 0;
m_did_light_sleep = false;
switch (esp_sleep_get_wakeup_cause())
{
// Interactive
case ESP_SLEEP_WAKEUP_EXT1: // Button press
m_light_sleep_delay = MODULE_POWER_INTERACTIVE_LIGHT_SLEEP_DELAY_MS;
m_deep_sleep_delay = MODULE_POWER_INTERACTIVE_DEEP_SLEEP_DELAY_MS;
break;
// Non-interactive
case ESP_SLEEP_WAKEUP_EXT0: // External RTC
case ESP_SLEEP_WAKEUP_TIMER: // Internal RTC
default: // Reset or something else
m_light_sleep_delay = MODULE_POWER_NONINTERACTIVE_LIGHT_SLEEP_DELAY_MS;
m_deep_sleep_delay = MODULE_POWER_NONINTERACTIVE_DEEP_SLEEP_DELAY_MS;
break;
}
watchos::subscribe(this, WATCHOS_MODULE_INPUT, WATCHOS_EVENT_TYPE_INPUT_PRESSED);
}
void Module_Power::tick()
{
if (m_last_tick == 0)
{
m_last_tick = millis();
}
else
{
if (m_light_sleep_enabled)
{
m_light_sleep_accumulator += millis() - m_last_tick;
}
if (m_deep_sleep_enabled)
{
m_deep_sleep_accumulator += millis() - m_last_tick;
}
}
m_last_tick = millis();
Event* e;
while (this->hasEvent())
{
e = this->getEvent();
if (e->source == WATCHOS_MODULE_INPUT && e->event == WATCHOS_EVENT_TYPE_INPUT_PRESSED)
{
watchos::debug("Resetting accumulators");
m_light_sleep_delay = MODULE_POWER_INTERACTIVE_LIGHT_SLEEP_DELAY_MS;
m_deep_sleep_delay = MODULE_POWER_INTERACTIVE_DEEP_SLEEP_DELAY_MS;
m_light_sleep_accumulator = 0;
m_deep_sleep_accumulator = 0;
}
this->popEvent();
}
if (m_deep_sleep_accumulator > m_deep_sleep_delay)
{
watchos::debug("Going into deep sleep");
//watchos::debug("Power: light %d/%d; heavy %d/%d", m_light_sleep_accumulator, m_light_sleep_delay, m_deep_sleep_accumulator, m_deep_sleep_delay);
watchos::kernel()->suspend();
// TODO: Configure a... hourly? alarm to wake up and refresh other things.
// Interrogate tasks for next requested wakeup?
if (m_did_light_sleep)
{
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
}
esp_sleep_enable_ext0_wakeup(HW_RTC, 0);
esp_sleep_enable_ext1_wakeup(HW_BUTTON_MASK, ESP_EXT1_WAKEUP_ANY_HIGH);
// Turn off RTC -- needs to be on to handle ext0/ext1 interrupts properly I guess
//esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
// Turn off RTC fast mem
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
// Keep RTC slow ram on explicitly
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
esp_deep_sleep_start();
}
else if (m_light_sleep_accumulator > m_light_sleep_delay)
{
//watchos::debug("Going into light sleep");
//watchos::debug("Power: light %d/%d; heavy %d/%d", m_light_sleep_accumulator, m_light_sleep_delay, m_deep_sleep_accumulator, m_deep_sleep_delay);
m_did_light_sleep = true;
// If nothing else happens, wake up when it's time to hibernate.
esp_sleep_enable_timer_wakeup((m_deep_sleep_delay - m_deep_sleep_accumulator) * 1000);
// Wake up if the RTC fires
esp_sleep_enable_ext0_wakeup(HW_RTC, 0);
// Wake up if any button is pressed
esp_sleep_enable_ext1_wakeup(HW_BUTTON_MASK, ESP_EXT1_WAKEUP_ANY_HIGH);
// Go into light sleep
esp_light_sleep_start();
// And we're back, let everything continue!
m_light_sleep_accumulator = 0;
}
}
void Module_Power::disableLightSleep()
{
m_light_sleep_enabled = false;
}
void Module_Power::enableLightSleep()
{
m_light_sleep_enabled = true;
}
void Module_Power::disableDeepSleep()
{
m_deep_sleep_enabled = false;
}
void Module_Power::enableDeepSleep()
{
m_deep_sleep_enabled = true;
}