circular_strip.cc 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #include "circular_strip.h"
  2. #include "application.h"
  3. #include <esp_log.h>
  4. #define TAG "CircularStrip"
  5. #define BLINK_INFINITE -1
  6. CircularStrip::CircularStrip(gpio_num_t gpio, uint8_t max_leds) : max_leds_(max_leds) {
  7. // If the gpio is not connected, you should use NoLed class
  8. assert(gpio != GPIO_NUM_NC);
  9. colors_.resize(max_leds_);
  10. led_strip_config_t strip_config = {};
  11. strip_config.strip_gpio_num = gpio;
  12. strip_config.max_leds = max_leds_;
  13. strip_config.led_pixel_format = LED_PIXEL_FORMAT_GRB;
  14. strip_config.led_model = LED_MODEL_WS2812;
  15. led_strip_rmt_config_t rmt_config = {};
  16. rmt_config.resolution_hz = 10 * 1000 * 1000; // 10MHz
  17. ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip_));
  18. led_strip_clear(led_strip_);
  19. esp_timer_create_args_t strip_timer_args = {
  20. .callback = [](void *arg) {
  21. auto strip = static_cast<CircularStrip*>(arg);
  22. std::lock_guard<std::mutex> lock(strip->mutex_);
  23. if (strip->strip_callback_ != nullptr) {
  24. strip->strip_callback_();
  25. }
  26. },
  27. .arg = this,
  28. .dispatch_method = ESP_TIMER_TASK,
  29. .name = "strip_timer",
  30. .skip_unhandled_events = false,
  31. };
  32. ESP_ERROR_CHECK(esp_timer_create(&strip_timer_args, &strip_timer_));
  33. }
  34. CircularStrip::~CircularStrip() {
  35. esp_timer_stop(strip_timer_);
  36. if (led_strip_ != nullptr) {
  37. led_strip_del(led_strip_);
  38. }
  39. }
  40. void CircularStrip::SetAllColor(StripColor color) {
  41. std::lock_guard<std::mutex> lock(mutex_);
  42. esp_timer_stop(strip_timer_);
  43. for (int i = 0; i < max_leds_; i++) {
  44. colors_[i] = color;
  45. led_strip_set_pixel(led_strip_, i, color.red, color.green, color.blue);
  46. }
  47. led_strip_refresh(led_strip_);
  48. }
  49. void CircularStrip::SetSingleColor(uint8_t index, StripColor color) {
  50. std::lock_guard<std::mutex> lock(mutex_);
  51. esp_timer_stop(strip_timer_);
  52. colors_[index] = color;
  53. led_strip_set_pixel(led_strip_, index, color.red, color.green, color.blue);
  54. led_strip_refresh(led_strip_);
  55. }
  56. void CircularStrip::Blink(StripColor color, int interval_ms) {
  57. for (int i = 0; i < max_leds_; i++) {
  58. colors_[i] = color;
  59. }
  60. StartStripTask(interval_ms, [this]() {
  61. static bool on = true;
  62. if (on) {
  63. for (int i = 0; i < max_leds_; i++) {
  64. led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue);
  65. }
  66. led_strip_refresh(led_strip_);
  67. } else {
  68. led_strip_clear(led_strip_);
  69. }
  70. on = !on;
  71. });
  72. }
  73. void CircularStrip::FadeOut(int interval_ms) {
  74. StartStripTask(interval_ms, [this]() {
  75. bool all_off = true;
  76. for (int i = 0; i < max_leds_; i++) {
  77. colors_[i].red /= 2;
  78. colors_[i].green /= 2;
  79. colors_[i].blue /= 2;
  80. if (colors_[i].red != 0 || colors_[i].green != 0 || colors_[i].blue != 0) {
  81. all_off = false;
  82. }
  83. led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue);
  84. }
  85. if (all_off) {
  86. led_strip_clear(led_strip_);
  87. esp_timer_stop(strip_timer_);
  88. } else {
  89. led_strip_refresh(led_strip_);
  90. }
  91. });
  92. }
  93. void CircularStrip::Breathe(StripColor low, StripColor high, int interval_ms) {
  94. StartStripTask(interval_ms, [this, low, high]() {
  95. static bool increase = true;
  96. static StripColor color = low;
  97. if (increase) {
  98. if (color.red < high.red) {
  99. color.red++;
  100. }
  101. if (color.green < high.green) {
  102. color.green++;
  103. }
  104. if (color.blue < high.blue) {
  105. color.blue++;
  106. }
  107. if (color.red == high.red && color.green == high.green && color.blue == high.blue) {
  108. increase = false;
  109. }
  110. } else {
  111. if (color.red > low.red) {
  112. color.red--;
  113. }
  114. if (color.green > low.green) {
  115. color.green--;
  116. }
  117. if (color.blue > low.blue) {
  118. color.blue--;
  119. }
  120. if (color.red == low.red && color.green == low.green && color.blue == low.blue) {
  121. increase = true;
  122. }
  123. }
  124. for (int i = 0; i < max_leds_; i++) {
  125. led_strip_set_pixel(led_strip_, i, color.red, color.green, color.blue);
  126. }
  127. led_strip_refresh(led_strip_);
  128. });
  129. }
  130. void CircularStrip::Scroll(StripColor low, StripColor high, int length, int interval_ms) {
  131. for (int i = 0; i < max_leds_; i++) {
  132. colors_[i] = low;
  133. }
  134. StartStripTask(interval_ms, [this, low, high, length]() {
  135. static int offset = 0;
  136. for (int i = 0; i < max_leds_; i++) {
  137. colors_[i] = low;
  138. }
  139. for (int j = 0; j < length; j++) {
  140. int i = (offset + j) % max_leds_;
  141. colors_[i] = high;
  142. }
  143. for (int i = 0; i < max_leds_; i++) {
  144. led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue);
  145. }
  146. led_strip_refresh(led_strip_);
  147. offset = (offset + 1) % max_leds_;
  148. });
  149. }
  150. void CircularStrip::StartStripTask(int interval_ms, std::function<void()> cb) {
  151. if (led_strip_ == nullptr) {
  152. return;
  153. }
  154. std::lock_guard<std::mutex> lock(mutex_);
  155. esp_timer_stop(strip_timer_);
  156. strip_callback_ = cb;
  157. esp_timer_start_periodic(strip_timer_, interval_ms * 1000);
  158. }
  159. void CircularStrip::SetBrightness(uint8_t default_brightness, uint8_t low_brightness) {
  160. default_brightness_ = default_brightness;
  161. low_brightness_ = low_brightness;
  162. OnStateChanged();
  163. }
  164. void CircularStrip::OnStateChanged() {
  165. auto& app = Application::GetInstance();
  166. auto device_state = app.GetDeviceState();
  167. switch (device_state) {
  168. case kDeviceStateStarting: {
  169. StripColor low = { 0, 0, 0 };
  170. StripColor high = { low_brightness_, low_brightness_, default_brightness_ };
  171. Scroll(low, high, 3, 100);
  172. break;
  173. }
  174. case kDeviceStateWifiConfiguring: {
  175. StripColor color = { low_brightness_, low_brightness_, default_brightness_ };
  176. Blink(color, 500);
  177. break;
  178. }
  179. case kDeviceStateIdle:
  180. FadeOut(50);
  181. break;
  182. case kDeviceStateConnecting: {
  183. StripColor color = { low_brightness_, low_brightness_, default_brightness_ };
  184. SetAllColor(color);
  185. break;
  186. }
  187. case kDeviceStateListening:
  188. case kDeviceStateAudioTesting: {
  189. StripColor color = { default_brightness_, low_brightness_, low_brightness_ };
  190. SetAllColor(color);
  191. break;
  192. }
  193. case kDeviceStateSpeaking: {
  194. StripColor color = { low_brightness_, default_brightness_, low_brightness_ };
  195. SetAllColor(color);
  196. break;
  197. }
  198. case kDeviceStateUpgrading: {
  199. StripColor color = { low_brightness_, default_brightness_, low_brightness_ };
  200. Blink(color, 100);
  201. break;
  202. }
  203. case kDeviceStateActivating: {
  204. StripColor color = { low_brightness_, default_brightness_, low_brightness_ };
  205. Blink(color, 500);
  206. break;
  207. }
  208. default:
  209. ESP_LOGW(TAG, "Unknown led strip event: %d", device_state);
  210. return;
  211. }
  212. }