|
@@ -0,0 +1,281 @@
|
|
|
+#define TWALI_INTERNAL
|
|
|
+#include "twali_system_internal.h"
|
|
|
+#include <stdlib.h>
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ int plugged_in;
|
|
|
+ int low_power;
|
|
|
+ int charging;
|
|
|
+ int read_irq;
|
|
|
+ long unsigned int now;
|
|
|
+
|
|
|
+
|
|
|
+ int battery_percentage;
|
|
|
+ float battery_current;
|
|
|
+ float vbus_current;
|
|
|
+ long unsigned int last_logged;
|
|
|
+
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+
|
|
|
+ twali_power_singleton.plugged_in = 0;
|
|
|
+ twali_power_singleton.charging = 0;
|
|
|
+ twali_power_singleton.read_irq = 0;
|
|
|
+ twali_power_singleton.now = 0;
|
|
|
+
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+
|
|
|
+ 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 sleep");
|
|
|
+}
|
|
|
+
|
|
|
+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);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|