twali_power.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #define TWALI_INTERNAL
  2. #include "twali_system_internal.h"
  3. #include <stdlib.h>
  4. extern "C" {
  5. #define POWER_DOWN_DELAY 11000
  6. #define SUSPEND_DELAY 15000
  7. #define SHORT_KEYPRESS_DELAY 200
  8. struct twali_power {
  9. uint32_t power_down_delay;
  10. uint32_t suspend_delay;
  11. struct twali_system * system;
  12. AXP20X_Class * power;
  13. // state of the system
  14. int plugged_in;
  15. int low_power;
  16. int charging;
  17. int read_irq;
  18. long unsigned int now;
  19. // statistics about the system
  20. int battery_percentage;
  21. float battery_current;
  22. float vbus_current;
  23. long unsigned int last_logged;
  24. // managing the sleep/low_power/high_power state
  25. long unsigned int last_touch;
  26. long unsigned int wake_time;
  27. long unsigned int sleep_time;
  28. long unsigned int last_interaction;
  29. };
  30. static struct twali_power twali_power_singleton;
  31. static struct twali_power* twali_power_singleton_pointer = NULL;
  32. struct twali_power * twali_power_make(struct twali_system *s) {
  33. if (NULL != twali_power_singleton_pointer) {
  34. return twali_power_singleton_pointer;
  35. }
  36. twali_power_singleton.power = s->handle->power;
  37. twali_power_singleton.power_down_delay = POWER_DOWN_DELAY;
  38. twali_power_singleton.suspend_delay = SUSPEND_DELAY;
  39. twali_power_singleton.system = s;
  40. // state of the system
  41. twali_power_singleton.plugged_in = 0;
  42. twali_power_singleton.charging = 0;
  43. twali_power_singleton.read_irq = 0;
  44. twali_power_singleton.now = 0;
  45. // statistics about the system
  46. twali_power_singleton.battery_percentage = 0;
  47. twali_power_singleton.battery_current = 0.0;
  48. twali_power_singleton.vbus_current = 0.0;
  49. twali_power_singleton.last_logged = 0;
  50. // managing the sleep/low_power/high_power state
  51. twali_power_singleton.last_touch = 0;
  52. twali_power_singleton.wake_time = 0;
  53. twali_power_singleton.sleep_time = 0;
  54. twali_power_singleton.last_interaction = 0;
  55. twali_power_singleton.low_power = 0;
  56. twali_power_singleton_pointer = &twali_power_singleton;
  57. return twali_power_singleton_pointer;
  58. }
  59. void twali_power_interrupt(struct twali_power *p) {
  60. p->read_irq = 1;
  61. }
  62. int twali_power_plugged_in(struct twali_power *p) {
  63. return p->plugged_in;
  64. }
  65. int twali_power_charging(struct twali_power *p) {
  66. return p->charging;
  67. }
  68. int twali_power_low(struct twali_power *p) {
  69. return p->low_power;
  70. }
  71. void twali_power_run(struct twali_power *p);
  72. int twali_power_battery_percentage(struct twali_power *p) {
  73. int actual_percentage = p->power->getBattPercentage();
  74. if (twali_power_plugged_in(p)) {
  75. if (actual_percentage >= p->battery_percentage) {
  76. p->battery_percentage = actual_percentage;
  77. }
  78. } else {
  79. if (actual_percentage <= p->battery_percentage) {
  80. p->battery_percentage = actual_percentage;
  81. }
  82. }
  83. return p->battery_percentage;
  84. }
  85. float twali_power_battery_current(struct twali_power *p) {
  86. return p->battery_current;
  87. }
  88. float twali_power_vbus_current(struct twali_power *p) {
  89. return p->vbus_current;
  90. }
  91. float twali_power_last_interaction(struct twali_power *p);
  92. float twali_power_now(struct twali_power *p);
  93. void twali_power_up(struct twali_power *p);
  94. void twali_power_down(struct twali_power *p) {
  95. printf("%s\n", __func__);
  96. p->system->handle->closeBL();
  97. p->system->handle->displaySleep();
  98. p->low_power = 1;
  99. p->sleep_time = p->now;
  100. }
  101. void twali_power_up(struct twali_power *p) {
  102. printf("%s\n", __func__);
  103. p->system->handle->displayWakeup();
  104. p->system->handle->openBL();
  105. p->system->tft->fillScreen(TFT_WHITE);
  106. p->wake_time = p->last_interaction = p->now;
  107. p->low_power = 0;
  108. }
  109. void twali_power_suspend(struct twali_power *p) {
  110. printf("%s\n", __func__);
  111. esp_sleep_enable_gpio_wakeup();
  112. p->system->tft->fillScreen(TFT_BLACK);
  113. esp_light_sleep_start();
  114. twali_system_wake_up(p->system);
  115. printf("%s\n", "back from sleep");
  116. }
  117. void twali_power_task(void * object);
  118. void twali_power_start_task(struct twali_power * p);
  119. int twali_power_check_touch(struct twali_power *p) {
  120. if (p->system->handle->touch->touched() > 0) {
  121. p->last_touch = p->last_interaction = p->now;
  122. return 1;
  123. }
  124. return 0;
  125. }
  126. void twali_power_init(struct twali_power *p) {
  127. p->power->setPowerOutPut(
  128. AXP202_EXTEN
  129. | AXP202_DCDC2
  130. | AXP202_LDO3
  131. | AXP202_LDO4
  132. , AXP202_OFF);
  133. p->power->adc1Enable(
  134. AXP202_BATT_VOL_ADC1
  135. | AXP202_BATT_CUR_ADC1
  136. | AXP202_VBUS_CUR_ADC1
  137. , AXP202_ON);
  138. p->power->adc1Enable(
  139. AXP202_VBUS_VOL_ADC1
  140. , AXP202_OFF);
  141. gpio_wakeup_enable((gpio_num_t)AXP202_INT, GPIO_INTR_LOW_LEVEL);
  142. p->power->enableIRQ(
  143. AXP202_VBUS_REMOVED_IRQ
  144. | AXP202_VBUS_CONNECT_IRQ
  145. | AXP202_CHARGING_IRQ
  146. | AXP202_CHARGING_FINISHED_IRQ
  147. | AXP202_PEK_LONGPRESS_IRQ
  148. | AXP202_PEK_SHORTPRESS_IRQ
  149. , AXP202_ON);
  150. p->power->clearIRQ();
  151. p->plugged_in = p->power->isVBUSPlug();
  152. p->charging = p->power->isChargeingEnable();
  153. p->battery_percentage = p->power->getBattPercentage();
  154. }
  155. void twali_power_read_irq(struct twali_power *p) {
  156. p->power->readIRQ();
  157. p->read_irq = false;
  158. if (p->power->isVbusPlugInIRQ()) p->plugged_in = 1;
  159. if (p->power->isVbusRemoveIRQ()) p->plugged_in = 0;
  160. if (p->power->isChargingIRQ()) p->charging = 0;
  161. if (p->power->isChargingDoneIRQ()) p->charging = 1;
  162. if (p->power->isPEKShortPressIRQ()) {
  163. if (p->now - p->last_interaction > SHORT_KEYPRESS_DELAY) {
  164. if (p->low_power) twali_power_up(p);
  165. else twali_power_down(p);
  166. }
  167. }
  168. p->power->clearIRQ();
  169. p->last_interaction = p->now;
  170. }
  171. void twali_power_up_try(struct twali_power *p) {
  172. if (p->last_touch > p->sleep_time) {
  173. twali_power_up(p);
  174. }
  175. }
  176. void twali_power_down_try(struct twali_power *p) {
  177. if (p->plugged_in) return;
  178. if (p->now - p->last_interaction > p->power_down_delay) {
  179. twali_power_down(p);
  180. }
  181. }
  182. void twali_power_suspend_try(struct twali_power *p) {
  183. if (p->plugged_in) return;
  184. if (p->now - p->last_interaction > p->suspend_delay) {
  185. twali_power_suspend(p);
  186. }
  187. }
  188. void twali_log_power(struct twali_power * p) {
  189. p->battery_current = (p->battery_current + p->power->getBattDischargeCurrent()) / 2;
  190. p->vbus_current = (p->vbus_current + p->power->getVbusCurrent()) / 2;
  191. p->last_logged = p->now;
  192. }
  193. void twali_power_run(struct twali_power *p) {
  194. p->now = millis();
  195. if (p->read_irq) twali_power_read_irq(p);
  196. twali_power_check_touch(p);
  197. if (p->low_power) {
  198. twali_power_up_try(p);
  199. if (p->low_power) {
  200. twali_power_suspend_try(p);
  201. }
  202. } else {
  203. twali_power_down_try(p);
  204. }
  205. if (p->now - p->last_logged > 500) {
  206. twali_log_power(p);
  207. }
  208. }
  209. void twali_power_task(void* object) {
  210. struct twali_power * p = (struct twali_power *) object;
  211. twali_power_init(p);
  212. for (;;) {
  213. twali_power_run(p);
  214. vTaskDelay(10 / portTICK_PERIOD_MS);
  215. }
  216. printf("deleting the power management task!\n");
  217. vTaskDelete(NULL);
  218. }
  219. void twali_power_start_task(struct twali_power * p) {
  220. xTaskCreate(twali_power_task, "power_manager", 10000, (void *) p, 30, NULL);
  221. }
  222. }