icon_animation.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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 = osTimerNew(icon_animation_timer_callback, osTimerPeriodic, instance, NULL);
  9. return instance;
  10. }
  11. void icon_animation_free(IconAnimation* instance) {
  12. furi_assert(instance);
  13. icon_animation_stop(instance);
  14. while(xTimerIsTimerActive(instance->timer) == pdTRUE) osDelay(1);
  15. furi_check(osTimerDelete(instance->timer) == osOK);
  16. free(instance);
  17. }
  18. void icon_animation_set_update_callback(
  19. IconAnimation* instance,
  20. IconAnimationCallback callback,
  21. void* context) {
  22. furi_assert(instance);
  23. instance->callback = callback;
  24. instance->callback_context = context;
  25. }
  26. const uint8_t* icon_animation_get_data(IconAnimation* instance) {
  27. return instance->icon->frames[instance->frame];
  28. }
  29. void icon_animation_next_frame(IconAnimation* instance) {
  30. furi_assert(instance);
  31. instance->frame = (instance->frame + 1) % instance->icon->frame_count;
  32. }
  33. void icon_animation_timer_callback(void* context) {
  34. furi_assert(context);
  35. IconAnimation* instance = context;
  36. if(!instance->animating) return;
  37. icon_animation_next_frame(instance);
  38. if(instance->callback) {
  39. instance->callback(instance, instance->callback_context);
  40. }
  41. }
  42. uint8_t icon_animation_get_width(IconAnimation* instance) {
  43. furi_assert(instance);
  44. return instance->icon->width;
  45. }
  46. uint8_t icon_animation_get_height(IconAnimation* instance) {
  47. furi_assert(instance);
  48. return instance->icon->height;
  49. }
  50. void icon_animation_start(IconAnimation* instance) {
  51. furi_assert(instance);
  52. if(!instance->animating) {
  53. instance->animating = true;
  54. furi_assert(instance->icon->frame_rate);
  55. furi_check(
  56. xTimerChangePeriod(
  57. instance->timer,
  58. (osKernelGetTickFreq() / instance->icon->frame_rate),
  59. portMAX_DELAY) == pdPASS);
  60. }
  61. }
  62. void icon_animation_stop(IconAnimation* instance) {
  63. furi_assert(instance);
  64. if(instance->animating) {
  65. instance->animating = false;
  66. furi_check(xTimerStop(instance->timer, portMAX_DELAY) == pdPASS);
  67. instance->frame = 0;
  68. }
  69. }
  70. bool icon_animation_is_last_frame(IconAnimation* instance) {
  71. furi_assert(instance);
  72. return instance->icon->frame_count - instance->frame <= 1;
  73. }