icon_animation.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #include "icon_animation_i.h"
  2. #include "icon_i.h"
  3. #include <furi.h>
  4. IconAnimation* icon_animation_alloc(const Icon* icon) {
  5. furi_assert(icon);
  6. IconAnimation* instance = malloc(sizeof(IconAnimation));
  7. instance->icon = icon;
  8. instance->timer =
  9. furi_timer_alloc(icon_animation_timer_callback, FuriTimerTypePeriodic, instance);
  10. return instance;
  11. }
  12. void icon_animation_free(IconAnimation* instance) {
  13. furi_assert(instance);
  14. icon_animation_stop(instance);
  15. while(xTimerIsTimerActive(instance->timer) == pdTRUE) furi_delay_tick(1);
  16. furi_timer_free(instance->timer);
  17. free(instance);
  18. }
  19. void icon_animation_set_update_callback(
  20. IconAnimation* instance,
  21. IconAnimationCallback callback,
  22. void* context) {
  23. furi_assert(instance);
  24. instance->callback = callback;
  25. instance->callback_context = context;
  26. }
  27. const uint8_t* icon_animation_get_data(IconAnimation* instance) {
  28. return instance->icon->frames[instance->frame];
  29. }
  30. void icon_animation_next_frame(IconAnimation* instance) {
  31. furi_assert(instance);
  32. instance->frame = (instance->frame + 1) % instance->icon->frame_count;
  33. }
  34. void icon_animation_timer_callback(void* context) {
  35. furi_assert(context);
  36. IconAnimation* instance = context;
  37. if(!instance->animating) return;
  38. icon_animation_next_frame(instance);
  39. if(instance->callback) {
  40. instance->callback(instance, instance->callback_context);
  41. }
  42. }
  43. uint8_t icon_animation_get_width(IconAnimation* instance) {
  44. furi_assert(instance);
  45. return instance->icon->width;
  46. }
  47. uint8_t icon_animation_get_height(IconAnimation* instance) {
  48. furi_assert(instance);
  49. return instance->icon->height;
  50. }
  51. void icon_animation_start(IconAnimation* instance) {
  52. furi_assert(instance);
  53. if(!instance->animating) {
  54. instance->animating = true;
  55. furi_assert(instance->icon->frame_rate);
  56. furi_check(
  57. xTimerChangePeriod(
  58. instance->timer,
  59. (furi_kernel_get_tick_frequency() / instance->icon->frame_rate),
  60. portMAX_DELAY) == pdPASS);
  61. }
  62. }
  63. void icon_animation_stop(IconAnimation* instance) {
  64. furi_assert(instance);
  65. if(instance->animating) {
  66. instance->animating = false;
  67. furi_check(xTimerStop(instance->timer, portMAX_DELAY) == pdPASS);
  68. instance->frame = 0;
  69. }
  70. }
  71. bool icon_animation_is_last_frame(IconAnimation* instance) {
  72. furi_assert(instance);
  73. return instance->icon->frame_count - instance->frame <= 1;
  74. }