|
- static const char *TAG = "random";
- #include <esp_log.h>
-
- #include <esp_random.h>
-
- #include "presets.hpp"
- #include "utils.hpp"
-
-
- static Color rand_color() {
- static const Color colors[] = {
- {255, 0, 0},
- { 78, 25, 0},
- {255, 160, 0},
- { 0, 255, 0},
- { 0, 0, 255},
- { 38, 10, 42},
- };
- return colors[esp_random() % 6];
- }
-
- class RandomPattern : public Pattern {
- private:
- struct State : Pattern::State {
- State(int _len, int gap) :
- last_us(0), step(0), offset(0),
- n_colors((_len + gap) / (gap + 1)), colors(new Color[n_colors])
- {
- for (Color *color = colors, *end = colors + n_colors; color < end; ++color) {
- *color = rand_color();
- }
- }
- ~State() { delete[] colors; }
-
- int64_t last_us;
- int step;
- int offset;
- int n_colors;
- Color *colors;
- };
-
- public:
- RandomPattern(int _delay_ms, int _gap) : delay_us(_delay_ms * 1000), gap(_gap) {}
-
- State* start(int len) const { return new State(len, gap); }
-
- void step(Color colors[], int len, Pattern::State *_state) const {
- State *state = (State*)_state;
-
- int64_t now_us = time_us();
- int64_t elapsed_us = now_us - state->last_us;
- bool should_step = (state->last_us == 0) || (elapsed_us >= delay_us && delay_us > 0);
- if (should_step) {
- state->last_us = (elapsed_us >= delay_us + 100000 ? now_us : state->last_us + delay_us);
-
- int step = state->step;
- int offset = state->offset;
- Color *inc = state->colors + offset;
- Color *outc = colors;
-
- if ((gap + 1 - step) % (gap + 1) == 0) *inc = rand_color();
-
- for (int i = 0; i < len; i++) {
- if ((i - step + gap + 1) % (gap + 1) == 0) {
- *outc = *inc--;
- if (inc < state->colors) inc += state->n_colors;
- } else {
- *outc = {0, 0, 0};
- }
- ++outc;
- }
-
- step++;
- if (step > gap) {
- step -= gap + 1;
- ++offset;
- if (offset >= state->n_colors) offset -= state->n_colors;
- state->offset = offset;
- }
- state->step = step;
- }
- }
-
- private:
- int delay_us;
- int gap;
- };
-
-
- Pattern* json_random_pattern(cJSON *pattern, const Presets::ColorMap &colors) {
- int delay_ms = 500;
- int gap = 1;
-
- if (pattern->type != cJSON_Object) {
- ESP_LOGE(TAG, "Not an object: %s", pattern->string);
- return NULL;
- }
-
- cJSON *jdelay = cJSON_GetObjectItem(pattern, "delay");
- if (jdelay) {
- if (jdelay->type != cJSON_Number) {
- ESP_LOGE(TAG, "Not a number: %s", jdelay->string);
- } else {
- delay_ms = jdelay->valuedouble * 1000.;
- }
- }
-
- cJSON *jgap = cJSON_GetObjectItem(pattern, "gap");
- if (jgap) {
- if (jgap->type != cJSON_Number) {
- ESP_LOGE(TAG, "Not a number: %s", jgap->string);
- } else {
- gap = jgap->valueint;
- }
- }
-
- return new RandomPattern(delay_ms, gap);
- }
|