#define TWALI_INTERNAL #include "twali_system_internal.h" #include extern "C" { #define POWER_DOWN_DELAY 11000 #define SUSPEND_DELAY 15000 #define SHORT_KEYPRESS_DELAY 200 struct twali_power { uint32_t power_down_delay; uint32_t suspend_delay; struct twali_system * system; AXP20X_Class * power; // state of the system int plugged_in; int low_power; int charging; int read_irq; long unsigned int now; // statistics about the system int battery_percentage; float battery_current; float vbus_current; long unsigned int last_logged; // managing the sleep/low_power/high_power state long unsigned int last_touch; long unsigned int wake_time; long unsigned int sleep_time; long unsigned int last_interaction; }; static struct twali_power twali_power_singleton; static struct twali_power* twali_power_singleton_pointer = NULL; struct twali_power * twali_power_make(struct twali_system *s) { if (NULL != twali_power_singleton_pointer) { return twali_power_singleton_pointer; } twali_power_singleton.power = s->handle->power; twali_power_singleton.power_down_delay = POWER_DOWN_DELAY; twali_power_singleton.suspend_delay = SUSPEND_DELAY; twali_power_singleton.system = s; // state of the system twali_power_singleton.plugged_in = 0; twali_power_singleton.charging = 0; twali_power_singleton.read_irq = 0; twali_power_singleton.now = 0; // statistics about the system twali_power_singleton.battery_percentage = 0; twali_power_singleton.battery_current = 0.0; twali_power_singleton.vbus_current = 0.0; twali_power_singleton.last_logged = 0; // managing the sleep/low_power/high_power state twali_power_singleton.last_touch = 0; twali_power_singleton.wake_time = 0; twali_power_singleton.sleep_time = 0; twali_power_singleton.last_interaction = 0; twali_power_singleton.low_power = 0; twali_power_singleton_pointer = &twali_power_singleton; return twali_power_singleton_pointer; } void twali_power_interrupt(struct twali_power *p) { p->read_irq = 1; } int twali_power_plugged_in(struct twali_power *p) { return p->plugged_in; } int twali_power_charging(struct twali_power *p) { return p->charging; } int twali_power_low(struct twali_power *p) { return p->low_power; } void twali_power_run(struct twali_power *p); int twali_power_battery_percentage(struct twali_power *p) { int actual_percentage = p->power->getBattPercentage(); if (twali_power_plugged_in(p)) { if (actual_percentage >= p->battery_percentage) { p->battery_percentage = actual_percentage; } } else { if (actual_percentage <= p->battery_percentage) { p->battery_percentage = actual_percentage; } } return p->battery_percentage; } float twali_power_battery_current(struct twali_power *p) { return p->battery_current; } float twali_power_vbus_current(struct twali_power *p) { return p->vbus_current; } float twali_power_last_interaction(struct twali_power *p); float twali_power_now(struct twali_power *p); void twali_power_up(struct twali_power *p); void twali_power_down(struct twali_power *p) { printf("%s\n", __func__); p->system->handle->closeBL(); p->system->handle->displaySleep(); p->low_power = 1; p->sleep_time = p->now; } void twali_power_up(struct twali_power *p) { printf("%s\n", __func__); p->system->handle->displayWakeup(); p->system->handle->openBL(); p->system->tft->fillScreen(TFT_WHITE); p->wake_time = p->last_interaction = p->now; p->low_power = 0; } void twali_power_suspend(struct twali_power *p) { printf("%s\n", __func__); esp_sleep_enable_gpio_wakeup(); p->system->tft->fillScreen(TFT_BLACK); esp_light_sleep_start(); twali_system_wake_up(p->system); printf("%s\n", "back from suspend"); } void twali_power_task(void * object); void twali_power_start_task(struct twali_power * p); int twali_power_check_touch(struct twali_power *p) { if (p->system->handle->touch->touched() > 0) { p->last_touch = p->last_interaction = p->now; return 1; } return 0; } void twali_power_init(struct twali_power *p) { p->power->setPowerOutPut( AXP202_EXTEN | AXP202_DCDC2 | AXP202_LDO3 | AXP202_LDO4 , AXP202_OFF); p->power->adc1Enable( AXP202_BATT_VOL_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_VBUS_CUR_ADC1 , AXP202_ON); p->power->adc1Enable( AXP202_VBUS_VOL_ADC1 , AXP202_OFF); gpio_wakeup_enable((gpio_num_t)AXP202_INT, GPIO_INTR_LOW_LEVEL); p->power->enableIRQ( AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_CHARGING_IRQ | AXP202_CHARGING_FINISHED_IRQ | AXP202_PEK_LONGPRESS_IRQ | AXP202_PEK_SHORTPRESS_IRQ , AXP202_ON); p->power->clearIRQ(); p->plugged_in = p->power->isVBUSPlug(); p->charging = p->power->isChargeingEnable(); p->battery_percentage = p->power->getBattPercentage(); } void twali_power_read_irq(struct twali_power *p) { p->power->readIRQ(); p->read_irq = false; if (p->power->isVbusPlugInIRQ()) p->plugged_in = 1; if (p->power->isVbusRemoveIRQ()) p->plugged_in = 0; if (p->power->isChargingIRQ()) p->charging = 0; if (p->power->isChargingDoneIRQ()) p->charging = 1; if (p->power->isPEKShortPressIRQ()) { if (p->now - p->last_interaction > SHORT_KEYPRESS_DELAY) { if (p->low_power) twali_power_up(p); else twali_power_down(p); } } p->power->clearIRQ(); p->last_interaction = p->now; } void twali_power_up_try(struct twali_power *p) { if (p->last_touch > p->sleep_time) { twali_power_up(p); } } void twali_power_down_try(struct twali_power *p) { if (p->plugged_in) return; if (p->now - p->last_interaction > p->power_down_delay) { twali_power_down(p); } } void twali_power_suspend_try(struct twali_power *p) { if (p->plugged_in) return; if (p->now - p->last_interaction > p->suspend_delay) { twali_power_suspend(p); } } void twali_log_power(struct twali_power * p) { p->battery_current = (p->battery_current + p->power->getBattDischargeCurrent()) / 2; p->vbus_current = (p->vbus_current + p->power->getVbusCurrent()) / 2; p->last_logged = p->now; } void twali_power_run(struct twali_power *p) { p->now = millis(); if (p->read_irq) twali_power_read_irq(p); twali_power_check_touch(p); if (p->low_power) { twali_power_up_try(p); if (p->low_power) { twali_power_suspend_try(p); } } else { twali_power_down_try(p); } if (p->now - p->last_logged > 500) { twali_log_power(p); } } void twali_power_task(void* object) { struct twali_power * p = (struct twali_power *) object; twali_power_init(p); for (;;) { twali_power_run(p); vTaskDelay(10 / portTICK_PERIOD_MS); } printf("deleting the power management task!\n"); vTaskDelete(NULL); } void twali_power_start_task(struct twali_power * p) { xTaskCreate(twali_power_task, "power_manager", 10000, (void *) p, 30, NULL); } }