ESP32 Native version of Blinky, featureful controller code for WS2811/WS2812/NeoPixels
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

132 строки
3.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. 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};
  9. int norm(int mean) {
  10. return (mean * 128) / ndist[esp_random() % 64];
  11. }
  12. struct Sparkle {
  13. Sparkle() : start_us(0), end_us(0), pos(0) {}
  14. Sparkle(int64_t time_us, int mean_dur_us, int len):
  15. start_us(time_us), end_us(time_us + (mean_dur_us)),
  16. pos(esp_random() % len) {}
  17. bool expired(int64_t time_us) { return time_us >= end_us; }
  18. uint8_t intensity_at(int64_t time_us) {
  19. if (time_us < start_us || time_us >= end_us) return 0;
  20. int64_t midpoint_us = (start_us + end_us) / 2;
  21. if (time_us >= midpoint_us) time_us = start_us + (end_us - time_us);
  22. return (((time_us - start_us) * 255) * 2) / (end_us - start_us);
  23. }
  24. int64_t start_us;
  25. int64_t end_us;
  26. int pos;
  27. };
  28. Color fade(Color c, unsigned int i) {
  29. return {
  30. (uint8_t)((c.r * i) / 255),
  31. (uint8_t)((c.g * i) / 255),
  32. (uint8_t)((c.b * i) / 255)
  33. };
  34. }
  35. class SparklePattern : public Pattern {
  36. private:
  37. struct State : Pattern::State {
  38. State(int n) : n_sparkles(n), sparkles(new Sparkle[n]) {}
  39. ~State() { delete[] sparkles; }
  40. int n_sparkles;
  41. Sparkle *sparkles;
  42. };
  43. public:
  44. SparklePattern(Color _color, int _duration_ms, int _delay_ms, int _density) :
  45. color(_color), duration_us(_duration_ms * 1000),
  46. delay_us(_delay_ms * 1000), density(_density)
  47. {}
  48. State* start(int len) const { return new State((len / density) + 1); }
  49. void step(Color colors[], int len, Pattern::State *_state) const {
  50. State *state = (State*)_state;
  51. int64_t now_us = time_us();
  52. memset(colors, 0, sizeof(*colors) * len);
  53. int64_t start_us = now_us;
  54. for (int i = 0; i < state->n_sparkles; ++i, start_us += delay_us) {
  55. Sparkle &sparkle = state->sparkles[i];
  56. if (sparkle.expired(now_us)) {
  57. sparkle = Sparkle(start_us, duration_us, len);
  58. } else {
  59. colors[sparkle.pos] = fade(color, sparkle.intensity_at(now_us));
  60. }
  61. }
  62. }
  63. private:
  64. Color color;
  65. int duration_us;
  66. int delay_us;
  67. int density;
  68. };
  69. Pattern* json_sparkle_pattern(cJSON *pattern, const Presets::ColorMap &colors) {
  70. int duration_ms = 250;
  71. int delay_ms = 3000;
  72. int density = 10;
  73. Color color = {255, 255, 255};
  74. if (pattern->type != cJSON_Object) {
  75. ESP_LOGE(TAG, "Not an object: %s", pattern->type);
  76. return NULL;
  77. }
  78. cJSON *jnum = cJSON_GetObjectItem(pattern, "delay");
  79. if (jnum) {
  80. if (jnum->type != cJSON_Number) {
  81. ESP_LOGE(TAG, "Not a number: %s", jnum->string);
  82. } else {
  83. delay_ms = jnum->valuedouble * 1000.;
  84. }
  85. }
  86. jnum = cJSON_GetObjectItem(pattern, "duration");
  87. if (jnum) {
  88. if (jnum->type != cJSON_Number) {
  89. ESP_LOGE(TAG, "Not a number: %s", jnum->string);
  90. } else {
  91. duration_ms = jnum->valuedouble * 1000.;
  92. }
  93. }
  94. jnum = cJSON_GetObjectItem(pattern, "density");
  95. if (jnum) {
  96. if (jnum->type != cJSON_Number) {
  97. ESP_LOGE(TAG, "Not a number: %s", jnum->string);
  98. } else {
  99. density = jnum->valuedouble;
  100. }
  101. }
  102. return new SparklePattern(color, duration_ms, delay_ms, density);
  103. }