[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:
		
							parent
							
								
									6f346597d2
								
							
						
					
					
						commit
						61aaed8abb
					
				| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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]); | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|         }); | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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
									
								
							
							
						
						
									
										54
									
								
								applications/gui/modules/menu.c
									
									
									
									
									
										
										
										Executable file → Normal 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; | ||||
|         }); | ||||
| } | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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
									
								
							
							
						
						
									
										38
									
								
								applications/power/power_service/power.c
									
									
									
									
									
										
										
										Executable file → Normal 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 | 
| @ -1 +1 @@ | ||||
| 10 | ||||
| 1 | ||||
| @ -1 +1 @@ | ||||
| 10 | ||||
| 1 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく