ESP32 Native version of Blinky, featureful controller code for WS2811/WS2812/NeoPixels
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

164 Zeilen
4.7KB

  1. static const char *TAG = "random";
  2. #include <esp_log.h>
  3. #include <list>
  4. #include <cstring>
  5. #include <esp_random.h>
  6. #include "presets.hpp"
  7. #include "utils.hpp"
  8. /*
  9. static const int8_t ndist[64] = {-127, -104, -92, -84, -77, -72, -67, -62, -58, -55, -51, -48, -45, -42, -39, -37, -34, -32, -29, -27, -25, -22, -20, -18, -16, -14, -11, -9, -7, -5, -3, -1, 1, 3, 5, 7, 9, 11, 14, 16, 18, 20, 22, 25, 27, 29, 32, 34, 37, 39, 42, 45, 48, 51, 55, 58, 62, 67, 72, 77, 84, 92, 104, 127};
  10. int norm(int mean) {
  11. return (mean * 128) / ndist[esp_random() % 64];
  12. }
  13. */
  14. static inline Color fade(Color c, unsigned int i) {
  15. return {
  16. (uint8_t)((c.r * i) / 255),
  17. (uint8_t)((c.g * i) / 255),
  18. (uint8_t)((c.b * i) / 255)
  19. };
  20. }
  21. struct Sparkle {
  22. Sparkle() : start_us(0), end_us(0), pos(0) {}
  23. Sparkle(Color _color, int64_t time_us, int mean_dur_us, int len):
  24. start_us(time_us), end_us(time_us + (mean_dur_us)),
  25. pos(esp_random() % len), color(_color) {}
  26. bool expired(int64_t time_us) { return time_us >= end_us; }
  27. uint8_t intensity_at(int64_t time_us) {
  28. if (time_us < start_us || time_us >= end_us) return 0;
  29. int64_t midpoint_us = (start_us + end_us) / 2;
  30. if (time_us >= midpoint_us) time_us = start_us + (end_us - time_us);
  31. return (((time_us - start_us) * 255) * 2) / (end_us - start_us);
  32. }
  33. Color color_at(int64_t time_us) {
  34. return fade(color, intensity_at(time_us));
  35. }
  36. int64_t start_us;
  37. int64_t end_us;
  38. int pos;
  39. Color color;
  40. };
  41. class SparklePattern : public Pattern {
  42. private:
  43. struct State : Pattern::State {
  44. State(int n) : n_sparkles(n), sparkles(new Sparkle[n]) {}
  45. ~State() { delete[] sparkles; }
  46. int n_sparkles;
  47. Sparkle *sparkles;
  48. };
  49. public:
  50. SparklePattern(const Color *_colors, int _n_colors, int _duration_ms, int _delay_ms, int _density) :
  51. n_colors(_n_colors), colors(_colors),
  52. duration_us(_duration_ms * 1000),
  53. delay_us(_delay_ms * 1000), density(_density)
  54. {}
  55. ~SparklePattern() { if (colors) delete[] colors; }
  56. State* start(int len) const { return new State((len / density) + 1); }
  57. void step(Color pixels[], int len, Pattern::State *_state) const {
  58. State *state = (State*)_state;
  59. int64_t now_us = time_us();
  60. memset(pixels, 0, sizeof(*pixels) * len);
  61. int64_t start_us = now_us;
  62. for (int i = 0; i < state->n_sparkles; ++i, start_us += delay_us / state->n_sparkles) {
  63. Sparkle &sparkle = state->sparkles[i];
  64. if (sparkle.expired(now_us)) {
  65. sparkle = Sparkle(
  66. colors[esp_random() % n_colors],
  67. start_us, duration_us, len
  68. );
  69. } else {
  70. pixels[sparkle.pos] = sparkle.color_at(now_us);
  71. }
  72. }
  73. }
  74. private:
  75. int n_colors;
  76. const Color* colors;
  77. int duration_us;
  78. int delay_us;
  79. int density;
  80. };
  81. Pattern* json_sparkle_pattern(cJSON *pattern, const Presets::ColorMap &colormap) {
  82. int duration_ms = 250;
  83. int delay_ms = 3000;
  84. int density = 10;
  85. int n_colors = 0;
  86. Color *colors = NULL;
  87. if (pattern->type != cJSON_Object) {
  88. ESP_LOGE(TAG, "Not an object: %s", pattern->string);
  89. return NULL;
  90. }
  91. cJSON *jcolors = cJSON_GetObjectItem(pattern, "colors");
  92. if (!jcolors || jcolors->type != cJSON_Array) {
  93. ESP_LOGW(TAG, "No colors in %s", pattern->string);
  94. } else {
  95. n_colors = cJSON_GetArraySize(jcolors);
  96. colors = new Color[n_colors];
  97. int i = 0;
  98. cJSON *jcolor;
  99. cJSON_ArrayForEach(jcolor, jcolors) {
  100. colors[i++] = Presets::json_color(jcolor, colormap);
  101. }
  102. }
  103. cJSON *jnum = cJSON_GetObjectItem(pattern, "delay");
  104. if (jnum) {
  105. if (jnum->type != cJSON_Number) {
  106. ESP_LOGE(TAG, "Not a number: %s", jnum->string);
  107. } else {
  108. delay_ms = jnum->valuedouble * 1000.;
  109. }
  110. }
  111. jnum = cJSON_GetObjectItem(pattern, "duration");
  112. if (jnum) {
  113. if (jnum->type != cJSON_Number) {
  114. ESP_LOGE(TAG, "Not a number: %s", jnum->string);
  115. } else {
  116. duration_ms = jnum->valuedouble * 1000.;
  117. }
  118. }
  119. jnum = cJSON_GetObjectItem(pattern, "density");
  120. if (jnum) {
  121. if (jnum->type != cJSON_Number) {
  122. ESP_LOGE(TAG, "Not a number: %s", jnum->string);
  123. } else {
  124. density = jnum->valuedouble;
  125. }
  126. }
  127. if (n_colors == 0) {
  128. n_colors = 1;
  129. colors = new Color{255,255,255};
  130. }
  131. return new SparklePattern(colors, n_colors, duration_ms, delay_ms, density);
  132. }