power_observer.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include <notification/notification_messages.h>
  4. typedef struct {
  5. osThreadId_t thread;
  6. } PowerObserverSrv;
  7. const NotificationMessage message_green_110 = {
  8. .type = NotificationMessageTypeLedGreen,
  9. .data.led.value = 110,
  10. };
  11. static const NotificationSequence sequence_overconsumption = {
  12. &message_green_110,
  13. &message_red_255,
  14. &message_delay_100,
  15. NULL,
  16. };
  17. typedef enum {
  18. EventReset = (1 << 0),
  19. EventRequest = (1 << 1),
  20. } UsbEvent;
  21. static void usb_state_callback(FuriHalUsbStateEvent state, void* context) {
  22. PowerObserverSrv* srv = (PowerObserverSrv*)(context);
  23. if(state == FuriHalUsbStateEventReset) {
  24. osThreadFlagsSet(srv->thread, EventReset);
  25. } else if(state == FuriHalUsbStateEventDescriptorRequest) {
  26. osThreadFlagsSet(srv->thread, EventRequest);
  27. }
  28. }
  29. int32_t power_observer_srv(void* p) {
  30. NotificationApp* notifications = furi_record_open("notification");
  31. PowerObserverSrv* srv = furi_alloc(sizeof(PowerObserverSrv));
  32. srv->thread = osThreadGetId();
  33. const float overconsumption_limit = 0.03f;
  34. bool usb_request_pending = false;
  35. uint8_t usb_wait_time = 0;
  36. furi_hal_usb_set_state_callback(usb_state_callback, srv);
  37. while(true) {
  38. uint32_t flags = osThreadFlagsWait(EventReset | EventRequest, osFlagsWaitAny, 500);
  39. if((flags & osFlagsError) == 0) {
  40. if(flags & EventReset) {
  41. usb_request_pending = true;
  42. usb_wait_time = 0;
  43. }
  44. if(flags & EventRequest) {
  45. usb_request_pending = false;
  46. }
  47. } else if(usb_request_pending) {
  48. usb_wait_time++;
  49. if(usb_wait_time > 4) {
  50. furi_hal_usb_reinit();
  51. usb_request_pending = false;
  52. }
  53. }
  54. float current = -furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge);
  55. if(current > overconsumption_limit) {
  56. notification_message_block(notifications, &sequence_overconsumption);
  57. }
  58. if(furi_hal_power_is_otg_enabled()) {
  59. furi_hal_power_check_otg_status();
  60. }
  61. }
  62. free(srv);
  63. return 0;
  64. }