[FL-1908] New animation update scheme (#737)

* Assets: update desktop animation frame rate and cleanup.

* Power: update ViewPort only if changed.

* Gui: tie IconAnimation with View, new update event generation scheme. Desktop: update IconAnimation usage.

Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
あく 2021-10-02 20:00:56 +03:00 committed by GitHub
parent 6f346597d2
commit 61aaed8abb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 271 additions and 175 deletions

View file

@ -45,7 +45,6 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
void desktop_scene_locked_on_exit(void* context) {
Desktop* desktop = (Desktop*)context;
DesktopLockedView* locked_view = desktop->locked_view;
desktop_locked_reset_counter(desktop->locked_view);
osTimerStop(locked_view->timer);
osTimerStop(desktop->locked_view->timer);
}

View file

@ -67,6 +67,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
desktop_switch_to_app(desktop, &FLIPPER_ARCHIVE);
consumed = true;
break;
case DesktopMainEventOpenFavorite:
desktop_settings_load(&desktop->settings);
desktop_switch_to_app(desktop, &FLIPPER_APPS[desktop->settings.favorite]);

View file

@ -20,13 +20,12 @@ void locked_view_timer_callback(void* context) {
}
// temporary locked screen animation managment
static void
desktop_scene_handler_set_scene(DesktopLockedView* locked_view, const Icon* icon_data) {
static void desktop_locked_set_scene(DesktopLockedView* locked_view, const Icon* icon_data) {
with_view_model(
locked_view->view, (DesktopLockedViewModel * model) {
if(model->animation) icon_animation_free(model->animation);
model->animation = icon_animation_alloc(icon_data);
icon_animation_start(model->animation);
view_tie_icon_animation(locked_view->view, model->animation);
return true;
});
}
@ -148,6 +147,25 @@ bool desktop_locked_input(InputEvent* event, void* context) {
return true;
}
void desktop_locked_enter(void* context) {
DesktopLockedView* locked_view = context;
with_view_model(
locked_view->view, (DesktopLockedViewModel * model) {
if(model->animation) icon_animation_start(model->animation);
return false;
});
}
void desktop_locked_exit(void* context) {
DesktopLockedView* locked_view = context;
with_view_model(
locked_view->view, (DesktopLockedViewModel * model) {
if(model->animation) icon_animation_stop(model->animation);
return false;
});
}
DesktopLockedView* desktop_locked_alloc() {
DesktopLockedView* locked_view = furi_alloc(sizeof(DesktopLockedView));
locked_view->view = view_alloc();
@ -158,8 +176,10 @@ DesktopLockedView* desktop_locked_alloc() {
view_set_context(locked_view->view, locked_view);
view_set_draw_callback(locked_view->view, (ViewDrawCallback)desktop_locked_render);
view_set_input_callback(locked_view->view, desktop_locked_input);
view_set_enter_callback(locked_view->view, desktop_locked_enter);
view_set_exit_callback(locked_view->view, desktop_locked_exit);
desktop_scene_handler_set_scene(locked_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
desktop_locked_set_scene(locked_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
return locked_view;
}

View file

@ -17,17 +17,18 @@ void desktop_main_set_callback(
void desktop_main_reset_hint(DesktopMainView* main_view) {
with_view_model(
main_view->view, (DesktopMainViewModel * model) {
model->hint_timeout = 0;
model->hint_expire_at = 0;
return true;
});
}
// temporary main screen animation managment
void desktop_scene_handler_set_scene(DesktopMainView* main_view, const Icon* icon_data) {
static void desktop_main_set_scene(DesktopMainView* main_view, const Icon* icon_data) {
with_view_model(
main_view->view, (DesktopMainViewModel * model) {
if(model->animation) icon_animation_free(model->animation);
model->animation = icon_animation_alloc(icon_data);
icon_animation_start(model->animation);
view_tie_icon_animation(main_view->view, model->animation);
return true;
});
}
@ -38,7 +39,6 @@ void desktop_scene_handler_switch_scene(DesktopMainView* main_view) {
if(icon_animation_is_last_frame(model->animation)) {
if(model->animation) icon_animation_free(model->animation);
model->animation = icon_animation_alloc(idle_scenes[model->scene_num]);
icon_animation_start(model->animation);
model->scene_num = random() % COUNT_OF(idle_scenes);
}
return true;
@ -53,8 +53,7 @@ void desktop_main_render(Canvas* canvas, void* model) {
canvas_draw_icon_animation(canvas, 0, -3, m->animation);
}
if(m->unlocked && m->hint_timeout) {
m->hint_timeout = CLAMP(m->hint_timeout - 1, 2, 0);
if(osKernelGetTickCount() < m->hint_expire_at) {
canvas_set_font(canvas, FontPrimary);
elements_multiline_text_framed(canvas, 42, 30, "Unlocked");
}
@ -87,6 +86,25 @@ bool desktop_main_input(InputEvent* event, void* context) {
return true;
}
void desktop_main_enter(void* context) {
DesktopMainView* main_view = context;
with_view_model(
main_view->view, (DesktopMainViewModel * model) {
if(model->animation) icon_animation_start(model->animation);
return false;
});
}
void desktop_main_exit(void* context) {
DesktopMainView* main_view = context;
with_view_model(
main_view->view, (DesktopMainViewModel * model) {
if(model->animation) icon_animation_stop(model->animation);
return false;
});
}
DesktopMainView* desktop_main_alloc() {
DesktopMainView* main_view = furi_alloc(sizeof(DesktopMainView));
main_view->view = view_alloc();
@ -94,8 +112,10 @@ DesktopMainView* desktop_main_alloc() {
view_set_context(main_view->view, main_view);
view_set_draw_callback(main_view->view, (ViewDrawCallback)desktop_main_render);
view_set_input_callback(main_view->view, desktop_main_input);
view_set_enter_callback(main_view->view, desktop_main_enter);
view_set_exit_callback(main_view->view, desktop_main_exit);
desktop_scene_handler_set_scene(main_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
desktop_main_set_scene(main_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
return main_view;
}
@ -109,8 +129,7 @@ void desktop_main_free(DesktopMainView* main_view) {
void desktop_main_unlocked(DesktopMainView* main_view) {
with_view_model(
main_view->view, (DesktopMainViewModel * model) {
model->unlocked = true;
model->hint_timeout = 2;
model->hint_expire_at = osKernelGetTickCount() + osKernelGetTickFreq();
return true;
});
}

View file

@ -28,8 +28,7 @@ struct DesktopMainView {
typedef struct {
IconAnimation* animation;
uint8_t scene_num;
uint8_t hint_timeout;
bool unlocked;
uint32_t hint_expire_at;
} DesktopMainViewModel;
void desktop_main_set_callback(
@ -40,4 +39,5 @@ void desktop_main_set_callback(
View* desktop_main_get_view(DesktopMainView* main_view);
DesktopMainView* desktop_main_alloc();
void desktop_main_free(DesktopMainView* main_view);

View file

@ -7,26 +7,26 @@ IconAnimation* icon_animation_alloc(const Icon* icon) {
furi_assert(icon);
IconAnimation* instance = furi_alloc(sizeof(IconAnimation));
instance->icon = icon;
instance->timer = osTimerNew(icon_animation_timer_callback, osTimerPeriodic, instance, NULL);
return instance;
}
void icon_animation_free(IconAnimation* instance) {
furi_assert(instance);
furi_check(osTimerDelete(instance->timer) == osOK);
free(instance);
}
const uint8_t* icon_animation_get_data(IconAnimation* instance) {
void icon_animation_set_update_callback(
IconAnimation* instance,
IconAnimationCallback callback,
void* context) {
furi_assert(instance);
if(instance->tick) {
uint32_t now = osKernelGetTickCount();
if(now < instance->tick) {
instance->tick = now;
icon_animation_next_frame(instance);
} else if(now - instance->tick > osKernelGetTickFreq() / instance->icon->frame_rate) {
instance->tick = now;
icon_animation_next_frame(instance);
}
}
instance->callback = callback;
instance->callback_context = context;
}
const uint8_t* icon_animation_get_data(IconAnimation* instance) {
return instance->icon->frames[instance->frame];
}
@ -35,6 +35,19 @@ void icon_animation_next_frame(IconAnimation* instance) {
instance->frame = (instance->frame + 1) % instance->icon->frame_count;
}
void icon_animation_timer_callback(void* context) {
furi_assert(context);
IconAnimation* instance = context;
if(!instance->animating) return;
icon_animation_next_frame(instance);
if(instance->callback) {
instance->callback(instance, instance->callback_context);
}
}
uint8_t icon_animation_get_width(IconAnimation* instance) {
furi_assert(instance);
return instance->icon->width;
@ -45,33 +58,26 @@ uint8_t icon_animation_get_height(IconAnimation* instance) {
return instance->icon->height;
}
bool icon_animation_is_animated(IconAnimation* instance) {
furi_assert(instance);
return instance->icon->frame_count > 1;
}
bool icon_animation_is_animating(IconAnimation* instance) {
furi_assert(instance);
return instance->tick > 0;
}
void icon_animation_start(IconAnimation* instance) {
furi_assert(instance);
instance->tick = osKernelGetTickCount();
if(!instance->animating) {
instance->animating = true;
furi_check(
osTimerStart(instance->timer, (osKernelGetTickFreq() / instance->icon->frame_rate)) ==
osOK);
}
}
void icon_animation_stop(IconAnimation* instance) {
furi_assert(instance);
instance->tick = 0;
instance->frame = 0;
}
uint8_t icon_animation_get_current_frame(IconAnimation* instance) {
furi_assert(instance);
return instance->frame;
if(instance->animating) {
instance->animating = false;
furi_check(osTimerStop(instance->timer) == osOK);
instance->frame = 0;
}
}
bool icon_animation_is_last_frame(IconAnimation* instance) {
furi_assert(instance);
return instance->icon->frame_count - instance->frame <= 1;
}
}

View file

@ -11,54 +11,41 @@ extern "C" {
typedef struct IconAnimation IconAnimation;
/*
* Allocate icon animation instance with const icon data.
typedef void (*IconAnimationCallback)(IconAnimation* instance, void* context);
/** Allocate icon animation instance with const icon data.
* always returns Icon or stops system if not enough memory
*/
IconAnimation* icon_animation_alloc(const Icon* icon);
/*
* Release icon animation instance
/** Release icon animation instance
*/
void icon_animation_free(IconAnimation* instance);
/*
* Get icon animation width
/** Get icon animation width
*/
void icon_animation_set_update_callback(
IconAnimation* instance,
IconAnimationCallback callback,
void* context);
/** Get icon animation width
*/
uint8_t icon_animation_get_width(IconAnimation* instance);
/*
* Get icon animation height
/** Get icon animation height
*/
uint8_t icon_animation_get_height(IconAnimation* instance);
/*
* Check if icon is animated
*/
bool icon_animation_is_animated(IconAnimation* instance);
/*
* Check if icon animation is active
*/
bool icon_animation_is_animating(IconAnimation* instance);
/*
* Start icon animation
/** Start icon animation
*/
void icon_animation_start(IconAnimation* instance);
/*
* Stop icon animation
/** Stop icon animation
*/
void icon_animation_stop(IconAnimation* instance);
/*
* Get current frame
*/
uint8_t icon_animation_get_current_frame(IconAnimation* instance);
/*
* Returns true if current frame is a last one
/** Returns true if current frame is a last one
*/
bool icon_animation_is_last_frame(IconAnimation* instance);

View file

@ -2,20 +2,22 @@
#include "icon_animation.h"
#include <stdint.h>
#include <furi.h>
struct IconAnimation {
const Icon* icon;
uint8_t frame;
uint32_t tick;
bool animating;
osTimerId_t timer;
IconAnimationCallback callback;
void* callback_context;
};
/*
* Get pointer to current frame data
*/
/** Get pointer to current frame data */
const uint8_t* icon_animation_get_data(IconAnimation* instance);
/*
* Advance to next frame
*/
/** Advance to next frame */
void icon_animation_next_frame(IconAnimation* instance);
/** IconAnimation timer callback */
void icon_animation_timer_callback(void* context);

54
applications/gui/modules/menu.c Executable file → Normal file
View file

@ -20,7 +20,7 @@ ARRAY_DEF(MenuItemArray, MenuItem, M_POD_OPLIST);
typedef struct {
MenuItemArray_t items;
uint8_t position;
size_t position;
} MenuModel;
static void menu_process_up(Menu* menu);
@ -32,7 +32,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
canvas_clear(canvas);
uint8_t position = model->position;
size_t position = model->position;
size_t items_count = MenuItemArray_size(model->items);
if(items_count) {
MenuItem* item;
@ -43,7 +43,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
item = MenuItemArray_get(model->items, shift_position);
if(item->icon) {
canvas_draw_icon_animation(canvas, 4, 3, item->icon);
icon_animation_stop(item->icon);
}
canvas_draw_str(canvas, 22, 14, item->label);
// Second line main
@ -52,7 +51,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
item = MenuItemArray_get(model->items, shift_position);
if(item->icon) {
canvas_draw_icon_animation(canvas, 4, 25, item->icon);
icon_animation_start(item->icon);
}
canvas_draw_str(canvas, 22, 36, item->label);
// Third line
@ -61,7 +59,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
item = MenuItemArray_get(model->items, shift_position);
if(item->icon) {
canvas_draw_icon_animation(canvas, 4, 47, item->icon);
icon_animation_stop(item->icon);
}
canvas_draw_str(canvas, 22, 58, item->label);
// Frame and scrollbar
@ -93,6 +90,30 @@ static bool menu_input_callback(InputEvent* event, void* context) {
return consumed;
}
static void menu_enter(void* context) {
Menu* menu = context;
with_view_model(
menu->view, (MenuModel * model) {
MenuItem* item = MenuItemArray_get(model->items, model->position);
if(item && item->icon) {
icon_animation_start(item->icon);
}
return false;
});
}
static void menu_exit(void* context) {
Menu* menu = context;
with_view_model(
menu->view, (MenuModel * model) {
MenuItem* item = MenuItemArray_get(model->items, model->position);
if(item && item->icon) {
icon_animation_stop(item->icon);
}
return false;
});
}
Menu* menu_alloc() {
Menu* menu = furi_alloc(sizeof(Menu));
menu->view = view_alloc(menu->view);
@ -100,6 +121,8 @@ Menu* menu_alloc() {
view_allocate_model(menu->view, ViewModelTypeLocking, sizeof(MenuModel));
view_set_draw_callback(menu->view, menu_draw_callback);
view_set_input_callback(menu->view, menu_input_callback);
view_set_enter_callback(menu->view, menu_enter);
view_set_exit_callback(menu->view, menu_exit);
with_view_model(
menu->view, (MenuModel * model) {
@ -143,6 +166,7 @@ void menu_add_item(
item = MenuItemArray_push_new(model->items);
item->label = label;
item->icon = icon;
view_tie_icon_animation(menu->view, item->icon);
item->index = index;
item->callback = callback;
item->callback_context = context;
@ -175,11 +199,21 @@ void menu_set_selected_item(Menu* menu, uint32_t index) {
static void menu_process_up(Menu* menu) {
with_view_model(
menu->view, (MenuModel * model) {
MenuItem* item = MenuItemArray_get(model->items, model->position);
if(item && item->icon) {
icon_animation_stop(item->icon);
}
if(model->position > 0) {
model->position--;
} else {
model->position = MenuItemArray_size(model->items) - 1;
}
item = MenuItemArray_get(model->items, model->position);
if(item && item->icon) {
icon_animation_start(item->icon);
}
return true;
});
}
@ -187,11 +221,21 @@ static void menu_process_up(Menu* menu) {
static void menu_process_down(Menu* menu) {
with_view_model(
menu->view, (MenuModel * model) {
MenuItem* item = MenuItemArray_get(model->items, model->position);
if(item && item->icon) {
icon_animation_stop(item->icon);
}
if(model->position < MenuItemArray_size(model->items) - 1) {
model->position++;
} else {
model->position = 0;
}
item = MenuItemArray_get(model->items, model->position);
if(item && item->icon) {
icon_animation_start(item->icon);
}
return true;
});
}

View file

@ -12,6 +12,11 @@ void view_free(View* view) {
free(view);
}
void view_tie_icon_animation(View* view, IconAnimation* icon_animation) {
furi_assert(view);
icon_animation_set_update_callback(icon_animation, view_icon_animation_callback, view);
}
void view_set_draw_callback(View* view, ViewDrawCallback callback) {
furi_assert(view);
furi_assert(view->draw_callback == NULL);
@ -120,6 +125,14 @@ void view_commit_model(View* view, bool update) {
}
}
void view_icon_animation_callback(IconAnimation* instance, void* context) {
furi_assert(context);
View* view = context;
if(view->update_callback) {
view->update_callback(view, view->update_callback_context);
}
}
void view_unlock_model(View* view) {
furi_assert(view);
if(view->model_type == ViewModelTypeLocking) {

View file

@ -1,6 +1,8 @@
#pragma once
#include <input/input.h>
#include "icon_animation.h"
#include "canvas.h"
#include <stddef.h>
@ -10,9 +12,10 @@
extern "C" {
#endif
/* Hides drawing view_port */
/** Hides drawing view_port */
#define VIEW_NONE 0xFFFFFFFF
/* Ignore navigation event */
/** Ignore navigation event */
#define VIEW_IGNORE 0xFFFFFFFE
typedef enum {
@ -20,17 +23,17 @@ typedef enum {
ViewOrientationVertical,
} ViewOrientation;
/* View, anonymous type */
/** View, anonymous type */
typedef struct View View;
/* View Draw callback
/** View Draw callback
* @param canvas, pointer to canvas
* @param view_model, pointer to context
* @warning called from GUI thread
*/
typedef void (*ViewDrawCallback)(Canvas* canvas, void* model);
/* View Input callback
/** View Input callback
* @param event, pointer to input event data
* @param context, pointer to context
* @return true if event handled, false if event ignored
@ -38,27 +41,27 @@ typedef void (*ViewDrawCallback)(Canvas* canvas, void* model);
*/
typedef bool (*ViewInputCallback)(InputEvent* event, void* context);
/* View Custom callback
/** View Custom callback
* @param event, number of custom event
* @param context, pointer to context
* @return true if event handled, false if event ignored
*/
typedef bool (*ViewCustomCallback)(uint32_t event, void* context);
/* View navigation callback
/** View navigation callback
* @param context, pointer to context
* @return next view id
* @warning called from GUI thread
*/
typedef uint32_t (*ViewNavigationCallback)(void* context);
/* View callback
/** View callback
* @param context, pointer to context
* @warning called from GUI thread
*/
typedef void (*ViewCallback)(void* context);
/* View Update Callback
/** View Update Callback
* Called upon model change, need to be propagated to GUI throw ViewPort update
* @param view, pointer to view
* @param context, pointer to context
@ -66,7 +69,7 @@ typedef void (*ViewCallback)(void* context);
*/
typedef void (*ViewUpdateCallback)(View* view, void* context);
/* View model types */
/** View model types */
typedef enum {
/* Model is not allocated */
ViewModelTypeNone,
@ -80,97 +83,103 @@ typedef enum {
ViewModelTypeLocking,
} ViewModelType;
/* Allocate and init View
* @return pointer to View
/** Allocate and init View
* @return View instance
*/
View* view_alloc();
/* Free View
* @param pointer to View
/** Free View
* @param View instance
*/
void view_free(View* view);
/* Set View Draw callback
* @param view, pointer to View
/** Tie IconAnimation with View
* @param view, View instance
* @param icon_animation, IconAnimation instance
*/
void view_tie_icon_animation(View* view, IconAnimation* icon_animation);
/** Set View Draw callback
* @param view, View instance
* @param callback, draw callback
*/
void view_set_draw_callback(View* view, ViewDrawCallback callback);
/* Set View Input callback
* @param view, pointer to View
/** Set View Input callback
* @param view, View instance
* @param callback, input callback
*/
void view_set_input_callback(View* view, ViewInputCallback callback);
/* Set View Custom callback
* @param view, pointer to View
/** Set View Custom callback
* @param view, View instance
* @param callback, input callback
*/
void view_set_custom_callback(View* view, ViewCustomCallback callback);
/* Set Navigation Previous callback
* @param view, pointer to View
/** Set Navigation Previous callback
* @param view, View instance
* @param callback, input callback
*/
void view_set_previous_callback(View* view, ViewNavigationCallback callback);
/* Set Enter callback
* @param view, pointer to View
/** Set Enter callback
* @param view, View instance
* @param callback, callback
*/
void view_set_enter_callback(View* view, ViewCallback callback);
/* Set Exit callback
* @param view, pointer to View
/** Set Exit callback
* @param view, View instance
* @param callback, callback
*/
void view_set_exit_callback(View* view, ViewCallback callback);
/* Set Update callback
* @param view, pointer to View
/** Set Update callback
* @param view, View instance
* @param callback, callback
*/
void view_set_update_callback(View* view, ViewUpdateCallback callback);
/* Set View Draw callback
* @param view, pointer to View
/** Set View Draw callback
* @param view, View instance
* @param context, context for callbacks
*/
void view_set_update_callback_context(View* view, void* context);
/* Set View Draw callback
* @param view, pointer to View
/** Set View Draw callback
* @param view, View instance
* @param context, context for callbacks
*/
void view_set_context(View* view, void* context);
/* Set View Orientation
* @param view, pointer to View
/** Set View Orientation
* @param view, View instance
* @param orientation, either vertical or horizontal
*/
void view_set_orientation(View* view, ViewOrientation orientation);
/* Allocate view model.
* @param view, pointer to View
/** Allocate view model.
* @param view, View instance
* @param type, View Model Type
* @param size, size
*/
void view_allocate_model(View* view, ViewModelType type, size_t size);
/* Free view model data memory.
* @param view, pointer to View
/** Free view model data memory.
* @param view, View instance
*/
void view_free_model(View* view);
/* Get view model data
* @param view, pointer to View
/** Get view model data
* @param view, View instance
* @return pointer to model data
* @warning Don't forget to commit model changes
*/
void* view_get_model(View* view);
/* Commit view model
* @param view, pointer to View
/** Commit view model
* @param view, View instance
* @param update, true if you want to emit view update, false otherwise
*/
void view_commit_model(View* view, bool update);
@ -187,7 +196,7 @@ void view_commit_model(View* view, bool update);
view_commit_model(view, update); \
}
#else
/*
/**
* With clause for view model
* @param view, View instance pointer
* @param function_body a (){} lambda declaration, executed within you parent function context

View file

@ -26,6 +26,9 @@ struct View {
void* context;
};
/* IconAnimation tie callback */
void view_icon_animation_callback(IconAnimation* instance, void* context);
/* Unlock model */
void view_unlock_model(View* view);

View file

@ -14,48 +14,41 @@ typedef enum {
ViewPortOrientationVertical,
} ViewPortOrientation;
/*
* ViewPort Draw callback
/** ViewPort Draw callback
* @warning called from GUI thread
*/
typedef void (*ViewPortDrawCallback)(Canvas* canvas, void* context);
/*
* ViewPort Input callback
/** ViewPort Input callback
* @warning called from GUI thread
*/
typedef void (*ViewPortInputCallback)(InputEvent* event, void* context);
/*
* ViewPort allocator
/** ViewPort allocator
* always returns view_port or stops system if not enough memory.
*/
ViewPort* view_port_alloc();
/*
* ViewPort deallocator
/** ViewPort deallocator
* Ensure that view_port was unregistered in GUI system before use.
*/
void view_port_free(ViewPort* view_port);
/*
* Set view_port width.
/** Set view_port width.
* Will be used to limit canvas drawing area and autolayout feature.
* @param width - wanted width, 0 - auto.
*/
void view_port_set_width(ViewPort* view_port, uint8_t width);
uint8_t view_port_get_width(ViewPort* view_port);
/*
* Set view_port height.
/** Set view_port height.
* Will be used to limit canvas drawing area and autolayout feature.
* @param height - wanted height, 0 - auto.
*/
void view_port_set_height(ViewPort* view_port, uint8_t height);
uint8_t view_port_get_height(ViewPort* view_port);
/*
* Enable or disable view_port rendering.
/** Enable or disable view_port rendering.
* @param view_port - ViewPort instance
* @param enabled
* @warning automatically dispatches update event
@ -63,8 +56,7 @@ uint8_t view_port_get_height(ViewPort* view_port);
void view_port_enabled_set(ViewPort* view_port, bool enabled);
bool view_port_is_enabled(ViewPort* view_port);
/*
* ViewPort event callbacks
/** ViewPort event callbacks
* @param callback - appropriate callback function
* @param context - context to pass to callback
*/
@ -74,14 +66,12 @@ void view_port_input_callback_set(
ViewPortInputCallback callback,
void* context);
/*
* Emit update signal to GUI system.
/** Emit update signal to GUI system.
* Rendering will happen later after GUI system process signal.
*/
void view_port_update(ViewPort* view_port);
/*
* Set ViewPort orientation.
/** Set ViewPort orientation.
* @param orientation, display orientation, horizontal or vertical.
*/
void view_port_set_orientation(ViewPort* view_port, ViewPortOrientation orientation);

38
applications/power/power_service/power.c Executable file → Normal file
View file

@ -97,23 +97,27 @@ static void power_check_charging_state(Power* power) {
}
}
static void power_update_info(Power* power) {
static bool power_update_info(Power* power) {
PowerInfo 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);
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);
bool need_refresh = power->info.charge != info.charge;
power->info = info;
osMutexRelease(power->info_mtx);
return need_refresh;
}
static void power_check_low_battery(Power* power) {
@ -156,7 +160,7 @@ int32_t power_srv(void* p) {
while(1) {
// Update data from gauge and charger
power_update_info(power);
bool need_refresh = power_update_info(power);
// Check low battery level
power_check_low_battery(power);
@ -168,7 +172,7 @@ int32_t power_srv(void* p) {
power_check_battery_level_change(power);
// Update battery view port
view_port_update(power->battery_view_port);
if(need_refresh) view_port_update(power->battery_view_port);
osDelay(1000);
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 830 B

View file

@ -1 +1 @@
10
1