#pragma once #include #include struct Color { uint8_t r, g, b; } __attribute__ ((packed)); typedef uint16_t Fixed; constexpr int factor = 65536; constexpr int shift = 16; struct Gradient { Color at(Fixed x) const; static Gradient* make(int n) { Gradient *gradient = (Gradient*)malloc( sizeof(Gradient) + n * sizeof(*colors) ); gradient->n_colors = n; return gradient; } unsigned int n_colors; Color colors[]; }; class Pattern { public: virtual ~Pattern() {}; struct State {}; virtual State* start(int) const = 0; virtual void step(Color[], int, State*) const = 0; }; class GradientPattern : public Pattern { public: GradientPattern( Gradient *_gradient, int _cycle_length=20, int _cycle_time_ms=-1, bool _reverse=false, bool _march=false ) : cycle_length(_cycle_length), cycle_time_ms( _cycle_time_ms < 0 ? _cycle_length * 500 : _cycle_time_ms ), reverse(_reverse), march(_march), gradient(_gradient) {} ~GradientPattern() { free(gradient); } State* start(int) const { return new State(); } void step(Color[], int, State*) const; private: struct State : Pattern::State { State() : last_us(0), offset(0) {} int64_t last_us; Fixed offset; }; int cycle_length; int cycle_time_ms; bool reverse; bool march; Gradient *gradient; }; class LEDStrip { public: LEDStrip(int length = 0); void step(); virtual void show() = 0; virtual void length_changing(int) {}; void setPattern(const Pattern *_pattern) { pattern = _pattern; update_state(); } const Pattern* getPattern() const { return pattern; } void setLength(int length); int getLength() const { return length; } protected: int length; const Pattern *pattern; Color *pixels; private: void update_state(); Pattern::State *state; }; class TerminalLEDs : public LEDStrip { public: TerminalLEDs(int length = 0) : LEDStrip(length) {} void show(); };