ESP32 Native version of Blinky, featureful controller code for WS2811/WS2812/NeoPixels
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

119 行
3.2KB

  1. static const char *TAG = "random";
  2. #include <esp_log.h>
  3. #include <esp_random.h>
  4. #include "presets.hpp"
  5. #include "utils.hpp"
  6. static Color rand_color() {
  7. static const Color colors[] = {
  8. {255, 0, 0},
  9. { 78, 25, 0},
  10. {255, 160, 0},
  11. { 0, 255, 0},
  12. { 0, 0, 255},
  13. { 38, 10, 42},
  14. };
  15. return colors[esp_random() % 6];
  16. }
  17. class RandomPattern : public Pattern {
  18. private:
  19. struct State : Pattern::State {
  20. State(int _len, int gap) :
  21. last_us(0), step(0), offset(0),
  22. n_colors((_len + gap) / (gap + 1)), colors(new Color[n_colors])
  23. {
  24. for (Color *color = colors, *end = colors + n_colors; color < end; ++color) {
  25. *color = rand_color();
  26. }
  27. }
  28. ~State() { delete[] colors; }
  29. int64_t last_us;
  30. int step;
  31. int offset;
  32. int n_colors;
  33. Color *colors;
  34. };
  35. public:
  36. RandomPattern(int _delay_ms, int _gap) : delay_us(_delay_ms * 1000), gap(_gap) {}
  37. State* start(int len) const { return new State(len, gap); }
  38. void step(Color colors[], int len, Pattern::State *_state) const {
  39. State *state = (State*)_state;
  40. int64_t now_us = time_us();
  41. int64_t elapsed_us = now_us - state->last_us;
  42. bool should_step = (state->last_us == 0) || (elapsed_us >= delay_us && delay_us > 0);
  43. if (should_step) {
  44. state->last_us = (elapsed_us >= delay_us + 100000 ? now_us : state->last_us + delay_us);
  45. int step = state->step;
  46. int offset = state->offset;
  47. Color *inc = state->colors + offset;
  48. Color *outc = colors;
  49. if ((gap + 1 - step) % (gap + 1) == 0) *inc = rand_color();
  50. for (int i = 0; i < len; i++) {
  51. if ((i - step + gap + 1) % (gap + 1) == 0) {
  52. *outc = *inc--;
  53. if (inc < state->colors) inc += state->n_colors;
  54. } else {
  55. *outc = {0, 0, 0};
  56. }
  57. ++outc;
  58. }
  59. step++;
  60. if (step > gap) {
  61. step -= gap + 1;
  62. ++offset;
  63. if (offset >= state->n_colors) offset -= state->n_colors;
  64. state->offset = offset;
  65. }
  66. state->step = step;
  67. }
  68. }
  69. private:
  70. int delay_us;
  71. int gap;
  72. };
  73. Pattern* json_random_pattern(cJSON *pattern, const Presets::ColorMap &colors) {
  74. int delay_ms = 500;
  75. int gap = 1;
  76. if (pattern->type != cJSON_Object) {
  77. ESP_LOGE(TAG, "Not an object: %s", pattern->string);
  78. return NULL;
  79. }
  80. cJSON *jdelay = cJSON_GetObjectItem(pattern, "delay");
  81. if (jdelay) {
  82. if (jdelay->type != cJSON_Number) {
  83. ESP_LOGE(TAG, "Not a number: %s", jdelay->string);
  84. } else {
  85. delay_ms = jdelay->valuedouble * 1000.;
  86. }
  87. }
  88. cJSON *jgap = cJSON_GetObjectItem(pattern, "gap");
  89. if (jgap) {
  90. if (jgap->type != cJSON_Number) {
  91. ESP_LOGE(TAG, "Not a number: %s", jgap->string);
  92. } else {
  93. gap = jgap->valueint;
  94. }
  95. }
  96. return new RandomPattern(delay_ms, gap);
  97. }