[FL-1783] Power service refactoring (#718)
* settings power: introduce power settings app * power: move power API to separate file * settings power: implement reboot scene * settings power: add power off scene * assets: add crying dolphin, fix Subghz assets names * settings power: fix power off scene GUI * settings power: add battery info scene * power: add cli to application on start hook * power: remove power from main menu * power: move to power service folder * power service: rework power off logic * power: add pubsub events * bt: subscribe to battery level change, update characteristic * application: change order of Settings applications * gui: add bubble element * power: gui improvements * application: rename Notification -> LCD and notifications * Applications: menu order according to documentation and add missing power cli init * settings power: add disconnect USB scene * power cli: notify user to disconnect USB after poweroff * Power: update poweroff message in cli Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
30
applications/applications.c
Normal file → Executable file
@ -46,12 +46,14 @@ extern void lfrfid_cli_init();
|
|||||||
extern void nfc_cli_init();
|
extern void nfc_cli_init();
|
||||||
extern void storage_cli_init();
|
extern void storage_cli_init();
|
||||||
extern void subghz_cli_init();
|
extern void subghz_cli_init();
|
||||||
|
extern void power_cli_init();
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
extern int32_t notification_settings_app(void* p);
|
extern int32_t notification_settings_app(void* p);
|
||||||
extern int32_t storage_settings_app(void* p);
|
extern int32_t storage_settings_app(void* p);
|
||||||
extern int32_t bt_settings_app(void* p);
|
extern int32_t bt_settings_app(void* p);
|
||||||
extern int32_t about_settings_app(void* p);
|
extern int32_t about_settings_app(void* p);
|
||||||
|
extern int32_t power_settings_app(void* p);
|
||||||
|
|
||||||
const FlipperApplication FLIPPER_SERVICES[] = {
|
const FlipperApplication FLIPPER_SERVICES[] = {
|
||||||
/* Services */
|
/* Services */
|
||||||
@ -143,18 +145,14 @@ const size_t FLIPPER_SERVICES_COUNT = sizeof(FLIPPER_SERVICES) / sizeof(FlipperA
|
|||||||
// Main menu APP
|
// Main menu APP
|
||||||
const FlipperApplication FLIPPER_APPS[] = {
|
const FlipperApplication FLIPPER_APPS[] = {
|
||||||
|
|
||||||
#ifdef APP_IBUTTON
|
#ifdef APP_SUBGHZ
|
||||||
{.app = ibutton_app, .name = "iButton", .stack_size = 2048, .icon = &A_iButton_14},
|
{.app = subghz_app, .name = "Sub-GHz", .stack_size = 2048, .icon = &A_Sub1ghz_14},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_NFC
|
#ifdef APP_NFC
|
||||||
{.app = nfc_app, .name = "NFC", .stack_size = 4096, .icon = &A_NFC_14},
|
{.app = nfc_app, .name = "NFC", .stack_size = 4096, .icon = &A_NFC_14},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_SUBGHZ
|
|
||||||
{.app = subghz_app, .name = "Sub-GHz", .stack_size = 2048, .icon = &A_Sub1ghz_14},
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef APP_LF_RFID
|
#ifdef APP_LF_RFID
|
||||||
{.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 2048, .icon = &A_125khz_14},
|
{.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 2048, .icon = &A_125khz_14},
|
||||||
#endif
|
#endif
|
||||||
@ -163,6 +161,10 @@ const FlipperApplication FLIPPER_APPS[] = {
|
|||||||
{.app = irda_app, .name = "Infrared", .stack_size = 1024 * 3, .icon = &A_Infrared_14},
|
{.app = irda_app, .name = "Infrared", .stack_size = 1024 * 3, .icon = &A_Infrared_14},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef APP_IBUTTON
|
||||||
|
{.app = ibutton_app, .name = "iButton", .stack_size = 2048, .icon = &A_iButton_14},
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef APP_GPIO_TEST
|
#ifdef APP_GPIO_TEST
|
||||||
{.app = gpio_test_app, .name = "GPIO", .stack_size = 1024, .icon = &A_GPIO_14},
|
{.app = gpio_test_app, .name = "GPIO", .stack_size = 1024, .icon = &A_GPIO_14},
|
||||||
#endif
|
#endif
|
||||||
@ -192,6 +194,9 @@ const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = {
|
|||||||
#ifdef SRV_BT
|
#ifdef SRV_BT
|
||||||
bt_cli_init,
|
bt_cli_init,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SRV_POWER
|
||||||
|
power_cli_init,
|
||||||
|
#endif
|
||||||
#ifdef SRV_STORAGE
|
#ifdef SRV_STORAGE
|
||||||
storage_cli_init,
|
storage_cli_init,
|
||||||
#endif
|
#endif
|
||||||
@ -258,16 +263,23 @@ const FlipperApplication FLIPPER_ARCHIVE =
|
|||||||
|
|
||||||
// Settings menu
|
// Settings menu
|
||||||
const FlipperApplication FLIPPER_SETTINGS_APPS[] = {
|
const FlipperApplication FLIPPER_SETTINGS_APPS[] = {
|
||||||
|
#ifdef SRV_BT
|
||||||
|
{.app = bt_settings_app, .name = "Bluetooth", .stack_size = 1024, .icon = NULL},
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_NOTIFICATION
|
#ifdef SRV_NOTIFICATION
|
||||||
{.app = notification_settings_app, .name = "Notification", .stack_size = 1024, .icon = NULL},
|
{.app = notification_settings_app,
|
||||||
|
.name = "LCD and notifications",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_STORAGE
|
#ifdef SRV_STORAGE
|
||||||
{.app = storage_settings_app, .name = "Storage", .stack_size = 2048, .icon = NULL},
|
{.app = storage_settings_app, .name = "Storage", .stack_size = 2048, .icon = NULL},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_BT
|
#ifdef SRV_POWER
|
||||||
{.app = bt_settings_app, .name = "Bluetooth", .stack_size = 1024, .icon = NULL},
|
{.app = power_settings_app, .name = "Power", .stack_size = 1024, .icon = NULL},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_ABOUT
|
#ifdef APP_ABOUT
|
||||||
|
@ -26,6 +26,17 @@ static void bt_pin_code_show_event_handler(Bt* bt, uint32_t pin) {
|
|||||||
string_clear(pin_str);
|
string_clear(pin_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bt_battery_level_changed_callback(const void* _event, void* context) {
|
||||||
|
furi_assert(_event);
|
||||||
|
furi_assert(context);
|
||||||
|
|
||||||
|
Bt* bt = context;
|
||||||
|
const PowerEvent* event = _event;
|
||||||
|
if(event->type == PowerEventTypeBatteryLevelChanged) {
|
||||||
|
bt_update_battery_level(bt, event->data.battery_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bt* bt_alloc() {
|
Bt* bt_alloc() {
|
||||||
Bt* bt = furi_alloc(sizeof(Bt));
|
Bt* bt = furi_alloc(sizeof(Bt));
|
||||||
// Load settings
|
// Load settings
|
||||||
@ -45,6 +56,11 @@ Bt* bt_alloc() {
|
|||||||
bt->dialogs = furi_record_open("dialogs");
|
bt->dialogs = furi_record_open("dialogs");
|
||||||
bt->dialog_message = dialog_message_alloc();
|
bt->dialog_message = dialog_message_alloc();
|
||||||
|
|
||||||
|
// Power
|
||||||
|
bt->power = furi_record_open("power");
|
||||||
|
PubSub* power_pubsub = power_get_pubsub(bt->power);
|
||||||
|
subscribe_pubsub(power_pubsub, bt_battery_level_changed_callback, bt);
|
||||||
|
|
||||||
return bt;
|
return bt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
#include <gui/view_port.h>
|
#include <gui/view_port.h>
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
|
|
||||||
#include <applications/dialogs/dialogs.h>
|
#include <dialogs/dialogs.h>
|
||||||
|
#include <power/power_service/power.h>
|
||||||
|
|
||||||
#include "../bt_settings.h"
|
#include "../bt_settings.h"
|
||||||
|
|
||||||
@ -36,4 +37,5 @@ struct Bt {
|
|||||||
ViewPort* statusbar_view_port;
|
ViewPort* statusbar_view_port;
|
||||||
DialogsApp* dialogs;
|
DialogsApp* dialogs;
|
||||||
DialogMessage* dialog_message;
|
DialogMessage* dialog_message;
|
||||||
|
Power* power;
|
||||||
};
|
};
|
||||||
|
@ -327,6 +327,17 @@ void elements_slightly_rounded_box(
|
|||||||
canvas_draw_rbox(canvas, x, y, width, height, 1);
|
canvas_draw_rbox(canvas, x, y, width, height, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void elements_bubble(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
|
||||||
|
furi_assert(canvas);
|
||||||
|
canvas_draw_rframe(canvas, x + 4, y, width, height, 3);
|
||||||
|
uint8_t y_corner = y + height * 2 / 3;
|
||||||
|
canvas_draw_line(canvas, x, y_corner, x + 4, y_corner - 4);
|
||||||
|
canvas_draw_line(canvas, x, y_corner, x + 4, y_corner + 4);
|
||||||
|
canvas_set_color(canvas, ColorWhite);
|
||||||
|
canvas_draw_line(canvas, x + 4, y_corner - 3, x + 4, y_corner + 3);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
}
|
||||||
|
|
||||||
void elements_string_fit_width(Canvas* canvas, string_t string, uint8_t width) {
|
void elements_string_fit_width(Canvas* canvas, string_t string, uint8_t width) {
|
||||||
furi_assert(canvas);
|
furi_assert(canvas);
|
||||||
furi_assert(string);
|
furi_assert(string);
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/** Draw progress bar.
|
||||||
* Draw progress bar.
|
|
||||||
* @param x - progress bar position on X axis
|
* @param x - progress bar position on X axis
|
||||||
* @param y - progress bar position on Y axis
|
* @param y - progress bar position on Y axis
|
||||||
* @param width - progress bar width
|
* @param width - progress bar width
|
||||||
@ -24,8 +23,7 @@ void elements_progress_bar(
|
|||||||
uint8_t progress,
|
uint8_t progress,
|
||||||
uint8_t total);
|
uint8_t total);
|
||||||
|
|
||||||
/*
|
/** Draw scrollbar on canvas at specific position.
|
||||||
* Draw scrollbar on canvas at specific position.
|
|
||||||
* @param x - scrollbar position on X axis
|
* @param x - scrollbar position on X axis
|
||||||
* @param y - scrollbar position on Y axis
|
* @param y - scrollbar position on Y axis
|
||||||
* @param height - scrollbar height
|
* @param height - scrollbar height
|
||||||
@ -40,41 +38,35 @@ void elements_scrollbar_pos(
|
|||||||
uint16_t pos,
|
uint16_t pos,
|
||||||
uint16_t total);
|
uint16_t total);
|
||||||
|
|
||||||
/*
|
/** Draw scrollbar on canvas.
|
||||||
* Draw scrollbar on canvas.
|
|
||||||
* width 3px, height equal to canvas height
|
* width 3px, height equal to canvas height
|
||||||
* @param pos - current element of total elements
|
* @param pos - current element of total elements
|
||||||
* @param total - total elements
|
* @param total - total elements
|
||||||
*/
|
*/
|
||||||
void elements_scrollbar(Canvas* canvas, uint16_t pos, uint16_t total);
|
void elements_scrollbar(Canvas* canvas, uint16_t pos, uint16_t total);
|
||||||
|
|
||||||
/*
|
/** Draw rounded frame
|
||||||
* Draw rounded frame
|
|
||||||
* @param x, y - top left corner coordinates
|
* @param x, y - top left corner coordinates
|
||||||
* @param width, height - frame width and height
|
* @param width, height - frame width and height
|
||||||
*/
|
*/
|
||||||
void elements_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
|
void elements_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
|
||||||
|
|
||||||
/*
|
/** Draw button in left corner
|
||||||
* Draw button in left corner
|
|
||||||
* @param str - button text
|
* @param str - button text
|
||||||
*/
|
*/
|
||||||
void elements_button_left(Canvas* canvas, const char* str);
|
void elements_button_left(Canvas* canvas, const char* str);
|
||||||
|
|
||||||
/*
|
/** Draw button in right corner
|
||||||
* Draw button in right corner
|
|
||||||
* @param str - button text
|
* @param str - button text
|
||||||
*/
|
*/
|
||||||
void elements_button_right(Canvas* canvas, const char* str);
|
void elements_button_right(Canvas* canvas, const char* str);
|
||||||
|
|
||||||
/*
|
/** Draw button in center
|
||||||
* Draw button in center
|
|
||||||
* @param str - button text
|
* @param str - button text
|
||||||
*/
|
*/
|
||||||
void elements_button_center(Canvas* canvas, const char* str);
|
void elements_button_center(Canvas* canvas, const char* str);
|
||||||
|
|
||||||
/*
|
/** Draw aligned multiline text
|
||||||
* Draw aligned multiline text
|
|
||||||
* @param x, y - coordinates based on align param
|
* @param x, y - coordinates based on align param
|
||||||
* @param horizontal, vertical - aligment of multiline text
|
* @param horizontal, vertical - aligment of multiline text
|
||||||
* @param text - string (possible multiline)
|
* @param text - string (possible multiline)
|
||||||
@ -87,22 +79,19 @@ void elements_multiline_text_aligned(
|
|||||||
Align vertical,
|
Align vertical,
|
||||||
const char* text);
|
const char* text);
|
||||||
|
|
||||||
/*
|
/** Draw multiline text
|
||||||
* Draw multiline text
|
|
||||||
* @param x, y - top left corner coordinates
|
* @param x, y - top left corner coordinates
|
||||||
* @param text - string (possible multiline)
|
* @param text - string (possible multiline)
|
||||||
*/
|
*/
|
||||||
void elements_multiline_text(Canvas* canvas, uint8_t x, uint8_t y, const char* text);
|
void elements_multiline_text(Canvas* canvas, uint8_t x, uint8_t y, const char* text);
|
||||||
|
|
||||||
/*
|
/** Draw framed multiline text
|
||||||
* Draw framed multiline text
|
|
||||||
* @param x, y - top left corner coordinates
|
* @param x, y - top left corner coordinates
|
||||||
* @param text - string (possible multiline)
|
* @param text - string (possible multiline)
|
||||||
*/
|
*/
|
||||||
void elements_multiline_text_framed(Canvas* canvas, uint8_t x, uint8_t y, const char* text);
|
void elements_multiline_text_framed(Canvas* canvas, uint8_t x, uint8_t y, const char* text);
|
||||||
|
|
||||||
/*
|
/** Draw slightly rounded frame
|
||||||
* Draw slightly rounded frame
|
|
||||||
* @param x, y - top left corner coordinates
|
* @param x, y - top left corner coordinates
|
||||||
* @param width, height - size of frame
|
* @param width, height - size of frame
|
||||||
*/
|
*/
|
||||||
@ -113,8 +102,7 @@ void elements_slightly_rounded_frame(
|
|||||||
uint8_t width,
|
uint8_t width,
|
||||||
uint8_t height);
|
uint8_t height);
|
||||||
|
|
||||||
/*
|
/** Draw slightly rounded box
|
||||||
* Draw slightly rounded box
|
|
||||||
* @param x, y - top left corner coordinates
|
* @param x, y - top left corner coordinates
|
||||||
* @param width, height - size of box
|
* @param width, height - size of box
|
||||||
*/
|
*/
|
||||||
@ -125,8 +113,15 @@ void elements_slightly_rounded_box(
|
|||||||
uint8_t width,
|
uint8_t width,
|
||||||
uint8_t height);
|
uint8_t height);
|
||||||
|
|
||||||
/*
|
/** Draw bubble frame for text
|
||||||
* Trim string buffer to fit width in pixels
|
* @param x - left x coordinates
|
||||||
|
* @param y - top y coordinate
|
||||||
|
* @param width - bubble width
|
||||||
|
* @param height - bubble height
|
||||||
|
*/
|
||||||
|
void elements_bubble(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
|
||||||
|
|
||||||
|
/** Trim string buffer to fit width in pixels
|
||||||
* @param string - string to trim
|
* @param string - string to trim
|
||||||
* @param width - max width
|
* @param width - max width
|
||||||
*/
|
*/
|
||||||
|
@ -1,278 +0,0 @@
|
|||||||
#include "power.h"
|
|
||||||
#include "power_cli.h"
|
|
||||||
#include "power_views.h"
|
|
||||||
|
|
||||||
#include <furi.h>
|
|
||||||
#include <furi-hal.h>
|
|
||||||
|
|
||||||
#include <menu/menu.h>
|
|
||||||
#include <menu/menu_item.h>
|
|
||||||
|
|
||||||
#include <gui/gui.h>
|
|
||||||
#include <gui/icon_animation.h>
|
|
||||||
#include <gui/view_port.h>
|
|
||||||
#include <gui/view.h>
|
|
||||||
#include <gui/view_dispatcher.h>
|
|
||||||
#include <gui/modules/dialog.h>
|
|
||||||
#include <assets_icons.h>
|
|
||||||
#include <stm32wbxx.h>
|
|
||||||
|
|
||||||
#include <notification/notification-messages.h>
|
|
||||||
#include <applications/bt/bt_service/bt.h>
|
|
||||||
|
|
||||||
#define POWER_OFF_TIMEOUT 30
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PowerStateNotCharging,
|
|
||||||
PowerStateCharging,
|
|
||||||
PowerStateCharged,
|
|
||||||
} PowerState;
|
|
||||||
|
|
||||||
struct Power {
|
|
||||||
ViewDispatcher* view_dispatcher;
|
|
||||||
View* info_view;
|
|
||||||
View* off_view;
|
|
||||||
View* disconnect_view;
|
|
||||||
|
|
||||||
ViewPort* battery_view_port;
|
|
||||||
|
|
||||||
Dialog* dialog;
|
|
||||||
|
|
||||||
ValueMutex* menu_vm;
|
|
||||||
Cli* cli;
|
|
||||||
Bt* bt;
|
|
||||||
MenuItem* menu;
|
|
||||||
|
|
||||||
PowerState state;
|
|
||||||
};
|
|
||||||
|
|
||||||
void power_draw_battery_callback(Canvas* canvas, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
Power* power = context;
|
|
||||||
canvas_draw_icon(canvas, 0, 0, &I_Battery_26x8);
|
|
||||||
with_view_model(
|
|
||||||
power->info_view, (PowerInfoModel * model) {
|
|
||||||
canvas_draw_box(canvas, 2, 2, (float)model->charge / 100 * 20, 4);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t power_info_back_callback(void* context) {
|
|
||||||
return VIEW_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_menu_off_callback(void* context) {
|
|
||||||
Power* power = context;
|
|
||||||
power_off(power);
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_menu_reset_dialog_result(DialogResult result, void* context) {
|
|
||||||
Power* power = context;
|
|
||||||
if(result == DialogResultLeft) {
|
|
||||||
power_reboot(power, PowerBootModeDfu);
|
|
||||||
} else if(result == DialogResultRight) {
|
|
||||||
power_reboot(power, PowerBootModeNormal);
|
|
||||||
} else if(result == DialogResultBack) {
|
|
||||||
view_dispatcher_switch_to_view(power->view_dispatcher, VIEW_NONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_menu_reset_callback(void* context) {
|
|
||||||
Power* power = context;
|
|
||||||
dialog_set_result_callback(power->dialog, power_menu_reset_dialog_result);
|
|
||||||
dialog_set_header_text(power->dialog, "Reboot type");
|
|
||||||
dialog_set_text(power->dialog, "Reboot where?");
|
|
||||||
dialog_set_left_button_text(power->dialog, "DFU");
|
|
||||||
dialog_set_right_button_text(power->dialog, "OS");
|
|
||||||
view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewDialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_menu_enable_otg_callback(void* context) {
|
|
||||||
furi_hal_power_enable_otg();
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_menu_disable_otg_callback(void* context) {
|
|
||||||
furi_hal_power_disable_otg();
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_menu_info_callback(void* context) {
|
|
||||||
Power* power = context;
|
|
||||||
view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
Power* power_alloc() {
|
|
||||||
Power* power = furi_alloc(sizeof(Power));
|
|
||||||
|
|
||||||
power->state = PowerStateNotCharging;
|
|
||||||
|
|
||||||
power->menu_vm = furi_record_open("menu");
|
|
||||||
|
|
||||||
power->cli = furi_record_open("cli");
|
|
||||||
power_cli_init(power->cli, power);
|
|
||||||
|
|
||||||
power->bt = furi_record_open("bt");
|
|
||||||
|
|
||||||
power->menu = menu_item_alloc_menu("Power", icon_animation_alloc(&A_Power_14));
|
|
||||||
menu_item_subitem_add(
|
|
||||||
power->menu, menu_item_alloc_function("Off", NULL, power_menu_off_callback, power));
|
|
||||||
menu_item_subitem_add(
|
|
||||||
power->menu, menu_item_alloc_function("Reboot", NULL, power_menu_reset_callback, power));
|
|
||||||
menu_item_subitem_add(
|
|
||||||
power->menu,
|
|
||||||
menu_item_alloc_function("Enable OTG", NULL, power_menu_enable_otg_callback, power));
|
|
||||||
menu_item_subitem_add(
|
|
||||||
power->menu,
|
|
||||||
menu_item_alloc_function("Disable OTG", NULL, power_menu_disable_otg_callback, power));
|
|
||||||
menu_item_subitem_add(
|
|
||||||
power->menu, menu_item_alloc_function("Info", NULL, power_menu_info_callback, power));
|
|
||||||
|
|
||||||
power->view_dispatcher = view_dispatcher_alloc();
|
|
||||||
power->info_view = view_alloc();
|
|
||||||
view_allocate_model(power->info_view, ViewModelTypeLockFree, sizeof(PowerInfoModel));
|
|
||||||
view_set_draw_callback(power->info_view, power_info_draw_callback);
|
|
||||||
view_set_previous_callback(power->info_view, power_info_back_callback);
|
|
||||||
view_dispatcher_add_view(power->view_dispatcher, PowerViewInfo, power->info_view);
|
|
||||||
|
|
||||||
power->off_view = view_alloc();
|
|
||||||
view_allocate_model(power->off_view, ViewModelTypeLockFree, sizeof(PowerOffModel));
|
|
||||||
view_set_draw_callback(power->off_view, power_off_draw_callback);
|
|
||||||
view_dispatcher_add_view(power->view_dispatcher, PowerViewOff, power->off_view);
|
|
||||||
|
|
||||||
power->disconnect_view = view_alloc();
|
|
||||||
view_set_draw_callback(power->disconnect_view, power_disconnect_draw_callback);
|
|
||||||
view_dispatcher_add_view(power->view_dispatcher, PowerViewDisconnect, power->disconnect_view);
|
|
||||||
|
|
||||||
power->dialog = dialog_alloc();
|
|
||||||
dialog_set_context(power->dialog, power);
|
|
||||||
view_dispatcher_add_view(
|
|
||||||
power->view_dispatcher, PowerViewDialog, dialog_get_view(power->dialog));
|
|
||||||
|
|
||||||
power->battery_view_port = view_port_alloc();
|
|
||||||
|
|
||||||
view_port_set_width(power->battery_view_port, icon_get_width(&I_Battery_26x8));
|
|
||||||
view_port_draw_callback_set(power->battery_view_port, power_draw_battery_callback, power);
|
|
||||||
return power;
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_free(Power* power) {
|
|
||||||
furi_assert(power);
|
|
||||||
free(power);
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_off(Power* power) {
|
|
||||||
furi_assert(power);
|
|
||||||
furi_hal_power_off();
|
|
||||||
view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewDisconnect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_reboot(Power* power, PowerBootMode mode) {
|
|
||||||
if(mode == PowerBootModeNormal) {
|
|
||||||
furi_hal_boot_set_mode(FuriHalBootModeNormal);
|
|
||||||
} else if(mode == PowerBootModeDfu) {
|
|
||||||
furi_hal_boot_set_mode(FuriHalBootModeDFU);
|
|
||||||
}
|
|
||||||
furi_hal_power_reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void power_charging_indication_handler(Power* power, NotificationApp* notifications) {
|
|
||||||
if(furi_hal_power_is_charging()) {
|
|
||||||
if(furi_hal_power_get_pct() == 100) {
|
|
||||||
if(power->state != PowerStateCharged) {
|
|
||||||
notification_internal_message(notifications, &sequence_charged);
|
|
||||||
power->state = PowerStateCharged;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(power->state != PowerStateCharging) {
|
|
||||||
notification_internal_message(notifications, &sequence_charging);
|
|
||||||
power->state = PowerStateCharging;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!furi_hal_power_is_charging()) {
|
|
||||||
if(power->state != PowerStateNotCharging) {
|
|
||||||
notification_internal_message(notifications, &sequence_not_charging);
|
|
||||||
power->state = PowerStateNotCharging;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t power_srv(void* p) {
|
|
||||||
(void)p;
|
|
||||||
Power* power = power_alloc();
|
|
||||||
|
|
||||||
NotificationApp* notifications = furi_record_open("notification");
|
|
||||||
Gui* gui = furi_record_open("gui");
|
|
||||||
gui_add_view_port(gui, power->battery_view_port, GuiLayerStatusBarRight);
|
|
||||||
view_dispatcher_attach_to_gui(power->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
|
||||||
|
|
||||||
with_value_mutex(
|
|
||||||
power->menu_vm, (Menu * menu) { menu_item_add(menu, power->menu); });
|
|
||||||
|
|
||||||
furi_record_create("power", power);
|
|
||||||
uint8_t battery_level = 0;
|
|
||||||
uint8_t battery_level_prev = 0;
|
|
||||||
while(1) {
|
|
||||||
bool battery_low = false;
|
|
||||||
|
|
||||||
with_view_model(
|
|
||||||
power->info_view, (PowerInfoModel * model) {
|
|
||||||
model->charge = furi_hal_power_get_pct();
|
|
||||||
battery_level = model->charge;
|
|
||||||
model->health = furi_hal_power_get_bat_health_pct();
|
|
||||||
model->capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
|
|
||||||
model->capacity_full = furi_hal_power_get_battery_full_capacity();
|
|
||||||
model->current_charger = furi_hal_power_get_battery_current(FuriHalPowerICCharger);
|
|
||||||
model->current_gauge = furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge);
|
|
||||||
model->voltage_charger = furi_hal_power_get_battery_voltage(FuriHalPowerICCharger);
|
|
||||||
model->voltage_gauge = furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge);
|
|
||||||
model->voltage_vbus = furi_hal_power_get_usb_voltage();
|
|
||||||
model->temperature_charger =
|
|
||||||
furi_hal_power_get_battery_temperature(FuriHalPowerICCharger);
|
|
||||||
model->temperature_gauge =
|
|
||||||
furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge);
|
|
||||||
|
|
||||||
if(model->charge == 0 && model->voltage_vbus < 4.0f) {
|
|
||||||
battery_low = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
with_view_model(
|
|
||||||
power->off_view, (PowerOffModel * model) {
|
|
||||||
if(battery_low) {
|
|
||||||
if(model->poweroff_tick == 0) {
|
|
||||||
model->poweroff_tick =
|
|
||||||
osKernelGetTickCount() + osKernelGetTickFreq() * POWER_OFF_TIMEOUT;
|
|
||||||
} else {
|
|
||||||
if(osKernelGetTickCount() > model->poweroff_tick) {
|
|
||||||
power_off(power);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
model->poweroff_tick = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(model->battery_low != battery_low) {
|
|
||||||
model->battery_low = battery_low;
|
|
||||||
view_dispatcher_switch_to_view(
|
|
||||||
power->view_dispatcher, battery_low ? PowerViewOff : VIEW_NONE);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
power_charging_indication_handler(power, notifications);
|
|
||||||
|
|
||||||
if(battery_level_prev != battery_level) {
|
|
||||||
battery_level_prev = battery_level;
|
|
||||||
bt_update_battery_level(power->bt, battery_level);
|
|
||||||
}
|
|
||||||
|
|
||||||
view_port_update(power->battery_view_port);
|
|
||||||
|
|
||||||
osDelay(1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
typedef struct Power Power;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PowerBootModeNormal,
|
|
||||||
PowerBootModeDfu,
|
|
||||||
} PowerBootMode;
|
|
||||||
|
|
||||||
/** Power off device
|
|
||||||
* @param power - Power instance
|
|
||||||
*/
|
|
||||||
void power_off(Power* power);
|
|
||||||
|
|
||||||
/** Reboot device
|
|
||||||
* @param power - Power instance
|
|
||||||
* @param mode - PowerBootMode
|
|
||||||
*/
|
|
||||||
void power_reboot(Power* power, PowerBootMode mode);
|
|
@ -1,29 +1,31 @@
|
|||||||
#include "power_cli.h"
|
#include "power_cli.h"
|
||||||
|
|
||||||
|
#include <power/power_service/power.h>
|
||||||
|
#include <cli/cli.h>
|
||||||
#include <furi-hal.h>
|
#include <furi-hal.h>
|
||||||
|
|
||||||
void power_cli_poweroff(Cli* cli, string_t args, void* context) {
|
void power_cli_poweroff(Cli* cli, string_t args, void* context) {
|
||||||
Power* power = context;
|
power_off();
|
||||||
power_off(power);
|
printf("It's now safe to disconnect USB from your flipper\r\n");
|
||||||
|
while(cli_getc(cli)) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void power_cli_reboot(Cli* cli, string_t args, void* context) {
|
void power_cli_reboot(Cli* cli, string_t args, void* context) {
|
||||||
Power* power = context;
|
power_reboot(PowerBootModeNormal);
|
||||||
power_reboot(power, PowerBootModeNormal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void power_cli_dfu(Cli* cli, string_t args, void* context) {
|
void power_cli_dfu(Cli* cli, string_t args, void* context) {
|
||||||
Power* power = context;
|
power_reboot(PowerBootModeDfu);
|
||||||
power_reboot(power, PowerBootModeDfu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void power_cli_factory_reset(Cli* cli, string_t args, void* context) {
|
void power_cli_factory_reset(Cli* cli, string_t args, void* context) {
|
||||||
Power* power = context;
|
|
||||||
printf("All data will be lost. Are you sure (y/n)?\r\n");
|
printf("All data will be lost. Are you sure (y/n)?\r\n");
|
||||||
char c = cli_getc(cli);
|
char c = cli_getc(cli);
|
||||||
if(c == 'y' || c == 'Y') {
|
if(c == 'y' || c == 'Y') {
|
||||||
printf("Data will be wiped after reboot.\r\n");
|
printf("Data will be wiped after reboot.\r\n");
|
||||||
furi_hal_boot_set_flags(FuriHalBootFlagFactoryReset);
|
furi_hal_boot_set_flags(FuriHalBootFlagFactoryReset);
|
||||||
power_reboot(power, PowerBootModeNormal);
|
power_reboot(PowerBootModeNormal);
|
||||||
} else {
|
} else {
|
||||||
printf("Safe choice.\r\n");
|
printf("Safe choice.\r\n");
|
||||||
}
|
}
|
||||||
@ -53,13 +55,17 @@ void power_cli_ext(Cli* cli, string_t args, void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void power_cli_init(Cli* cli, Power* power) {
|
void power_cli_init() {
|
||||||
cli_add_command(cli, "poweroff", CliCommandFlagParallelSafe, power_cli_poweroff, power);
|
Cli* cli = furi_record_open("cli");
|
||||||
cli_add_command(cli, "reboot", CliCommandFlagParallelSafe, power_cli_reboot, power);
|
|
||||||
|
cli_add_command(cli, "poweroff", CliCommandFlagParallelSafe, power_cli_poweroff, NULL);
|
||||||
|
cli_add_command(cli, "reboot", CliCommandFlagParallelSafe, power_cli_reboot, NULL);
|
||||||
cli_add_command(
|
cli_add_command(
|
||||||
cli, "factory_reset", CliCommandFlagParallelSafe, power_cli_factory_reset, power);
|
cli, "factory_reset", CliCommandFlagParallelSafe, power_cli_factory_reset, NULL);
|
||||||
cli_add_command(cli, "dfu", CliCommandFlagParallelSafe, power_cli_dfu, power);
|
cli_add_command(cli, "dfu", CliCommandFlagParallelSafe, power_cli_dfu, NULL);
|
||||||
cli_add_command(cli, "power_info", CliCommandFlagParallelSafe, power_cli_info, power);
|
cli_add_command(cli, "power_info", CliCommandFlagParallelSafe, power_cli_info, NULL);
|
||||||
cli_add_command(cli, "power_otg", CliCommandFlagParallelSafe, power_cli_otg, power);
|
cli_add_command(cli, "power_otg", CliCommandFlagParallelSafe, power_cli_otg, NULL);
|
||||||
cli_add_command(cli, "power_ext", CliCommandFlagParallelSafe, power_cli_ext, power);
|
cli_add_command(cli, "power_ext", CliCommandFlagParallelSafe, power_cli_ext, NULL);
|
||||||
|
|
||||||
|
furi_record_close("cli");
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cli/cli.h>
|
void power_cli_init();
|
||||||
#include "power.h"
|
|
||||||
|
|
||||||
void power_cli_init(Cli* cli, Power* power);
|
|
||||||
|
179
applications/power/power_service/power.c
Executable file
@ -0,0 +1,179 @@
|
|||||||
|
#include "power_i.h"
|
||||||
|
#include "views/power_off.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi-hal.h>
|
||||||
|
#include <gui/view_port.h>
|
||||||
|
#include <gui/view.h>
|
||||||
|
|
||||||
|
#define POWER_OFF_TIMEOUT 90
|
||||||
|
|
||||||
|
void power_draw_battery_callback(Canvas* canvas, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
Power* power = context;
|
||||||
|
canvas_draw_icon(canvas, 0, 0, &I_Battery_26x8);
|
||||||
|
canvas_draw_box(canvas, 2, 2, power->info.charge / 5, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ViewPort* power_battery_view_port_alloc(Power* power) {
|
||||||
|
ViewPort* battery_view_port = view_port_alloc();
|
||||||
|
view_port_set_width(battery_view_port, icon_get_width(&I_Battery_26x8));
|
||||||
|
view_port_draw_callback_set(battery_view_port, power_draw_battery_callback, power);
|
||||||
|
gui_add_view_port(power->gui, battery_view_port, GuiLayerStatusBarRight);
|
||||||
|
return battery_view_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
Power* power_alloc() {
|
||||||
|
Power* power = furi_alloc(sizeof(Power));
|
||||||
|
|
||||||
|
// Records
|
||||||
|
power->notification = furi_record_open("notification");
|
||||||
|
power->gui = furi_record_open("gui");
|
||||||
|
|
||||||
|
// Pubsub
|
||||||
|
init_pubsub(&power->event_pubsub);
|
||||||
|
|
||||||
|
// State initialization
|
||||||
|
power->state = PowerStateNotCharging;
|
||||||
|
power->battery_low = false;
|
||||||
|
power->power_off_timeout = POWER_OFF_TIMEOUT;
|
||||||
|
power->info_mtx = osMutexNew(NULL);
|
||||||
|
|
||||||
|
// Gui
|
||||||
|
power->view_dispatcher = view_dispatcher_alloc();
|
||||||
|
power->power_off = power_off_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
power->view_dispatcher, PowerViewOff, power_off_get_view(power->power_off));
|
||||||
|
view_dispatcher_attach_to_gui(
|
||||||
|
power->view_dispatcher, power->gui, ViewDispatcherTypeFullscreen);
|
||||||
|
|
||||||
|
// Battery view port
|
||||||
|
power->battery_view_port = power_battery_view_port_alloc(power);
|
||||||
|
|
||||||
|
return power;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_free(Power* power) {
|
||||||
|
furi_assert(power);
|
||||||
|
|
||||||
|
// Records
|
||||||
|
furi_record_close("notification");
|
||||||
|
furi_record_close("gui");
|
||||||
|
|
||||||
|
// Gui
|
||||||
|
view_dispatcher_remove_view(power->view_dispatcher, PowerViewOff);
|
||||||
|
power_off_free(power->power_off);
|
||||||
|
view_port_free(power->battery_view_port);
|
||||||
|
|
||||||
|
// State
|
||||||
|
osMutexDelete(power->info_mtx);
|
||||||
|
free(power);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void power_check_charging_state(Power* power) {
|
||||||
|
if(furi_hal_power_is_charging()) {
|
||||||
|
if(power->info.charge == 100) {
|
||||||
|
if(power->state != PowerStateCharged) {
|
||||||
|
notification_internal_message(power->notification, &sequence_charged);
|
||||||
|
power->state = PowerStateCharged;
|
||||||
|
power->event.type = PowerEventTypeFullyCharged;
|
||||||
|
notify_pubsub(&power->event_pubsub, &power->event);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(power->state != PowerStateCharging) {
|
||||||
|
notification_internal_message(power->notification, &sequence_charging);
|
||||||
|
power->state = PowerStateCharging;
|
||||||
|
power->event.type = PowerEventTypeStartCharging;
|
||||||
|
notify_pubsub(&power->event_pubsub, &power->event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(power->state != PowerStateNotCharging) {
|
||||||
|
notification_internal_message(power->notification, &sequence_not_charging);
|
||||||
|
power->state = PowerStateNotCharging;
|
||||||
|
power->event.type = PowerEventTypeStopCharging;
|
||||||
|
notify_pubsub(&power->event_pubsub, &power->event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void power_update_info(Power* power) {
|
||||||
|
osMutexAcquire(power->info_mtx, osWaitForever);
|
||||||
|
PowerInfo* info = &power->info;
|
||||||
|
|
||||||
|
info->charge = furi_hal_power_get_pct();
|
||||||
|
info->health = furi_hal_power_get_bat_health_pct();
|
||||||
|
info->capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
|
||||||
|
info->capacity_full = furi_hal_power_get_battery_full_capacity();
|
||||||
|
info->current_charger = furi_hal_power_get_battery_current(FuriHalPowerICCharger);
|
||||||
|
info->current_gauge = furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge);
|
||||||
|
info->voltage_charger = furi_hal_power_get_battery_voltage(FuriHalPowerICCharger);
|
||||||
|
info->voltage_gauge = furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge);
|
||||||
|
info->voltage_vbus = furi_hal_power_get_usb_voltage();
|
||||||
|
info->temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger);
|
||||||
|
info->temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge);
|
||||||
|
|
||||||
|
osMutexRelease(power->info_mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void power_check_low_battery(Power* power) {
|
||||||
|
// Check battery charge and vbus voltage
|
||||||
|
if((power->info.charge == 0) && (power->info.voltage_vbus < 4.0f)) {
|
||||||
|
if(!power->battery_low) {
|
||||||
|
view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewOff);
|
||||||
|
}
|
||||||
|
power->battery_low = true;
|
||||||
|
} else {
|
||||||
|
if(power->battery_low) {
|
||||||
|
view_dispatcher_switch_to_view(power->view_dispatcher, VIEW_NONE);
|
||||||
|
power->power_off_timeout = POWER_OFF_TIMEOUT;
|
||||||
|
}
|
||||||
|
power->battery_low = false;
|
||||||
|
}
|
||||||
|
// If battery low, update view and switch off power after timeout
|
||||||
|
if(power->battery_low) {
|
||||||
|
if(power->power_off_timeout) {
|
||||||
|
power_off_set_time_left(power->power_off, power->power_off_timeout--);
|
||||||
|
} else {
|
||||||
|
power_off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void power_check_battery_level_change(Power* power) {
|
||||||
|
if(power->battery_level != power->info.charge) {
|
||||||
|
power->battery_level = power->info.charge;
|
||||||
|
power->event.type = PowerEventTypeBatteryLevelChanged;
|
||||||
|
power->event.data.battery_level = power->battery_level;
|
||||||
|
notify_pubsub(&power->event_pubsub, &power->event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t power_srv(void* p) {
|
||||||
|
(void)p;
|
||||||
|
Power* power = power_alloc();
|
||||||
|
furi_record_create("power", power);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
// Update data from gauge and charger
|
||||||
|
power_update_info(power);
|
||||||
|
|
||||||
|
// Check low battery level
|
||||||
|
power_check_low_battery(power);
|
||||||
|
|
||||||
|
// Check and notify about charging state
|
||||||
|
power_check_charging_state(power);
|
||||||
|
|
||||||
|
// Check and notify about battery level change
|
||||||
|
power_check_battery_level_change(power);
|
||||||
|
|
||||||
|
// Update battery view port
|
||||||
|
view_port_update(power->battery_view_port);
|
||||||
|
|
||||||
|
osDelay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
power_free(power);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
65
applications/power/power_service/power.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <furi/pubsub.h>
|
||||||
|
|
||||||
|
typedef struct Power Power;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PowerBootModeNormal,
|
||||||
|
PowerBootModeDfu,
|
||||||
|
} PowerBootMode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PowerEventTypeStopCharging,
|
||||||
|
PowerEventTypeStartCharging,
|
||||||
|
PowerEventTypeFullyCharged,
|
||||||
|
PowerEventTypeBatteryLevelChanged,
|
||||||
|
} PowerEventType;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint8_t battery_level;
|
||||||
|
} PowerEventData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PowerEventType type;
|
||||||
|
PowerEventData data;
|
||||||
|
} PowerEvent;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float current_charger;
|
||||||
|
float current_gauge;
|
||||||
|
|
||||||
|
float voltage_charger;
|
||||||
|
float voltage_gauge;
|
||||||
|
float voltage_vbus;
|
||||||
|
|
||||||
|
uint32_t capacity_remaining;
|
||||||
|
uint32_t capacity_full;
|
||||||
|
|
||||||
|
float temperature_charger;
|
||||||
|
float temperature_gauge;
|
||||||
|
|
||||||
|
uint8_t charge;
|
||||||
|
uint8_t health;
|
||||||
|
} PowerInfo;
|
||||||
|
|
||||||
|
/** Power off device
|
||||||
|
*/
|
||||||
|
void power_off();
|
||||||
|
|
||||||
|
/** Reboot device
|
||||||
|
* @param mode - PowerBootMode
|
||||||
|
*/
|
||||||
|
void power_reboot(PowerBootMode mode);
|
||||||
|
|
||||||
|
/** Get power info
|
||||||
|
* @param power - Power instance
|
||||||
|
* @param info - PowerInfo instance
|
||||||
|
*/
|
||||||
|
void power_get_info(Power* power, PowerInfo* info);
|
||||||
|
|
||||||
|
/** Get power event pubsub handler
|
||||||
|
* @param power - Power instance
|
||||||
|
*/
|
||||||
|
PubSub* power_get_pubsub(Power* power);
|
31
applications/power/power_service/power_api.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "power_i.h"
|
||||||
|
#include <furi.h>
|
||||||
|
#include "furi-hal-power.h"
|
||||||
|
#include "furi-hal-boot.h"
|
||||||
|
|
||||||
|
void power_off() {
|
||||||
|
furi_hal_power_off();
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_reboot(PowerBootMode mode) {
|
||||||
|
if(mode == PowerBootModeNormal) {
|
||||||
|
furi_hal_boot_set_mode(FuriHalBootModeNormal);
|
||||||
|
} else if(mode == PowerBootModeDfu) {
|
||||||
|
furi_hal_boot_set_mode(FuriHalBootModeDFU);
|
||||||
|
}
|
||||||
|
furi_hal_power_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_get_info(Power* power, PowerInfo* info) {
|
||||||
|
furi_assert(power);
|
||||||
|
furi_assert(info);
|
||||||
|
|
||||||
|
osMutexAcquire(power->info_mtx, osWaitForever);
|
||||||
|
memcpy(info, &power->info, sizeof(power->info));
|
||||||
|
osMutexRelease(power->info_mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
PubSub* power_get_pubsub(Power* power) {
|
||||||
|
furi_assert(power);
|
||||||
|
return &power->event_pubsub;
|
||||||
|
}
|
37
applications/power/power_service/power_i.h
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "power.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include "views/power_off.h"
|
||||||
|
|
||||||
|
#include <notification/notification-messages.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PowerStateNotCharging,
|
||||||
|
PowerStateCharging,
|
||||||
|
PowerStateCharged,
|
||||||
|
} PowerState;
|
||||||
|
|
||||||
|
struct Power {
|
||||||
|
ViewDispatcher* view_dispatcher;
|
||||||
|
PowerOff* power_off;
|
||||||
|
|
||||||
|
ViewPort* battery_view_port;
|
||||||
|
Gui* gui;
|
||||||
|
NotificationApp* notification;
|
||||||
|
PubSub event_pubsub;
|
||||||
|
PowerEvent event;
|
||||||
|
|
||||||
|
PowerState state;
|
||||||
|
PowerInfo info;
|
||||||
|
osMutexId_t info_mtx;
|
||||||
|
|
||||||
|
bool battery_low;
|
||||||
|
uint8_t battery_level;
|
||||||
|
uint8_t power_off_timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum { PowerViewOff } PowerView;
|
57
applications/power/power_service/views/power_off.c
Executable file
@ -0,0 +1,57 @@
|
|||||||
|
#include "power_off.h"
|
||||||
|
#include <furi.h>
|
||||||
|
#include <gui/elements.h>
|
||||||
|
|
||||||
|
struct PowerOff {
|
||||||
|
View* view;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t time_left_sec;
|
||||||
|
} PowerOffModel;
|
||||||
|
|
||||||
|
static void power_off_draw_callback(Canvas* canvas, void* _model) {
|
||||||
|
furi_assert(_model);
|
||||||
|
PowerOffModel* model = _model;
|
||||||
|
char buff[32];
|
||||||
|
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 1, AlignCenter, AlignTop, "Battery low!");
|
||||||
|
canvas_draw_icon(canvas, 0, 18, &I_BatteryBody_52x28);
|
||||||
|
canvas_draw_icon(canvas, 16, 25, &I_FaceNopower_29x14);
|
||||||
|
elements_bubble(canvas, 54, 17, 70, 30);
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
elements_multiline_text_aligned(
|
||||||
|
canvas, 70, 23, AlignLeft, AlignTop, "Connect me\n to charger.");
|
||||||
|
snprintf(buff, sizeof(buff), "Poweroff in %lds.", model->time_left_sec);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 60, AlignCenter, AlignBottom, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerOff* power_off_alloc() {
|
||||||
|
PowerOff* power_off = furi_alloc(sizeof(PowerOff));
|
||||||
|
power_off->view = view_alloc();
|
||||||
|
view_allocate_model(power_off->view, ViewModelTypeLocking, sizeof(PowerOffModel));
|
||||||
|
view_set_draw_callback(power_off->view, power_off_draw_callback);
|
||||||
|
return power_off;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_off_free(PowerOff* power_off) {
|
||||||
|
furi_assert(power_off);
|
||||||
|
view_free(power_off->view);
|
||||||
|
free(power_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
View* power_off_get_view(PowerOff* power_off) {
|
||||||
|
furi_assert(power_off);
|
||||||
|
return power_off->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_off_set_time_left(PowerOff* power_off, uint8_t time_left) {
|
||||||
|
furi_assert(power_off);
|
||||||
|
with_view_model(
|
||||||
|
power_off->view, (PowerOffModel * model) {
|
||||||
|
model->time_left_sec = time_left;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
13
applications/power/power_service/views/power_off.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct PowerOff PowerOff;
|
||||||
|
|
||||||
|
#include <gui/view.h>
|
||||||
|
|
||||||
|
PowerOff* power_off_alloc();
|
||||||
|
|
||||||
|
void power_off_free(PowerOff* power_off);
|
||||||
|
|
||||||
|
View* power_off_get_view(PowerOff* power_off);
|
||||||
|
|
||||||
|
void power_off_set_time_left(PowerOff* power_off, uint8_t time_left);
|
82
applications/power/power_settings_app/power_settings_app.c
Executable file
@ -0,0 +1,82 @@
|
|||||||
|
#include "power_settings_app.h"
|
||||||
|
|
||||||
|
static bool power_settings_custom_event_callback(void* context, uint32_t event) {
|
||||||
|
furi_assert(context);
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool power_settings_back_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
return scene_manager_handle_back_event(app->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void power_settings_tick_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
scene_manager_handle_tick_event(app->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerSettingsApp* power_settings_app_alloc() {
|
||||||
|
PowerSettingsApp* app = furi_alloc(sizeof(PowerSettingsApp));
|
||||||
|
|
||||||
|
// Records
|
||||||
|
app->gui = furi_record_open("gui");
|
||||||
|
app->power = furi_record_open("power");
|
||||||
|
|
||||||
|
// View dispatcher
|
||||||
|
app->view_dispatcher = view_dispatcher_alloc();
|
||||||
|
app->scene_manager = scene_manager_alloc(&power_settings_scene_handlers, app);
|
||||||
|
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||||
|
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||||
|
view_dispatcher_set_custom_event_callback(
|
||||||
|
app->view_dispatcher, power_settings_custom_event_callback);
|
||||||
|
view_dispatcher_set_navigation_event_callback(
|
||||||
|
app->view_dispatcher, power_settings_back_event_callback);
|
||||||
|
view_dispatcher_set_tick_event_callback(
|
||||||
|
app->view_dispatcher, power_settings_tick_event_callback, 2000);
|
||||||
|
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||||
|
|
||||||
|
// Views
|
||||||
|
app->batery_info = battery_info_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
PowerSettingsAppViewBatteryInfo,
|
||||||
|
battery_info_get_view(app->batery_info));
|
||||||
|
app->submenu = submenu_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, PowerSettingsAppViewSubmenu, submenu_get_view(app->submenu));
|
||||||
|
app->dialog = dialog_ex_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, PowerSettingsAppViewDialog, dialog_ex_get_view(app->dialog));
|
||||||
|
|
||||||
|
// Set first scene
|
||||||
|
scene_manager_next_scene(app->scene_manager, PowerSettingsAppSceneStart);
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_app_free(PowerSettingsApp* app) {
|
||||||
|
furi_assert(app);
|
||||||
|
// Views
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, PowerSettingsAppViewBatteryInfo);
|
||||||
|
battery_info_free(app->batery_info);
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, PowerSettingsAppViewSubmenu);
|
||||||
|
submenu_free(app->submenu);
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, PowerSettingsAppViewDialog);
|
||||||
|
dialog_ex_free(app->dialog);
|
||||||
|
// View dispatcher
|
||||||
|
view_dispatcher_free(app->view_dispatcher);
|
||||||
|
scene_manager_free(app->scene_manager);
|
||||||
|
// Records
|
||||||
|
furi_record_close("power");
|
||||||
|
furi_record_close("gui");
|
||||||
|
free(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int32_t power_settings_app(void* p) {
|
||||||
|
PowerSettingsApp* app = power_settings_app_alloc();
|
||||||
|
view_dispatcher_run(app->view_dispatcher);
|
||||||
|
power_settings_app_free(app);
|
||||||
|
return 0;
|
||||||
|
}
|
31
applications/power/power_settings_app/power_settings_app.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <power/power_service/power.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/view.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <gui/scene_manager.h>
|
||||||
|
|
||||||
|
#include "views/battery_info.h"
|
||||||
|
#include <gui/modules/submenu.h>
|
||||||
|
#include <gui/modules/dialog_ex.h>
|
||||||
|
|
||||||
|
#include "scenes/power_settings_scene.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Power* power;
|
||||||
|
Gui* gui;
|
||||||
|
SceneManager* scene_manager;
|
||||||
|
ViewDispatcher* view_dispatcher;
|
||||||
|
BatteryInfo* batery_info;
|
||||||
|
Submenu* submenu;
|
||||||
|
DialogEx* dialog;
|
||||||
|
PowerInfo info;
|
||||||
|
} PowerSettingsApp;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PowerSettingsAppViewBatteryInfo,
|
||||||
|
PowerSettingsAppViewSubmenu,
|
||||||
|
PowerSettingsAppViewDialog,
|
||||||
|
} PowerSettingsAppView;
|
@ -0,0 +1,17 @@
|
|||||||
|
#include "../power_settings_app.h"
|
||||||
|
|
||||||
|
void power_settings_scene_usb_disconnect_on_enter(void* context) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
|
||||||
|
dialog_ex_set_header(
|
||||||
|
app->dialog, "Disconnect USB for safe\nshutdown", 64, 26, AlignCenter, AlignTop);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool power_settings_scene_usb_disconnect_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_usb_disconnect_on_exit(void* context) {
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
#include "power_settings_scene.h"
|
||||||
|
|
||||||
|
// Generate scene on_enter handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||||
|
void (*const power_settings_on_enter_handlers[])(void*) = {
|
||||||
|
#include "power_settings_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_event handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||||
|
bool (*const power_settings_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||||
|
#include "power_settings_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_exit handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||||
|
void (*const power_settings_on_exit_handlers[])(void* context) = {
|
||||||
|
#include "power_settings_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Initialize scene handlers configuration structure
|
||||||
|
const SceneManagerHandlers power_settings_scene_handlers = {
|
||||||
|
.on_enter_handlers = power_settings_on_enter_handlers,
|
||||||
|
.on_event_handlers = power_settings_on_event_handlers,
|
||||||
|
.on_exit_handlers = power_settings_on_exit_handlers,
|
||||||
|
.scene_num = PowerSettingsAppSceneNum,
|
||||||
|
};
|
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gui/scene_manager.h>
|
||||||
|
|
||||||
|
// Generate scene id and total number
|
||||||
|
#define ADD_SCENE(prefix, name, id) PowerSettingsAppScene##id,
|
||||||
|
typedef enum {
|
||||||
|
#include "power_settings_scene_config.h"
|
||||||
|
PowerSettingsAppSceneNum,
|
||||||
|
} PowerSettingsAppScene;
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
extern const SceneManagerHandlers power_settings_scene_handlers;
|
||||||
|
|
||||||
|
// Generate scene on_enter handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||||
|
#include "power_settings_scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_event handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) \
|
||||||
|
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||||
|
#include "power_settings_scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_exit handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||||
|
#include "power_settings_scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
@ -0,0 +1,34 @@
|
|||||||
|
#include "../power_settings_app.h"
|
||||||
|
|
||||||
|
static void power_settings_scene_battery_info_update_model(PowerSettingsApp* app) {
|
||||||
|
power_get_info(app->power, &app->info);
|
||||||
|
BatteryInfoModel battery_info_data = {
|
||||||
|
.vbus_voltage = app->info.voltage_vbus,
|
||||||
|
.gauge_voltage = app->info.voltage_gauge,
|
||||||
|
.gauge_current = app->info.current_gauge,
|
||||||
|
.gauge_temperature = app->info.temperature_gauge,
|
||||||
|
.charge = app->info.charge,
|
||||||
|
.health = app->info.health,
|
||||||
|
};
|
||||||
|
battery_info_set_data(app->batery_info, &battery_info_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_battery_info_on_enter(void* context) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
power_settings_scene_battery_info_update_model(app);
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewBatteryInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool power_settings_scene_battery_info_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeTick) {
|
||||||
|
power_settings_scene_battery_info_update_model(app);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_battery_info_on_exit(void* context) {
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
ADD_SCENE(power_settings, start, Start)
|
||||||
|
ADD_SCENE(power_settings, battery_info, BatteryInfo)
|
||||||
|
ADD_SCENE(power_settings, reboot, Reboot)
|
||||||
|
ADD_SCENE(power_settings, power_off, PowerOff)
|
||||||
|
ADD_SCENE(power_settings, usb_disconnect, UsbDisconnect)
|
@ -0,0 +1,48 @@
|
|||||||
|
#include "../power_settings_app.h"
|
||||||
|
|
||||||
|
void power_settings_scene_power_off_dialog_callback(DialogExResult result, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_power_off_on_enter(void* context) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
DialogEx* dialog = app->dialog;
|
||||||
|
|
||||||
|
dialog_ex_set_header(dialog, "Turn off Device?", 64, 2, AlignCenter, AlignTop);
|
||||||
|
dialog_ex_set_text(
|
||||||
|
dialog, " I will be\nwaiting for\n you here...", 78, 16, AlignLeft, AlignTop);
|
||||||
|
dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52);
|
||||||
|
dialog_ex_set_left_button_text(dialog, "Back");
|
||||||
|
dialog_ex_set_right_button_text(dialog, "OFF");
|
||||||
|
dialog_ex_set_result_callback(dialog, power_settings_scene_power_off_dialog_callback);
|
||||||
|
dialog_ex_set_context(dialog, app);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool power_settings_scene_power_off_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == DialogExResultLeft) {
|
||||||
|
scene_manager_previous_scene(app->scene_manager);
|
||||||
|
} else if(event.event == DialogExResultRight) {
|
||||||
|
power_off();
|
||||||
|
// Check if USB is connected
|
||||||
|
power_get_info(app->power, &app->info);
|
||||||
|
if(app->info.voltage_vbus > 4.0f) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, PowerSettingsAppSceneUsbDisconnect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_power_off_on_exit(void* context) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
dialog_ex_clean(app->dialog);
|
||||||
|
}
|
52
applications/power/power_settings_app/scenes/power_settings_scene_reboot.c
Executable file
@ -0,0 +1,52 @@
|
|||||||
|
#include "../power_settings_app.h"
|
||||||
|
|
||||||
|
enum PowerSettingsRebootSubmenuIndex {
|
||||||
|
PowerSettingsRebootSubmenuIndexDfu,
|
||||||
|
PowerSettingsRebootSubmenuIndexOs,
|
||||||
|
};
|
||||||
|
|
||||||
|
void power_settings_scene_reboot_submenu_callback(void* context, uint32_t index) {
|
||||||
|
furi_assert(context);
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_reboot_on_enter(void* context) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
Submenu* submenu = app->submenu;
|
||||||
|
|
||||||
|
submenu_set_header(submenu, "Reboot type");
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Firmware upgrade",
|
||||||
|
PowerSettingsRebootSubmenuIndexDfu,
|
||||||
|
power_settings_scene_reboot_submenu_callback,
|
||||||
|
app);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Flipper OS",
|
||||||
|
PowerSettingsRebootSubmenuIndexOs,
|
||||||
|
power_settings_scene_reboot_submenu_callback,
|
||||||
|
app);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool power_settings_scene_reboot_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == PowerSettingsRebootSubmenuIndexDfu) {
|
||||||
|
power_reboot(PowerBootModeDfu);
|
||||||
|
} else if(event.event == PowerSettingsRebootSubmenuIndexOs) {
|
||||||
|
power_reboot(PowerBootModeNormal);
|
||||||
|
}
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_reboot_on_exit(void* context) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
submenu_clean(app->submenu);
|
||||||
|
}
|
64
applications/power/power_settings_app/scenes/power_settings_scene_start.c
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
#include "../power_settings_app.h"
|
||||||
|
|
||||||
|
enum PowerSettingsSubmenuIndex {
|
||||||
|
PowerSettingsSubmenuIndexBatteryInfo,
|
||||||
|
PowerSettingsSubmenuIndexReboot,
|
||||||
|
PowerSettingsSubmenuIndexOff,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void power_settings_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||||
|
furi_assert(context);
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_start_on_enter(void* context) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
Submenu* submenu = app->submenu;
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Battery info",
|
||||||
|
PowerSettingsSubmenuIndexBatteryInfo,
|
||||||
|
power_settings_scene_start_submenu_callback,
|
||||||
|
app);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Reboot",
|
||||||
|
PowerSettingsSubmenuIndexReboot,
|
||||||
|
power_settings_scene_start_submenu_callback,
|
||||||
|
app);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Power OFF",
|
||||||
|
PowerSettingsSubmenuIndexOff,
|
||||||
|
power_settings_scene_start_submenu_callback,
|
||||||
|
app);
|
||||||
|
submenu_set_selected_item(
|
||||||
|
submenu, scene_manager_get_scene_state(app->scene_manager, PowerSettingsAppSceneStart));
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool power_settings_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == PowerSettingsSubmenuIndexBatteryInfo) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, PowerSettingsAppSceneBatteryInfo);
|
||||||
|
} else if(event.event == PowerSettingsSubmenuIndexReboot) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, PowerSettingsAppSceneReboot);
|
||||||
|
} else if(event.event == PowerSettingsSubmenuIndexOff) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, PowerSettingsAppScenePowerOff);
|
||||||
|
}
|
||||||
|
scene_manager_set_scene_state(app->scene_manager, PowerSettingsAppSceneStart, event.event);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_settings_scene_start_on_exit(void* context) {
|
||||||
|
PowerSettingsApp* app = context;
|
||||||
|
submenu_clean(app->submenu);
|
||||||
|
}
|
126
applications/power/power_settings_app/views/battery_info.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#include "battery_info.h"
|
||||||
|
#include <furi.h>
|
||||||
|
#include <gui/elements.h>
|
||||||
|
|
||||||
|
struct BatteryInfo {
|
||||||
|
View* view;
|
||||||
|
};
|
||||||
|
|
||||||
|
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, BatteryInfoModel* data, int x, int y) {
|
||||||
|
char emote[20] = {};
|
||||||
|
char header[20] = {};
|
||||||
|
char value[20] = {};
|
||||||
|
|
||||||
|
int32_t drain_current = data->gauge_current * (-1000);
|
||||||
|
uint32_t charge_current = data->gauge_current * 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 > 100) {
|
||||||
|
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14);
|
||||||
|
} else if(data->charge < 10) {
|
||||||
|
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, 53, 0, 71, 39);
|
||||||
|
|
||||||
|
// Set text
|
||||||
|
if(charge_current > 0) {
|
||||||
|
snprintf(emote, sizeof(emote), "%s", "Yummy!");
|
||||||
|
snprintf(header, sizeof(header), "%s", "Charging at");
|
||||||
|
snprintf(
|
||||||
|
value,
|
||||||
|
sizeof(value),
|
||||||
|
"%ld.%ldV %ldmA",
|
||||||
|
(uint32_t)(data->vbus_voltage),
|
||||||
|
(uint32_t)(data->vbus_voltage * 10) % 10,
|
||||||
|
charge_current);
|
||||||
|
} else if(drain_current > 0) {
|
||||||
|
snprintf(emote, sizeof(emote), "%s", drain_current > 100 ? "Oh no!" : "Om-nom-nom!");
|
||||||
|
snprintf(header, sizeof(header), "%s", "Consumption is");
|
||||||
|
snprintf(
|
||||||
|
value, sizeof(value), "%ld %s", drain_current, drain_current > 100 ? "mA!" : "mA");
|
||||||
|
} else if(charge_current != 0 || drain_current != 0) {
|
||||||
|
snprintf(header, 20, "...");
|
||||||
|
} else {
|
||||||
|
snprintf(header, sizeof(header), "Charged!");
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote);
|
||||||
|
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
|
||||||
|
canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
static void battery_info_draw_callback(Canvas* canvas, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
BatteryInfoModel* model = context;
|
||||||
|
|
||||||
|
canvas_clear(canvas);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
draw_battery(canvas, model, 0, 5);
|
||||||
|
|
||||||
|
char batt_level[10];
|
||||||
|
char temperature[10];
|
||||||
|
char voltage[10];
|
||||||
|
char health[10];
|
||||||
|
|
||||||
|
snprintf(batt_level, sizeof(batt_level), "%ld%%", (uint32_t)model->charge);
|
||||||
|
snprintf(temperature, sizeof(temperature), "%ld C", (uint32_t)model->gauge_temperature);
|
||||||
|
snprintf(
|
||||||
|
voltage,
|
||||||
|
sizeof(voltage),
|
||||||
|
"%ld.%01ld V",
|
||||||
|
(uint32_t)model->gauge_voltage,
|
||||||
|
(uint32_t)(model->gauge_voltage * 10) % 10);
|
||||||
|
snprintf(health, sizeof(health), "%d%%", model->health);
|
||||||
|
|
||||||
|
draw_stat(canvas, 8, 42, &I_Battery_16x16, batt_level);
|
||||||
|
draw_stat(canvas, 40, 42, &I_Temperature_16x16, temperature);
|
||||||
|
draw_stat(canvas, 72, 42, &I_Voltage_16x16, voltage);
|
||||||
|
draw_stat(canvas, 104, 42, &I_Health_16x16, health);
|
||||||
|
}
|
||||||
|
|
||||||
|
BatteryInfo* battery_info_alloc() {
|
||||||
|
BatteryInfo* battery_info = furi_alloc(sizeof(BatteryInfo));
|
||||||
|
battery_info->view = view_alloc();
|
||||||
|
view_set_context(battery_info->view, battery_info);
|
||||||
|
view_allocate_model(battery_info->view, ViewModelTypeLocking, sizeof(BatteryInfoModel));
|
||||||
|
view_set_draw_callback(battery_info->view, battery_info_draw_callback);
|
||||||
|
|
||||||
|
return battery_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void battery_info_free(BatteryInfo* battery_info) {
|
||||||
|
furi_assert(battery_info);
|
||||||
|
view_free(battery_info->view);
|
||||||
|
free(battery_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
View* battery_info_get_view(BatteryInfo* battery_info) {
|
||||||
|
furi_assert(battery_info);
|
||||||
|
return battery_info->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data) {
|
||||||
|
furi_assert(battery_info);
|
||||||
|
furi_assert(data);
|
||||||
|
with_view_model(
|
||||||
|
battery_info->view, (BatteryInfoModel * model) {
|
||||||
|
memcpy(model, data, sizeof(BatteryInfoModel));
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
22
applications/power/power_settings_app/views/battery_info.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gui/view.h>
|
||||||
|
|
||||||
|
typedef struct BatteryInfo BatteryInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float vbus_voltage;
|
||||||
|
float gauge_voltage;
|
||||||
|
float gauge_current;
|
||||||
|
float gauge_temperature;
|
||||||
|
uint8_t charge;
|
||||||
|
uint8_t health;
|
||||||
|
} BatteryInfoModel;
|
||||||
|
|
||||||
|
BatteryInfo* battery_info_alloc();
|
||||||
|
|
||||||
|
void battery_info_free(BatteryInfo* battery_info);
|
||||||
|
|
||||||
|
View* battery_info_get_view(BatteryInfo* battery_info);
|
||||||
|
|
||||||
|
void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data);
|
@ -1,131 +0,0 @@
|
|||||||
#include "power_views.h"
|
|
||||||
#include <gui/elements.h>
|
|
||||||
|
|
||||||
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, PowerInfoModel* data, int x, int y) {
|
|
||||||
char emote[20];
|
|
||||||
char header[20];
|
|
||||||
char value[20];
|
|
||||||
|
|
||||||
int32_t drain_current = -data->current_gauge * 1000;
|
|
||||||
uint32_t charge_current = data->current_gauge * 1000;
|
|
||||||
// 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 > 100) {
|
|
||||||
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14);
|
|
||||||
} else if(data->charge < 10) {
|
|
||||||
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14);
|
|
||||||
} else {
|
|
||||||
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14);
|
|
||||||
}
|
|
||||||
|
|
||||||
//bubble
|
|
||||||
canvas_draw_frame(canvas, 57, 0, 71, 39);
|
|
||||||
canvas_draw_line(canvas, 53, 23, 57, 19);
|
|
||||||
canvas_draw_line(canvas, 53, 23, 57, 27);
|
|
||||||
canvas_set_color(canvas, ColorWhite);
|
|
||||||
canvas_draw_box(canvas, 57, 0, 2, 2);
|
|
||||||
canvas_draw_box(canvas, 57, 37, 2, 2);
|
|
||||||
canvas_draw_box(canvas, 126, 0, 2, 2);
|
|
||||||
canvas_draw_box(canvas, 126, 37, 2, 2);
|
|
||||||
canvas_draw_line(canvas, 57, 20, 57, 26);
|
|
||||||
canvas_set_color(canvas, ColorBlack);
|
|
||||||
canvas_draw_dot(canvas, 58, 1);
|
|
||||||
canvas_draw_dot(canvas, 58, 37);
|
|
||||||
canvas_draw_dot(canvas, 126, 1);
|
|
||||||
canvas_draw_dot(canvas, 126, 37);
|
|
||||||
|
|
||||||
// text
|
|
||||||
if(charge_current > 0) {
|
|
||||||
snprintf(emote, sizeof(emote), "%s", "Yummy!");
|
|
||||||
snprintf(header, sizeof(header), "%s", "Charging at");
|
|
||||||
snprintf(
|
|
||||||
value,
|
|
||||||
sizeof(value),
|
|
||||||
"%ld.%ldV %ldmA",
|
|
||||||
(uint32_t)(data->voltage_vbus),
|
|
||||||
(uint32_t)(data->voltage_vbus * 10) % 10,
|
|
||||||
charge_current);
|
|
||||||
} else if(drain_current > 0) {
|
|
||||||
snprintf(emote, sizeof(emote), "%s", drain_current > 100 ? "Oh no!" : "Om-nom-nom!");
|
|
||||||
snprintf(header, sizeof(header), "%s", "Consumption is");
|
|
||||||
snprintf(
|
|
||||||
value, sizeof(value), "%ld %s", drain_current, drain_current > 100 ? "mA!" : "mA");
|
|
||||||
} else if(charge_current != 0 || drain_current != 0) {
|
|
||||||
snprintf(header, 20, "%s", "...");
|
|
||||||
memset(value, 0, sizeof(value));
|
|
||||||
memset(emote, 0, sizeof(emote));
|
|
||||||
} else {
|
|
||||||
snprintf(header, sizeof(header), "%s", "Charged!");
|
|
||||||
memset(value, 0, sizeof(value));
|
|
||||||
memset(emote, 0, sizeof(emote));
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote);
|
|
||||||
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
|
|
||||||
canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
void power_info_draw_callback(Canvas* canvas, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
PowerInfoModel* data = context;
|
|
||||||
|
|
||||||
canvas_clear(canvas);
|
|
||||||
canvas_set_color(canvas, ColorBlack);
|
|
||||||
draw_battery(canvas, data, 0, 5);
|
|
||||||
|
|
||||||
char batt_level[10];
|
|
||||||
char temperature[10];
|
|
||||||
char voltage[10];
|
|
||||||
char health[10];
|
|
||||||
|
|
||||||
snprintf(batt_level, sizeof(batt_level), "%ld%s", (uint32_t)data->charge, "%");
|
|
||||||
snprintf(temperature, sizeof(temperature), "%ld %s", (uint32_t)data->temperature_gauge, "C");
|
|
||||||
snprintf(
|
|
||||||
voltage,
|
|
||||||
sizeof(voltage),
|
|
||||||
"%ld.%01ld V",
|
|
||||||
(uint32_t)data->voltage_gauge,
|
|
||||||
(uint32_t)(data->voltage_gauge * 10) % 10);
|
|
||||||
snprintf(health, sizeof(health), "%d%s", data->health, "%");
|
|
||||||
|
|
||||||
draw_stat(canvas, 8, 42, &I_Battery_16x16, batt_level);
|
|
||||||
draw_stat(canvas, 40, 42, &I_Temperature_16x16, temperature);
|
|
||||||
draw_stat(canvas, 72, 42, &I_Voltage_16x16, voltage);
|
|
||||||
draw_stat(canvas, 104, 42, &I_Health_16x16, health);
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_off_draw_callback(Canvas* canvas, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
PowerOffModel* model = context;
|
|
||||||
|
|
||||||
canvas_set_color(canvas, ColorBlack);
|
|
||||||
canvas_set_font(canvas, FontPrimary);
|
|
||||||
canvas_draw_str(canvas, 2, 15, "!!! Low Battery !!!");
|
|
||||||
|
|
||||||
char buffer[64];
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
|
||||||
canvas_draw_str(canvas, 5, 30, "Connect to charger");
|
|
||||||
snprintf(
|
|
||||||
buffer,
|
|
||||||
64,
|
|
||||||
"Or poweroff in %lds",
|
|
||||||
(model->poweroff_tick - osKernelGetTickCount()) / osKernelGetTickFreq());
|
|
||||||
canvas_draw_str(canvas, 5, 42, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_disconnect_draw_callback(Canvas* canvas, void* context) {
|
|
||||||
canvas_set_font(canvas, FontPrimary);
|
|
||||||
elements_multiline_text_aligned(
|
|
||||||
canvas, 64, 32, AlignCenter, AlignCenter, "It's now safe to turn off\nyour flipper");
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <furi.h>
|
|
||||||
#include <gui/canvas.h>
|
|
||||||
#include <gui/view.h>
|
|
||||||
|
|
||||||
typedef enum { PowerViewInfo, PowerViewDialog, PowerViewOff, PowerViewDisconnect } PowerView;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float current_charger;
|
|
||||||
float current_gauge;
|
|
||||||
|
|
||||||
float voltage_charger;
|
|
||||||
float voltage_gauge;
|
|
||||||
float voltage_vbus;
|
|
||||||
|
|
||||||
uint32_t capacity_remaining;
|
|
||||||
uint32_t capacity_full;
|
|
||||||
|
|
||||||
float temperature_charger;
|
|
||||||
float temperature_gauge;
|
|
||||||
|
|
||||||
uint8_t charge;
|
|
||||||
uint8_t health;
|
|
||||||
} PowerInfoModel;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t poweroff_tick;
|
|
||||||
bool battery_low;
|
|
||||||
} PowerOffModel;
|
|
||||||
|
|
||||||
void power_info_draw_callback(Canvas* canvas, void* context);
|
|
||||||
|
|
||||||
void power_off_draw_callback(Canvas* canvas, void* context);
|
|
||||||
|
|
||||||
void power_disconnect_draw_callback(Canvas* canvas, void* context);
|
|
@ -5,64 +5,64 @@ extern const Icon I_Certification1_103x23;
|
|||||||
extern const Icon I_Certification2_119x30;
|
extern const Icon I_Certification2_119x30;
|
||||||
extern const Icon A_WatchingTV_128x64;
|
extern const Icon A_WatchingTV_128x64;
|
||||||
extern const Icon A_Wink_128x64;
|
extern const Icon A_Wink_128x64;
|
||||||
extern const Icon I_125_10px;
|
|
||||||
extern const Icon I_ble_10px;
|
|
||||||
extern const Icon I_dir_10px;
|
extern const Icon I_dir_10px;
|
||||||
extern const Icon I_ibutt_10px;
|
|
||||||
extern const Icon I_ir_10px;
|
|
||||||
extern const Icon I_Nfc_10px;
|
extern const Icon I_Nfc_10px;
|
||||||
extern const Icon I_sub1_10px;
|
extern const Icon I_sub1_10px;
|
||||||
|
extern const Icon I_ir_10px;
|
||||||
|
extern const Icon I_ibutt_10px;
|
||||||
extern const Icon I_unknown_10px;
|
extern const Icon I_unknown_10px;
|
||||||
extern const Icon I_ButtonCenter_7x7;
|
extern const Icon I_ble_10px;
|
||||||
extern const Icon I_ButtonLeftSmall_3x5;
|
extern const Icon I_125_10px;
|
||||||
extern const Icon I_ButtonLeft_4x7;
|
|
||||||
extern const Icon I_ButtonRightSmall_3x5;
|
extern const Icon I_ButtonRightSmall_3x5;
|
||||||
extern const Icon I_ButtonRight_4x7;
|
extern const Icon I_ButtonLeft_4x7;
|
||||||
|
extern const Icon I_ButtonLeftSmall_3x5;
|
||||||
extern const Icon I_DFU_128x50;
|
extern const Icon I_DFU_128x50;
|
||||||
extern const Icon I_Warning_30x23;
|
extern const Icon I_Warning_30x23;
|
||||||
extern const Icon I_DolphinFirstStart0_70x53;
|
extern const Icon I_ButtonRight_4x7;
|
||||||
extern const Icon I_DolphinFirstStart1_59x53;
|
extern const Icon I_ButtonCenter_7x7;
|
||||||
extern const Icon I_DolphinFirstStart2_59x51;
|
|
||||||
extern const Icon I_DolphinFirstStart3_57x48;
|
|
||||||
extern const Icon I_DolphinFirstStart4_67x53;
|
|
||||||
extern const Icon I_DolphinFirstStart5_54x49;
|
|
||||||
extern const Icon I_DolphinFirstStart6_58x54;
|
|
||||||
extern const Icon I_DolphinFirstStart7_61x51;
|
|
||||||
extern const Icon I_DolphinFirstStart8_56x51;
|
|
||||||
extern const Icon I_DolphinOkay_41x43;
|
extern const Icon I_DolphinOkay_41x43;
|
||||||
|
extern const Icon I_DolphinFirstStart4_67x53;
|
||||||
|
extern const Icon I_DolphinFirstStart2_59x51;
|
||||||
|
extern const Icon I_DolphinFirstStart5_54x49;
|
||||||
|
extern const Icon I_DolphinFirstStart0_70x53;
|
||||||
|
extern const Icon I_DolphinFirstStart6_58x54;
|
||||||
|
extern const Icon I_DolphinFirstStart1_59x53;
|
||||||
|
extern const Icon I_DolphinFirstStart8_56x51;
|
||||||
|
extern const Icon I_DolphinFirstStart7_61x51;
|
||||||
extern const Icon I_Flipper_young_80x60;
|
extern const Icon I_Flipper_young_80x60;
|
||||||
extern const Icon I_DoorLeft_70x55;
|
extern const Icon I_DolphinFirstStart3_57x48;
|
||||||
|
extern const Icon I_PassportBottom_128x17;
|
||||||
extern const Icon I_DoorLeft_8x56;
|
extern const Icon I_DoorLeft_8x56;
|
||||||
extern const Icon I_DoorLocked_10x56;
|
extern const Icon I_DoorLocked_10x56;
|
||||||
extern const Icon I_DoorRight_70x55;
|
|
||||||
extern const Icon I_DoorRight_8x56;
|
extern const Icon I_DoorRight_8x56;
|
||||||
extern const Icon I_LockPopup_100x49;
|
extern const Icon I_DoorLeft_70x55;
|
||||||
extern const Icon I_PassportBottom_128x17;
|
|
||||||
extern const Icon I_PassportLeft_6x47;
|
extern const Icon I_PassportLeft_6x47;
|
||||||
extern const Icon I_Back_15x10;
|
extern const Icon I_DoorRight_70x55;
|
||||||
|
extern const Icon I_LockPopup_100x49;
|
||||||
|
extern const Icon I_Mute_25x27;
|
||||||
|
extern const Icon I_IrdaArrowUp_4x8;
|
||||||
|
extern const Icon I_Up_hvr_25x27;
|
||||||
|
extern const Icon I_Mute_hvr_25x27;
|
||||||
|
extern const Icon I_Vol_down_25x27;
|
||||||
extern const Icon I_Down_25x27;
|
extern const Icon I_Down_25x27;
|
||||||
|
extern const Icon I_Power_hvr_25x27;
|
||||||
|
extern const Icon I_IrdaLearnShort_128x31;
|
||||||
|
extern const Icon I_IrdaArrowDown_4x8;
|
||||||
|
extern const Icon I_Vol_down_hvr_25x27;
|
||||||
|
extern const Icon I_IrdaLearn_128x64;
|
||||||
extern const Icon I_Down_hvr_25x27;
|
extern const Icon I_Down_hvr_25x27;
|
||||||
extern const Icon I_Fill_marker_7x7;
|
extern const Icon I_Fill_marker_7x7;
|
||||||
extern const Icon I_IrdaArrowDown_4x8;
|
|
||||||
extern const Icon I_IrdaArrowUp_4x8;
|
|
||||||
extern const Icon I_IrdaLearnShort_128x31;
|
|
||||||
extern const Icon I_IrdaLearn_128x64;
|
|
||||||
extern const Icon I_IrdaSendShort_128x34;
|
|
||||||
extern const Icon I_IrdaSend_128x64;
|
|
||||||
extern const Icon I_Mute_25x27;
|
|
||||||
extern const Icon I_Mute_hvr_25x27;
|
|
||||||
extern const Icon I_Power_25x27;
|
extern const Icon I_Power_25x27;
|
||||||
extern const Icon I_Power_hvr_25x27;
|
|
||||||
extern const Icon I_Up_25x27;
|
|
||||||
extern const Icon I_Up_hvr_25x27;
|
|
||||||
extern const Icon I_Vol_down_25x27;
|
|
||||||
extern const Icon I_Vol_down_hvr_25x27;
|
|
||||||
extern const Icon I_Vol_up_25x27;
|
extern const Icon I_Vol_up_25x27;
|
||||||
|
extern const Icon I_Up_25x27;
|
||||||
|
extern const Icon I_Back_15x10;
|
||||||
|
extern const Icon I_IrdaSend_128x64;
|
||||||
|
extern const Icon I_IrdaSendShort_128x34;
|
||||||
extern const Icon I_Vol_up_hvr_25x27;
|
extern const Icon I_Vol_up_hvr_25x27;
|
||||||
extern const Icon I_KeyBackspaceSelected_16x9;
|
|
||||||
extern const Icon I_KeyBackspace_16x9;
|
|
||||||
extern const Icon I_KeySaveSelected_24x11;
|
|
||||||
extern const Icon I_KeySave_24x11;
|
extern const Icon I_KeySave_24x11;
|
||||||
|
extern const Icon I_KeyBackspaceSelected_16x9;
|
||||||
|
extern const Icon I_KeySaveSelected_24x11;
|
||||||
|
extern const Icon I_KeyBackspace_16x9;
|
||||||
extern const Icon A_125khz_14;
|
extern const Icon A_125khz_14;
|
||||||
extern const Icon A_Bluetooth_14;
|
extern const Icon A_Bluetooth_14;
|
||||||
extern const Icon A_Debug_14;
|
extern const Icon A_Debug_14;
|
||||||
@ -81,41 +81,42 @@ extern const Icon A_U2F_14;
|
|||||||
extern const Icon A_iButton_14;
|
extern const Icon A_iButton_14;
|
||||||
extern const Icon I_Detailed_chip_17x13;
|
extern const Icon I_Detailed_chip_17x13;
|
||||||
extern const Icon I_Medium_chip_22x21;
|
extern const Icon I_Medium_chip_22x21;
|
||||||
extern const Icon I_BatteryBody_52x28;
|
extern const Icon I_Health_16x16;
|
||||||
extern const Icon I_Battery_16x16;
|
|
||||||
extern const Icon I_FaceCharging_29x14;
|
extern const Icon I_FaceCharging_29x14;
|
||||||
extern const Icon I_FaceConfused_29x14;
|
extern const Icon I_BatteryBody_52x28;
|
||||||
|
extern const Icon I_Voltage_16x16;
|
||||||
|
extern const Icon I_Temperature_16x16;
|
||||||
extern const Icon I_FaceNopower_29x14;
|
extern const Icon I_FaceNopower_29x14;
|
||||||
extern const Icon I_FaceNormal_29x14;
|
extern const Icon I_FaceNormal_29x14;
|
||||||
extern const Icon I_Health_16x16;
|
extern const Icon I_Battery_16x16;
|
||||||
extern const Icon I_Temperature_16x16;
|
extern const Icon I_FaceConfused_29x14;
|
||||||
extern const Icon I_Voltage_16x16;
|
|
||||||
extern const Icon I_RFIDBigChip_37x36;
|
|
||||||
extern const Icon I_RFIDDolphinReceive_97x61;
|
|
||||||
extern const Icon I_RFIDDolphinSend_97x61;
|
|
||||||
extern const Icon I_RFIDDolphinSuccess_108x57;
|
extern const Icon I_RFIDDolphinSuccess_108x57;
|
||||||
extern const Icon I_SDError_43x35;
|
extern const Icon I_RFIDBigChip_37x36;
|
||||||
|
extern const Icon I_RFIDDolphinSend_97x61;
|
||||||
|
extern const Icon I_RFIDDolphinReceive_97x61;
|
||||||
extern const Icon I_SDQuestion_35x43;
|
extern const Icon I_SDQuestion_35x43;
|
||||||
extern const Icon I_Background_128x11;
|
extern const Icon I_SDError_43x35;
|
||||||
extern const Icon I_Background_128x8;
|
extern const Icon I_Cry_dolph_55x52;
|
||||||
extern const Icon I_BadUsb_9x8;
|
extern const Icon I_BadUsb_9x8;
|
||||||
extern const Icon I_Battery_19x8;
|
|
||||||
extern const Icon I_Battery_26x8;
|
|
||||||
extern const Icon I_Bluetooth_5x8;
|
|
||||||
extern const Icon I_Lock_8x8;
|
|
||||||
extern const Icon I_PlaceholderL_11x13;
|
|
||||||
extern const Icon I_PlaceholderR_30x13;
|
extern const Icon I_PlaceholderR_30x13;
|
||||||
extern const Icon I_SDcardFail_11x8;
|
extern const Icon I_Background_128x8;
|
||||||
|
extern const Icon I_Lock_8x8;
|
||||||
|
extern const Icon I_Battery_26x8;
|
||||||
|
extern const Icon I_PlaceholderL_11x13;
|
||||||
|
extern const Icon I_Battery_19x8;
|
||||||
extern const Icon I_SDcardMounted_11x8;
|
extern const Icon I_SDcardMounted_11x8;
|
||||||
|
extern const Icon I_SDcardFail_11x8;
|
||||||
extern const Icon I_USBConnected_15x8;
|
extern const Icon I_USBConnected_15x8;
|
||||||
extern const Icon I_Lock_7x8;
|
extern const Icon I_Bluetooth_5x8;
|
||||||
extern const Icon I_Quest_7x8;
|
extern const Icon I_Background_128x11;
|
||||||
extern const Icon I_Scanning_123x52;
|
extern const Icon I_Scanning_123x52;
|
||||||
|
extern const Icon I_Quest_7x8;
|
||||||
extern const Icon I_Unlock_7x8;
|
extern const Icon I_Unlock_7x8;
|
||||||
extern const Icon I_DolphinExcited_64x63;
|
extern const Icon I_Lock_7x8;
|
||||||
extern const Icon I_DolphinMafia_115x62;
|
extern const Icon I_DolphinMafia_115x62;
|
||||||
extern const Icon I_DolphinNice_96x59;
|
extern const Icon I_DolphinExcited_64x63;
|
||||||
extern const Icon I_DolphinWait_61x59;
|
|
||||||
extern const Icon I_iButtonDolphinSuccess_109x60;
|
extern const Icon I_iButtonDolphinSuccess_109x60;
|
||||||
extern const Icon I_iButtonDolphinVerySuccess_108x52;
|
extern const Icon I_iButtonDolphinVerySuccess_108x52;
|
||||||
extern const Icon I_iButtonKey_49x44;
|
extern const Icon I_iButtonKey_49x44;
|
||||||
|
extern const Icon I_DolphinNice_96x59;
|
||||||
|
extern const Icon I_DolphinWait_61x59;
|
||||||
|
BIN
assets/icons/Settings/Cry_dolph_55x52.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |