emoji_display.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include <cstring>
  2. #include "display/lcd_display.h"
  3. #include <esp_log.h>
  4. #include "mmap_generate_emoji.h"
  5. #include "emoji_display.h"
  6. #include <esp_lcd_panel_io.h>
  7. #include <freertos/FreeRTOS.h>
  8. #include <freertos/task.h>
  9. #include <freertos/queue.h>
  10. #include <freertos/event_groups.h>
  11. static const char *TAG = "emoji";
  12. namespace anim {
  13. bool EmojiPlayer::OnFlushIoReady(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
  14. {
  15. auto* disp_drv = static_cast<anim_player_handle_t*>(user_ctx);
  16. anim_player_flush_ready(disp_drv);
  17. return true;
  18. }
  19. void EmojiPlayer::OnFlush(anim_player_handle_t handle, int x_start, int y_start, int x_end, int y_end, const void *color_data)
  20. {
  21. auto* panel = static_cast<esp_lcd_panel_handle_t>(anim_player_get_user_data(handle));
  22. esp_lcd_panel_draw_bitmap(panel, x_start, y_start, x_end, y_end, color_data);
  23. }
  24. EmojiPlayer::EmojiPlayer(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io)
  25. {
  26. ESP_LOGI(TAG, "Create EmojiPlayer, panel: %p, panel_io: %p", panel, panel_io);
  27. const mmap_assets_config_t assets_cfg = {
  28. .partition_label = "assets_A",
  29. .max_files = MMAP_EMOJI_FILES,
  30. .checksum = MMAP_EMOJI_CHECKSUM,
  31. .flags = {.mmap_enable = true, .full_check = true}
  32. };
  33. mmap_assets_new(&assets_cfg, &assets_handle_);
  34. anim_player_config_t player_cfg = {
  35. .flush_cb = OnFlush,
  36. .update_cb = NULL,
  37. .user_data = panel,
  38. .flags = {.swap = true},
  39. .task = ANIM_PLAYER_INIT_CONFIG()
  40. };
  41. player_handle_ = anim_player_init(&player_cfg);
  42. const esp_lcd_panel_io_callbacks_t cbs = {
  43. .on_color_trans_done = OnFlushIoReady,
  44. };
  45. esp_lcd_panel_io_register_event_callbacks(panel_io, &cbs, player_handle_);
  46. StartPlayer(MMAP_EMOJI_CONNECTING_AAF, true, 15);
  47. }
  48. EmojiPlayer::~EmojiPlayer()
  49. {
  50. if (player_handle_) {
  51. anim_player_update(player_handle_, PLAYER_ACTION_STOP);
  52. anim_player_deinit(player_handle_);
  53. player_handle_ = nullptr;
  54. }
  55. if (assets_handle_) {
  56. mmap_assets_del(assets_handle_);
  57. assets_handle_ = NULL;
  58. }
  59. }
  60. void EmojiPlayer::StartPlayer(int aaf, bool repeat, int fps)
  61. {
  62. if (player_handle_) {
  63. uint32_t start, end;
  64. const void *src_data;
  65. size_t src_len;
  66. src_data = mmap_assets_get_mem(assets_handle_, aaf);
  67. src_len = mmap_assets_get_size(assets_handle_, aaf);
  68. anim_player_set_src_data(player_handle_, src_data, src_len);
  69. anim_player_get_segment(player_handle_, &start, &end);
  70. if(MMAP_EMOJI_WAKE_AAF == aaf){
  71. start = 7;
  72. }
  73. anim_player_set_segment(player_handle_, start, end, fps, true);
  74. anim_player_update(player_handle_, PLAYER_ACTION_START);
  75. }
  76. }
  77. void EmojiPlayer::StopPlayer()
  78. {
  79. if (player_handle_) {
  80. anim_player_update(player_handle_, PLAYER_ACTION_STOP);
  81. }
  82. }
  83. EmojiWidget::EmojiWidget(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io)
  84. {
  85. InitializePlayer(panel, panel_io);
  86. }
  87. EmojiWidget::~EmojiWidget()
  88. {
  89. }
  90. void EmojiWidget::SetEmotion(const char* emotion)
  91. {
  92. if (!player_) {
  93. return;
  94. }
  95. using Param = std::tuple<int, bool, int>;
  96. static const std::unordered_map<std::string, Param> emotion_map = {
  97. {"happy", {MMAP_EMOJI_HAPPY_LOOP_AAF, true, 25}},
  98. {"laughing", {MMAP_EMOJI_HAPPY_LOOP_AAF, true, 25}},
  99. {"funny", {MMAP_EMOJI_HAPPY_LOOP_AAF, true, 25}},
  100. {"loving", {MMAP_EMOJI_HAPPY_LOOP_AAF, true, 25}},
  101. {"embarrassed", {MMAP_EMOJI_HAPPY_LOOP_AAF, true, 25}},
  102. {"confident", {MMAP_EMOJI_HAPPY_LOOP_AAF, true, 25}},
  103. {"delicious", {MMAP_EMOJI_HAPPY_LOOP_AAF, true, 25}},
  104. {"sad", {MMAP_EMOJI_SAD_LOOP_AAF, true, 25}},
  105. {"crying", {MMAP_EMOJI_SAD_LOOP_AAF, true, 25}},
  106. {"sleepy", {MMAP_EMOJI_SAD_LOOP_AAF, true, 25}},
  107. {"silly", {MMAP_EMOJI_SAD_LOOP_AAF, true, 25}},
  108. {"angry", {MMAP_EMOJI_ANGER_LOOP_AAF, true, 25}},
  109. {"surprised", {MMAP_EMOJI_PANIC_LOOP_AAF, true, 25}},
  110. {"shocked", {MMAP_EMOJI_PANIC_LOOP_AAF, true, 25}},
  111. {"thinking", {MMAP_EMOJI_HAPPY_LOOP_AAF, true, 25}},
  112. {"winking", {MMAP_EMOJI_BLINK_QUICK_AAF, true, 5}},
  113. {"relaxed", {MMAP_EMOJI_SCORN_LOOP_AAF, true, 25}},
  114. {"confused", {MMAP_EMOJI_SCORN_LOOP_AAF, true, 25}},
  115. };
  116. auto it = emotion_map.find(emotion);
  117. if (it != emotion_map.end()) {
  118. const auto& [aaf, repeat, fps] = it->second;
  119. player_->StartPlayer(aaf, repeat, fps);
  120. } else if (strcmp(emotion, "neutral") == 0) {
  121. }
  122. }
  123. void EmojiWidget::SetStatus(const char* status)
  124. {
  125. if (player_) {
  126. if (strcmp(status, "聆听中...") == 0) {
  127. player_->StartPlayer(MMAP_EMOJI_ASKING_AAF, true, 15);
  128. } else if (strcmp(status, "待命") == 0) {
  129. player_->StartPlayer(MMAP_EMOJI_WAKE_AAF, true, 15);
  130. }
  131. }
  132. }
  133. void EmojiWidget::InitializePlayer(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io)
  134. {
  135. player_ = std::make_unique<EmojiPlayer>(panel, panel_io);
  136. }
  137. bool EmojiWidget::Lock(int timeout_ms)
  138. {
  139. return true;
  140. }
  141. void EmojiWidget::Unlock()
  142. {
  143. }
  144. } // namespace anim