diff --git a/applications/applications.c b/applications/applications.c index 57596c473..7b125f6a1 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -42,6 +42,7 @@ extern int32_t usb_mouse_app(void* p); extern int32_t usb_test_app(void* p); extern int32_t vibro_test_app(void* p); extern int32_t bt_hid_app(void* p); +extern int32_t battery_test_app(void* p); // Plugins extern int32_t music_player_app(void* p); @@ -278,6 +279,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = { #ifdef APP_DISPLAY_TEST {.app = display_test_app, .name = "Display Test", .stack_size = 1024, .icon = NULL}, #endif + +#ifdef APP_BATTERY_TEST + {.app = battery_test_app, .name = "Battery Test", .stack_size = 1024, .icon = NULL}, +#endif }; const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication); diff --git a/applications/applications.mk b/applications/applications.mk index 0aa887745..aa17e05f3 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -155,6 +155,11 @@ CFLAGS += -DAPP_DISPLAY_TEST SRV_GUI = 1 endif +APP_BATTERY_TEST ?= 0 +ifeq ($(APP_BATTERY_TEST), 1) +CFLAGS += -DAPP_BATTERY_TEST +SRV_GUI = 1 +endif APP_USB_MOUSE ?= 0 ifeq ($(APP_USB_MOUSE), 1) diff --git a/applications/desktop/animations/animation_manager.c b/applications/desktop/animations/animation_manager.c index 6f645fea3..2778b29f6 100644 --- a/applications/desktop/animations/animation_manager.c +++ b/applications/desktop/animations/animation_manager.c @@ -268,9 +268,7 @@ static StorageAnimation* animation_storage_fill_animation_list(&animation_list); Power* power = furi_record_open("power"); - PowerInfo info; - power_get_info(power, &info); - bool battery_is_well = power_is_battery_well(&info); + bool battery_is_well = power_is_battery_healthy(power); furi_record_close("power"); Storage* storage = furi_record_open("storage"); diff --git a/applications/power/battery_test_app/battery_test_app.c b/applications/power/battery_test_app/battery_test_app.c new file mode 100755 index 000000000..6097cec57 --- /dev/null +++ b/applications/power/battery_test_app/battery_test_app.c @@ -0,0 +1,100 @@ +#include "battery_test_app.h" + +#include + +void battery_test_dialog_callback(DialogExResult result, void* context) { + furi_assert(context); + BatteryTestApp* app = context; + if(result == DialogExResultLeft) { + view_dispatcher_stop(app->view_dispatcher); + } else if(result == DialogExResultRight) { + view_dispatcher_switch_to_view(app->view_dispatcher, BatteryTestAppViewBatteryInfo); + } +} + +uint32_t battery_test_exit_confirm_view() { + return BatteryTestAppViewExitDialog; +} + +static void battery_test_battery_info_update_model(void* context) { + BatteryTestApp* app = context; + 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); + notification_message(app->notifications, &sequence_display_on); +} + +BatteryTestApp* battery_test_alloc() { + BatteryTestApp* app = furi_alloc(sizeof(BatteryTestApp)); + + // Records + app->gui = furi_record_open("gui"); + app->power = furi_record_open("power"); + app->notifications = furi_record_open("notification"); + + // View dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_tick_event_callback( + app->view_dispatcher, battery_test_battery_info_update_model, 500); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Views + app->batery_info = battery_info_alloc(); + view_set_previous_callback( + battery_info_get_view(app->batery_info), battery_test_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, + BatteryTestAppViewBatteryInfo, + battery_info_get_view(app->batery_info)); + + app->dialog = dialog_ex_alloc(); + dialog_ex_set_header(app->dialog, "Close battery test?", 64, 12, AlignCenter, AlignTop); + dialog_ex_set_left_button_text(app->dialog, "Exit"); + dialog_ex_set_right_button_text(app->dialog, "Stay"); + dialog_ex_set_result_callback(app->dialog, battery_test_dialog_callback); + dialog_ex_set_context(app->dialog, app); + + view_dispatcher_add_view( + app->view_dispatcher, BatteryTestAppViewExitDialog, dialog_ex_get_view(app->dialog)); + + battery_test_battery_info_update_model(app); + view_dispatcher_switch_to_view(app->view_dispatcher, BatteryTestAppViewBatteryInfo); + return app; +} + +void battery_test_free(BatteryTestApp* app) { + furi_assert(app); + + // Views + view_dispatcher_remove_view(app->view_dispatcher, BatteryTestAppViewBatteryInfo); + battery_info_free(app->batery_info); + view_dispatcher_remove_view(app->view_dispatcher, BatteryTestAppViewExitDialog); + dialog_ex_free(app->dialog); + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + // Records + furi_record_close("power"); + furi_record_close("gui"); + furi_record_close("notification"); + free(app); +} + +int32_t battery_test_app(void* p) { + BatteryTestApp* app = battery_test_alloc(); + // Disable battery low level notification + power_enable_low_battery_level_notification(app->power, false); + + view_dispatcher_run(app->view_dispatcher); + power_enable_low_battery_level_notification(app->power, true); + battery_test_free(app); + return 0; +} \ No newline at end of file diff --git a/applications/power/battery_test_app/battery_test_app.h b/applications/power/battery_test_app/battery_test_app.h new file mode 100644 index 000000000..9c17626da --- /dev/null +++ b/applications/power/battery_test_app/battery_test_app.h @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +typedef struct { + Power* power; + Gui* gui; + NotificationApp* notifications; + ViewDispatcher* view_dispatcher; + BatteryInfo* batery_info; + DialogEx* dialog; + PowerInfo info; +} BatteryTestApp; + +typedef enum { + BatteryTestAppViewBatteryInfo, + BatteryTestAppViewExitDialog, +} BatteryTestAppView; diff --git a/applications/power/power_service/power.c b/applications/power/power_service/power.c old mode 100644 new mode 100755 index 65749a69d..d9deb9d92 --- a/applications/power/power_service/power.c +++ b/applications/power/power_service/power.c @@ -7,11 +7,6 @@ #include #define POWER_OFF_TIMEOUT 90 -#define POWER_BATTERY_WELL_LEVEL 70 - -bool power_is_battery_well(PowerInfo* info) { - return info->health > POWER_BATTERY_WELL_LEVEL; -} void power_draw_battery_callback(Canvas* canvas, void* context) { furi_assert(context); @@ -50,7 +45,7 @@ Power* power_alloc() { power->state = PowerStateNotCharging; power->battery_low = false; power->power_off_timeout = POWER_OFF_TIMEOUT; - power->info_mtx = osMutexNew(NULL); + power->api_mtx = osMutexNew(NULL); // Gui power->view_dispatcher = view_dispatcher_alloc(); @@ -66,6 +61,7 @@ Power* power_alloc() { // Battery view port power->battery_view_port = power_battery_view_port_alloc(power); + power->show_low_bat_level_message = true; return power; } @@ -81,7 +77,7 @@ void power_free(Power* power) { view_port_free(power->battery_view_port); // State - osMutexDelete(power->info_mtx); + osMutexDelete(power->api_mtx); // FuriPubSub furi_pubsub_free(power->event_pubsub); @@ -135,17 +131,18 @@ static bool power_update_info(Power* power) { info.temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger); info.temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge); - osMutexAcquire(power->info_mtx, osWaitForever); + osMutexAcquire(power->api_mtx, osWaitForever); bool need_refresh = power->info.charge != info.charge; power->info = info; - osMutexRelease(power->info_mtx); + osMutexRelease(power->api_mtx); return need_refresh; } 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->info.charge == 0) && (power->info.voltage_vbus < 4.0f) && + power->show_low_bat_level_message) { if(!power->battery_low) { view_dispatcher_send_to_front(power->view_dispatcher); view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewOff); diff --git a/applications/power/power_service/power.h b/applications/power/power_service/power.h index 0e53fdef0..093c52ed9 100644 --- a/applications/power/power_service/power.h +++ b/applications/power/power_service/power.h @@ -50,19 +50,35 @@ typedef struct { void power_off(Power* power); /** Reboot device - * @param mode - PowerBootMode + * + * @param mode PowerBootMode */ void power_reboot(PowerBootMode mode); /** Get power info - * @param power - Power instance - * @param info - PowerInfo instance + * + * @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 + * + * @param power Power instance + * + * @return FuriPubSub instance */ FuriPubSub* power_get_pubsub(Power* power); -bool power_is_battery_well(PowerInfo* info); +/** Check battery health + * + * @return true if battery is healthy + */ +bool power_is_battery_healthy(Power* power); + +/** Enable or disable battery low level notification mesage + * + * @param power Power instance + * @param enable true - enable, false - disable + */ +void power_enable_low_battery_level_notification(Power* power, bool enable); diff --git a/applications/power/power_service/power_api.c b/applications/power/power_service/power_api.c index a3278f9b2..9509e6cb8 100644 --- a/applications/power/power_service/power_api.c +++ b/applications/power/power_service/power_api.c @@ -26,12 +26,28 @@ void power_get_info(Power* power, PowerInfo* info) { furi_assert(power); furi_assert(info); - osMutexAcquire(power->info_mtx, osWaitForever); + osMutexAcquire(power->api_mtx, osWaitForever); memcpy(info, &power->info, sizeof(power->info)); - osMutexRelease(power->info_mtx); + osMutexRelease(power->api_mtx); } FuriPubSub* power_get_pubsub(Power* power) { furi_assert(power); return power->event_pubsub; } + +bool power_is_battery_healthy(Power* power) { + furi_assert(power); + bool is_healthy = false; + osMutexAcquire(power->api_mtx, osWaitForever); + is_healthy = power->info.health > POWER_BATTERY_HEALTHY_LEVEL; + osMutexRelease(power->api_mtx); + return is_healthy; +} + +void power_enable_low_battery_level_notification(Power* power, bool enable) { + furi_assert(power); + osMutexAcquire(power->api_mtx, osWaitForever); + power->show_low_bat_level_message = enable; + osMutexRelease(power->api_mtx); +} diff --git a/applications/power/power_service/power_i.h b/applications/power/power_service/power_i.h index 9833df5f8..dd72b8192 100755 --- a/applications/power/power_service/power_i.h +++ b/applications/power/power_service/power_i.h @@ -11,6 +11,8 @@ #include +#define POWER_BATTERY_HEALTHY_LEVEL 70 + typedef enum { PowerStateNotCharging, PowerStateCharging, @@ -30,11 +32,13 @@ struct Power { PowerState state; PowerInfo info; - osMutexId_t info_mtx; bool battery_low; + bool show_low_bat_level_message; uint8_t battery_level; uint8_t power_off_timeout; + + osMutexId_t api_mtx; }; typedef enum { diff --git a/applications/power/power_settings_app/power_settings_app.c b/applications/power/power_settings_app/power_settings_app.c index 69adcc9e3..8e77716e9 100755 --- a/applications/power/power_settings_app/power_settings_app.c +++ b/applications/power/power_settings_app/power_settings_app.c @@ -74,7 +74,7 @@ void power_settings_app_free(PowerSettingsApp* app) { free(app); } -extern int32_t power_settings_app(void* p) { +int32_t power_settings_app(void* p) { PowerSettingsApp* app = power_settings_app_alloc(); view_dispatcher_run(app->view_dispatcher); power_settings_app_free(app);