From bc6c3741384e6a65bba4edbc18f2409c37c385b1 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Sun, 22 Jan 2023 04:52:38 +0000 Subject: [PATCH] Add battery to hold desktop right --- .../animations/views/bubble_animation_view.c | 2 +- .../views/one_shot_animation_view.c | 2 +- applications/settings/about/about.c | 207 ++++++++++++++++-- 3 files changed, 186 insertions(+), 25 deletions(-) diff --git a/applications/services/desktop/animations/views/bubble_animation_view.c b/applications/services/desktop/animations/views/bubble_animation_view.c index 65fafdcb7..3cef74a81 100644 --- a/applications/services/desktop/animations/views/bubble_animation_view.c +++ b/applications/services/desktop/animations/views/bubble_animation_view.c @@ -136,7 +136,7 @@ static bool bubble_animation_input_callback(InputEvent* event, void* context) { } } else if(event->type == InputTypeLong) { Loader* loader = furi_record_open(RECORD_LOADER); - loader_start(loader, "About", NULL); + loader_start(loader, "About", "batt"); furi_record_close(RECORD_LOADER); } } diff --git a/applications/services/desktop/animations/views/one_shot_animation_view.c b/applications/services/desktop/animations/views/one_shot_animation_view.c index dd8b997a2..d12c4ccbe 100644 --- a/applications/services/desktop/animations/views/one_shot_animation_view.c +++ b/applications/services/desktop/animations/views/one_shot_animation_view.c @@ -73,7 +73,7 @@ static bool one_shot_view_input(InputEvent* event, void* context) { } } else if(event->type == InputTypeLong) { Loader* loader = furi_record_open(RECORD_LOADER); - loader_start(loader, "About", NULL); + loader_start(loader, "About", "batt"); furi_record_close(RECORD_LOADER); } } diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 17c734a20..c040fec4a 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -3,10 +3,17 @@ #include #include #include +#include #include #include #include #include +#include + +int screen_index; + +#define LOW_CHARGE_THRESHOLD 10 +#define HIGH_DRAIN_CURRENT_THRESHOLD 100 typedef DialogMessageButton (*AboutDialogScreen)(DialogsApp* dialogs, DialogMessage* message); @@ -151,6 +158,134 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* return result; } +static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) { + canvas_draw_frame(canvas, x - 7, y + 7, 30, 13); + canvas_draw_icon(canvas, x, y, icon); + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, x - 4, y + 16, 24, 6); + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val); +}; + +static void draw_battery(Canvas* canvas, PowerInfo* info, int x, int y) { + char header[20] = {}; + char value[20] = {}; + + int32_t drain_current = info->current_gauge * (-1000); + uint32_t charge_current = info->current_gauge * 1000; + + // Draw battery + canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28); + if(charge_current > 0) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14); + } else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14); + } else if(info->charge < LOW_CHARGE_THRESHOLD) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14); + } else { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14); + } + + // Draw bubble + elements_bubble(canvas, x + 53, y + 0, 71, 28); + + // Set text + if(charge_current > 0) { + snprintf(header, sizeof(header), "%s", "Charging at"); + snprintf( + value, + sizeof(value), + "%lu.%luV %lumA", + (uint32_t)(info->voltage_vbus), + (uint32_t)(info->voltage_vbus * 10) % 10, + charge_current); + } else if(drain_current > 0) { + snprintf(header, sizeof(header), "%s", "Consumption is"); + snprintf( + value, + sizeof(value), + "%ld %s", + drain_current, + drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA"); + } else if(drain_current != 0) { + snprintf(header, 20, "..."); + } else if(info->voltage_battery_charging < 4.2) { + // Non-default battery charging limit, mention it + snprintf(header, sizeof(header), "Limited to"); + snprintf( + value, + sizeof(value), + "%lu.%luV", + (uint32_t)(info->voltage_battery_charging), + (uint32_t)(info->voltage_battery_charging * 10) % 10); + } else { + snprintf(header, sizeof(header), "Charged!"); + } + + if (!strcmp(value, "")) { + canvas_draw_str_aligned(canvas, x + 92, y + 14, AlignCenter, AlignCenter, header); + } else if (!strcmp(header, "")) { + canvas_draw_str_aligned(canvas, x + 92, y + 14, AlignCenter, AlignCenter, value); + } else { + canvas_draw_str_aligned(canvas, x + 92, y + 9, AlignCenter, AlignCenter, header); + canvas_draw_str_aligned(canvas, x + 92, y + 19, AlignCenter, AlignCenter, value); + } +}; + +static void battery_info_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + PowerInfo* info = context; + + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + draw_battery(canvas, info, 0, 0); + + char batt_level[10]; + char temperature[10]; + char voltage[10]; + char health[10]; + + snprintf(batt_level, sizeof(batt_level), "%lu%%", (uint32_t)info->charge); + snprintf(temperature, sizeof(temperature), "%lu C", (uint32_t)info->temperature_gauge); + snprintf( + voltage, + sizeof(voltage), + "%lu.%01lu V", + (uint32_t)info->voltage_gauge, + (uint32_t)(info->voltage_gauge * 10) % 10UL); + snprintf(health, sizeof(health), "%d%%", info->health); + + draw_stat(canvas, 8, 28, &I_Battery_16x16, batt_level); + draw_stat(canvas, 40, 28, &I_Temperature_16x16, temperature); + draw_stat(canvas, 72, 28, &I_Voltage_16x16, voltage); + draw_stat(canvas, 104, 28, &I_Health_16x16, health); + + elements_button_right(canvas, "Next"); +} + +static bool battery_info_input_callback(InputEvent* event, void* context) { + FuriSemaphore* semaphore = context; + + bool consumed = false; + if(event->type == InputTypeShort) { + if(event->key == InputKeyLeft) { + screen_index--; + consumed = true; + } else if(event->key == InputKeyRight) { + screen_index++; + consumed = true; + } else if(event->key == InputKeyBack) { + screen_index = -2; + consumed = true; + } + } + + if(consumed) { + furi_semaphore_release(semaphore); + } + return consumed; +} + const AboutDialogScreen about_screens[] = { product_screen, hw_version_screen, @@ -160,55 +295,81 @@ const AboutDialogScreen about_screens[] = { compliance_screen, address_screen}; -const size_t about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); +const int about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); + int32_t about_settings_app(void* p) { - UNUSED(p); - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - DialogMessage* message = dialog_message_alloc(); + bool battery_info = false; + if(p && strlen(p) && !strcmp(p, "batt")) { + battery_info = true; + } Gui* gui = furi_record_open(RECORD_GUI); ViewDispatcher* view_dispatcher = view_dispatcher_alloc(); - EmptyScreen* empty_screen = empty_screen_alloc(); - const uint32_t empty_screen_index = 0; + const uint32_t battery_info_index = 0; + const uint32_t empty_screen_index = 1; - size_t screen_index = 0; + FuriSemaphore* semaphore = furi_semaphore_alloc(1, 0); + Power* power = furi_record_open(RECORD_POWER); + View* battery_view = view_alloc(); + view_set_context(battery_view, semaphore); + view_set_input_callback(battery_view, battery_info_input_callback); + view_allocate_model(battery_view, ViewModelTypeLocking, sizeof(PowerInfo)); + view_set_draw_callback(battery_view, battery_info_draw_callback); + + DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); + DialogMessage* message = dialog_message_alloc(); + EmptyScreen* empty_screen = empty_screen_alloc(); DialogMessageButton screen_result; // draw empty screen to prevent menu flickering + view_dispatcher_add_view( + view_dispatcher, battery_info_index, battery_view); view_dispatcher_add_view( view_dispatcher, empty_screen_index, empty_screen_get_view(empty_screen)); view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); - view_dispatcher_switch_to_view(view_dispatcher, empty_screen_index); - while(1) { - if(screen_index >= about_screens_count - 1) { - dialog_message_set_buttons(message, "Back", NULL, NULL); - } else { - dialog_message_set_buttons(message, "Back", NULL, "Next"); - } + screen_index = -1 + !battery_info; + while(screen_index > -2) { - screen_result = about_screens[screen_index](dialogs, message); - - if(screen_result == DialogMessageButtonLeft) { - if(screen_index <= 0) { + if (screen_index == -1) { + if (!battery_info) { break; + } + with_view_model( + battery_view, + PowerInfo * model, + { power_get_info(power, model); }, + true); + view_dispatcher_switch_to_view(view_dispatcher, battery_info_index); + furi_semaphore_acquire(semaphore, 2000); + } else { + view_dispatcher_switch_to_view(view_dispatcher, empty_screen_index); + if(screen_index >= about_screens_count - 1) { + dialog_message_set_buttons(message, "Back", NULL, NULL); } else { + dialog_message_set_buttons(message, "Back", NULL, "Next"); + } + screen_result = about_screens[screen_index](dialogs, message); + if(screen_result == DialogMessageButtonLeft) { screen_index--; - } - } else if(screen_result == DialogMessageButtonRight) { - if(screen_index < about_screens_count) { + } else if(screen_result == DialogMessageButtonRight) { screen_index++; + } else if(screen_result == DialogMessageButtonBack) { + screen_index = -2; } - } else if(screen_result == DialogMessageButtonBack) { - break; } + } dialog_message_free(message); furi_record_close(RECORD_DIALOGS); + furi_record_close(RECORD_POWER); + furi_semaphore_free(semaphore); view_dispatcher_remove_view(view_dispatcher, empty_screen_index); + view_dispatcher_remove_view(view_dispatcher, battery_info_index); + view_free(battery_view); view_dispatcher_free(view_dispatcher); empty_screen_free(empty_screen); furi_record_close(RECORD_GUI);