├── OLD ├── README └── xmas_neopixel_lite.ino ├── schematics.jpg ├── Random.h ├── .gitignore ├── neopixel.h ├── neopixel.cpp ├── README.md ├── manager.h ├── clrutils.h ├── clean.h ├── xmas_neopixel_lite.ino ├── manager.cpp ├── clean.cpp ├── clrutils.cpp ├── animation.h ├── LICENSE └── animation.cpp /OLD/README: -------------------------------------------------------------------------------- 1 | This is a prevoius release for reference. 2 | -------------------------------------------------------------------------------- /schematics.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfrwmaker/xtmas_neopixel/HEAD/schematics.jpg -------------------------------------------------------------------------------- /Random.h: -------------------------------------------------------------------------------- 1 | #ifndef __RANDOM_H 2 | #define __RANDOM_H 3 | 4 | inline uint32_t Random(uint32_t a, uint32_t b) { return random(a, b); } 5 | inline uint32_t Random(uint32_t a) { return random(a); } 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | -------------------------------------------------------------------------------- /neopixel.h: -------------------------------------------------------------------------------- 1 | #ifndef __NEOPIXEL_H 2 | #define __NEOPIXEL_H 3 | #include 4 | #ifdef __AVR__ 5 | #include 6 | #endif 7 | 8 | typedef uint32_t COLOR; 9 | 10 | class NEOPIXEL : public Adafruit_NeoPixel { 11 | public: 12 | NEOPIXEL(uint16_t n, uint8_t p, uint16_t t) : Adafruit_NeoPixel(n, p, t) { } 13 | COLOR wheel(uint8_t wheel_pos); 14 | COLOR lightWheel(uint8_t wheel_pos); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /neopixel.cpp: -------------------------------------------------------------------------------- 1 | #include "neopixel.h" 2 | 3 | COLOR NEOPIXEL::wheel(uint8_t wheel_pos) { 4 | wheel_pos = 255 - wheel_pos; 5 | if(wheel_pos < 85) { 6 | return Color(255 - wheel_pos * 3, 0, wheel_pos * 3); 7 | } 8 | if (wheel_pos < 170) { 9 | wheel_pos -= 85; 10 | return Color(0, wheel_pos * 3, 255 - wheel_pos * 3); 11 | } 12 | wheel_pos -= 170; 13 | return Color(wheel_pos * 3, 255 - wheel_pos * 3, 0); 14 | } 15 | 16 | COLOR NEOPIXEL::lightWheel(uint8_t wheel_pos) { 17 | wheel_pos = 255 - wheel_pos; 18 | if(wheel_pos < 85) { 19 | return Color(255 - wheel_pos, 255, wheel_pos * 3); 20 | } 21 | if (wheel_pos < 170) { 22 | wheel_pos -= 85; 23 | return Color(255, wheel_pos * 3, 255 - wheel_pos); 24 | } 25 | wheel_pos -= 170; 26 | return Color(wheel_pos * 3, 255 - wheel_pos, 255); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xtmas_neopixel 2 | Updated DEC 13 2018. In this new update the code was revisited and new animation programs were added. Not all animations are enabled in the source code, some of there are commented out to decrease memory requirements. But many animations are beautiful, so i kept them all. Please, look at xtmas_neopixel_lite.ino file and select your own animation set. To do this, first comment out or remove comment from animation definition instance 3 | symmRun symRun; 4 | //metSingle mtrSgl; 5 | Then add or remove the reference to animation class to anims array. Be carefull of warnings about memory limit if Arduino IDE. The program can be unstable in case of insufficient memory amount. 6 | 7 | animation* anims[] = { 8 | &cWipe, &cWalk, &cCreep, &cRainbow, &cRainCycle, &cRainFull, &cWave, &lUp, &sRnd, &rFade, 9 | &cCollEnd, &cRun, &cSeven, &mOne, &mWave, &cOne, &cFire, &cEvenOdd, &rFill, &cCollMdl, 10 | &cBlend, &cSwing, &cSwingS, &cFlash, &sWave, &cWorms, &cInterf, &cToward, &rToward, &lHouse, 11 | &cDrops, &wSeven, &fSeven, &sCreep, &tChase, &mtrSky, &symRun, &cRipe 12 | }; 13 | 14 | The article is available here: https://www.hackster.io/sfrwmaker/5-minute-christmas-neopixel-led-strip-0abf33 15 | 16 | In case of issues, the previous release is available in OLD directory. 17 | -------------------------------------------------------------------------------- /manager.h: -------------------------------------------------------------------------------- 1 | #ifndef __MANAGER_H 2 | #define __MANAGER_H 3 | #include "animation.h" 4 | #include "clean.h" 5 | 6 | //---------------------------------------------- Shuffle the animation in the random order -------------------------------- 7 | class shuffle { 8 | public: 9 | shuffle(uint8_t a_size); 10 | uint8_t next(void); 11 | private: 12 | void randomize(void); 13 | uint8_t *index; // The array of animations, allocated by new() 14 | uint8_t num_anim; // The active animation number 15 | uint8_t curr; 16 | }; 17 | 18 | // --------------------------------------------- The sequence manager ----------------------------------------------------- 19 | class MANAGER : public shuffle { 20 | public: 21 | MANAGER(animation* a[], uint8_t a_size, clr* c[], uint8_t clr_size); 22 | void init(void); 23 | void show(void); 24 | void menu(void) { stp_period --; if (stp_period < 1) stp_period = 1; } 25 | void menu_l(void) { initClear(); } 26 | void incr(void) { stp_period ++; if (stp_period > 20) stp_period = 20; } 27 | private: 28 | void initClear(void); 29 | bool isClean(void); 30 | animation** anims; 31 | clr** clearance; 32 | uint8_t num_clr; 33 | uint32_t stp; 34 | uint16_t stp_period = 0; 35 | uint16_t clr_stp_period = 0; 36 | uint32_t next = 0; // The time for the next animation, ms 37 | uint8_t aIndex = 0; // Current animation index 38 | animation* a = 0; 39 | clr* c = 0; 40 | bool do_clear; // Whether cleaning the strip 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /clrutils.h: -------------------------------------------------------------------------------- 1 | #ifndef __CLRUTILS_H 2 | #define __CLRUTILS_H 3 | #include "neopixel.h" 4 | #include "Random.h" 5 | 6 | extern NEOPIXEL strip; 7 | 8 | // --------------------------------------------- creep the sequence up or down, superclass -------------------------------- 9 | class CRAWL { 10 | public: 11 | CRAWL(void) { } 12 | void step(void); 13 | protected: 14 | bool fwd = true; // direction to crawl: false - backward, true - forward 15 | COLOR next_color = 0; 16 | }; 17 | 18 | //---------------------------------------------- Brightness manipulation -------------------------------------------------- 19 | class BRGTN { 20 | public: 21 | BRGTN() { } 22 | void setColor(uint32_t c); 23 | bool changeClr(COLOR& c, int8_t val); 24 | bool change(uint16_t index, int8_t val); 25 | bool changeAll(int8_t val); 26 | protected: 27 | uint8_t color[3]; 28 | }; 29 | 30 | //---------------------------------------------- Blend manipulations ------------------------------------------------------ 31 | class BLEND { 32 | public: 33 | BLEND() { } 34 | COLOR add(COLOR color1, COLOR color2); 35 | COLOR sub(COLOR color1, COLOR color2); 36 | void blendPixel(uint16_t p, uint8_t deviation = 20); 37 | }; 38 | 39 | //---------------------------------------------- Color superposition class ------------------------------------------------ 40 | class TWOCLR { 41 | public: 42 | TWOCLR() { } 43 | COLOR add(COLOR c1, COLOR c2); 44 | }; 45 | 46 | //---------------------------------------------- The sine wave value class ------------------------------------------------ 47 | class WAVE { 48 | public: 49 | WAVE() { } 50 | uint8_t amplitude(uint8_t n); // sin(PI*n/32) * 127 + 127 51 | COLOR intencity(COLOR c, uint8_t n); 52 | private: 53 | const uint8_t sine[17] = { 127, 139, 152, 164, 176, 187, 198, 208, 217, 225, 233, 239, 244, 249, 252, 253, 254 }; 54 | }; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /clean.h: -------------------------------------------------------------------------------- 1 | #ifndef __CLEAN_H 2 | #define __CLEAN_H 3 | #include "neopixel.h" 4 | #include "Random.h" 5 | 6 | extern NEOPIXEL strip; 7 | 8 | //---------------------------------------------- Classes for strip clearing ---------------------------------------------- 9 | class clr { 10 | public: 11 | clr(void) { complete = false; } 12 | virtual ~clr(void) { } 13 | virtual void init(void) = 0; 14 | virtual void show(void) = 0; 15 | bool isComplete(void); 16 | bool fade(uint16_t index, uint8_t val); 17 | bool fadeAll(uint8_t val); 18 | protected: 19 | bool complete; 20 | }; 21 | 22 | // --------------------------------------------- Clear the strip from the either side ------------------------------------- 23 | class clearSide : public clr { 24 | public: 25 | clearSide(void) { index = 0; fwd = true; color = 0; } 26 | virtual void init(void); 27 | virtual void show(void); 28 | private: 29 | COLOR color; 30 | int index; 31 | bool fwd; 32 | }; 33 | 34 | // --------------------------------------------- Clear the strip from the center to both ends ----------------------------- 35 | class clearCntr : public clr { 36 | public: 37 | clearCntr(void) { color = 0; l = r = 0; fwd = true; } 38 | virtual void init(void); 39 | virtual void show(void); 40 | private: 41 | COLOR color; 42 | int l, r; 43 | bool fwd; 44 | }; 45 | 46 | 47 | // --------------------------------------------- Clear the strip from the ether side -------------------------------------- 48 | class clearFade : public clr { 49 | public: 50 | clearFade() { decrement = 0; } 51 | virtual void init(void) { complete = false; decrement = Random(4, 16); } 52 | virtual void show(void) { complete = clr::fadeAll(decrement); } 53 | private: 54 | uint8_t decrement; 55 | }; 56 | 57 | // --------------------------------------------- Clear the strip by 'eating' the pixels from the center ------------------- 58 | class eatCntr : public clr { 59 | public: 60 | eatCntr() { remain = 0; } 61 | virtual void init(void) { complete = false; remain = strip.numPixels()/2 + 1;} 62 | virtual void show(void); 63 | private: 64 | int remain; 65 | }; 66 | 67 | //---------------------------------------------- Clear the strip by dividing it by 2 ------------------------------------ 68 | class clearHalf : public clr { 69 | public: 70 | clearHalf() { one_step = 0; } 71 | virtual void init(void); 72 | virtual void show(void); 73 | private: 74 | int one_step; 75 | }; 76 | 77 | 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /xmas_neopixel_lite.ino: -------------------------------------------------------------------------------- 1 | #include "neopixel.h" 2 | #include "clrutils.h" 3 | #include "animation.h" 4 | #include "clean.h" 5 | #include "manager.h" 6 | 7 | const uint8_t NEO_BRGHT = 255; 8 | const uint8_t NEO_PIN = 6; // Pin of Neopixel Strip 9 | const uint16_t StripSize = 100; // Length of Neopixel Strip 10 | 11 | NEOPIXEL strip = NEOPIXEL(StripSize, NEO_PIN, NEO_RGB + NEO_KHZ800); 12 | 13 | colorWipe cWipe; 14 | colorWalk cWalk; 15 | randomCreep cCreep; 16 | rainbow cRainbow; 17 | rainCycle cRainCycle; 18 | rainFull cRainFull; 19 | colorWave cWave; 20 | lightUp lUp; 21 | sparks sRnd; 22 | rndFade rFade; 23 | centerRun cRun; 24 | shineSeven cSeven; 25 | walkSeven wSeven; 26 | flashSeven fSeven; 27 | shineFlash cFlash; 28 | mergeOne mOne; 29 | mergeWave mWave; 30 | collideOne cOne; 31 | neoFire cFire; 32 | evenOdd cEvenOdd; 33 | collMdl cCollMdl; 34 | collEnd cCollEnd; 35 | rainBlend cBlend; 36 | swing cSwing; 37 | swingSingle cSwingS; 38 | randomFill rFill; 39 | singleWave sWave; 40 | worms cWorms; 41 | interfer cInterf; 42 | toward cToward; 43 | towardRain rToward; 44 | lghtHouse lHouse; 45 | rndDrops cDrops; 46 | solCreep sCreep; 47 | //theatChase tChase; 48 | //meteorSky mtrSky; 49 | symmRun symRun; 50 | //metSingle mtrSgl; 51 | //pureStrip pStrip; 52 | //sideFill sFill; 53 | //browMotion cBrowian; 54 | //rainDrops cRainDrp; 55 | ripeFruit cRipe; 56 | //brightWave bWave; 57 | //brColCreep bcCreep; 58 | 59 | clearSide clrSide; 60 | clearCntr clrCntr; 61 | clearFade clrFade; 62 | eatCntr clrEat; 63 | clearHalf clrHalf; 64 | animation* anims[] = { 65 | &cWipe, &cWalk, &cCreep, &cRainbow, &cRainCycle, &cRainFull, &cWave, &lUp, &sRnd, &rFade, 66 | &cCollEnd, &cRun, &cSeven, &mOne, &mWave, &cOne, &cFire, &cEvenOdd, &rFill, &cCollMdl, 67 | &cBlend, &cSwing, &cSwingS, &cFlash, &sWave, &cWorms, &cInterf, &cToward, &rToward, &lHouse, 68 | &cDrops, &wSeven, &fSeven, &sCreep, &symRun, &cRipe 69 | }; 70 | clr* clearance[] = { &clrSide, &clrCntr, &clrFade, &clrEat, &clrHalf }; 71 | const byte num_anim = sizeof(anims) / sizeof(animation*); 72 | const byte num_clr = sizeof(clearance) / sizeof(clr*); 73 | 74 | MANAGER mgr(anims, num_anim, clearance, num_clr); 75 | 76 | void setup() { 77 | //Serial.begin(115200); 78 | 79 | uint32_t rnd = 0; 80 | for (byte i = A0; i < A4; ++i) { 81 | pinMode(i, INPUT); 82 | rnd <<= 6; 83 | rnd += analogRead(i); 84 | } 85 | randomSeed(rnd); 86 | 87 | // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket 88 | #if defined (__AVR_ATtiny85__) 89 | if (F_CPU == 16000000) clock_prescale_set(clock_div_1); 90 | #endif 91 | 92 | strip.begin(); 93 | strip.setBrightness(NEO_BRGHT); 94 | strip.show(); // Initialize all pixels to 'off' 95 | mgr.init(); 96 | } 97 | 98 | void loop() { 99 | mgr.show(); 100 | } 101 | -------------------------------------------------------------------------------- /manager.cpp: -------------------------------------------------------------------------------- 1 | #include "manager.h" 2 | #include 3 | 4 | //---------------------------------------------- Shuffle the animation in the aRandom order -------------------------------- 5 | shuffle::shuffle(uint8_t a_size) { 6 | index = (uint8_t *)malloc(a_size); 7 | if (!index) a_size = 0; 8 | for (uint8_t i = 0; i < a_size; ++i) index[i] = i; 9 | curr = num_anim = a_size; 10 | } 11 | 12 | uint8_t shuffle::next(void) { 13 | if (num_anim == 0) return 0; 14 | if (curr >= num_anim) randomize(); 15 | return index[curr++]; 16 | } 17 | 18 | void shuffle::randomize(void) { 19 | for (uint8_t i = 0; i < num_anim*2; ++i) { 20 | uint8_t p1 = Random(num_anim); 21 | uint8_t p2 = Random(num_anim); 22 | if (p1 != p2) { 23 | uint8_t t = index[p2]; 24 | index[p2] = index[p1]; 25 | index[p1] = t; 26 | } 27 | } 28 | curr = 0; 29 | } 30 | 31 | // --------------------------------------------- The sequence manager ----------------------------------------------------- 32 | MANAGER::MANAGER(animation* a[], uint8_t a_size, clr* c[], uint8_t clr_size) : shuffle(a_size) { 33 | anims = a; 34 | clearance = c; 35 | num_clr = clr_size; 36 | stp = 0; 37 | do_clear = false; 38 | aIndex = 0; 39 | } 40 | 41 | void MANAGER::init(void) { 42 | if (!anims[aIndex]->do_clear) { 43 | aIndex = shuffle::next(); 44 | // aIndex = 44; 45 | a = anims[aIndex]; 46 | 47 | uint32_t period = a->show_time; 48 | period = Random(period, period * 3); // time in 10-seconds intervals 49 | period *= 10000; // Now time in ms 50 | next = millis() + period; 51 | } 52 | 53 | a = anims[aIndex]; 54 | strip.clear(); 55 | a->init(); // Initialization procedure can change period parameters (min_p & max_p) 56 | uint16_t min_stp = uint16_t(a->min_p) * 10; 57 | uint16_t max_stp = uint16_t(a->max_p) * 10; 58 | stp_period = Random(min_stp, max_stp) + 1; // If a->min_p == 0, ensure the step period is greater than 0 59 | stp = 0; 60 | 61 | strip.show(); 62 | a->do_clear = false; 63 | } 64 | 65 | void MANAGER::show(void) { 66 | uint32_t ms = millis(); 67 | if (!do_clear && (ms > next) && a->complete) { // The current animation is timed out 68 | if (isClean()) 69 | init(); 70 | else 71 | initClear(); 72 | } 73 | 74 | if (ms < stp) { // It is not time for next step, return 75 | return; 76 | } 77 | 78 | if (do_clear) 79 | stp = ms + clr_stp_period; 80 | else 81 | stp = ms + stp_period; 82 | 83 | if (do_clear) { 84 | if (c->isComplete()) { 85 | do_clear = false; 86 | if (ms > next) a->do_clear = false; // It is too late to continue the animation 87 | init(); 88 | } else 89 | c->show(); // Keep running clear session till it ends 90 | } else { 91 | if (a->do_clear) initClear(); 92 | a->show(); 93 | } 94 | strip.show(); 95 | } 96 | 97 | 98 | void MANAGER::initClear(void) { 99 | do_clear = true; // Start clearing sequence 100 | uint8_t ni = Random(num_clr); 101 | c = clearance[ni]; 102 | c->init(); 103 | stp = 0; 104 | clr_stp_period = Random(3, 10) * 10; 105 | } 106 | 107 | bool MANAGER::isClean(void) { 108 | for (uint16_t i = 0; i < strip.numPixels(); ++i) 109 | if (strip.getPixelColor(i)) return false; 110 | return true; 111 | } 112 | -------------------------------------------------------------------------------- /clean.cpp: -------------------------------------------------------------------------------- 1 | #include "clean.h" 2 | 3 | //---------------------------------------------- Classes for strip clearing ---------------------------------------------- 4 | bool clr::fadeAll(uint8_t val) { 5 | bool finish = true; 6 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 7 | if (!fade(i, val)) finish = false; 8 | } 9 | return finish; 10 | } 11 | 12 | bool clr::fade(uint16_t index, uint8_t val) { 13 | COLOR c = strip.getPixelColor(index); 14 | uint8_t bound = 0; 15 | for (int8_t s = 16; s >= 0; s -= 8) { 16 | int32_t cc = c >> s; // The color component (red, green or blue) 17 | cc &= 0xff; 18 | cc -= int(val); 19 | if (cc < 0) { 20 | cc = 0; 21 | bound ++; 22 | } 23 | uint32_t mask = 0xff; mask <<= s; mask = ~mask; 24 | cc <<= s; 25 | c &= mask; 26 | c |= cc; 27 | } 28 | strip.setPixelColor(index, c); 29 | return (bound >= 3); 30 | } 31 | 32 | bool clr::isComplete(void) { 33 | return complete; 34 | } 35 | 36 | // --------------------------------------------- Clear the strip from the ether side -------------------------------------- 37 | void clearSide::init(void) { 38 | complete = false; 39 | color = strip.wheel(Random(256)); 40 | fwd = Random(2); 41 | if (fwd) 42 | index = 0; 43 | else 44 | index = strip.numPixels() - 1; 45 | } 46 | 47 | void clearSide::show(void) { 48 | if (fwd) { 49 | if (index < int(strip.numPixels())) { 50 | strip.setPixelColor(index, color); 51 | if (index > 0) strip.setPixelColor(index-1, 0); 52 | } 53 | ++index; 54 | complete = (index >= int(strip.numPixels())); 55 | } else { 56 | if (index >= 0) { 57 | strip.setPixelColor(index, color); 58 | if (index < int(strip.numPixels() - 1)) strip.setPixelColor(index+1, 0); 59 | } 60 | --index; 61 | complete = (index < 0); 62 | } 63 | } 64 | 65 | // --------------------------------------------- Clear the strip from the center to both ends ----------------------------- 66 | void clearCntr::init(void) { 67 | complete = false; 68 | color = strip.wheel(Random(256)); 69 | l = strip.numPixels() / 2; 70 | r = l + 1; 71 | } 72 | 73 | void clearCntr::show(void) { 74 | if (r < int(strip.numPixels())) { 75 | strip.setPixelColor(r, color); 76 | if (r > 0) strip.setPixelColor(r-1, 0); 77 | } 78 | ++r; 79 | if (l >= 0) { 80 | strip.setPixelColor(l, color); 81 | if (l < int(strip.numPixels() - 1)) strip.setPixelColor(l+1, 0); 82 | } 83 | --l; 84 | complete = (l < 0); 85 | } 86 | 87 | // --------------------------------------------- Clear the strip by 'eating' the pixels from the center ------------------- 88 | void eatCntr::show(void) { 89 | int n = strip.numPixels(); 90 | int c = n / 2; 91 | for (int i = c; i > 0; --i) { 92 | COLOR c = strip.getPixelColor(i-1); 93 | strip.setPixelColor(i, c); 94 | } 95 | for (int i = c; i < n-1; ++i) { 96 | COLOR c = strip.getPixelColor(i+1); 97 | strip.setPixelColor(i, c); 98 | } 99 | strip.setPixelColor(0, 0); 100 | strip.setPixelColor(n-1, 0); 101 | --remain; 102 | complete = (remain <= 0); 103 | } 104 | 105 | //---------------------------------------------- Clear the strip by deviding it by 2 ------------------------------------ 106 | void clearHalf::init(void) { 107 | complete = false; 108 | one_step = strip.numPixels() / 2; 109 | } 110 | 111 | void clearHalf::show(void) { 112 | for (uint16_t i = 0; i < strip.numPixels(); i += one_step) { 113 | if (i > 0 || (one_step == 1)) strip.setPixelColor(i, 0); 114 | } 115 | complete = ((one_step >>= 1) == 0); 116 | } 117 | 118 | 119 | -------------------------------------------------------------------------------- /clrutils.cpp: -------------------------------------------------------------------------------- 1 | #include "clrutils.h" 2 | 3 | // --------------------------------------------- creep the sequence up or down, superclass -------------------------------- 4 | void CRAWL::step(void) { 5 | if (fwd) { // creep forward 6 | for (int i = strip.numPixels()-1; i > 0; --i) { 7 | uint32_t c = strip.getPixelColor(i-1); 8 | strip.setPixelColor(i, c); 9 | } 10 | strip.setPixelColor(0, next_color); 11 | } else { // creep backward 12 | int last = strip.numPixels()-1; 13 | for (int i = 0; i < last; ++i) { 14 | uint32_t c = strip.getPixelColor(i+1); 15 | strip.setPixelColor(i, c); 16 | } 17 | strip.setPixelColor(last, next_color); 18 | } 19 | } 20 | 21 | //---------------------------------------------- Brightness manipulation -------------------------------------------------- 22 | void BRGTN::setColor(COLOR c) { 23 | color[0] = c & 0xff; c >>= 8; // Blue 24 | color[1] = c & 0xff; c >>= 8; // Green 25 | color[2] = c & 0xff; // Red 26 | } 27 | 28 | bool BRGTN::changeClr(COLOR& c, int8_t val) { 29 | COLOR new_color = 0; 30 | uint8_t bound = 0; 31 | 32 | if (val < 0) { // Decrement color 33 | if (c == 0) // Cannot decrement zero color 34 | return true; 35 | int16_t e = 256 + val; 36 | for (uint8_t i = 0; i < 3; ++i) { 37 | int32_t cc = c & 0xff; c >>= 8; // Color component value (b, g, r) 38 | int32_t new_cc = cc * e; new_cc >>= 8; // New color component = (cc * e) / 256; 39 | if (new_cc == cc) { // For small COLOR component value use addition instead of multiplication 40 | cc += val; 41 | } else { 42 | cc = new_cc; 43 | } 44 | if (cc <= 0) { 45 | cc = 0; 46 | ++bound; 47 | } 48 | new_color >>= 8; 49 | cc <<= 16; new_color |= cc; // Build new color by shift the components from left to right 50 | } 51 | } else { // Increment color 52 | for (uint8_t i = 0; i < 3; ++i) { 53 | int16_t e = (color[i] * val) >> 8; 54 | if (e == 0) e = 1; 55 | int32_t cc = c & 0xff; c >>= 8; // Color component value (b, g, r) 56 | cc += e; 57 | if (cc >= color[i]) { // Limit component value by the component of the preset color 58 | cc = color[i]; 59 | ++bound; 60 | } 61 | new_color >>= 8; 62 | cc <<= 16; new_color |= cc; // Build new color by shift the components from left to right 63 | } 64 | } 65 | 66 | c = new_color; 67 | return (bound >= 3); 68 | } 69 | 70 | bool BRGTN::change(uint16_t index, int8_t val) { 71 | COLOR c = strip.getPixelColor(index); 72 | bool done = changeClr(c, val); 73 | strip.setPixelColor(index, c); 74 | return done; 75 | } 76 | 77 | bool BRGTN::changeAll(int8_t val) { 78 | bool finish = true; 79 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 80 | COLOR c = strip.getPixelColor(i); 81 | if (!changeClr(c, val)) finish = false; 82 | strip.setPixelColor(i, c); 83 | } 84 | return finish; 85 | } 86 | 87 | //---------------------------------------------- Blend manipulations ------------------------------------------------------ 88 | COLOR BLEND::add(COLOR color1, COLOR color2) { 89 | uint8_t r1,g1,b1; 90 | uint8_t r2,g2,b2; 91 | 92 | r1 = (uint8_t)(color1 >> 16); 93 | g1 = (uint8_t)(color1 >> 8); 94 | b1 = (uint8_t)(color1 >> 0); 95 | 96 | r2 = (uint8_t)(color2 >> 16); 97 | g2 = (uint8_t)(color2 >> 8); 98 | b2 = (uint8_t)(color2 >> 0); 99 | 100 | return strip.Color(constrain(r1+r2, 0, 255), constrain(g1+g2, 0, 255), constrain(b1+b2, 0, 255)); 101 | } 102 | 103 | COLOR BLEND::sub(COLOR color1, COLOR color2) { 104 | uint8_t r1,g1,b1; 105 | uint8_t r2,g2,b2; 106 | int16_t r,g,b; 107 | 108 | r1 = (uint8_t)(color1 >> 16); 109 | g1 = (uint8_t)(color1 >> 8); 110 | b1 = (uint8_t)(color1 >> 0); 111 | 112 | r2 = (uint8_t)(color2 >> 16); 113 | g2 = (uint8_t)(color2 >> 8); 114 | b2 = (uint8_t)(color2 >> 0); 115 | 116 | r = (int16_t)r1 - (int16_t)r2; 117 | g = (int16_t)g1 - (int16_t)g2; 118 | b = (int16_t)b1 - (int16_t)b2; 119 | if (r < 0) r = 0; 120 | if (g < 0) g = 0; 121 | if (b < 0) b = 0; 122 | 123 | return strip.Color(r, g, b); 124 | } 125 | 126 | void BLEND::blendPixel(uint16_t p, uint8_t deviation) { 127 | if (deviation < 3) deviation = 3; 128 | uint8_t r1 = Random(deviation); 129 | uint8_t g1 = Random(deviation); 130 | uint8_t b1 = Random(deviation); 131 | uint32_t diff_color = strip.Color(r1, g1, b1); 132 | uint32_t blended_color = add(diff_color, strip.getPixelColor(p)); 133 | r1 = Random(deviation); 134 | g1 = Random(deviation); 135 | b1 = Random(deviation); 136 | diff_color = strip.Color(r1, g1, b1); 137 | blended_color = sub(blended_color, diff_color); 138 | strip.setPixelColor(p, blended_color); 139 | } 140 | 141 | //---------------------------------------------- Color superposition class ------------------------------------------------ 142 | COLOR TWOCLR::add(COLOR c1, COLOR c2) { 143 | COLOR c = 0; 144 | for (uint8_t i = 0; i < 3; ++i) { 145 | uint32_t p = c1 >> (i*8); 146 | p += c2 >> (i*8); 147 | p &= 0xff; 148 | p <<= i*8; 149 | c |= p; 150 | } 151 | return c; 152 | } 153 | 154 | //---------------------------------------------- The sine wave value class ------------------------------------------------ 155 | uint8_t WAVE::amplitude(uint8_t n) { 156 | n &= 0x3F; // The sin(PI*n/32) period is 64 157 | if (n >= 32) { 158 | n -= 32; 159 | if (n > 16) 160 | return 254 - sine[32-n]; 161 | else 162 | return 254 - sine[n]; 163 | } else { 164 | if (n > 16) 165 | return sine[32-n]; 166 | else 167 | return sine[n]; 168 | } 169 | } 170 | 171 | COLOR WAVE::intencity(COLOR c, uint8_t n) { 172 | COLOR res = 0; 173 | for (uint8_t i = 0; i < 3; ++i) { // Get the color components: b, g, r 174 | res >>= 8; 175 | uint32_t cc = c & 0xFF; c >>= 8; 176 | cc *= amplitude(n); 177 | cc /= 254; 178 | cc <<= 16; res |= cc; 179 | } 180 | return res; 181 | } 182 | -------------------------------------------------------------------------------- /animation.h: -------------------------------------------------------------------------------- 1 | #ifndef __ANIMATION_H 2 | #define __ANIMATION_H 3 | #include "clrutils.h" 4 | 5 | const uint8_t min_time = 30; // Minimal sequence show time (seconds) 6 | 7 | //---------------------------------------------- Base animation class with useful functions ------------------------------- 8 | class animation { 9 | public: 10 | animation(void); 11 | virtual ~animation(void) { } 12 | virtual void init(void) = 0; 13 | virtual void show(void) = 0; 14 | void getLimits(uint8_t& mi_p, uint8_t& ma_p) { mi_p = min_p; ma_p = max_p; } 15 | uint8_t min_p; // The minimum period in tenth of second to show the stage 16 | uint8_t max_p; // The maximum period in tenth of second to show the stage 17 | uint8_t show_time; // The minimum time to show whole the sequence in 10-seconds intervals 18 | bool do_clear; // Whether the strip have to be cleaned for the next loop 19 | bool complete; // Whether the animation can be changed to the next one 20 | }; 21 | 22 | // --------------------------------------------- Fill the dots one after the other with a color --------------------------- 23 | class colorWipe: public animation { 24 | public: 25 | colorWipe(void) { w = Random(256); index = 0; fwd = true; } 26 | virtual void init(void); 27 | virtual void show(void); 28 | private: 29 | uint8_t w; 30 | int index; 31 | bool fwd; 32 | }; 33 | 34 | // --------------------------------------------- Walk the dots one after the other with a color --------------------------- 35 | class colorWalk: public animation { 36 | public: 37 | colorWalk(void) { min_p = 4; max_p = 12; index = 0; period = 0; fwd = true; w = 0; } 38 | virtual void init(void); 39 | virtual void show(void); 40 | private: 41 | int index; 42 | uint8_t period; 43 | bool fwd; 44 | uint8_t w; 45 | }; 46 | 47 | // --------------------------------------------- creep the aRandom sequence up or down ------------------------------------- 48 | class randomCreep: public animation, public CRAWL { 49 | public: 50 | randomCreep(void) { min_p = 6; max_p = 24; space = cnt = 0; change_direction = 0;} 51 | virtual void init(void); 52 | virtual void show(void); 53 | private: 54 | uint8_t space; // space between the color dots 55 | int change_direction; 56 | uint8_t cnt; 57 | }; 58 | 59 | // --------------------------------------------- show the color Wave using rainbowCycle ----------------------------------- 60 | class colorWave: public animation, public CRAWL, public BRGTN { 61 | public: 62 | colorWave(void) { index = 0; rdy = false; } 63 | virtual void init(void); 64 | virtual void show(void); 65 | private: 66 | uint8_t index; 67 | bool rdy; 68 | }; 69 | 70 | // --------------------------------------------- show the rainbow (from the NEOPIXEL example) ----------------------------- 71 | class rainbow: public animation, public BRGTN { 72 | public: 73 | rainbow(void) { index = 0; rdy = false; } 74 | virtual void init(void) { index = 0; rdy = false; } 75 | virtual void show(void); 76 | private: 77 | uint8_t index; 78 | bool rdy; 79 | }; 80 | 81 | // --------------------------------------------- show the rainbowCycle (from the NEOPIXEL example) ------------------------ 82 | class rainCycle: public animation, public BRGTN { 83 | public: 84 | rainCycle(void) { index = 0; rdy = false; } 85 | virtual void init(void) { index = 0; rdy = false; } 86 | virtual void show(void); 87 | private: 88 | uint8_t index; 89 | bool rdy; 90 | }; 91 | 92 | // --------------------------------------------- show the rainbow colors on the entire strip ------------------------------ 93 | class rainFull: public animation, public BRGTN { 94 | public: 95 | rainFull(void) { min_p = 6; max_p = 24; index = 0; rdy = false; } 96 | virtual void init(void) { index = Random(256); rdy = false; } 97 | virtual void show(void); 98 | private: 99 | uint8_t index; 100 | bool rdy; 101 | }; 102 | 103 | //---------------------------------------------- Light up with the Random color than fade out ----------------------------- 104 | class lightUp : public animation, public BRGTN { 105 | public: 106 | lightUp() { min_p = 6; max_p = 24; show_time = 12; sp = inc = 0; } 107 | virtual void init(void) { sp = 1; inc = sp; newColor(); } 108 | virtual void show(void); 109 | private: 110 | void newColor(void); 111 | uint8_t sp; 112 | int8_t inc; 113 | }; 114 | 115 | //---------------------------------------------- aRandom sparcs ------------------------------------------------------------ 116 | class sparks : public animation, public BRGTN { 117 | public: 118 | sparks() { min_p = 2; max_p = 6; show_time = 12; } 119 | virtual void init(void) { for (uint8_t i = 0; i < 8; ++i) pos[i] = 0; } 120 | virtual void show(void); 121 | private: 122 | uint16_t pos[8]; 123 | }; 124 | 125 | //---------------------------------------------- aRandom sparks fade out --------------------------------------------------- 126 | class rndFade : public animation, public BRGTN { 127 | public: 128 | rndFade() { min_p = 6; max_p = 24; show_time = 12; } 129 | virtual void init(void) { } 130 | virtual void show(void); 131 | }; 132 | 133 | //---------------------------------------------- Lights run from the center ----------------------------------------------- 134 | class centerRun : public animation { 135 | public: 136 | centerRun() { min_p = 4; max_p = 20; m = l = r = 0; color = 0; } 137 | virtual void init(void); 138 | virtual void show(void); 139 | private: 140 | COLOR color; 141 | int16_t m, l, r; 142 | }; 143 | 144 | //---------------------------------------------- Slow shining by the different colors ------------------------------------- 145 | class shineSeven : public animation, public BRGTN { 146 | public: 147 | shineSeven() { min_p = 4; max_p = 20; show_time = 12; curs = w = base = 0; } 148 | virtual void init(void); 149 | virtual void show(void); 150 | private: 151 | void startNewColor(void); 152 | uint8_t curs; 153 | uint8_t w; 154 | uint8_t base; 155 | }; 156 | 157 | //---------------------------------------------- Rapid walking by the different colors ----------------------------------- 158 | class walkSeven : public animation, public BRGTN, public TWOCLR { 159 | public: 160 | walkSeven() { min_p = 8; max_p = 15; show_time = 9; curs = w = ch_dir = period = 0; fwd = true; } 161 | virtual void init(void); 162 | virtual void show(void); 163 | private: 164 | int8_t curs; 165 | uint8_t w; 166 | bool fwd; 167 | int ch_dir; 168 | uint8_t period; 169 | }; 170 | 171 | //---------------------------------------------- Rapid flashing by the difference colors --------------------------------- 172 | class flashSeven : public animation, public BRGTN { 173 | public: 174 | flashSeven() { min_p = 4; max_p = 8; show_time = 9; curs = w = ch_dir = period = 0; fwd = true; } 175 | virtual void init(void); 176 | virtual void show(void); 177 | private: 178 | int8_t curs; 179 | uint8_t w; 180 | bool fwd; 181 | int ch_dir; 182 | uint8_t period; 183 | }; 184 | 185 | //---------------------------------------------- Slow merging of two colors ----------------------------------------------- 186 | class mergeOne : public animation, public TWOCLR { 187 | public: 188 | mergeOne() { min_p = 8; max_p = 30; cl = cr = 0; l = r = 0; } 189 | virtual void init(void); 190 | virtual void show(void); 191 | private: 192 | COLOR cl, cr; 193 | int16_t l, r; 194 | }; 195 | 196 | //---------------------------------------------- Fast merging of Waves ---------------------------------------------------- 197 | class mergeWave : public animation { 198 | public: 199 | mergeWave() { min_p = 3; max_p = 20; show_time = 2; l = r = 0; index = len = 0;} 200 | virtual void init(void); 201 | virtual void show(void); 202 | private: 203 | int l, r; 204 | uint8_t index; 205 | uint8_t len; 206 | }; 207 | 208 | //---------------------------------------------- Fast collide of two colors --------------------------------------------- 209 | class collideOne : public animation { 210 | public: 211 | collideOne() { min_p = 1; max_p = 3; show_time = 2; cl = cr = 0; l = r = 0; boom = true; } 212 | virtual void init(void); 213 | virtual void show(void); 214 | private: 215 | COLOR cl, cr; 216 | int16_t l, r; 217 | bool boom; 218 | }; 219 | 220 | //---------------------------------------------- Neo fire animation by Robert Ulbricht ---------------------------------- 221 | class neoFire : public animation, public BLEND { 222 | public: 223 | neoFire() { min_p = 1; max_p = 5; color = 0; pause = 0; } 224 | virtual void init(void); 225 | virtual void show(void); 226 | private: 227 | COLOR color; 228 | int8_t pause; 229 | const COLOR c1 = 80; 230 | const COLOR c2 = 25; 231 | }; 232 | 233 | //---------------------------------------------- Even and odd position leds are moving towards each other --------------- 234 | class evenOdd : public animation { 235 | public: 236 | evenOdd() { min_p = 10; max_p = 20; cl = cr = 0; l = r = 0; } 237 | virtual void init(void); 238 | virtual void show(void); 239 | private: 240 | COLOR cl, cr; 241 | int16_t l, r; 242 | }; 243 | 244 | //---------------------------------------------- aRandom colors from left and right move to the center ------------------- 245 | class collMdl : public animation, public BLEND { 246 | public: 247 | collMdl() { min_p = 1; max_p = 6; show_time = 8; cl = cr = 0; l = r = ml = mr = 0; clr = false; } 248 | virtual void init(void); 249 | virtual void show(void); 250 | private: 251 | void newColors(void); 252 | COLOR cl, cr; 253 | int16_t l, r, ml, mr; 254 | bool clr; 255 | }; 256 | 257 | //------------------------------------------- aRandom colors from left and right move to the other end ------------------- 258 | class collEnd : public animation, public BLEND { 259 | public: 260 | collEnd() { min_p = 1; max_p = 6; show_time = 10; cl = cr = 0; l = r = ml = mr = 0; } 261 | virtual void init(void); 262 | virtual void show(void); 263 | private: 264 | void newColors(void); 265 | COLOR cl, cr; 266 | int16_t l, r, ml, mr; 267 | }; 268 | 269 | //------------------------------------------- Rainbow colors blend -------------------------------------------------------- 270 | class rainBlend : public animation, public BLEND { 271 | public: 272 | rainBlend() { min_p = 1; max_p = 6; index = 0; } 273 | virtual void init(void) { index = 0; } 274 | virtual void show(void); 275 | private: 276 | int16_t index; 277 | }; 278 | 279 | //---------------------------------------------- Color swing -------------------------------------------------------------- 280 | class swing : public animation, public CRAWL { 281 | public: 282 | swing() { min_p = 3; max_p = 10; show_time = 10; len = index = 0; w = 0; rnd = false; } 283 | virtual void init(void); 284 | virtual void show(void); 285 | private: 286 | int16_t len, index; 287 | uint8_t w; 288 | bool rnd; 289 | }; 290 | 291 | //---------------------------------------------- Single color swing ------------------------------------------------------- 292 | class swingSingle : public animation { 293 | public: 294 | swingSingle() { min_p = 3; max_p = 10; show_time = 10; color = 0; len = index = 0; w = 0; fwd = true; } 295 | virtual void init(void); 296 | virtual void show(void); 297 | private: 298 | COLOR color; 299 | int16_t len, index; 300 | bool fwd; 301 | uint8_t w; 302 | }; 303 | 304 | //---------------------------------------------- Fill the strip by the color in aRandom order ---------------------------- 305 | class randomFill : public animation, public BRGTN, public BLEND { 306 | public: 307 | randomFill() { min_p = 2; max_p = 4; show_time = 15; } 308 | virtual void init(void); 309 | virtual void show(void); 310 | private: 311 | void newDot(bool clr); 312 | uint8_t w = 0; 313 | int16_t remain = 0; 314 | uint16_t pos = 0; 315 | bool clr = false; 316 | }; 317 | 318 | //---------------------------------------------- Slow shining and flash by the different colors --------------------------- 319 | class shineFlash : public animation, public BRGTN { 320 | public: 321 | shineFlash() { min_p = 4; max_p = 20; show_time = 12; w = mode = wait = 0; remain = indx = 0; flash = false; } 322 | virtual void init(void); 323 | virtual void show(void); 324 | private: 325 | void startNewColor(void); 326 | uint8_t w; 327 | uint8_t mode; 328 | bool flash; 329 | int16_t remain; 330 | int16_t indx; 331 | int8_t wait; 332 | }; 333 | 334 | //---------------------------------------------- Show single wave moving in Random direction ------------------------------ 335 | class singleWave : public animation, public BRGTN { 336 | public: 337 | singleWave() { min_p = 4; max_p = 20; show_time = 12; pos = 0; stp = remain = incr = mode = w = 0; } 338 | virtual void init(void); 339 | virtual void show(void); 340 | private: 341 | COLOR dot[5]; 342 | int16_t pos; 343 | uint8_t stp; 344 | uint8_t remain; 345 | int8_t incr; 346 | uint8_t mode; 347 | uint8_t w; 348 | }; 349 | 350 | //---------------------------------------------- Several worms are moving Randomly --------------------------------------- 351 | class worms : public animation, public BRGTN, public TWOCLR { 352 | public: 353 | worms() { min_p = 10; max_p = 20; show_time = 9; active = 0; } 354 | virtual void init(void); 355 | virtual void show(void); 356 | private: 357 | void add(void); 358 | void die(uint8_t index); 359 | struct worm { 360 | COLOR color; 361 | int16_t pos; 362 | bool fwd; 363 | }; 364 | struct worm w[5]; 365 | uint8_t active; 366 | }; 367 | 368 | //---------------------------------------------- Show interferention from many sources ---------------------------------- 369 | class interfer : public animation, public TWOCLR { 370 | #define num_inter 3 371 | public: 372 | interfer() { min_p = 6; max_p = 10; show_time = 6; tm = active = 0; } 373 | virtual void init(void); 374 | virtual void show(void); 375 | private: 376 | void add(void); 377 | uint32_t clr(int p, uint8_t source); 378 | int16_t tm; // Time the animation starts (in cycles) 379 | int16_t pos[num_inter]; // The position of the source 380 | int16_t start[num_inter]; // Time when the source activated 381 | uint8_t w[num_inter]; // Wheel Color index of the source 382 | uint8_t active; // The number of active sources 383 | }; 384 | 385 | //------------------------------------------- Random colors toward each other ------------------------------------------ 386 | class toward : public animation { 387 | public: 388 | toward() { min_p = 5; max_p = 10; show_time = 6; w = 0; } 389 | virtual void init(void) { w = Random(256); } 390 | virtual void show(void); 391 | private: 392 | uint8_t w; 393 | }; 394 | 395 | //------------------------------------------- Raindow colors toward each other ------------------------------------------ 396 | class towardRain : public animation { 397 | public: 398 | towardRain() { min_p = 10; max_p = 20; show_time = 8; w = 0; } 399 | virtual void init(void) { w = Random(256); } 400 | virtual void show(void); 401 | private: 402 | uint8_t w; 403 | }; 404 | 405 | //---------------------------------------------- Slow single wave moving in aRandom direction -- --------------------------- 406 | class lghtHouse : public animation, public BRGTN { 407 | public: 408 | lghtHouse() { min_p = 2; max_p = 10; show_time = 6; pos = 0; stp = incr = sp = dlay = 0; } 409 | virtual void init(void); 410 | virtual void show(void); 411 | private: 412 | COLOR dot[5]; 413 | int16_t pos; 414 | uint8_t stp; 415 | int8_t incr; 416 | uint8_t sp; 417 | uint8_t dlay; 418 | }; 419 | 420 | //---------------------------------------------- Random dropped color dot fading out from epicenter ---------------------- 421 | class rndDrops : public animation, public BRGTN, public TWOCLR { 422 | public: 423 | rndDrops() { min_p = 2; max_p = 7; show_time = 9; num = 0; } 424 | virtual void init(void) { num = 0; add(); } 425 | virtual void show(void); 426 | private: 427 | void add(void); 428 | struct drop { 429 | int16_t pos; 430 | int8_t tm; 431 | }; 432 | struct drop dr[16]; 433 | int8_t num; 434 | }; 435 | 436 | // --------------------------------------------- Solitons are creaping up or down ----------------------------------------- 437 | class solCreep: public animation, public CRAWL { 438 | public: 439 | solCreep(void) { min_p = 6; max_p = 14; show_time = 9; space = change_direction = sol = 0; w = 0; } 440 | virtual void init(void); 441 | virtual void show(void); 442 | private: 443 | void newSoliton(void); 444 | int16_t space; // space between the solitons 445 | int16_t change_direction; // the time to change direction 446 | COLOR dot[5]; 447 | int16_t sol; 448 | uint8_t w; 449 | }; 450 | 451 | // --------------------------------------------- Theatre-style crawling lights from NEOPIXEL example ---------------------- 452 | class theatChase: public animation { 453 | public: 454 | theatChase(void) { min_p = 3; max_p = 8; show_time = 3; w = color_period = color_shift = stp = 0; } 455 | virtual void init(void); 456 | virtual void show(void); 457 | private: 458 | uint8_t w; // color wheel index 459 | uint8_t color_period; // color period shift 460 | int8_t color_shift; 461 | uint8_t stp; 462 | }; 463 | 464 | // --------------------------------------------- Meteors falling down ----------------------------------------------------- 465 | class meteorSky: public animation, public BRGTN { 466 | public: 467 | meteorSky(void) { min_p = 1; max_p = 3; } 468 | virtual void init(void); 469 | virtual void show(void); 470 | private: 471 | bool grow = true; 472 | uint16_t head = 0; 473 | uint16_t tail = 0; 474 | }; 475 | 476 | // --------------------------------------------- Symmetrical dots run ----------------------------------------------------- 477 | class symmRun: public animation, public BRGTN { 478 | public: 479 | symmRun(void) { min_p = 0; max_p = 3; } 480 | virtual void init(void); 481 | virtual void show(void); 482 | private: 483 | uint16_t left = 0; 484 | uint16_t right = 0; 485 | uint8_t w = 0; 486 | uint8_t phase = 0; 487 | uint8_t drk_stp = 0; 488 | }; 489 | 490 | // --------------------------------------------- Defined Meteors falling down fast ---------------------------------------- 491 | class metSingle: public animation { 492 | public: 493 | metSingle(void) { min_p = 1; max_p = 3; show_time = 3; } 494 | virtual void init(void); 495 | virtual void show(void); 496 | private: 497 | uint8_t head = 0; 498 | const COLOR clr[8] = { 0xffb844, 0xfcff96, 0xfdffce, 0xffffff, 0xffb540, 0xfe9e4a, 0xe65634, 0x91182b }; 499 | const uint8_t clr_size = 8; 500 | }; 501 | 502 | // --------------------------------------------- Classical multicolor strip simulation ------------------------------------ 503 | class pureStrip: public animation, public BRGTN { 504 | public: 505 | pureStrip(void) { } 506 | virtual void init(void); 507 | virtual void show(void); 508 | private: 509 | uint8_t mode = 0; 510 | uint8_t stage = 0; 511 | uint8_t blink = 0; 512 | uint8_t num_color = 0; // The number of different colors in the strip 2-6 513 | COLOR clr[6]; // Colors of the strip 514 | }; 515 | 516 | // --------------------------------------------- Multiple attemption to fill up the strip from one side ------------------- 517 | class sideFill: public animation, public BRGTN { 518 | public: 519 | sideFill(void) { min_p = 2; max_p = 4; show_time = 4; } 520 | virtual void init(void); 521 | virtual void show(void); 522 | private: 523 | bool fwd = false; // Which side to fill-up 524 | bool on = true; 525 | bool rainbow = false; // Whether use a rainbow color or just monochrome 526 | uint16_t stage = 0; // Current maximum length of lit leds 527 | uint16_t index = 0; // The index of led that should be lit in this step 528 | uint8_t w = 0; // Color wheel index 529 | }; 530 | 531 | // --------------------------------------------- Browian Motion with the tail -------------------------------------------- 532 | class browMotion: public animation, public BRGTN { 533 | public: 534 | browMotion(void) { min_p = 3; max_p = 8; show_time = 4; } 535 | virtual void init(void); 536 | virtual void show(void); 537 | private: 538 | void newDestination(uint16_t num_pixels); 539 | uint8_t w = 0; // color wheel index 540 | int8_t speed = 0; // distance of one move 541 | uint16_t pos = 0; // current position 542 | uint16_t destination = 0; // next destination index (0 - num_pixel) 543 | }; 544 | 545 | // --------------------------------------------- Rain drops running down ------------------------------------------------- 546 | class rainDrops: public animation, public BRGTN { 547 | public: 548 | rainDrops(void) { min_p = 6; max_p = 16; show_time = 4; } 549 | virtual void init(void); 550 | virtual void show(void); 551 | private: 552 | struct r_drop { 553 | uint16_t head; // Position of the drop 554 | COLOR c; // color of the drop 555 | uint8_t speed; // Speed: the number of pixel crossed by one move 556 | }; 557 | void newDrop(void); 558 | const uint8_t max_drops = 10; 559 | struct r_drop drop[10]; 560 | uint8_t active_drops = 0; 561 | }; 562 | 563 | // --------------------------------------------- Ripe fruits booms and run two pieces ------------------------------------ 564 | class ripeFruit: public animation, public BRGTN { 565 | public: 566 | ripeFruit(void) { min_p = 6; max_p = 16; show_time = 4; } 567 | virtual void init(void); 568 | virtual void show(void); 569 | private: 570 | struct r_fruit { 571 | uint16_t part[2]; // Position of the half of the fruit 572 | COLOR c; // color of the fruit 573 | uint8_t speed; // Speed: the number of pixel crossed by one move 574 | }; 575 | void newFruit(void); 576 | const uint8_t max_fruits = 10; 577 | struct r_fruit fruit[10]; 578 | uint8_t active_fruits = 0; 579 | }; 580 | 581 | // --------------------------------------------- The single color that changes the brightness as a sine ------------------ 582 | class brightWave: public animation, public WAVE { 583 | public: 584 | brightWave(void) { min_p = 6; max_p = 16; show_time = 4; } 585 | virtual void init(void); 586 | virtual void show(void); 587 | private: 588 | uint8_t w = 0; // The color wheel index 589 | uint8_t t = 0; 590 | bool fwd = false; 591 | }; 592 | 593 | // --------------------------------------------- Color pixels walking up and down with sine brightness ------------------- 594 | class brColCreep: public animation, public WAVE, public CRAWL { 595 | public: 596 | brColCreep(void) { min_p = 6; max_p = 16; show_time = 4; } 597 | virtual void init(void); 598 | virtual void show(void); 599 | private: 600 | uint8_t w = 0; // The color wheel index 601 | uint8_t t = 0; 602 | }; 603 | 604 | #endif 605 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /animation.cpp: -------------------------------------------------------------------------------- 1 | #include "animation.h" 2 | #include "math.h" 3 | 4 | //---------------------------------------------- Base animation class with useful functions ------------------------------- 5 | animation::animation(void) { 6 | min_p = 2; 7 | max_p = 8; 8 | show_time = min_time / 10; 9 | do_clear = false; 10 | complete = true; 11 | } 12 | 13 | // --------------------------------------------- Fill the dots one after the other with a color --------------------------- 14 | void colorWipe::init(void) { 15 | int p = Random(2, 4); 16 | w += p*16 + 1; 17 | fwd = Random(2); 18 | index = 0; 19 | if (!fwd) index = strip.numPixels() - 1; 20 | } 21 | 22 | void colorWipe::show(void) { 23 | uint32_t color = strip.wheel(w); 24 | if (fwd) { 25 | if (index > int(strip.numPixels())) { // Start new sequence with the new color 26 | init(); 27 | complete = true; 28 | return; 29 | } 30 | strip.setPixelColor(index++, color); 31 | } else { 32 | if (index < 0) { // Start new sequence with the new color 33 | init(); 34 | complete = true; 35 | return; 36 | } 37 | strip.setPixelColor(index--, color); 38 | } 39 | complete = false; 40 | } 41 | 42 | // --------------------------------------------- Walk the dots one after the other with a color --------------------------- 43 | void colorWalk::init(void) { 44 | index = 0; 45 | w = Random(256); 46 | fwd = Random(2); 47 | period = Random(10, 30); 48 | } 49 | 50 | void colorWalk::show(void) { 51 | int n = strip.numPixels(); 52 | if (fwd) { 53 | if (index > n) { 54 | index -= period; 55 | strip.setPixelColor(n-1, 0); 56 | } 57 | uint32_t color = strip.wheel(w--); 58 | for (int i = index; i > 0; i -= period) { 59 | if (i > 0) strip.setPixelColor(i-1, 0); 60 | strip.setPixelColor(i, color); 61 | } 62 | ++index; 63 | } else { 64 | if (index < 0) { 65 | index += period; 66 | strip.setPixelColor(0, 0); 67 | } 68 | uint32_t color = strip.wheel(w++); 69 | for (int i = index; i < n; i += period) { 70 | if (i < int(strip.numPixels() - 1)) strip.setPixelColor(i+1, 0); 71 | strip.setPixelColor(i, color); 72 | } 73 | --index; 74 | } 75 | } 76 | 77 | // --------------------------------------------- creep the aRandom sequence up or down ------------------------------------- 78 | void randomCreep::init(void) { 79 | space = Random(2, 5); 80 | change_direction = Random(100, 500); 81 | cnt = 0; 82 | } 83 | 84 | void randomCreep::show(void) { 85 | -- change_direction; 86 | if (change_direction <= 0) { 87 | fwd = !fwd; 88 | init(); 89 | } 90 | 91 | next_color = 0; 92 | ++cnt; 93 | if (cnt > space) { 94 | cnt = 0; 95 | next_color = strip.wheel(Random(256)); 96 | } 97 | step(); 98 | } 99 | 100 | // --------------------------------------------- show the color Wave using rainbowCycle ----------------------------------- 101 | void colorWave::init(void) { 102 | index = 0; 103 | rdy = false; 104 | fwd = Random(2); 105 | } 106 | 107 | void colorWave::show(void) { 108 | if (!rdy) { 109 | rdy = true; 110 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 111 | setColor(strip.wheel(((i * 256 / strip.numPixels())) & 255)); 112 | if (!change(i, 2)) rdy = false; 113 | } 114 | return; 115 | } 116 | 117 | step(); 118 | if (fwd) 119 | strip.setPixelColor(0, strip.wheel(index & 255)); 120 | else 121 | strip.setPixelColor(strip.numPixels() - 1, strip.wheel(index & 255)); 122 | ++index; 123 | } 124 | 125 | // --------------------------------------------- show the rainbow (from the NEOPIXEL example) ----------------------------- 126 | void rainbow::show(void) { 127 | if (!rdy) { 128 | rdy = true; 129 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 130 | setColor(strip.wheel(i & 255)); 131 | if (!change(i, 2)) rdy = false; 132 | } 133 | return; 134 | } 135 | 136 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 137 | strip.setPixelColor(i, strip.wheel((i+index) & 255)); 138 | } 139 | ++index; // index is from 0 to 255 140 | } 141 | 142 | // --------------------------------------------- show the rainbowCycle (from the NEOPIXEL example) ------------------------ 143 | void rainCycle::show(void) { 144 | if (!rdy) { 145 | rdy = true; 146 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 147 | setColor(strip.wheel((i * 256 / strip.numPixels()) & 255)); 148 | if (change(i, 1)) rdy = false; 149 | } 150 | return; 151 | } 152 | 153 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 154 | strip.setPixelColor(i, strip.wheel(((i * 256 / strip.numPixels()) + index) & 255)); 155 | } 156 | ++index; // index is from 0 to 255 157 | } 158 | 159 | // --------------------------------------------- show the rainbow colors on the entire strip ------------------------------ 160 | void rainFull::show(void) { 161 | if (!rdy) { 162 | rdy = true; 163 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 164 | setColor(strip.wheel(index)); 165 | if (!change(i, 1)) rdy = false; 166 | } 167 | return; 168 | } 169 | 170 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 171 | strip.setPixelColor(i, strip.wheel(index)); 172 | } 173 | ++index; // index is from 0 to 255 174 | } 175 | 176 | //---------------------------------------------- Light up with the aRandom color than fade out ----------------------------- 177 | void lightUp::show(void) { 178 | bool finish = changeAll(inc); 179 | if (finish) { 180 | if (inc > 0) { 181 | inc = -8; 182 | } else { 183 | ++sp; 184 | inc = sp; 185 | if (sp > 8) { 186 | sp = 1; 187 | newColor(); 188 | } 189 | } 190 | } 191 | } 192 | 193 | void lightUp::newColor(void) { 194 | uint32_t c = 0; 195 | for (uint8_t i = 0; i < 3; ++i) { 196 | c <<= 8; 197 | uint8_t d = Random(16) << 4; 198 | c |= d; 199 | } 200 | setColor(c); 201 | } 202 | 203 | //---------------------------------------------- Random sparcs ------------------------------------------------------------ 204 | void sparks::show(void) { 205 | uint32_t c = strip.wheel(Random(256)); 206 | for (int8_t i = 7; i >= 1; --i) { 207 | if (i == 6) 208 | strip.setPixelColor(pos[uint8_t(i)], 0); 209 | else 210 | change(pos[uint8_t(i)], -128); 211 | pos[uint8_t(i)] = pos[uint8_t(i-1)]; 212 | } 213 | int16_t p = Random(strip.numPixels()+1); 214 | pos[0] = p; 215 | strip.setPixelColor(p, c); 216 | } 217 | 218 | //---------------------------------------------- Random sparks fade out --------------------------------------------------- 219 | void rndFade::show(void) { 220 | changeAll(-16); 221 | uint8_t newDot = Random(1, 5); 222 | for (uint8_t i = 0; i < newDot; ++i) { 223 | uint16_t p = Random(strip.numPixels()+1); 224 | uint32_t c = strip.wheel(Random(256)); 225 | if (strip.getPixelColor(p) == 0) 226 | strip.setPixelColor(p, c); 227 | } 228 | } 229 | 230 | //---------------------------------------------- Lights run from the center ----------------------------------------------- 231 | void centerRun::init(void) { 232 | color = strip.wheel(Random(256)); 233 | int n = strip.numPixels(); 234 | int diff = n >> 3; 235 | m = l = r = Random(diff+2) + ((n * 7) >> 4); 236 | } 237 | 238 | void centerRun::show(void) { 239 | if (l >= 0) strip.setPixelColor(l, color); 240 | if (r < int(strip.numPixels())) strip.setPixelColor(r, color); 241 | l -= 2; r += 2; 242 | if ((l < 0) && r >= int(strip.numPixels())) { 243 | l = r = m + 1; 244 | color = strip.wheel(Random(256)); 245 | } 246 | } 247 | 248 | //---------------------------------------------- Slow shining by the different colors ------------------------------------- 249 | void shineSeven::init(void) { 250 | curs = 0; 251 | w = Random(256); 252 | base = Random(4, 8); 253 | startNewColor(); 254 | } 255 | 256 | void shineSeven::show() { 257 | int16_t n = strip.numPixels(); 258 | bool finish = true; 259 | for (int16_t i = int16_t(curs) - 1; i < n; i += base) { // Fade out previous color 260 | if (i >= 0) 261 | if (!change(i, -8)) finish = false; 262 | } 263 | for (int16_t i = curs; i < n; i += base) // Light up current color 264 | if (!change(i, 8)) finish = false; 265 | if (finish) { // The current color has been light fully 266 | ++curs; if (curs >= base) curs = 0; 267 | startNewColor(); 268 | } 269 | } 270 | 271 | void shineSeven::startNewColor(void) { 272 | uint32_t c = strip.wheel(w); 273 | w += 97; 274 | setColor(c); 275 | c &= 0x10101; 276 | for (uint16_t i = curs; i < strip.numPixels(); i += base) 277 | strip.setPixelColor(i, c); 278 | } 279 | 280 | //---------------------------------------------- Rapid walking by the different colors ----------------------------------- 281 | void walkSeven::init() { 282 | w = Random(256); 283 | fwd = Random(2); 284 | ch_dir = Random(30, 100); 285 | period = Random(13, 20); 286 | curs = 0; 287 | } 288 | 289 | void walkSeven::show(void) { 290 | changeAll(-64); 291 | 292 | int n = strip.numPixels(); 293 | uint32_t c1 = strip.wheel(w); 294 | w += 71; 295 | for (int i = curs; i < n; i += period) { 296 | uint32_t c2 = strip.getPixelColor(i); 297 | c2 = TWOCLR::add(c1, c2); 298 | strip.setPixelColor(i, c2); 299 | } 300 | 301 | if (fwd) ++curs; else --curs; 302 | curs %= period; 303 | 304 | if (--ch_dir < 0) { 305 | ch_dir = Random(70, 300); 306 | fwd = !fwd; 307 | } 308 | } 309 | 310 | //---------------------------------------------- Rapid flashing by the differenc colors --------------------------------- 311 | void flashSeven::init() { 312 | w = Random(256); 313 | fwd = Random(2); 314 | ch_dir = Random(30, 100); 315 | period = Random(7, 20); 316 | curs = 0; 317 | } 318 | 319 | void flashSeven::show(void) { 320 | changeAll(-64); 321 | 322 | int n = strip.numPixels(); 323 | for (int i = curs; i < n; i += period) { 324 | change(i, -128); 325 | } 326 | 327 | if (fwd) ++curs; else --curs; 328 | curs %= period; 329 | 330 | uint32_t c = strip.wheel(w); 331 | w += 71; 332 | for (int i = curs; i < n; i += period) { 333 | strip.setPixelColor(i, c); 334 | } 335 | 336 | if (--ch_dir < 0) { 337 | ch_dir = Random(70, 300); 338 | fwd = !fwd; 339 | } 340 | } 341 | 342 | //---------------------------------------------- Slow merging of two colors ----------------------------------------------- 343 | void mergeOne::init(void) { 344 | l = 0; 345 | r = strip.numPixels(); 346 | uint8_t indx = Random(256); 347 | cl = strip.wheel(indx); 348 | indx += Random(4, 16); 349 | cr = strip.wheel(indx); 350 | strip.clear(); 351 | } 352 | 353 | void mergeOne::show(void) { 354 | if (l < r) { 355 | strip.setPixelColor(l, cl); 356 | strip.setPixelColor(r, cr); 357 | } else { 358 | uint32_t c = strip.getPixelColor(l); 359 | c = add(c, cl); 360 | strip.setPixelColor(l, c); 361 | c = strip.getPixelColor(r); 362 | c = add(c, cr); 363 | strip.setPixelColor(r, c); 364 | } 365 | 366 | --r; ++l; 367 | if (r < 0) { // Force the strip to be clean 368 | do_clear = true; 369 | complete = true; 370 | return; 371 | } 372 | complete = false; 373 | } 374 | 375 | //---------------------------------------------- Fast merging of Waves ---------------------------------------------------- 376 | void mergeWave::init(void) { 377 | l = 0; 378 | r = strip.numPixels() - 1; 379 | index = Random(256); 380 | len = Random(8, 17); 381 | strip.clear(); 382 | } 383 | 384 | void mergeWave::show(void) { 385 | if (l < r) { 386 | strip.setPixelColor(l, strip.wheel(l & 255)); 387 | if (l > len) strip.setPixelColor(l-len, 0); 388 | strip.setPixelColor(r, strip.wheel((index + r) & 255)); 389 | if ((r + len) > int(strip.numPixels())) strip.setPixelColor(r+len, 0); 390 | } else { 391 | uint32_t c = strip.getPixelColor(l); 392 | c |= strip.wheel(l & 255); 393 | strip.setPixelColor(l, c); 394 | c = strip.getPixelColor(r); 395 | c |= strip.wheel((index + r) & 255); 396 | strip.setPixelColor(r, c); 397 | strip.setPixelColor(l-len, 0); 398 | strip.setPixelColor(r+len, 0); 399 | } 400 | --r; ++l; index += 4; 401 | if (r < 0) { // Force the strip to be clean 402 | do_clear = true; 403 | complete = true; 404 | } 405 | complete = false; 406 | } 407 | 408 | //---------------------------------------------- Fast collide of two colors --------------------------------------------- 409 | void collideOne::init(void) { 410 | l = 0; 411 | r = strip.numPixels() - 1; 412 | uint8_t w = Random(256); 413 | cl = strip.wheel(w); 414 | w += Random(8, 16); 415 | cr = strip.wheel(w); 416 | strip.clear(); 417 | boom = false; 418 | } 419 | 420 | void collideOne::show(void) { 421 | if (boom) { 422 | strip.setPixelColor(l, 0xffffff); 423 | strip.setPixelColor(r, 0xffffff); 424 | if ((r - l) >= 12) { 425 | strip.setPixelColor(l+6, 0); 426 | strip.setPixelColor(r-6, 0); 427 | } 428 | --l; ++r; 429 | if (l < 0) { 430 | init(); 431 | complete = true; 432 | return; 433 | } 434 | } else { 435 | if (l < r) { 436 | strip.setPixelColor(l, cl); 437 | strip.setPixelColor(r, cr); 438 | --r; ++l; 439 | } else { 440 | boom = true; 441 | } 442 | } 443 | complete = false; 444 | } 445 | 446 | //---------------------------------------------- Neo fire animation by Robert Ulbricht ---------------------------------- 447 | void neoFire::init(void) { 448 | color = 0; 449 | uint8_t m = Random(3); 450 | color |= c1 << (m*8); 451 | m += Random(1,3); 452 | if (m >= 3) m = 0; 453 | color |= c2 << (m*8); 454 | } 455 | 456 | void neoFire::show(void) { 457 | if (pause > 0) { 458 | --pause; 459 | return; 460 | } 461 | pause = Random(8); 462 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 463 | uint32_t blended_color = add(strip.getPixelColor(i), color); 464 | uint8_t r = Random(80); 465 | uint32_t diff_color = strip.Color(r, r/2, r/2); 466 | blended_color = sub(blended_color, diff_color); 467 | strip.setPixelColor(i, blended_color); 468 | } 469 | } 470 | 471 | //---------------------------------------------- Even and odd position leds are moving towards each other --------------- 472 | void evenOdd::init(void) { 473 | uint8_t indx = Random(256); 474 | cl = strip.wheel(indx); 475 | indx += Random(4, 16); 476 | cr = strip.wheel(indx); 477 | l = 0; 478 | r = strip.numPixels() - 1; // r is Odd 479 | } 480 | 481 | void evenOdd::show(void) { 482 | strip.setPixelColor(l, cl); 483 | strip.setPixelColor(r, cr); 484 | l += 2; r -= 2; 485 | if (r < 0) { 486 | if (cr) { 487 | cr = cl = 0; 488 | l = 0; 489 | r = strip.numPixels() - 1; // r is Odd 490 | } else { 491 | init(); 492 | complete = true; 493 | return; 494 | } 495 | } 496 | complete = false; 497 | } 498 | 499 | //---------------------------------------------- aRandom colors from left and right move to the center ------------------- 500 | void collMdl::init(void) { 501 | ml = (strip.numPixels() - 1) / 2; 502 | mr = ml + 1; 503 | newColors(); 504 | clr = false; 505 | } 506 | 507 | void collMdl::show(void) { 508 | if (clr) { 509 | strip.setPixelColor(l, 0); 510 | strip.setPixelColor(r, 0); 511 | l--; r++; 512 | if (l < 0) { 513 | init(); 514 | complete = true; 515 | } 516 | return; 517 | } 518 | 519 | // blend colors in the middle 520 | if ((mr - ml) > 1) { 521 | for (int i = ml; i < mr; ++i) 522 | blendPixel(i); 523 | } 524 | 525 | // New colors are moving to the center 526 | if (l <= ml) { 527 | if (l > 1)strip.setPixelColor(l-2, 0); 528 | strip.setPixelColor(l, cl); 529 | } 530 | if (r >= mr) { 531 | if (r < int(strip.numPixels() - 2)) strip.setPixelColor(r+2, 0); 532 | strip.setPixelColor(r, cr); 533 | } 534 | if ((l >= ml) && (r <= mr)) { 535 | ml--; mr++; 536 | if (ml < 0) { 537 | clr = true; 538 | l = (strip.numPixels() - 1) / 2; 539 | r = l + 1; 540 | return; 541 | } 542 | newColors(); 543 | return; 544 | } 545 | l++; r--; 546 | complete = false; 547 | } 548 | 549 | void collMdl::newColors(void) { 550 | cl = strip.wheel(Random(256)); 551 | cr = strip.wheel(Random(256)); 552 | l = 0; 553 | r = strip.numPixels() - 1; 554 | } 555 | 556 | //------------------------------------------- aRandom colors from left and right move to the other end ------------------- 557 | void collEnd::init(void) { 558 | ml = strip.numPixels() - 1; 559 | mr = 0; 560 | newColors(); 561 | } 562 | 563 | void collEnd::show(void) { 564 | // blend colors in the both ends 565 | if (mr > 1) { 566 | for (int i = 0; i < mr; ++i) 567 | blendPixel(i); 568 | for (uint16_t i = ml; i < strip.numPixels(); ++i) 569 | blendPixel(i); 570 | } 571 | 572 | // New colors are moving to the other end 573 | if (l <= ml) { 574 | if (l > (mr + 1)) 575 | strip.setPixelColor(l-2, 0); 576 | strip.setPixelColor(l, cl); 577 | } 578 | if (r >= mr) { 579 | if (r < (ml - 1)) 580 | strip.setPixelColor(r+2, 0); 581 | strip.setPixelColor(r, cr); 582 | } 583 | if ((l >= ml) && (r <= mr)) { 584 | ml--; mr++; 585 | if (ml < 0) { 586 | do_clear = true; // Force the strip to be cleaned 587 | complete = true; 588 | return; 589 | } 590 | newColors(); 591 | return; 592 | } 593 | l++; r--; 594 | complete = false; 595 | } 596 | 597 | void collEnd::newColors(void) { 598 | cl = strip.wheel(Random(256)); 599 | cr = strip.wheel(Random(256)); 600 | l = mr; 601 | r = ml; 602 | } 603 | 604 | //------------------------------------------- Rainbow colors blend -------------------------------------------------------- 605 | void rainBlend::show(void) { 606 | if (index < int(strip.numPixels())) { 607 | strip.setPixelColor(index, strip.wheel(((index * 256 / strip.numPixels())) & 255)); 608 | ++index; 609 | return; 610 | } 611 | for(uint16_t i = 0; i < strip.numPixels(); ++i) 612 | blendPixel(i); 613 | } 614 | 615 | //---------------------------------------------- Color swing -------------------------------------------------------------- 616 | void swing::init(void) { 617 | len = 1; 618 | rnd = Random(2); 619 | uint32_t c = strip.wheel(Random(256)); 620 | if (!rnd) { // Use rainbow colors from Wheel 621 | w = Random(256); 622 | c = strip.wheel(w); 623 | } 624 | strip.setPixelColor(0, c); 625 | fwd = true; 626 | next_color = 0; 627 | index = strip.numPixels() - len - 1; 628 | } 629 | 630 | void swing::show(void) { 631 | step(); 632 | --index; 633 | 634 | if (index < 0) { 635 | COLOR c = strip.wheel(Random(256)); 636 | if (!rnd) { 637 | w += 4; 638 | c = strip.wheel(w); 639 | } 640 | if (fwd) 641 | strip.setPixelColor(strip.numPixels() - len - 1, c); 642 | else 643 | strip.setPixelColor(len, c); 644 | ++len; 645 | fwd = !fwd; 646 | index = strip.numPixels() - len - 1; 647 | if (len >= int(strip.numPixels())) { 648 | do_clear = true; // Force the strip to be cleaned 649 | complete = true; 650 | return; 651 | } 652 | } 653 | complete = false; 654 | } 655 | 656 | //---------------------------------------------- Single color swing ------------------------------------------------------- 657 | void swingSingle::init(void) { 658 | len = 1; 659 | w = Random(256); 660 | color = strip.wheel(w); 661 | fwd = true; 662 | index = len; 663 | strip.setPixelColor(0, color); 664 | } 665 | 666 | void swingSingle::show(void) { 667 | if (fwd) { 668 | for (int i = 0; i <= index; ++i) { 669 | if (i < (index - len)) 670 | strip.setPixelColor(i, 0); 671 | else 672 | strip.setPixelColor(i, color); 673 | } 674 | ++index; 675 | if (index >= int(strip.numPixels())) { 676 | fwd = false; 677 | len += Random(1, strip.numPixels() >> 4); 678 | index = strip.numPixels() - len - 1; 679 | w += 4; 680 | } 681 | } else { 682 | for (int i = strip.numPixels() - 1; i >= index; --i) { 683 | if (i > (index + len)) 684 | strip.setPixelColor(i, 0); 685 | else 686 | strip.setPixelColor(i, color); 687 | } 688 | --index; 689 | if (index < 0) { 690 | fwd = true; 691 | index = len; 692 | w += 4; 693 | } 694 | } 695 | if (len >= int(strip.numPixels())) { 696 | do_clear = true; // Force the strip to be cleaned 697 | complete = true; 698 | return; 699 | } 700 | complete = false; 701 | } 702 | 703 | //---------------------------------------------- Fill the strip by the color in aRandom order ---------------------------- 704 | void randomFill::init(void) { 705 | w = Random(256); 706 | remain = strip.numPixels(); 707 | clr = false; 708 | newDot(clr); 709 | } 710 | 711 | void randomFill::show() { 712 | int8_t val = 12; 713 | if (clr) val = -12; 714 | if (change(pos, val)) { 715 | if (remain <= 0) { 716 | if (clr) { 717 | strip.clear(); 718 | w += 71; 719 | init(); 720 | complete = true; 721 | return; 722 | } else { 723 | clr = true; 724 | remain = strip.numPixels(); 725 | newDot(clr); 726 | } 727 | } else { 728 | newDot(clr); 729 | } 730 | } 731 | 732 | // Blend active pixels 733 | COLOR color = strip.wheel(w); 734 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 735 | if (i != pos && strip.getPixelColor(i) != 0) { 736 | strip.setPixelColor(i, color); // Restore original color to disable huge deviation 737 | blendPixel(i, 10); 738 | } 739 | } 740 | complete = false; 741 | } 742 | 743 | void randomFill::newDot(bool clr) { 744 | COLOR color = 0; 745 | if (!clr) color = strip.wheel(w); 746 | 747 | uint8_t p = Random(remain); 748 | uint8_t c = 0; 749 | for (pos = 0; (pos < strip.numPixels()) && (c < p); ++pos) { 750 | if (!color) { 751 | while(strip.getPixelColor(pos) == 0) pos++; 752 | ++c; 753 | } else { 754 | while(strip.getPixelColor(pos) != 0) pos++; 755 | ++c; 756 | } 757 | } 758 | if (!color) { 759 | while(strip.getPixelColor(pos) == 0) pos++; 760 | } else { 761 | while(strip.getPixelColor(pos) != 0) pos++; 762 | } 763 | if (pos >= strip.numPixels()) { // something is wrong in the code 764 | for (uint16_t i = 0; i < strip.numPixels(); ++i) 765 | strip.setPixelColor(i, color); 766 | remain = 0; 767 | } 768 | setColor(color); 769 | remain--; 770 | } 771 | 772 | //---------------------------------------------- Slow shining and flash by the different colors --------------------------- 773 | void shineFlash::init(void) { 774 | w = Random(256); 775 | mode = 0; 776 | flash = false; 777 | startNewColor(); 778 | } 779 | 780 | void shineFlash::show() { 781 | int n = strip.numPixels(); 782 | bool finish = true; 783 | switch(mode) { 784 | case 0: // Light up 785 | finish = changeAll(4); 786 | if (finish) { 787 | flash = true; 788 | remain = Random(17, 30); 789 | wait = 0; 790 | } 791 | break; 792 | case 1: // Run flash 793 | if (flash) { // Lit the LED 794 | if (--wait > 0) return; 795 | wait = Random(2, 7); 796 | indx = Random(n); 797 | if (remain > 0) { 798 | COLOR c = strip.getPixelColor(indx); 799 | c |= 0x808080; 800 | strip.setPixelColor(indx, c); 801 | flash = false; 802 | remain --; 803 | } else { 804 | mode ++; 805 | } 806 | } else { 807 | COLOR c = strip.getPixelColor(indx); 808 | c &= 0x7f7f7f; 809 | strip.setPixelColor(indx, c); 810 | flash = true; 811 | } 812 | finish = false; 813 | break; 814 | case 2: // Fade out 815 | default: 816 | finish = changeAll(-4); 817 | break; 818 | } 819 | 820 | if (finish) { // The current color has been light fully 821 | ++mode; 822 | if (mode >= 3) { 823 | startNewColor(); 824 | mode = 0; 825 | complete = true; 826 | return; 827 | } 828 | } 829 | complete = false; 830 | } 831 | 832 | void shineFlash::startNewColor(void) { 833 | COLOR c = strip.wheel(w); 834 | c &= 0x7f7f7f; 835 | w += 17; 836 | setColor(c); 837 | c &= 0x10101; 838 | int n = strip.numPixels(); 839 | for (int16_t i = 0; i < n; ++i) 840 | strip.setPixelColor(i, c); 841 | } 842 | 843 | //---------------------------------------------- Show single wave moving in Random direction ------------------------------ 844 | void singleWave::init(void) { 845 | COLOR c = strip.wheel(Random(256)); 846 | uint32_t r = c & 0xff; 847 | uint32_t g = (c >> 8) & 0xff; 848 | uint32_t b = (c >> 16) & 0xff; 849 | for (uint8_t i = 1; i <= 4; ++i) { 850 | r >>= 1; 851 | g >>= 1; 852 | b >>= 1; 853 | uint32_t cc = b & 0xff; cc <<= 8; 854 | cc |= g & 0xff; cc <<= 8; 855 | cc |= r & 0xff; 856 | dot[i] = cc; 857 | } 858 | 859 | setColor(dot[3]); 860 | c &= 0x10101; 861 | uint16_t n = strip.numPixels(); 862 | for (uint16_t i = 0; i < n; ++i) 863 | strip.setPixelColor(i, c); 864 | mode = 0; 865 | pos = Random(n); 866 | remain = Random(5, 15); 867 | stp = 0; 868 | } 869 | 870 | void singleWave::show() { 871 | uint16_t n = strip.numPixels(); 872 | bool finish = true; 873 | switch(mode) { 874 | case 0: // Light up 875 | finish = changeAll(4); 876 | break; 877 | case 1: // move the soliton 878 | finish = false; 879 | if (stp <= 0) { 880 | incr = 1; 881 | if (pos > int(n >> 1)) incr = -1; 882 | int m = int(n) - pos - 2; 883 | if (incr < 0) m = pos - 2; 884 | stp = Random(5, m); 885 | --remain; 886 | if (remain <= 0) { 887 | for (uint16_t i = 0; i < n; ++i) 888 | strip.setPixelColor(i, dot[3]); 889 | finish = true; 890 | break; 891 | } 892 | } 893 | pos += incr; 894 | for (uint16_t i = 0; i < n; ++i) { 895 | strip.setPixelColor(i, dot[3]); 896 | } 897 | changeAll(Random(9) - 4); 898 | for (int16_t i = 3; i > 0; --i) { 899 | if ((pos - i) >= 0) strip.setPixelColor(pos - i, dot[i]); 900 | } 901 | for (uint16_t i = 0; i <= 3; ++i) { 902 | if ((pos + i) < n) strip.setPixelColor(pos + i, dot[i]); 903 | } 904 | stp --; 905 | break; 906 | case 2: // Fade out 907 | default: 908 | finish = changeAll(-4); 909 | break; 910 | } 911 | 912 | if (finish) { // The current color has been light fully 913 | ++mode; 914 | if (mode >= 3) { 915 | init (); 916 | complete = true; 917 | return; 918 | } 919 | } 920 | complete = false; 921 | } 922 | 923 | //---------------------------------------------- Several worms are moving Randomly --------------------------------------- 924 | void worms::init(void) { 925 | active = 0; 926 | add(); 927 | } 928 | 929 | void worms::show(void) { 930 | int16_t n = strip.numPixels(); 931 | 932 | // fade away 933 | changeAll(-32); 934 | 935 | // Move existing 936 | for (uint8_t wi = 0; wi < active; ++wi) { 937 | int np = w[wi].pos - 1; 938 | if (w[wi].fwd) np += 2; 939 | if ((np < 0) || (np >= n)) { 940 | die(wi); 941 | --wi; 942 | continue; 943 | } 944 | COLOR c = strip.getPixelColor(np); 945 | if ((c != 0) && (Random(10) == 0)) { 946 | die(wi); 947 | --wi; 948 | continue; 949 | } else { 950 | c = TWOCLR::add(c, w[wi].color); 951 | w[wi].pos = np; 952 | strip.setPixelColor(np, c); 953 | } 954 | } 955 | 956 | if (Random(12) == 0) add(); 957 | } 958 | 959 | void worms::add(void) { 960 | if (active >= 5) return; 961 | 962 | uint8_t mode = Random(3); 963 | int n = strip.numPixels(); 964 | switch (mode) { 965 | case 0: // Run from the start 966 | w[active].pos = 0; 967 | break; 968 | case 1: // Run from the end 969 | w[active].pos = n-1; 970 | break; 971 | case 2: // Run from the aRandom position 972 | default: 973 | w[active].pos = Random(n); 974 | break; 975 | } 976 | w[active].color = strip.wheel(Random(256)); 977 | if (strip.getPixelColor(w[active].pos) != 0) return; 978 | if (w[active].pos < n/3) { 979 | w[active].fwd = true; 980 | } else if ((n - w[active].pos) < n/3) { 981 | w[active].fwd = false; 982 | } else { 983 | w[active].fwd = Random(2); 984 | } 985 | ++active; 986 | } 987 | 988 | void worms::die(uint8_t index) { 989 | --active; 990 | w[index].color = w[active].color; 991 | w[index].pos = w[active].pos; 992 | w[index].fwd = w[active].fwd; 993 | } 994 | 995 | //---------------------------------------------- Show interferention from many sources ---------------------------------- 996 | void interfer::init(void) { 997 | active = 0; 998 | tm = 0; 999 | add(); 1000 | } 1001 | 1002 | void interfer::show(void) { 1003 | int n = strip.numPixels(); 1004 | 1005 | for (int i = 0; i < n; ++i) { 1006 | COLOR c = 0; 1007 | for (uint8_t j = 0; j < active; ++j) { 1008 | COLOR c1 = clr(i, j); 1009 | c = TWOCLR::add(c, c1); 1010 | } 1011 | strip.setPixelColor(i, c); 1012 | } 1013 | ++tm; 1014 | if (tm %64 == 0) { 1015 | for (uint8_t i = 0; i < active; ++i) 1016 | w[i] += 4; 1017 | } 1018 | 1019 | if (!Random(20)) add(); 1020 | } 1021 | 1022 | void interfer::add(void) { 1023 | if (active >= num_inter) return; 1024 | pos[active] = Random(strip.numPixels()); 1025 | w[active] = Random(256); 1026 | start[active] = tm; 1027 | active++; 1028 | } 1029 | 1030 | uint32_t interfer::clr(int p, uint8_t source) { 1031 | uint32_t c = 0; 1032 | int s_pos = pos[source]; 1033 | int e = tm - start[source]; 1034 | e -= abs(p - s_pos); 1035 | if (e < 0) return c; // The wave is not here yet 1036 | e %= 64; // The wave period 1037 | uint8_t elm = 0; 1038 | if (e < 32) // Half way 1039 | elm = (31 - e) << 3; 1040 | else 1041 | elm = (e - 64) << 3; 1042 | 1043 | uint32_t color = strip.wheel(w[source]); 1044 | for (uint8_t i = 0; i < 3; ++i) { 1045 | int max_c = (color >> (8*i)) & 0xff; 1046 | max_c -= elm; 1047 | if (max_c < 0) max_c = 0; 1048 | uint32_t nc = max_c; 1049 | nc <<= 8*i; 1050 | c |= nc; 1051 | } 1052 | return c; 1053 | } 1054 | 1055 | //------------------------------------------- Random colors toward each other ------------------------------------------ 1056 | void toward::show(void) { 1057 | int n = strip.numPixels(); 1058 | for (int i = n-2; i >= 2; i -= 2) { 1059 | COLOR c = strip.getPixelColor(i-2); 1060 | strip.setPixelColor(i, c); 1061 | } 1062 | for (int i = 1; i < n-1; i += 2) { 1063 | COLOR c = strip.getPixelColor(i+2); 1064 | strip.setPixelColor(i, c); 1065 | } 1066 | if (Random(16) == 0) { 1067 | strip.setPixelColor(0, 0); 1068 | strip.setPixelColor(n-1, 0); 1069 | w += 4; 1070 | } else { 1071 | strip.setPixelColor(0, strip.wheel(w+128)); 1072 | strip.setPixelColor(n-1, strip.wheel(w)); 1073 | } 1074 | } 1075 | 1076 | //------------------------------------------- Raindow colors toward each other ------------------------------------------ 1077 | void towardRain::show(void) { 1078 | int n = strip.numPixels(); 1079 | for (int i = n-2; i >= 2; i -= 2) { 1080 | COLOR c = strip.getPixelColor(i-2); 1081 | strip.setPixelColor(i, c); 1082 | } 1083 | for (int i = 1; i < n-1; i += 2) { 1084 | COLOR c = strip.getPixelColor(i+2); 1085 | strip.setPixelColor(i, c); 1086 | } 1087 | 1088 | if (!Random(17)) { 1089 | strip.setPixelColor(0, 0); 1090 | strip.setPixelColor(n-1, 0); 1091 | } else { 1092 | strip.setPixelColor(0, strip.wheel(w)); w += 9; 1093 | strip.setPixelColor(n-1, strip.wheel(w)); w += 3; 1094 | } 1095 | } 1096 | 1097 | //---------------------------------------------- Slow single wave moving in aRandom direction -- --------------------------- 1098 | void lghtHouse::init(void) { 1099 | COLOR c = 0xff; 1100 | for (uint8_t i = 0; i <= 4; ++i) { 1101 | dot[i] = c | (c << 8) | (c << 16); 1102 | c >>= 1; 1103 | } 1104 | setColor(dot[4]); 1105 | pos = Random(strip.numPixels()); 1106 | stp = 0; 1107 | sp = Random(1, 4); 1108 | dlay = sp; 1109 | } 1110 | 1111 | void lghtHouse::show() { 1112 | changeAll(-8); 1113 | if (--dlay > 0) return; 1114 | dlay = sp; 1115 | 1116 | int n = strip.numPixels(); 1117 | if (stp <= 0) { 1118 | incr = 1; 1119 | if (pos > n / 2) incr = -1; 1120 | stp = Random(5, n); 1121 | sp += Random(3) - 1; 1122 | if (sp < 1) 1123 | sp = 1; 1124 | else if (sp > 3) 1125 | sp = 3; 1126 | } 1127 | pos += incr; 1128 | pos %= n; 1129 | 1130 | for (int i = 0; i <= 5; ++i) { 1131 | uint8_t indx = i; 1132 | if (indx >= 1) indx --; 1133 | int x = pos + i; 1134 | if (x >= n) 1135 | x -= n; 1136 | else if (x < 0) 1137 | x += n; 1138 | strip.setPixelColor(x, dot[indx]); 1139 | x = pos - i; 1140 | if (x >= n) 1141 | x -= n; 1142 | else if (x < 0) 1143 | x += n; 1144 | strip.setPixelColor(x, dot[indx]); 1145 | } 1146 | stp --; 1147 | } 1148 | 1149 | //---------------------------------------------- Random dropped color dot fading out from epicenter ---------------------- 1150 | void rndDrops::show(void) { 1151 | int n = strip.numPixels(); 1152 | for (uint8_t i = 0; i < num; ++i) { 1153 | if (++dr[i].tm > 7) { // Delete old drops 1154 | dr[i].pos = dr[uint8_t(num-1)].pos; 1155 | dr[i].tm = dr[uint8_t(num-1)].tm; 1156 | --num; --i; 1157 | continue; 1158 | } 1159 | int p = dr[i].pos - dr[i].tm; 1160 | if (p < 0) p += n; 1161 | COLOR c1 = strip.getPixelColor(p+1); 1162 | change(p+1, -64); 1163 | COLOR c2 = strip.getPixelColor(p); 1164 | c2 = TWOCLR::add(c1, c2); 1165 | strip.setPixelColor(p, c2); 1166 | 1167 | p = dr[i].pos + dr[i].tm; 1168 | if (p >= n) p -= n; 1169 | c1 = strip.getPixelColor(p-1); 1170 | if (dr[i].tm > 1) change(p-1, -32); 1171 | c2 = strip.getPixelColor(p); 1172 | c2 = TWOCLR::add(c1, c2); 1173 | strip.setPixelColor(p, c2); 1174 | 1175 | change(dr[i].pos, -64); 1176 | } 1177 | 1178 | changeAll(-32); 1179 | add(); 1180 | } 1181 | 1182 | void rndDrops::add(void) { 1183 | if (num >= 16) return; 1184 | int pos = Random(strip.numPixels()); 1185 | COLOR c = strip.getPixelColor(pos); 1186 | if (c) return; 1187 | c = strip.wheel(Random(256)); 1188 | strip.setPixelColor(pos, c); 1189 | dr[uint8_t(num)].pos = pos; 1190 | dr[uint8_t(num)].tm = 0; 1191 | num++; 1192 | } 1193 | 1194 | // --------------------------------------------- Solitons are creaping up or down ----------------------------------------- 1195 | void solCreep::init(void) { 1196 | w = Random(256); 1197 | fwd = Random(2); 1198 | change_direction = Random(200, 500); 1199 | newSoliton(); 1200 | } 1201 | 1202 | void solCreep::show(void) { 1203 | step(); 1204 | 1205 | if (--change_direction <= 0) { 1206 | fwd = !fwd; 1207 | change_direction = Random(200, 500); 1208 | } 1209 | 1210 | int pos = strip.numPixels() - 1; 1211 | if (fwd) pos = 0; 1212 | 1213 | if (sol <= 4) { 1214 | int i = abs(sol); 1215 | strip.setPixelColor(pos, dot[i]); 1216 | ++sol; 1217 | } else { 1218 | if (--space >= 0) { 1219 | strip.setPixelColor(pos, 0); 1220 | } else { 1221 | newSoliton(); 1222 | } 1223 | } 1224 | } 1225 | 1226 | void solCreep::newSoliton(void) { 1227 | sol = -3; 1228 | COLOR c = strip.wheel(w); 1229 | dot[0] = c; 1230 | w += 71; 1231 | uint32_t r = c & 0xff; 1232 | uint32_t g = (c >> 8) & 0xff; 1233 | uint32_t b = (c >> 16) & 0xff; 1234 | for (uint8_t i = 1; i <= 4; ++i) { 1235 | r >>= 1; 1236 | g >>= 1; 1237 | b >>= 1; 1238 | COLOR cc = b & 0xff; cc <<= 8; 1239 | cc |= g & 0xff; cc <<= 8; 1240 | cc |= r & 0xff; 1241 | dot[i] = cc; 1242 | } 1243 | space = Random(3, 10); 1244 | 1245 | int16_t pos = strip.numPixels() - 1; 1246 | if (fwd) pos = 0; 1247 | strip.setPixelColor(pos, dot[4]); 1248 | } 1249 | 1250 | // --------------------------------------------- Theatre-style crawling lights from neopixel example ---------------------- 1251 | void theatChase::init(void) { 1252 | w = Random(256); 1253 | color_period = Random(5, 20); 1254 | color_shift = color_period; 1255 | stp = 0; 1256 | } 1257 | 1258 | void theatChase::show(void) { 1259 | int n = strip.numPixels(); 1260 | for (int16_t i = 0; i < n; i += 3) 1261 | strip.setPixelColor(i + stp, 0); // turn off previous state pixels 1262 | 1263 | if (++stp >= 3) stp = 0; 1264 | COLOR color = strip.wheel(w); 1265 | for (int i = 0; i < n; i += 3) 1266 | strip.setPixelColor(i + stp, color); 1267 | if (--color_shift <= 0) { 1268 | color_shift = color_period; 1269 | ++w; 1270 | } 1271 | } 1272 | 1273 | // --------------------------------------------- Meteors falling down ----------------------------------------------------- 1274 | void meteorSky::init(void) { 1275 | uint16_t n = strip.numPixels(); 1276 | head = Random(n - (n >> 2), n); // Select starting position of the meteor head 1277 | tail = head; 1278 | grow = true; // The brightness should grow first 1279 | complete = false; 1280 | COLOR c = 0xffffff; // Pure white 1281 | if (Random(2)) { // Generate white color with probability 50% 1282 | c = strip.lightWheel(Random(256)); 1283 | } 1284 | setColor(c); // Grow color to specified one 1285 | changeClr(c, -32); // Select starting color of the pixel 1286 | strip.setPixelColor(head, c); 1287 | do_clear = false; 1288 | } 1289 | 1290 | void meteorSky::show(void) { 1291 | uint16_t fade = head; 1292 | COLOR c = strip.getPixelColor(head); 1293 | if (grow) { 1294 | if (c && head > 0) { 1295 | grow = !changeClr(c, 16); // Increase brightness 1296 | strip.setPixelColor(--head, c); 1297 | } 1298 | ++fade; // Start fade next pixel 1299 | } else { 1300 | if (c && head > 0) { 1301 | strip.setPixelColor(--head, c); 1302 | } 1303 | } 1304 | 1305 | // Fade pixels in the tail 1306 | for (int16_t i = tail; i >= int16_t(fade); --i) { 1307 | c = strip.getPixelColor(i); 1308 | changeClr(c, -80); 1309 | strip.setPixelColor(i, c); 1310 | if (c == 0) { 1311 | tail = i; 1312 | } 1313 | } 1314 | complete = (c == 0) && (head == tail); 1315 | 1316 | if (complete && Random(20) == 0) init(); 1317 | } 1318 | 1319 | 1320 | // --------------------------------------------- Symmetrical dots run ----------------------------------------------------- 1321 | void symmRun::init(void) { 1322 | w = Random(256); // Select random color of the pixels 1323 | COLOR c = strip.lightWheel(w); 1324 | left = 0; 1325 | right = strip.numPixels() - 1; 1326 | complete = false; 1327 | phase = 0; 1328 | setColor(c); 1329 | do_clear = false; 1330 | } 1331 | 1332 | void symmRun::show(void) { 1333 | bool done = true; // Whether we reach the required color 1334 | bool dark = true; // Whether we fade all the pixels 1335 | uint16_t n = strip.numPixels(); 1336 | 1337 | switch (phase) { 1338 | case 0: 1339 | // Increase the brightness of two current pixels 1340 | if (left < right) { 1341 | if (!change(left, 70)) done = false; 1342 | if (!change(right, 70)) done = false; 1343 | } 1344 | 1345 | if (done && (left < right)) { // The current pixels have been reached required color 1346 | ++left; 1347 | --right; 1348 | } 1349 | if (done && dark && (left > right)) { 1350 | phase = 1; // Activate the second phase, fade the pixels 1351 | left = 0; 1352 | right = strip.numPixels() - 1; 1353 | drk_stp = 0; 1354 | } 1355 | return; 1356 | 1357 | case 1: // The second phase, fade out the tail 1358 | // Fade the left and right parts 1359 | for (uint16_t i = 0; i < left; ++i) // Fade left part 1360 | if (!change(i, -2)) dark = false; 1361 | for (uint16_t i = right+1; i < n; ++i) 1362 | if (!change(i, -2)) dark = false; 1363 | if (++drk_stp >= 10) { 1364 | drk_stp = 0; 1365 | if (left+2 < right) { 1366 | ++ left; 1367 | --right; 1368 | } else { 1369 | if (dark) { 1370 | phase = 2; 1371 | setColor(0xffffff); 1372 | } 1373 | } 1374 | } 1375 | return; 1376 | 1377 | case 2: // The second phase, boom 1378 | if (!change(left, 1)) done = false; 1379 | if (!change(right, 1)) done = false; 1380 | if (done) 1381 | phase = 3; 1382 | return; 1383 | 1384 | case 3: // The third phase, gone away 1385 | strip.setPixelColor(left, 0); 1386 | strip.setPixelColor(right, 0); 1387 | if (left > 0) { 1388 | -- left; 1389 | ++right; 1390 | COLOR c = strip.lightWheel(w); // Our color 1391 | strip.setPixelColor(left, c); 1392 | strip.setPixelColor(right, c); 1393 | } else { 1394 | phase = 4; 1395 | complete = true; 1396 | } 1397 | return; 1398 | 1399 | case 4: // Wait for new sequence 1400 | default: 1401 | if (Random(10) == 0) init(); 1402 | return; 1403 | } 1404 | 1405 | } 1406 | 1407 | // --------------------------------------------- Defined Meteors falling down fast ---------------------------------------- 1408 | void metSingle::init(void) { 1409 | uint16_t n = strip.numPixels(); 1410 | head = Random(n - (n >> 2), n); // Select starting position of the meteor head 1411 | complete = false; 1412 | do_clear = false; 1413 | } 1414 | 1415 | void metSingle::show(void) { 1416 | if (complete) { 1417 | if (Random(20) == 0) init(); 1418 | return; 1419 | } 1420 | 1421 | uint16_t n = strip.numPixels(); 1422 | if (uint16_t(head)+clr_size+1 < n) 1423 | strip.setPixelColor(head+clr_size+1, 0); 1424 | for (uint16_t i = 0; i < clr_size; ++i) { 1425 | if (head + i < n) { 1426 | strip.setPixelColor(head+i, clr[i]); 1427 | } 1428 | } 1429 | if (head > 0) { 1430 | --head; 1431 | } else { 1432 | strip.clear(); 1433 | complete = true; 1434 | } 1435 | } 1436 | 1437 | // --------------------------------------------- Classical multicolor strip simulation ------------------------------------ 1438 | void pureStrip::init(void) { 1439 | mode = Random(4); 1440 | if (mode > 2) { // Fast modes 1441 | min_p = 50; max_p = 100; 1442 | } else { // Slowly modes 1443 | min_p = 1; max_p = 5; 1444 | } 1445 | 1446 | num_color = Random(3, 7); // 3-6 different colors in the strip 1447 | if (Random(5) == 0) { // Monochrome strip 1448 | COLOR c = strip.wheel(Random(256)); 1449 | for (uint8_t i = 0; i < 6; ++i) 1450 | clr[i] = c; 1451 | } else { // Multicolor strip 1452 | uint8_t available[6]; // Generate available color codes. This make sure each color used just obce 1453 | for (uint8_t i = 0; i < 6; ++i) 1454 | available[i] = i+1; 1455 | for (uint8_t i = 0; i < 50; ++i) { // Shuffle the color codes 1456 | uint8_t pos = Random(6); 1457 | if (pos) { 1458 | uint8_t tmp = available[0]; 1459 | available[0] = available[pos]; 1460 | available[pos] = tmp; 1461 | } 1462 | } 1463 | 1464 | for (uint8_t i = 0; i < num_color; ++i) { // Define the colors 1465 | uint8_t code = available[i]; 1466 | clr[i] = 0; 1467 | if (code & 1) clr[i] |= 0xff; // Whole blue 1468 | if (code & 2) clr[i] |= 0xff00; // Whole green 1469 | if (code & 4) clr[i] |= 0xff0000; // Whole red 1470 | } 1471 | } 1472 | stage = num_color-1; 1473 | blink = 0; 1474 | complete = true; // Can be interrupted any time 1475 | do_clear = true; // Clear the strip after the end of sequence 1476 | } 1477 | 1478 | void pureStrip::show(void) { 1479 | uint16_t n = strip.numPixels(); 1480 | bool done = true; 1481 | uint8_t nxt = stage + 1; 1482 | if (nxt >= num_color) nxt = 0; 1483 | 1484 | switch (mode) { 1485 | case 0: // Slowly increment brightness, slowly date out 1486 | for (uint16_t i = stage; i < n; i += num_color) 1487 | change(i, -8); 1488 | setColor(clr[nxt]); 1489 | for (uint16_t i = nxt; i < n; i += num_color) 1490 | if (!change(i, 8)) done = false; 1491 | break; 1492 | 1493 | case 1: // Switch on colors one by one, then switch them off 1494 | setColor(clr[nxt]); 1495 | for (uint16_t i = nxt; i < n; i += num_color) { 1496 | if (blink < num_color) { 1497 | if (!change(i, 8)) done = false; 1498 | } else { 1499 | if (!change(i, -8)) done = false; 1500 | } 1501 | } 1502 | if (done) { 1503 | if (++blink >= (num_color << 1)) 1504 | blink = 0; 1505 | } 1506 | break; 1507 | 1508 | case 2: // All on then all off 1509 | for (uint8_t j = 0; j < num_color; ++j) { 1510 | setColor(clr[j]); 1511 | for (uint16_t i = j; i < n; i += num_color) { 1512 | if (!blink) { 1513 | if (!change(i, 4)) done = false; 1514 | } else { 1515 | if (!change(i, -4)) done = false; 1516 | } 1517 | } 1518 | } 1519 | if (done) blink = !blink; 1520 | break; 1521 | 1522 | case 3: // Simple sequential switch 1523 | default: 1524 | for (uint16_t i = stage; i < n; i += num_color) 1525 | strip.setPixelColor(i, 0); 1526 | for (uint16_t i = nxt; i < n; i += num_color) 1527 | strip.setPixelColor(i, clr[nxt]); 1528 | break; 1529 | } 1530 | if (done) stage = nxt; 1531 | } 1532 | 1533 | void sideFill::init(void) { 1534 | w = Random(256); 1535 | fwd = Random(2); 1536 | rainbow = Random(2); 1537 | stage = 1; // Current maximum length of lit leds 1538 | index = 0; // The index of led that should be lit in this step 1539 | on = true; 1540 | complete = false; 1541 | do_clear = true; 1542 | } 1543 | 1544 | void sideFill::show(void) { 1545 | if (complete) init(); 1546 | 1547 | uint16_t n = strip.numPixels(); 1548 | uint16_t led_index = index; 1549 | if (!fwd) 1550 | led_index = n - index -1; // If we fill the strip from the back, fix the led position 1551 | 1552 | if (on) { // switch on new pixel 1553 | COLOR c = strip.wheel(w); 1554 | if (rainbow) ++w; 1555 | strip.setPixelColor(led_index, c); 1556 | if (++index >= stage) { // The stage is finished 1557 | --index; 1558 | on = false; // Start to clear the pixels 1559 | } 1560 | } else { // clear off new pixel 1561 | strip.setPixelColor(led_index, 0); 1562 | if (index > 0) { 1563 | --index; 1564 | } else { // Start the next stage 1565 | on = true; 1566 | uint16_t incr = 1; 1567 | if (n > stage + 1) incr = Random(1, ((n-stage+1) >> 1) + 1); 1568 | if (incr > 10) incr = 10; 1569 | stage += incr; 1570 | if (stage >= n) { // All the string was filled up, change the direction 1571 | complete = true; 1572 | } 1573 | } 1574 | } 1575 | } 1576 | 1577 | // --------------------------------------------- Browian Motion with the tail -------------------------------------------- 1578 | void browMotion::init(void) { 1579 | uint16_t n = strip.numPixels(); 1580 | pos = Random(n+1); 1581 | newDestination(n); 1582 | complete = true; 1583 | do_clear = true; 1584 | } 1585 | 1586 | void browMotion::show(void) { 1587 | changeAll(-12); 1588 | COLOR c = strip.wheel(w); 1589 | uint16_t n = strip.numPixels(); 1590 | if (speed > 0) { // Go forward 1591 | for (uint8_t i = 0; i <= speed; ++i) { 1592 | strip.setPixelColor(pos, c); 1593 | if (pos == destination) { 1594 | newDestination(n); 1595 | return; 1596 | } 1597 | if (pos < n+1) { 1598 | ++pos; 1599 | } else { 1600 | speed = speed * (-1); 1601 | } 1602 | } 1603 | } else { // Go backward 1604 | for (uint8_t i = 0; i <= abs(speed); ++i) { 1605 | strip.setPixelColor(pos, c); 1606 | if (pos == destination) { 1607 | newDestination(n); 1608 | return; 1609 | } 1610 | if (pos > 0) { 1611 | --pos; 1612 | } else { 1613 | speed = speed * (-1); 1614 | } 1615 | } 1616 | } 1617 | } 1618 | 1619 | void browMotion::newDestination(uint16_t num_pixels) { 1620 | w = Random(256); 1621 | destination = Random(num_pixels+1); 1622 | speed = (int16_t(destination) - int16_t(pos)) * 10 / num_pixels; 1623 | speed = constrain(speed, 1, 3); 1624 | } 1625 | 1626 | 1627 | // --------------------------------------------- Rain drops running down ------------------------------------------------- 1628 | void rainDrops::init(void) { 1629 | active_drops = 0; 1630 | complete = true; 1631 | do_clear = true; 1632 | newDrop(); 1633 | } 1634 | 1635 | void rainDrops::show(void) { 1636 | changeAll(-24); 1637 | for (uint8_t d = 0; d < active_drops; ++d) { 1638 | for (uint8_t s = 0; s <= drop[d].speed; ++s) { 1639 | if (drop[d].head < s) { 1640 | drop[d].c = 0; // Mark the drop to be deleted 1641 | break; 1642 | } 1643 | strip.setPixelColor(drop[d].head-s, drop[d].c); 1644 | } 1645 | if (drop[d].head >= drop[d].speed) { 1646 | drop[d].head -= drop[d].speed; 1647 | } 1648 | changeClr(drop[d].c, -16); 1649 | } 1650 | 1651 | // Remove inactive drops 1652 | for (int8_t d = active_drops-1; d >= 0; --d) { 1653 | if (drop[d].c == 0) { 1654 | drop[d].c = drop[active_drops-1].c; 1655 | drop[d].speed = drop[active_drops-1].speed; 1656 | drop[d].head = drop[active_drops-1].head; 1657 | if (--active_drops == 0) break; 1658 | } 1659 | } 1660 | 1661 | // Create new Drops 1662 | if (active_drops < max_drops && Random(10) == 0) { 1663 | newDrop(); 1664 | } 1665 | } 1666 | 1667 | void rainDrops::newDrop(void) { 1668 | if (active_drops >= max_drops) 1669 | return; 1670 | uint16_t n = strip.numPixels(); 1671 | drop[active_drops].head = Random(n >> 1, n+1); 1672 | drop[active_drops].c = strip.wheel(Random(256)); 1673 | drop[active_drops].speed = Random(1, 4); 1674 | ++active_drops; 1675 | } 1676 | 1677 | // --------------------------------------------- Ripe fruits booms and run two pieces ------------------------------------ 1678 | void ripeFruit::init(void) { 1679 | active_fruits = 0; 1680 | complete = true; 1681 | do_clear = true; 1682 | newFruit(); 1683 | } 1684 | 1685 | void ripeFruit::show(void) { 1686 | uint16_t n = strip.numPixels(); 1687 | for (uint16_t i = 0; i < n; ++i) { // Fade out all pixels except the active one 1688 | bool skip = false; 1689 | for (uint8_t f = 0; f < active_fruits; ++f) { 1690 | if ((fruit[f].speed == 0) && (i == fruit[f].part[0])) { 1691 | skip = true; 1692 | break; 1693 | } 1694 | } 1695 | if (!skip) change(i, -16); 1696 | } 1697 | 1698 | for (uint8_t f = 0; f < active_fruits; ++f) { 1699 | if (fruit[f].speed == 0) { // The fruit is getting ready 1700 | setColor(fruit[f].c); 1701 | if (change(fruit[f].part[0], 2)) { // The fruit is ripen 1702 | strip.setPixelColor(fruit[f].part[0], 0xffffff); 1703 | fruit[f].part[1] = fruit[f].part[0] + 1; 1704 | fruit[f].speed = Random(1, 3); // Start moving 1705 | } 1706 | } else { // The fruit parts are moving 1707 | for (uint8_t s = 0; s <= fruit[f].speed; ++s) { 1708 | if (fruit[f].part[0] >= s) { 1709 | strip.setPixelColor(fruit[f].part[0]-s, fruit[f].c); 1710 | } 1711 | if (fruit[f].part[1] + s < n) { 1712 | strip.setPixelColor(fruit[f].part[1]+s, fruit[f].c); 1713 | } 1714 | } 1715 | 1716 | if (fruit[f].part[0] >= fruit[f].speed) { 1717 | fruit[f].part[0] -= fruit[f].speed; 1718 | } else { 1719 | fruit[f].c = 0; // Mark to be deleted 1720 | } 1721 | if (fruit[f].part[1] + fruit[f].speed < n) { 1722 | fruit[f].part[1] += fruit[f].speed; 1723 | } else { 1724 | fruit[f].c = 0; // Mark to be deleted 1725 | } 1726 | 1727 | } 1728 | changeClr(fruit[f].c, -16); 1729 | } 1730 | // Remove inactive fruits 1731 | for (int8_t f = active_fruits-1; f >= 0; --f) { 1732 | if (fruit[f].c == 0) { 1733 | fruit[f].c = fruit[active_fruits-1].c; 1734 | fruit[f].speed = fruit[active_fruits-1].speed; 1735 | fruit[f].part[0] = fruit[active_fruits-1].part[0]; 1736 | fruit[f].part[1] = fruit[active_fruits-1].part[1]; 1737 | if (--active_fruits == 0) break; 1738 | } 1739 | } 1740 | 1741 | // Create new Fruit 1742 | if (active_fruits < max_fruits && Random(5) == 0) { 1743 | newFruit(); 1744 | } 1745 | } 1746 | 1747 | void ripeFruit::newFruit(void) { 1748 | if (active_fruits >= max_fruits) 1749 | return; 1750 | uint16_t n = strip.numPixels(); 1751 | fruit[active_fruits].part[0]= Random(4, n - 5); 1752 | fruit[active_fruits].part[1]= n; // Not active yet 1753 | fruit[active_fruits].c = strip.wheel(Random(256)); 1754 | fruit[active_fruits].speed = 0; 1755 | ++active_fruits; 1756 | } 1757 | 1758 | // --------------------------------------------- The single color that changes the brightness as a sine ------------------ 1759 | void brightWave::init(void) { 1760 | w = Random(256); 1761 | t = 0; 1762 | fwd = Random(2); 1763 | complete = true; 1764 | do_clear = true; 1765 | } 1766 | 1767 | void brightWave::show(void) { 1768 | COLOR color = strip.wheel(w); 1769 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 1770 | COLOR c = intencity(color, i+t); 1771 | strip.setPixelColor(i, c); 1772 | } 1773 | if (fwd) --t; else ++t; 1774 | if (Random(10) == 0) { 1775 | ++w; 1776 | if (Random(30) == 0) 1777 | fwd = !fwd; 1778 | } 1779 | } 1780 | 1781 | // --------------------------------------------- Color pixels walking up and down with sine brightness ------------------- 1782 | void brColCreep::init(void) { 1783 | fwd = Random(2); 1784 | w = Random(256); 1785 | t = Random(64); 1786 | complete = true; 1787 | do_clear = true; 1788 | } 1789 | 1790 | void brColCreep::show(void) { 1791 | step(); 1792 | uint16_t pos = strip.numPixels() - 1; 1793 | if (fwd) pos = 0; 1794 | COLOR c = strip.wheel(++w); 1795 | c = intencity(c, t); 1796 | if (++t >= 64) t = 0; 1797 | strip.setPixelColor(pos, c); 1798 | } 1799 | -------------------------------------------------------------------------------- /OLD/xmas_neopixel_lite.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #ifdef __AVR__ 3 | #include 4 | #endif 5 | 6 | const byte NEO_BRGHT = 255; 7 | const byte NEO_PIN = 6; // Pin of Neopixel Strip 8 | const byte StripSize = 100; // Length of Neopixel Strip 9 | const byte min_time = 30; // Minimal sequence show time (secons) 10 | 11 | // Parameter 1 = number of pixels in strip 12 | // Parameter 2 = Arduino pin number (most are valid) 13 | // Parameter 3 = pixel type flags, add together as needed: 14 | // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) 15 | // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) 16 | // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) 17 | // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) 18 | Adafruit_NeoPixel strip = Adafruit_NeoPixel(StripSize, NEO_PIN, NEO_GRB + NEO_KHZ800); 19 | 20 | //---------------------------------------------- Base animatio class with usefull functions ------------------------------- 21 | class BASE { 22 | public: 23 | uint32_t Wheel(byte WheelPos); 24 | }; 25 | 26 | // Input a value 0 to 255 to get a color value. The colours are a transition r - g - b - back to r. 27 | uint32_t BASE::Wheel(byte WheelPos) { 28 | WheelPos = 255 - WheelPos; 29 | if(WheelPos < 85) { 30 | return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); 31 | } 32 | if(WheelPos < 170) { 33 | WheelPos -= 85; 34 | return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); 35 | } 36 | WheelPos -= 170; 37 | return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); 38 | } 39 | 40 | //---------------------------------------------- Classes for strip animation ---------------------------------------------- 41 | class animation : public BASE { 42 | public: 43 | animation() { min_p = 2; max_p = 8; show_time = min_time / 10; do_clear = false; complete = true; } 44 | virtual void init(void) = 0; 45 | virtual void show(void) = 0; 46 | void get_limits(byte& mi_p, byte& ma_p) { mi_p = min_p; ma_p = max_p; } 47 | byte min_p; // The minimum period in tenth of second to show the stage 48 | byte max_p; // The maximum period in tenth of second to show the stage 49 | byte show_time; // The minimum time to show the sequence in 10-secons intervals 50 | bool do_clear; // Whether the strip have to be cleaned for the next loop 51 | bool complete; // Whether the animation can be changed to the next one 52 | }; 53 | 54 | // --------------------------------------------- creep the sequence up or down, superclass -------------------------------- 55 | class CRAWL { 56 | public: 57 | CRAWL(void) { fwd = true; } 58 | void step(void); 59 | protected: 60 | bool fwd; // direction to crawl: false - backward, true - formard 61 | uint32_t next_color; 62 | }; 63 | 64 | void CRAWL::step(void) { 65 | if (fwd) { // creep forward 66 | for (int i = strip.numPixels()-1; i > 0; --i) { 67 | uint32_t c = strip.getPixelColor(i-1); 68 | strip.setPixelColor(i, c); 69 | } 70 | strip.setPixelColor(0, next_color); 71 | } else { // creep backward 72 | int last = strip.numPixels()-1; 73 | for (int i = 0; i < last; ++i) { 74 | uint32_t c = strip.getPixelColor(i+1); 75 | strip.setPixelColor(i, c); 76 | } 77 | strip.setPixelColor(last, next_color); 78 | } 79 | } 80 | 81 | //---------------------------------------------- Brighttess manipulation -------------------------------------------------- 82 | class BRGTN { 83 | public: 84 | BRGTN() { } 85 | void setColor(uint32_t c); 86 | bool change(uint16_t index, int val); 87 | bool changeAll(int val); 88 | protected: 89 | byte color[3]; 90 | }; 91 | 92 | void BRGTN::setColor(uint32_t c) { 93 | color[0] = c & 0xff; 94 | c >>= 8; 95 | color[1] = c & 0xff; 96 | c >>= 8; 97 | color[2] = c & 0xff; 98 | } 99 | 100 | bool BRGTN::changeAll(int val) { 101 | bool finish = true; 102 | for (byte i = 0; i < strip.numPixels(); ++i) { 103 | if (!change(i, val)) finish = false; 104 | } 105 | return finish; 106 | } 107 | 108 | bool BRGTN::change(uint16_t index, int val) { 109 | uint32_t c = strip.getPixelColor(index); 110 | byte bound = 0; 111 | int e = 256 + val; 112 | for (char s = 2; s >= 0; --s) { 113 | long cc = c >> (s*8); 114 | cc &= 0xff; 115 | long cs = cc; 116 | cc *= e; cc >>= 8; 117 | if (cs == cc) cc += val; 118 | if ((val > 0) && (cc >= color[byte(s)])) { 119 | cc = color[byte(s)]; 120 | bound ++; 121 | } 122 | if ((val < 0) && (cc <= 0)){ 123 | cc = 0; 124 | bound ++; 125 | } 126 | uint32_t mask = 0xff; mask <<= (8*s); mask = ~mask; 127 | cc <<= (s*8); 128 | c &= mask; 129 | c |= cc; 130 | } 131 | strip.setPixelColor(index, c); 132 | return (bound >= 3); 133 | } 134 | 135 | //---------------------------------------------- Blend manipulations ------------------------------------------------------ 136 | class BLEND { 137 | public: 138 | BLEND() {} 139 | uint32_t add(uint32_t color1, uint32_t color2); 140 | uint32_t sub(uint32_t color1, uint32_t color2); 141 | void blendPixel(uint16_t p); 142 | }; 143 | 144 | uint32_t BLEND::add(uint32_t color1, uint32_t color2) { 145 | uint8_t r1,g1,b1; 146 | uint8_t r2,g2,b2; 147 | 148 | r1 = (uint8_t)(color1 >> 16), 149 | g1 = (uint8_t)(color1 >> 8), 150 | b1 = (uint8_t)(color1 >> 0); 151 | 152 | r2 = (uint8_t)(color2 >> 16), 153 | g2 = (uint8_t)(color2 >> 8), 154 | b2 = (uint8_t)(color2 >> 0); 155 | 156 | return strip.Color(constrain(r1+r2, 0, 255), constrain(g1+g2, 0, 255), constrain(b1+b2, 0, 255)); 157 | } 158 | 159 | uint32_t BLEND::sub(uint32_t color1, uint32_t color2) { 160 | uint8_t r1,g1,b1; 161 | uint8_t r2,g2,b2; 162 | int16_t r,g,b; 163 | 164 | r1 = (uint8_t)(color1 >> 16), 165 | g1 = (uint8_t)(color1 >> 8), 166 | b1 = (uint8_t)(color1 >> 0); 167 | 168 | r2 = (uint8_t)(color2 >> 16), 169 | g2 = (uint8_t)(color2 >> 8), 170 | b2 = (uint8_t)(color2 >> 0); 171 | 172 | r = (int16_t)r1 - (int16_t)r2; 173 | g = (int16_t)g1 - (int16_t)g2; 174 | b = (int16_t)b1 - (int16_t)b2; 175 | if (r < 0) r = 0; 176 | if (g < 0) g = 0; 177 | if (b < 0) b = 0; 178 | 179 | return strip.Color(r, g, b); 180 | } 181 | 182 | void BLEND::blendPixel(uint16_t p) { 183 | byte r1 = random(20); 184 | byte g1 = random(20); 185 | byte b1 = random(20); 186 | uint32_t diff_color = strip.Color(r1, g1, b1); 187 | uint32_t blended_color = BLEND::add(diff_color, strip.getPixelColor(p)); 188 | r1 = random(20); 189 | g1 = random(20); 190 | b1 = random(20); 191 | diff_color = strip.Color(r1, g1, b1); 192 | blended_color = BLEND::sub(blended_color, diff_color); 193 | strip.setPixelColor(p, blended_color); 194 | } 195 | 196 | //---------------------------------------------- Color superposition class ------------------------------------------------ 197 | class TWOCLR { 198 | public: 199 | TWOCLR() {} 200 | uint32_t add(uint32_t c1, uint32_t c2); 201 | }; 202 | 203 | uint32_t TWOCLR::add(uint32_t c1, uint32_t c2) { 204 | uint32_t c = 0; 205 | for (byte i = 0; i < 3; ++i) { 206 | uint32_t p = c1 >> (i*8); 207 | p += c2 >> (i*8); 208 | p &= 0xff; 209 | p <<= i*8; 210 | c |= p; 211 | } 212 | return c; 213 | } 214 | 215 | // --------------------------------------------- Fill the dots one after the other with a color --------------------------- 216 | class colorWipe: public animation { 217 | public: 218 | colorWipe(void) { w = random(256); } 219 | virtual void init(void); 220 | virtual void show(void); 221 | private: 222 | byte w; 223 | int index; 224 | bool fwd; 225 | }; 226 | 227 | void colorWipe::init(void) { 228 | int p = random(2, 4); 229 | w += p*16 + 1; 230 | fwd = random(2); 231 | index = 0; 232 | if (!fwd) index = strip.numPixels() - 1; 233 | } 234 | 235 | void colorWipe::show(void) { 236 | uint32_t color = Wheel(w); 237 | if (fwd) { 238 | if (index > int(strip.numPixels())) { // Start new sequence with the new color 239 | init(); 240 | complete = true; 241 | return; 242 | } 243 | strip.setPixelColor(index++, color); 244 | } else { 245 | if (index < 0) { // Start new sequence with the new color 246 | init(); 247 | complete = true; 248 | return; 249 | } 250 | strip.setPixelColor(index--, color); 251 | } 252 | complete = false; 253 | } 254 | 255 | // --------------------------------------------- Walk the dots one after the other with a color --------------------------- 256 | class colorWalk: public animation { 257 | public: 258 | colorWalk(void) { min_p = 4; max_p = 12;} 259 | virtual void init(void); 260 | virtual void show(void); 261 | private: 262 | int index; 263 | byte period; 264 | bool fwd; 265 | byte w; 266 | }; 267 | 268 | void colorWalk::init(void) { 269 | index = 0; 270 | w = random(256); 271 | fwd = random(2); 272 | period = random(10, 30); 273 | } 274 | 275 | void colorWalk::show(void) { 276 | int n = strip.numPixels(); 277 | if (fwd) { 278 | if (index > n) { 279 | index -= period; 280 | strip.setPixelColor(n-1, 0); 281 | } 282 | uint32_t color = Wheel(w--); 283 | for (int i = index; i > 0; i -= period) { 284 | if (i > 0) strip.setPixelColor(i-1, 0); 285 | strip.setPixelColor(i, color); 286 | } 287 | ++index; 288 | } else { 289 | if (index < 0) { 290 | index += period; 291 | strip.setPixelColor(0, 0); 292 | } 293 | uint32_t color = Wheel(w++); 294 | for (int i = index; i < n; i += period) { 295 | if (i < int(strip.numPixels() - 1)) strip.setPixelColor(i+1, 0); 296 | strip.setPixelColor(i, color); 297 | } 298 | --index; 299 | } 300 | } 301 | 302 | // --------------------------------------------- creep the random sequence up or down ------------------------------------- 303 | class randomCreep: public CRAWL, public animation { 304 | public: 305 | randomCreep(void) { min_p = 6; max_p = 24;} 306 | virtual void init(void); 307 | virtual void show(void); 308 | private: 309 | byte space; // space between the color dots 310 | int change_direction; 311 | byte cnt; 312 | }; 313 | 314 | void randomCreep::init(void) { 315 | space = random(2, 5); 316 | change_direction = random(100, 500); 317 | cnt = 0; 318 | } 319 | 320 | void randomCreep::show(void) { 321 | -- change_direction; 322 | if (change_direction <= 0) { 323 | CRAWL::fwd = !CRAWL::fwd; 324 | init(); 325 | } 326 | 327 | next_color = 0; 328 | ++cnt; 329 | if (cnt > space) { 330 | cnt = 0; 331 | next_color = Wheel(random(256)); 332 | } 333 | 334 | CRAWL::step(); 335 | } 336 | 337 | // --------------------------------------------- show the color Wave using rainbowCycle ----------------------------------- 338 | class colorWave: public CRAWL, public BRGTN, public animation { 339 | public: 340 | colorWave(void) { } 341 | virtual void init(void); 342 | virtual void show(void); 343 | private: 344 | byte index; 345 | bool rdy; 346 | }; 347 | 348 | void colorWave::init(void) { 349 | index = 0; 350 | rdy = false; 351 | CRAWL::fwd = random(2); 352 | } 353 | 354 | void colorWave::show(void) { 355 | if (!rdy) { 356 | rdy = true; 357 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 358 | BRGTN::setColor(Wheel(((i * 256 / strip.numPixels())) & 255)); 359 | if (!BRGTN::change(i, 2)) rdy = false; 360 | } 361 | return; 362 | } 363 | 364 | CRAWL::step(); 365 | if (CRAWL::fwd) 366 | strip.setPixelColor(0, Wheel(index & 255)); 367 | else 368 | strip.setPixelColor(strip.numPixels() - 1, Wheel(index & 255)); 369 | ++index; 370 | } 371 | 372 | // --------------------------------------------- show the rainbow (from neopixel example) --------------------------------- 373 | class rainbow: public BRGTN, public animation { 374 | public: 375 | rainbow(void) {} 376 | virtual void init(void) { index = 0; rdy = false; } 377 | virtual void show(void); 378 | private: 379 | byte index; 380 | bool rdy; 381 | }; 382 | 383 | void rainbow::show(void) { 384 | if (!rdy) { 385 | rdy = true; 386 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 387 | BRGTN::setColor(Wheel(i & 255)); 388 | if (!BRGTN::change(i, 2)) rdy = false; 389 | } 390 | return; 391 | } 392 | 393 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 394 | strip.setPixelColor(i, Wheel((i+index) & 255)); 395 | } 396 | ++index; // index is from 0 to 255 397 | } 398 | 399 | // --------------------------------------------- show the rainbowCycle (from neopixel example) ---------------------------- 400 | class rainCycle: public BRGTN, public animation { 401 | public: 402 | rainCycle(void) {} 403 | virtual void init(void) { index = 0; rdy = false; } 404 | virtual void show(void); 405 | private: 406 | byte index; 407 | bool rdy; 408 | }; 409 | 410 | void rainCycle::show(void) { 411 | if (!rdy) { 412 | rdy = true; 413 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 414 | BRGTN::setColor(Wheel((i * 256 / strip.numPixels()) & 255)); 415 | if (!BRGTN::change(i, 1)) rdy = false; 416 | } 417 | return; 418 | } 419 | 420 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 421 | strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + index) & 255)); 422 | } 423 | ++index; // index is from 0 to 255 424 | } 425 | 426 | // --------------------------------------------- show the rainbow colors on the entire strip ------------------------------ 427 | class rainFull: public BRGTN, public animation { 428 | public: 429 | rainFull(void) { min_p = 6; max_p = 24; } 430 | virtual void init(void) { index = random(256); rdy = false; } 431 | virtual void show(void); 432 | private: 433 | byte index; 434 | bool rdy; 435 | }; 436 | 437 | void rainFull::show(void) { 438 | if (!rdy) { 439 | rdy = true; 440 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 441 | BRGTN::setColor(Wheel(index)); 442 | if (!BRGTN::change(i, 1)) rdy = false; 443 | } 444 | return; 445 | } 446 | 447 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 448 | strip.setPixelColor(i, Wheel(index)); 449 | } 450 | ++index; // index is from 0 to 255 451 | } 452 | 453 | //---------------------------------------------- Light up with the random color than fade out ----------------------------- 454 | class lightUp : public BRGTN, public animation { 455 | public: 456 | lightUp() { min_p = 6; max_p = 24; show_time = 12; } 457 | virtual void init(void) { sp = 1; inc = sp; newColor(); } 458 | virtual void show(void); 459 | private: 460 | void newColor(void); 461 | byte sp; 462 | char inc; 463 | }; 464 | 465 | void lightUp::show(void) { 466 | bool finish = BRGTN::changeAll(inc); 467 | if (finish) { 468 | if (inc > 0) 469 | inc = -8; 470 | else { 471 | ++sp; 472 | inc = sp; 473 | if (sp > 8) { 474 | sp = 1; 475 | newColor(); 476 | } 477 | } 478 | } 479 | } 480 | 481 | void lightUp::newColor(void) { 482 | uint32_t c = 0; 483 | for (byte i = 0; i < 3; ++i) { 484 | c <<= 8; 485 | byte d = random(16) << 4; 486 | c |= d; 487 | } 488 | BRGTN::setColor(c); 489 | } 490 | 491 | //---------------------------------------------- Random sparcs ------------------------------------------------------------ 492 | class sparks : public BRGTN, public animation { 493 | public: 494 | sparks() { min_p = 2; max_p = 6; show_time = 12; } 495 | virtual void init(void) { for (byte i = 0; i < 8; ++i) pos[i] = 0; } 496 | virtual void show(void); 497 | private: 498 | uint16_t pos[8]; 499 | }; 500 | 501 | void sparks::show(void) { 502 | uint32_t c = Wheel(random(265)); 503 | for (char i = 7; i >= 1; --i) { 504 | if (i == 6) 505 | strip.setPixelColor(pos[byte(i)], 0); 506 | else 507 | BRGTN::change(pos[byte(i)], -128); 508 | pos[byte(i)] = pos[byte(i-1)]; 509 | } 510 | int p = random(strip.numPixels()+1); 511 | pos[0] = p; 512 | strip.setPixelColor(p, c); 513 | } 514 | 515 | //---------------------------------------------- Random sparks fade out --------------------------------------------------- 516 | class rndFade : public BRGTN, public animation { 517 | public: 518 | rndFade() { min_p = 6; max_p = 24; show_time = 12; } 519 | virtual void init(void) {} 520 | virtual void show(void); 521 | }; 522 | 523 | void rndFade::show(void) { 524 | BRGTN::changeAll(-16); 525 | byte newDot = random(1, 5); 526 | for (byte i = 0; i < newDot; ++i) { 527 | int p = random(strip.numPixels()+1); 528 | uint32_t c = Wheel(random(256)); 529 | if (strip.getPixelColor(p) == 0) 530 | strip.setPixelColor(p, c); 531 | } 532 | } 533 | 534 | //---------------------------------------------- Lights run from the center ----------------------------------------------- 535 | class centerRun : public animation { 536 | public: 537 | centerRun() { min_p = 4; max_p = 20; } 538 | virtual void init(void); 539 | virtual void show(void); 540 | private: 541 | uint32_t color; 542 | int m, l, r; 543 | }; 544 | 545 | void centerRun::init(void) { 546 | color = Wheel(random(256)); 547 | int n = strip.numPixels(); 548 | int diff = n >> 3; 549 | m = l = r = random(diff+2) + ((n * 7) >> 4); 550 | } 551 | 552 | void centerRun::show(void) { 553 | if (l >= 0) strip.setPixelColor(l, color); 554 | if (r < int(strip.numPixels())) strip.setPixelColor(r, color); 555 | l -= 2; r += 2; 556 | if ((l < 0) && r >= int(strip.numPixels())) { 557 | l = r = m + 1; 558 | color = Wheel(random(256)); 559 | } 560 | } 561 | 562 | //---------------------------------------------- Slow shining by the different colors ------------------------------------- 563 | class shineSeven : public BRGTN, public animation { 564 | public: 565 | shineSeven() { min_p = 4; max_p = 20; show_time = 12; } 566 | virtual void init(void); 567 | virtual void show(void); 568 | private: 569 | void startNewColor(void); 570 | byte curs; 571 | byte w; 572 | byte base; 573 | }; 574 | 575 | void shineSeven::init(void) { 576 | curs = 0; 577 | w = random(256); 578 | base = random(4, 8); 579 | startNewColor(); 580 | } 581 | 582 | void shineSeven::show() { 583 | int n = strip.numPixels(); 584 | bool finish = true; 585 | for (int i = int(curs) - 1; i < n; i += base) { // Fade out previous color 586 | if (i >= 0) 587 | if(!BRGTN::change(i, -8)) finish = false; 588 | } 589 | for (int i = curs; i < n; i += base) // Light up current color 590 | if (!BRGTN::change(i, 8)) finish = false; 591 | if (finish) { // The current color has been light fully 592 | ++curs; if (curs >= base) curs = 0; 593 | startNewColor(); 594 | } 595 | } 596 | 597 | void shineSeven::startNewColor(void) { 598 | uint32_t c = Wheel(w); 599 | w += 97; 600 | BRGTN::setColor(c); 601 | c &= 0x10101; 602 | for (uint16_t i = curs; i < strip.numPixels(); i += base) 603 | strip.setPixelColor(i, c); 604 | } 605 | 606 | //---------------------------------------------- Rapid walking by the different colors ----------------------------------- 607 | class walkSeven : public BRGTN, public TWOCLR, public animation { 608 | public: 609 | walkSeven() { min_p = 8; max_p = 15; show_time = 9; } 610 | virtual void init(void); 611 | virtual void show(void); 612 | private: 613 | char curs; 614 | byte w; 615 | bool fwd; 616 | int ch_dir; 617 | byte period; 618 | }; 619 | 620 | void walkSeven::init() { 621 | w = random(256); 622 | fwd = random(2); 623 | ch_dir = random(30, 100); 624 | period = random(13, 20); 625 | curs = 0; 626 | } 627 | 628 | void walkSeven::show(void) { 629 | BRGTN::changeAll(-64); 630 | 631 | int n = strip.numPixels(); 632 | uint32_t c1 = Wheel(w); 633 | w += 71; 634 | for (int i = curs; i < n; i += period) { 635 | uint32_t c2 = strip.getPixelColor(i); 636 | c2 = TWOCLR::add(c1, c2); 637 | strip.setPixelColor(i, c2); 638 | } 639 | 640 | if (fwd) ++curs; else --curs; 641 | curs %= period; 642 | 643 | if (--ch_dir < 0) { 644 | ch_dir = random(70, 300); 645 | fwd = !fwd; 646 | } 647 | } 648 | 649 | //---------------------------------------------- Rapid flashing by the differenc colors --------------------------------- 650 | class flashSeven : public BRGTN, public animation { 651 | public: 652 | flashSeven() { min_p = 4; max_p = 8; show_time = 9; } 653 | virtual void init(void); 654 | virtual void show(void); 655 | private: 656 | char curs; 657 | byte w; 658 | bool fwd; 659 | int ch_dir; 660 | byte period; 661 | }; 662 | 663 | void flashSeven::init() { 664 | w = random(256); 665 | fwd = random(2); 666 | ch_dir = random(30, 100); 667 | period = random(7, 20); 668 | curs = 0; 669 | } 670 | 671 | void flashSeven::show(void) { 672 | BRGTN::changeAll(-64); 673 | 674 | int n = strip.numPixels(); 675 | for (int i = curs; i < n; i += period) { 676 | BRGTN::change(i, -128); 677 | } 678 | 679 | if (fwd) ++curs; else --curs; 680 | curs %= period; 681 | 682 | uint32_t c = Wheel(w); 683 | w += 71; 684 | for (int i = curs; i < n; i += period) { 685 | strip.setPixelColor(i, c); 686 | } 687 | 688 | if (--ch_dir < 0) { 689 | ch_dir = random(70, 300); 690 | fwd = !fwd; 691 | } 692 | } 693 | 694 | //---------------------------------------------- Slow merging of two colors ----------------------------------------------- 695 | class mergeOne : public TWOCLR, public animation { 696 | public: 697 | mergeOne() { min_p = 8; max_p = 30; } 698 | virtual void init(void); 699 | virtual void show(void); 700 | private: 701 | uint32_t cl, cr; 702 | int l, r; 703 | }; 704 | 705 | void mergeOne::init(void) { 706 | l = 0; 707 | r = strip.numPixels(); 708 | byte indx = random(256); 709 | cl = Wheel(indx); 710 | indx += random(4, 16); 711 | cr = Wheel(indx); 712 | strip.clear(); 713 | } 714 | 715 | void mergeOne::show(void) { 716 | if (l < r) { 717 | strip.setPixelColor(l, cl); 718 | strip.setPixelColor(r, cr); 719 | } else { 720 | uint32_t c = strip.getPixelColor(l); 721 | c = TWOCLR::add(c, cl); 722 | strip.setPixelColor(l, c); 723 | c = strip.getPixelColor(r); 724 | c = TWOCLR::add(c, cr); 725 | strip.setPixelColor(r, c); 726 | } 727 | 728 | --r; ++l; 729 | if (r < 0) { // Force the strip clerance 730 | do_clear = true; 731 | complete = true; 732 | return; 733 | } 734 | complete = false; 735 | } 736 | 737 | //---------------------------------------------- Fast merging of Waves ---------------------------------------------------- 738 | class mergeWave : public animation { 739 | public: 740 | mergeWave() { min_p = 3; max_p = 20; show_time = 2; } 741 | virtual void init(void); 742 | virtual void show(void); 743 | private: 744 | int l, r; 745 | byte index; 746 | byte len; 747 | }; 748 | 749 | void mergeWave::init(void) { 750 | l = 0; 751 | r = strip.numPixels() - 1; 752 | index = random(256); 753 | len = random(8, 17); 754 | strip.clear(); 755 | } 756 | 757 | void mergeWave::show(void) { 758 | if (l < r) { 759 | strip.setPixelColor(l, Wheel(l & 255)); 760 | if (l > len) strip.setPixelColor(l-len, 0); 761 | strip.setPixelColor(r, Wheel((index + r) & 255)); 762 | if ((r + len) > int(strip.numPixels())) strip.setPixelColor(r+len, 0); 763 | } else { 764 | uint32_t c = strip.getPixelColor(l); 765 | c |= Wheel(l & 255); 766 | strip.setPixelColor(l, c); 767 | c = strip.getPixelColor(r); 768 | c |= Wheel((index + r) & 255); 769 | strip.setPixelColor(r, c); 770 | strip.setPixelColor(l-len, 0); 771 | strip.setPixelColor(r+len, 0); 772 | } 773 | --r; ++l; index += 4; 774 | if (r < 0) { // Force the strip clerance 775 | do_clear = true; 776 | complete = true; 777 | } 778 | complete = false; 779 | } 780 | 781 | //---------------------------------------------- Fast collide of two colors --------------------------------------------- 782 | class collideOne : public animation { 783 | public: 784 | collideOne() { min_p = 1; max_p = 3; show_time = 2; } 785 | virtual void init(void); 786 | virtual void show(void); 787 | private: 788 | uint32_t cl, cr; 789 | int l, r; 790 | bool boom; 791 | }; 792 | 793 | void collideOne::init(void) { 794 | l = 0; 795 | r = strip.numPixels() - 1; 796 | byte w = random(256); 797 | cl = Wheel(w); 798 | w += random(8, 16); 799 | cr = Wheel(w); 800 | strip.clear(); 801 | boom = false; 802 | } 803 | 804 | void collideOne::show(void) { 805 | if (boom) { 806 | strip.setPixelColor(l, 0xffffff); 807 | strip.setPixelColor(r, 0xffffff); 808 | if ((r - l) >= 12) { 809 | strip.setPixelColor(l+6, 0); 810 | strip.setPixelColor(r-6, 0); 811 | } 812 | --l; ++r; 813 | if (l < 0) { 814 | init(); 815 | complete = true; 816 | return; 817 | } 818 | } else { 819 | if (l < r) { 820 | strip.setPixelColor(l, cl); 821 | strip.setPixelColor(r, cr); 822 | --r; ++l; 823 | } else { 824 | boom = true; 825 | } 826 | } 827 | complete = false; 828 | } 829 | 830 | //---------------------------------------------- Neo fire animation by Robert Ulbricht ---------------------------------- 831 | class neoFire : public BLEND, public animation { 832 | public: 833 | neoFire() { min_p = 1; max_p = 5; } 834 | virtual void init(void); 835 | virtual void show(void); 836 | private: 837 | uint32_t color; 838 | char pause; 839 | const uint32_t c1 = 80; 840 | const uint32_t c2 = 25; 841 | }; 842 | 843 | void neoFire::init(void) { 844 | color = 0; 845 | byte m = random(3); 846 | color |= c1 << (m*8); 847 | m += random(1,3); 848 | if (m >= 3) m = 0; 849 | color |= c2 << (m*8); 850 | } 851 | 852 | void neoFire::show(void) { 853 | if (pause > 0) { 854 | --pause; 855 | return; 856 | } 857 | pause = random(8); 858 | for(uint16_t i = 0; i < strip.numPixels(); ++i) { 859 | uint32_t blended_color = BLEND::add(strip.getPixelColor(i), color); 860 | byte r = random(80); 861 | uint32_t diff_color = strip.Color(r, r/2, r/2); 862 | blended_color = BLEND::sub(blended_color, diff_color); 863 | strip.setPixelColor(i, blended_color); 864 | } 865 | } 866 | 867 | //---------------------------------------------- Even and odd position leds are moving towards each other --------------- 868 | class evenOdd : public animation { 869 | public: 870 | evenOdd() { min_p = 10; max_p = 20; } 871 | virtual void init(void); 872 | virtual void show(void); 873 | private: 874 | uint32_t cl, cr; 875 | int l, r; 876 | }; 877 | 878 | void evenOdd::init(void) { 879 | byte indx = random(256); 880 | cl = Wheel(indx); 881 | indx += random(4, 16); 882 | cr = Wheel(indx); 883 | l = 0; 884 | r = strip.numPixels() - 1; // r is Odd 885 | } 886 | 887 | void evenOdd::show(void) { 888 | strip.setPixelColor(l, cl); 889 | strip.setPixelColor(r, cr); 890 | l += 2; r -= 2; 891 | if (r < 0) { 892 | if (cr) { 893 | cr = cl = 0; 894 | l = 0; 895 | r = strip.numPixels() - 1; // r is Odd 896 | } else { 897 | init(); 898 | complete = true; 899 | return; 900 | } 901 | } 902 | complete = false; 903 | } 904 | 905 | //---------------------------------------------- Random colors from left and right move to the center ------------------- 906 | class collMdl : public BLEND, public animation { 907 | public: 908 | collMdl() { min_p = 1; max_p = 6; show_time = 8; } 909 | virtual void init(void); 910 | virtual void show(void); 911 | private: 912 | void newColors(void); 913 | uint32_t cl, cr; 914 | int l, r, ml, mr; 915 | bool clr; 916 | }; 917 | 918 | void collMdl::init(void) { 919 | ml = (strip.numPixels() - 1) / 2; 920 | mr = ml + 1; 921 | newColors(); 922 | clr = false; 923 | } 924 | 925 | void collMdl::show(void) { 926 | if (clr) { 927 | strip.setPixelColor(l, 0); 928 | strip.setPixelColor(r, 0); 929 | l--; r++; 930 | if (l < 0) { 931 | init(); 932 | complete = true; 933 | } 934 | return; 935 | } 936 | 937 | // blend colors in the middle 938 | if ((mr - ml) > 1) { 939 | for (int i = ml; i < mr; ++i) 940 | BLEND::blendPixel(i); 941 | } 942 | 943 | // New colors are moving to the center 944 | if (l <= ml) { 945 | if (l > 1)strip.setPixelColor(l-2, 0); 946 | strip.setPixelColor(l, cl); 947 | } 948 | if (r >= mr) { 949 | if (r < int(strip.numPixels() - 2)) strip.setPixelColor(r+2, 0); 950 | strip.setPixelColor(r, cr); 951 | } 952 | if ((l >= ml) && (r <= mr)) { 953 | ml--; mr++; 954 | if (ml < 0) { 955 | clr = true; 956 | l = (strip.numPixels() - 1) / 2; 957 | r = l + 1; 958 | return; 959 | } 960 | newColors(); 961 | return; 962 | } 963 | l++; r--; 964 | complete = false; 965 | } 966 | 967 | void collMdl::newColors(void) { 968 | cl = Wheel(random(256)); 969 | cr = Wheel(random(256)); 970 | l = 0; 971 | r = strip.numPixels() - 1; 972 | } 973 | 974 | //------------------------------------------- Random colors from left and right move to the other end ------------------- 975 | class collEnd : public BLEND, public animation { 976 | public: 977 | collEnd() { min_p = 1; max_p = 6; show_time = 10; } 978 | virtual void init(void); 979 | virtual void show(void); 980 | private: 981 | void newColors(void); 982 | uint32_t cl, cr; 983 | int l, r, ml, mr; 984 | }; 985 | 986 | void collEnd::init(void) { 987 | ml = strip.numPixels() - 1; 988 | mr = 0; 989 | newColors(); 990 | } 991 | 992 | void collEnd::show(void) { 993 | // blend colors in the both ends 994 | if (mr > 1) { 995 | for (int i = 0; i < mr; ++i) 996 | BLEND::blendPixel(i); 997 | for (uint16_t i = ml; i < strip.numPixels(); ++i) 998 | BLEND::blendPixel(i); 999 | } 1000 | 1001 | // New colors are moving to the other end 1002 | if (l <= ml) { 1003 | if (l > (mr + 1)) 1004 | strip.setPixelColor(l-2, 0); 1005 | strip.setPixelColor(l, cl); 1006 | } 1007 | if (r >= mr) { 1008 | if (r < (ml - 1)) 1009 | strip.setPixelColor(r+2, 0); 1010 | strip.setPixelColor(r, cr); 1011 | } 1012 | if ((l >= ml) && (r <= mr)) { 1013 | ml--; mr++; 1014 | if (ml < 0) { 1015 | do_clear = true; // Force the strip clerance 1016 | complete = true; 1017 | return; 1018 | } 1019 | newColors(); 1020 | return; 1021 | } 1022 | l++; r--; 1023 | complete = false; 1024 | } 1025 | 1026 | void collEnd::newColors(void) { 1027 | cl = Wheel(random(256)); 1028 | cr = Wheel(random(256)); 1029 | l = mr; 1030 | r = ml; 1031 | } 1032 | 1033 | //------------------------------------------- Rainbow colors blend -------------------------------------------------------- 1034 | class rainBlend : public BLEND, public animation { 1035 | public: 1036 | rainBlend() { min_p = 1; max_p = 6; } 1037 | virtual void init(void) { index = 0; } 1038 | virtual void show(void); 1039 | private: 1040 | int index; 1041 | }; 1042 | 1043 | 1044 | void rainBlend::show(void) { 1045 | if (index < int(strip.numPixels())) { 1046 | strip.setPixelColor(index, Wheel(((index * 256 / strip.numPixels())) & 255)); 1047 | ++index; 1048 | return; 1049 | } 1050 | for(uint16_t i = 0; i < strip.numPixels(); ++i) 1051 | BLEND::blendPixel(i); 1052 | } 1053 | 1054 | //---------------------------------------------- Color swing -------------------------------------------------------------- 1055 | class swing : public CRAWL, public animation { 1056 | public: 1057 | swing() { min_p = 3; max_p = 10; show_time = 10; } 1058 | virtual void init(void); 1059 | virtual void show(void); 1060 | private: 1061 | int len, index; 1062 | byte w; 1063 | bool rnd; 1064 | }; 1065 | 1066 | void swing::init(void) { 1067 | len = 1; 1068 | rnd = random(2); 1069 | uint32_t c = Wheel(random(256)); 1070 | if (!rnd) { // Use rainbow colors from Wheel 1071 | w = random(256); 1072 | c = Wheel(w); 1073 | } 1074 | strip.setPixelColor(0, c); 1075 | CRAWL::fwd = true; 1076 | CRAWL::next_color = 0; 1077 | index = strip.numPixels() - len - 1; 1078 | } 1079 | 1080 | void swing::show(void) { 1081 | CRAWL::step(); 1082 | --index; 1083 | 1084 | if (index < 0) { 1085 | uint32_t c = Wheel(random(256)); 1086 | if (!rnd) { 1087 | w += 4; 1088 | c = Wheel(w); 1089 | } 1090 | if (CRAWL::fwd) 1091 | strip.setPixelColor(strip.numPixels() - len - 1, c); 1092 | else 1093 | strip.setPixelColor(len, c); 1094 | ++len; 1095 | CRAWL::fwd = !CRAWL::fwd; 1096 | index = strip.numPixels() - len - 1; 1097 | if (len >= int(strip.numPixels())) { 1098 | do_clear = true; // Force the strip clerance 1099 | complete = true; 1100 | return; 1101 | } 1102 | } 1103 | complete = false; 1104 | } 1105 | 1106 | //---------------------------------------------- Single color swing ------------------------------------------------------- 1107 | class swingSingle : public animation { 1108 | public: 1109 | swingSingle() { min_p = 3; max_p = 10; show_time = 10; } 1110 | virtual void init(void); 1111 | virtual void show(void); 1112 | private: 1113 | uint32_t color; 1114 | int len, index; 1115 | bool fwd; 1116 | byte w; 1117 | }; 1118 | 1119 | void swingSingle::init(void) { 1120 | len = 1; 1121 | w = random(256); 1122 | color = Wheel(w); 1123 | strip.setPixelColor(0, color); 1124 | fwd = true; 1125 | index = len; 1126 | } 1127 | 1128 | void swingSingle::show(void) { 1129 | if (fwd) { 1130 | for (int i = 0; i <= index; ++i) { 1131 | if (i < (index - len)) 1132 | strip.setPixelColor(i, 0); 1133 | else 1134 | strip.setPixelColor(i, color); 1135 | } 1136 | ++index; 1137 | if (index >= int(strip.numPixels())) { 1138 | fwd = false; 1139 | len += random(1, strip.numPixels() >> 4); 1140 | index = strip.numPixels() - len - 1; 1141 | w += 4; 1142 | } 1143 | } else { 1144 | for (int i = strip.numPixels() - 1; i >= index; --i) { 1145 | if (i > (index + len)) 1146 | strip.setPixelColor(i, 0); 1147 | else 1148 | strip.setPixelColor(i, color); 1149 | } 1150 | --index; 1151 | if (index < 0) { 1152 | fwd = true; 1153 | index = len; 1154 | w += 4; 1155 | } 1156 | } 1157 | if (len >= int(strip.numPixels())) { 1158 | do_clear = true; // Force the strip clerance 1159 | complete = true; 1160 | return; 1161 | } 1162 | complete = false; 1163 | } 1164 | 1165 | //---------------------------------------------- Fill the strip by the color in random order ---------------------------- 1166 | class randomFill : public BRGTN, public animation { 1167 | public: 1168 | randomFill() { min_p = 2; max_p = 4; show_time = 15; } 1169 | virtual void init(void); 1170 | virtual void show(void); 1171 | private: 1172 | void newDot(bool clr); 1173 | byte w; 1174 | int remain; 1175 | uint16_t pos; 1176 | bool clr; 1177 | }; 1178 | 1179 | void randomFill::init(void) { 1180 | w = random(256); 1181 | remain = strip.numPixels(); 1182 | clr = false; 1183 | newDot(clr); 1184 | } 1185 | 1186 | void randomFill::show() { 1187 | char val = 12; 1188 | if (clr) val = -12; 1189 | if (BRGTN::change(pos, val)) { 1190 | 1191 | if (remain <= 0) { 1192 | if (clr) { 1193 | strip.clear(); 1194 | w += 71; 1195 | init(); 1196 | complete = true; 1197 | return; 1198 | } else { 1199 | clr = true; 1200 | remain = strip.numPixels(); 1201 | newDot(clr); 1202 | } 1203 | } else { 1204 | newDot(clr); 1205 | } 1206 | 1207 | } 1208 | complete = false; 1209 | } 1210 | 1211 | void randomFill::newDot(bool clr) { 1212 | uint32_t color = 0; 1213 | if (!clr) color = Wheel(w); 1214 | 1215 | byte p = random(remain); 1216 | byte c = 0; 1217 | for (pos = 0; (pos < strip.numPixels()) && (c < p); ++pos) { 1218 | if (!color) { 1219 | while(strip.getPixelColor(pos) == 0) pos++; 1220 | ++c; 1221 | } else { 1222 | while(strip.getPixelColor(pos) != 0) pos++; 1223 | ++c; 1224 | } 1225 | } 1226 | if (!color) { 1227 | while(strip.getPixelColor(pos) == 0) pos++; 1228 | } else { 1229 | while(strip.getPixelColor(pos) != 0) pos++; 1230 | } 1231 | if (pos >= strip.numPixels()) { // something is wrong in the code 1232 | for (uint16_t i = 0; i < strip.numPixels(); ++i) 1233 | strip.setPixelColor(i, color); 1234 | remain = 0; 1235 | } 1236 | BRGTN::setColor(color); 1237 | remain--; 1238 | } 1239 | 1240 | //---------------------------------------------- Slow shining and flash by the different colors --------------------------- 1241 | class shineFlash : public BRGTN, public animation { 1242 | public: 1243 | shineFlash() { min_p = 4; max_p = 20; show_time = 12; } 1244 | virtual void init(void); 1245 | virtual void show(void); 1246 | private: 1247 | void startNewColor(void); 1248 | byte w; 1249 | byte mode; 1250 | bool flash; 1251 | int remain; 1252 | int indx; 1253 | char wait; 1254 | }; 1255 | 1256 | void shineFlash::init(void) { 1257 | w = random(256); 1258 | mode = 0; 1259 | flash = false; 1260 | startNewColor(); 1261 | } 1262 | 1263 | void shineFlash::show() { 1264 | int n = strip.numPixels(); 1265 | bool finish = true; 1266 | switch(mode) { 1267 | case 0: // Light up 1268 | finish = BRGTN::changeAll(4); 1269 | if (finish) { 1270 | flash = true; 1271 | remain = random(17, 30); 1272 | wait = 0; 1273 | } 1274 | break; 1275 | case 1: // Run flash 1276 | if (flash) { // Lit the LED 1277 | if (--wait > 0) return; 1278 | wait = random(2, 7); 1279 | indx = random(n); 1280 | if (remain > 0) { 1281 | uint32_t c = strip.getPixelColor(indx); 1282 | c |= 0x808080; 1283 | strip.setPixelColor(indx, c); 1284 | flash = false; 1285 | remain --; 1286 | } else { 1287 | mode ++; 1288 | } 1289 | } else { 1290 | uint32_t c = strip.getPixelColor(indx); 1291 | c &= 0x7f7f7f; 1292 | strip.setPixelColor(indx, c); 1293 | flash = true; 1294 | } 1295 | finish = false; 1296 | break; 1297 | case 2: // Fade out 1298 | default: 1299 | finish = BRGTN::changeAll(-4); 1300 | break; 1301 | } 1302 | 1303 | if (finish) { // The current color has been light fully 1304 | ++mode; 1305 | if (mode >= 3) { 1306 | startNewColor(); 1307 | mode = 0; 1308 | complete = true; 1309 | return; 1310 | } 1311 | } 1312 | complete = false; 1313 | } 1314 | 1315 | void shineFlash::startNewColor(void) { 1316 | uint32_t c = Wheel(w); 1317 | c &= 0x7f7f7f; 1318 | w += 17; 1319 | BRGTN::setColor(c); 1320 | c &= 0x10101; 1321 | int n = strip.numPixels(); 1322 | for (int i = 0; i < n; ++i) 1323 | strip.setPixelColor(i, c); 1324 | } 1325 | 1326 | //---------------------------------------------- Show single wave moving in random direction -- --------------------------- 1327 | class singleWave : public BRGTN, public animation { 1328 | public: 1329 | singleWave() { min_p = 4; max_p = 20; show_time = 12; } 1330 | virtual void init(void); 1331 | virtual void show(void); 1332 | private: 1333 | uint32_t dot[5]; 1334 | int pos; 1335 | byte stp; 1336 | byte remain; 1337 | char incr; 1338 | byte mode; 1339 | byte w; 1340 | }; 1341 | 1342 | void singleWave::init(void) { 1343 | uint32_t c = Wheel(random(256)); 1344 | uint32_t r = c & 0xff; 1345 | uint32_t g = (c >> 8) & 0xff; 1346 | uint32_t b = (c >> 16) & 0xff; 1347 | for (byte i = 1; i <= 4; ++i) { 1348 | r >>= 1; 1349 | g >>= 1; 1350 | b >>= 1; 1351 | uint32_t cc = b & 0xff; cc <<= 8; 1352 | cc |= g & 0xff; cc <<= 8; 1353 | cc |= r & 0xff; 1354 | dot[i] = cc; 1355 | } 1356 | 1357 | BRGTN::setColor(dot[3]); 1358 | c &= 0x10101; 1359 | int n = strip.numPixels(); 1360 | for (int i = 0; i < n; ++i) 1361 | strip.setPixelColor(i, c); 1362 | mode = 0; 1363 | pos = random(n); 1364 | remain = random(5, 15); 1365 | stp = 0; 1366 | } 1367 | 1368 | void singleWave::show() { 1369 | int n = strip.numPixels(); 1370 | bool finish = true; 1371 | switch(mode) { 1372 | case 0: // Light up 1373 | finish = BRGTN::changeAll(4); 1374 | break; 1375 | case 1: // move the soliton 1376 | finish = false; 1377 | if (stp <= 0) { 1378 | incr = 1; 1379 | if (pos > n / 2) incr = -1; 1380 | int m = n - pos - 2; 1381 | if (incr < 0) m = pos - 2; 1382 | stp = random(5, m); 1383 | --remain; 1384 | if (remain <= 0) { 1385 | for (int i = 0; i < n; ++i) 1386 | strip.setPixelColor(i, dot[3]); 1387 | finish = true; 1388 | break; 1389 | } 1390 | } 1391 | pos += incr; 1392 | for (int i = 0; i < n; ++i) { 1393 | strip.setPixelColor(i, dot[3]); 1394 | } 1395 | BRGTN::changeAll(random(9) - 4); 1396 | for (int i = 3; i > 0; --i) { 1397 | if ((pos - i) >= 0) strip.setPixelColor(pos - i, dot[i]); 1398 | } 1399 | for (int i = 0; i <= 3; ++i) { 1400 | if ((pos + i) < n) strip.setPixelColor(pos + i, dot[i]); 1401 | } 1402 | stp --; 1403 | break; 1404 | case 2: // Fade out 1405 | default: 1406 | finish = BRGTN::changeAll(-4); 1407 | break; 1408 | } 1409 | 1410 | if (finish) { // The current color has been light fully 1411 | ++mode; 1412 | if (mode >= 3) { 1413 | init (); 1414 | complete = true; 1415 | return; 1416 | } 1417 | } 1418 | complete = false; 1419 | } 1420 | 1421 | //---------------------------------------------- Several worms are moving randomly --------------------------------------- 1422 | class worms : public BRGTN, public TWOCLR, public animation { 1423 | public: 1424 | worms() { min_p = 10; max_p = 20; show_time = 9; } 1425 | virtual void init(void); 1426 | virtual void show(void); 1427 | private: 1428 | void add(void); 1429 | void die(byte index); 1430 | struct worm { 1431 | uint32_t color; 1432 | int pos; 1433 | bool fwd; 1434 | }; 1435 | struct worm w[5]; 1436 | byte active; 1437 | }; 1438 | 1439 | void worms::init(void) { 1440 | active = 0; 1441 | add(); 1442 | } 1443 | 1444 | void worms::show(void) { 1445 | int n = strip.numPixels(); 1446 | 1447 | // fade away 1448 | BRGTN::changeAll(-32); 1449 | 1450 | // Move existing 1451 | for (byte wi = 0; wi < active; ++wi) { 1452 | int np = w[wi].pos - 1; 1453 | if (w[wi].fwd) np += 2; 1454 | if ((np < 0) || (np >= n)) { 1455 | die(wi); 1456 | --wi; 1457 | continue; 1458 | } 1459 | uint32_t c = strip.getPixelColor(np); 1460 | if ((c != 0) && (random(10) == 0)) { 1461 | die(wi); 1462 | --wi; 1463 | continue; 1464 | } else { 1465 | c = TWOCLR::add(c, w[wi].color); 1466 | w[wi].pos = np; 1467 | strip.setPixelColor(np, c); 1468 | } 1469 | } 1470 | 1471 | if (random(12) == 0) add(); 1472 | } 1473 | 1474 | void worms::add(void) { 1475 | if (active >= 5) return; 1476 | 1477 | byte mode = random(3); 1478 | int n = strip.numPixels(); 1479 | switch (mode) { 1480 | case 0: // Run from the start 1481 | w[active].pos = 0; 1482 | break; 1483 | case 1: // Run from the end 1484 | w[active].pos = n-1; 1485 | break; 1486 | case 2: // Run from the random position 1487 | default: 1488 | w[active].pos = random(n); 1489 | break; 1490 | } 1491 | w[active].color = Wheel(random(256)); 1492 | if (strip.getPixelColor(w[active].pos) != 0) return; 1493 | if (w[active].pos < n/3) { 1494 | w[active].fwd = true; 1495 | } else if ((n - w[active].pos) < n/3) { 1496 | w[active].fwd = false; 1497 | } else { 1498 | w[active].fwd = random(2); 1499 | } 1500 | ++active; 1501 | } 1502 | 1503 | void worms::die(byte index) { 1504 | --active; 1505 | w[index].color = w[active].color; 1506 | w[index].pos = w[active].pos; 1507 | w[index].fwd = w[active].fwd; 1508 | } 1509 | 1510 | //---------------------------------------------- Show interferention from many sources ---------------------------------- 1511 | class interfer : public TWOCLR, public animation { 1512 | #define num_inter 3 1513 | public: 1514 | interfer() { min_p = 6; max_p = 10; show_time = 6; } 1515 | virtual void init(void); 1516 | virtual void show(void); 1517 | private: 1518 | void add(void); 1519 | uint32_t clr(int p, byte source); 1520 | int tm; // Time the animation starts (in cycles) 1521 | int pos[num_inter]; // The position os the source 1522 | int start[num_inter]; // Time whan the source activated 1523 | byte w[num_inter]; // Wheel Color index of the source 1524 | byte active; // The number of active sources 1525 | }; 1526 | 1527 | void interfer::init(void) { 1528 | active = 0; 1529 | tm = 0; 1530 | add(); 1531 | } 1532 | 1533 | void interfer::show(void) { 1534 | int n = strip.numPixels(); 1535 | 1536 | for (int i = 0; i < n; ++i) { 1537 | uint32_t c = 0; 1538 | for (byte j = 0; j < active; ++j) { 1539 | uint32_t c1 = clr(i, j); 1540 | c = TWOCLR::add(c, c1); 1541 | } 1542 | strip.setPixelColor(i, c); 1543 | } 1544 | ++tm; 1545 | if (tm %64 == 0) { 1546 | for (byte i = 0; i < active; ++i) 1547 | w[i] += 4; 1548 | } 1549 | 1550 | if (!random(20)) add(); 1551 | } 1552 | 1553 | void interfer::add(void) { 1554 | if (active >= num_inter) return; 1555 | pos[active] = random(strip.numPixels()); 1556 | w[active] = random(256); 1557 | start[active] = tm; 1558 | active++; 1559 | } 1560 | 1561 | uint32_t interfer::clr(int p, byte source) { 1562 | uint32_t c = 0; 1563 | int s_pos = pos[source]; 1564 | int e = tm - start[source]; 1565 | e -= abs(p - s_pos); 1566 | if (e < 0) return c; // The wave is not here yet 1567 | e %= 64; // The wave period 1568 | byte elm = 0; 1569 | if (e < 32) // Half way 1570 | elm = (31 - e) << 3; 1571 | else 1572 | elm = (e - 64) << 3; 1573 | 1574 | uint32_t color = Wheel(w[source]); 1575 | for (byte i = 0; i < 3; ++i) { 1576 | int max_c = (color >> (8*i)) & 0xff; 1577 | max_c -= elm; 1578 | if (max_c < 0) max_c = 0; 1579 | uint32_t nc = max_c; 1580 | nc <<= 8*i; 1581 | c |= nc; 1582 | } 1583 | return c; 1584 | } 1585 | 1586 | //------------------------------------------- Random colors toward each other ------------------------------------------ 1587 | class toward : public animation { 1588 | public: 1589 | toward() { min_p = 5; max_p = 10; show_time = 6; } 1590 | virtual void init(void) { w = random(256); } 1591 | virtual void show(void); 1592 | private: 1593 | byte w; 1594 | }; 1595 | 1596 | void toward::show(void) { 1597 | int n = strip.numPixels(); 1598 | for (int i = n-2; i >= 2; i -= 2) { 1599 | uint32_t c = strip.getPixelColor(i-2); 1600 | strip.setPixelColor(i, c); 1601 | } 1602 | for (int i = 1; i < n-1; i += 2) { 1603 | uint32_t c = strip.getPixelColor(i+2); 1604 | strip.setPixelColor(i, c); 1605 | } 1606 | if (random(16) == 0) { 1607 | strip.setPixelColor(0, 0); 1608 | strip.setPixelColor(n-1, 0); 1609 | w += 4; 1610 | } else { 1611 | strip.setPixelColor(0, Wheel(w+128)); 1612 | strip.setPixelColor(n-1, Wheel(w)); 1613 | } 1614 | } 1615 | 1616 | //------------------------------------------- Raindow colors toward each other ------------------------------------------ 1617 | class towardRain : public animation { 1618 | public: 1619 | towardRain() { min_p = 10; max_p = 20; show_time = 8; } 1620 | virtual void init(void) { w = random(256); } 1621 | virtual void show(void); 1622 | private: 1623 | byte w; 1624 | }; 1625 | 1626 | void towardRain::show(void) { 1627 | int n = strip.numPixels(); 1628 | for (int i = n-2; i >= 2; i -= 2) { 1629 | uint32_t c = strip.getPixelColor(i-2); 1630 | strip.setPixelColor(i, c); 1631 | } 1632 | for (int i = 1; i < n-1; i += 2) { 1633 | uint32_t c = strip.getPixelColor(i+2); 1634 | strip.setPixelColor(i, c); 1635 | } 1636 | 1637 | if (!random(17)) { 1638 | strip.setPixelColor(0, 0); 1639 | strip.setPixelColor(n-1, 0); 1640 | } else { 1641 | strip.setPixelColor(0, Wheel(w)); w += 9; 1642 | strip.setPixelColor(n-1, Wheel(w)); w += 3; 1643 | } 1644 | } 1645 | 1646 | 1647 | //---------------------------------------------- Slow single wave moving in random direction -- --------------------------- 1648 | class lghtHouse : public BRGTN, public animation { 1649 | public: 1650 | lghtHouse() { min_p = 2; max_p = 10; show_time = 6; } 1651 | virtual void init(void); 1652 | virtual void show(void); 1653 | private: 1654 | uint32_t dot[5]; 1655 | int pos; 1656 | byte stp; 1657 | char incr; 1658 | byte sp; 1659 | byte dlay; 1660 | }; 1661 | 1662 | void lghtHouse::init(void) { 1663 | uint32_t c = 0xff; 1664 | for (byte i = 0; i <= 4; ++i) { 1665 | dot[i] = c | (c << 8) | (c << 16); 1666 | c >>= 1; 1667 | } 1668 | BRGTN::setColor(dot[4]); 1669 | pos = random(strip.numPixels()); 1670 | stp = 0; 1671 | sp = random(1, 4); 1672 | dlay = sp; 1673 | } 1674 | 1675 | void lghtHouse::show() { 1676 | BRGTN::changeAll(-8); 1677 | if (--dlay > 0) return; 1678 | dlay = sp; 1679 | 1680 | int n = strip.numPixels(); 1681 | if (stp <= 0) { 1682 | incr = 1; 1683 | if (pos > n / 2) incr = -1; 1684 | stp = random(5, n); 1685 | sp += random(3) - 1; 1686 | if (sp < 1) 1687 | sp = 1; 1688 | else if (sp > 3) 1689 | sp = 3; 1690 | } 1691 | pos += incr; 1692 | pos %= n; 1693 | 1694 | for (int i = 0; i <= 5; ++i) { 1695 | byte indx = i; 1696 | if (indx >= 1) indx --; 1697 | int x = pos + i; 1698 | if (x >= n) 1699 | x -= n; 1700 | else if (x < 0) 1701 | x += n; 1702 | strip.setPixelColor(x, dot[indx]); 1703 | x = pos - i; 1704 | if (x >= n) 1705 | x -= n; 1706 | else if (x < 0) 1707 | x += n; 1708 | strip.setPixelColor(x, dot[indx]); 1709 | } 1710 | stp --; 1711 | 1712 | } 1713 | 1714 | //---------------------------------------------- Random dropped color dot fading out from epicenter ---------------------- 1715 | class rndDrops : public BRGTN, public TWOCLR, public animation { 1716 | public: 1717 | rndDrops() { min_p = 2; max_p = 7; show_time = 9; } 1718 | virtual void init(void) { num = 0; add(); } 1719 | virtual void show(void); 1720 | private: 1721 | void add(void); 1722 | struct drop { 1723 | int pos; 1724 | char tm; 1725 | }; 1726 | struct drop dr[16]; 1727 | char num; 1728 | }; 1729 | 1730 | 1731 | void rndDrops::show(void) { 1732 | 1733 | int n = strip.numPixels(); 1734 | for (byte i = 0; i < num; ++i) { 1735 | if (++dr[i].tm > 7) { // Delete old drops 1736 | dr[i].pos = dr[byte(num-1)].pos; 1737 | dr[i].tm = dr[byte(num-1)].tm; 1738 | --num; --i; 1739 | continue; 1740 | } 1741 | int p = dr[i].pos - dr[i].tm; 1742 | if (p < 0) p += n; 1743 | uint32_t c1 = strip.getPixelColor(p+1); 1744 | BRGTN::change(p+1, -64); 1745 | uint32_t c2 = strip.getPixelColor(p); 1746 | c2 = TWOCLR::add(c1, c2); 1747 | strip.setPixelColor(p, c2); 1748 | 1749 | p = dr[i].pos + dr[i].tm; 1750 | if (p >= n) p -= n; 1751 | c1 = strip.getPixelColor(p-1); 1752 | if (dr[i].tm > 1) BRGTN::change(p-1, -32); 1753 | c2 = strip.getPixelColor(p); 1754 | c2 = TWOCLR::add(c1, c2); 1755 | strip.setPixelColor(p, c2); 1756 | 1757 | BRGTN::change(dr[i].pos, -64); 1758 | } 1759 | 1760 | BRGTN::changeAll(-32); 1761 | 1762 | add(); 1763 | } 1764 | 1765 | void rndDrops::add(void) { 1766 | if (num >= 16) return; 1767 | int pos = random(strip.numPixels()); 1768 | uint32_t c = strip.getPixelColor(pos); 1769 | if (c) return; 1770 | c = Wheel(random(256)); 1771 | strip.setPixelColor(pos, c); 1772 | dr[byte(num)].pos = pos; 1773 | dr[byte(num)].tm = 0; 1774 | num++; 1775 | } 1776 | 1777 | // --------------------------------------------- Solitons are creaping up or down ----------------------------------------- 1778 | class solCreep: public CRAWL, public animation { 1779 | public: 1780 | solCreep(void) { min_p = 6; max_p = 14; show_time = 9; } 1781 | virtual void init(void); 1782 | virtual void show(void); 1783 | private: 1784 | void newSoliton(void); 1785 | int space; // space between the solitons 1786 | int change_direction; // the time to change direction 1787 | uint32_t dot[5]; 1788 | int sol; 1789 | byte w; 1790 | }; 1791 | 1792 | void solCreep::init(void) { 1793 | w = random(256); 1794 | CRAWL::fwd = random(2); 1795 | change_direction = random(200, 500); 1796 | newSoliton(); 1797 | } 1798 | 1799 | void solCreep::show(void) { 1800 | CRAWL::step(); 1801 | 1802 | if (--change_direction <= 0) { 1803 | CRAWL::fwd = !CRAWL::fwd; 1804 | change_direction = random(200, 500); 1805 | } 1806 | 1807 | int pos = strip.numPixels() - 1; 1808 | if (CRAWL::fwd) pos = 0; 1809 | 1810 | if (sol <= 4) { 1811 | int i = abs(sol); 1812 | strip.setPixelColor(pos, dot[i]); 1813 | ++sol; 1814 | } else { 1815 | if (--space >= 0) { 1816 | strip.setPixelColor(pos, 0); 1817 | } else { 1818 | newSoliton(); 1819 | } 1820 | } 1821 | } 1822 | 1823 | void solCreep::newSoliton(void) { 1824 | sol = -3; 1825 | uint32_t c = Wheel(w); 1826 | dot[0] = c; 1827 | w += 71; 1828 | uint32_t r = c & 0xff; 1829 | uint32_t g = (c >> 8) & 0xff; 1830 | uint32_t b = (c >> 16) & 0xff; 1831 | for (byte i = 1; i <= 4; ++i) { 1832 | r >>= 1; 1833 | g >>= 1; 1834 | b >>= 1; 1835 | uint32_t cc = b & 0xff; cc <<= 8; 1836 | cc |= g & 0xff; cc <<= 8; 1837 | cc |= r & 0xff; 1838 | dot[i] = cc; 1839 | } 1840 | space = random(3, 10); 1841 | 1842 | int pos = strip.numPixels() - 1; 1843 | if (CRAWL::fwd) pos = 0; 1844 | strip.setPixelColor(pos, dot[4]); 1845 | } 1846 | 1847 | // --------------------------------------------- Theatre-style crawling lights from neopixel example ---------------------- 1848 | class theatChase: public animation { 1849 | public: 1850 | theaterChase(void) { min_p = 3; max_p = 8; show_time = 3; } 1851 | virtual void init(void); 1852 | virtual void show(void); 1853 | private: 1854 | byte w; // color wheel index 1855 | byte color_period; // color period shift 1856 | char color_shift; 1857 | byte stp; 1858 | }; 1859 | 1860 | void theatChase::init(void) { 1861 | w = random(256); 1862 | color_period = random(5, 20); 1863 | color_shift = color_period; 1864 | stp = 0; 1865 | } 1866 | 1867 | void theatChase::show(void) { 1868 | int n = strip.numPixels(); 1869 | for (int i = 0; i < n; i += 3) 1870 | strip.setPixelColor(i + stp, 0); // turn off previous state pixels 1871 | 1872 | if (++stp >= 3) stp = 0; 1873 | uint32_t color = Wheel(w); 1874 | for (int i = 0; i < n; i += 3) 1875 | strip.setPixelColor(i + stp, color); 1876 | if (--color_shift <= 0) { 1877 | color_shift = color_period; 1878 | ++w; 1879 | } 1880 | } 1881 | 1882 | //---------------------------------------------- Classes for strip clearing ---------------------------------------------- 1883 | class clr : public BASE { 1884 | public: 1885 | clr() {} 1886 | virtual void init(void) = 0; 1887 | virtual void show(void) = 0; 1888 | bool isComplete(void) { return complete; } 1889 | bool fade(uint16_t index, byte val); 1890 | bool fadeAll(byte val); 1891 | protected: 1892 | bool complete; 1893 | }; 1894 | 1895 | bool clr::fadeAll(byte val) { 1896 | bool finish = true; 1897 | for (uint16_t i = 0; i < strip.numPixels(); ++i) { 1898 | if (!fade(i, val)) finish = false; 1899 | } 1900 | return finish; 1901 | } 1902 | 1903 | bool clr::fade(uint16_t index, byte val) { 1904 | uint32_t c = strip.getPixelColor(index); 1905 | byte bound = 0; 1906 | for (char s = 16; s >= 0; s -= 8) { 1907 | long cc = c >> s; // The color component (red, green or blue) 1908 | cc &= 0xff; 1909 | cc -= int(val); 1910 | if (cc < 0) { 1911 | cc = 0; 1912 | bound ++; 1913 | } 1914 | uint32_t mask = 0xff; mask <<= s; mask = ~mask; 1915 | cc <<= s; 1916 | c &= mask; 1917 | c |= cc; 1918 | } 1919 | strip.setPixelColor(index, c); 1920 | return (bound >= 3); 1921 | } 1922 | 1923 | // --------------------------------------------- Clear the strip from the ether side -------------------------------------- 1924 | class clearSide : public clr { 1925 | public: 1926 | clearSide() {} 1927 | virtual void init(void); 1928 | virtual void show(void); 1929 | private: 1930 | uint32_t color; 1931 | int index; 1932 | bool fwd; 1933 | }; 1934 | 1935 | void clearSide::init(void) { 1936 | complete = false; 1937 | color = Wheel(random(256)); 1938 | fwd = random(2); 1939 | if (fwd) 1940 | index = 0; 1941 | else 1942 | index = strip.numPixels() - 1; 1943 | } 1944 | 1945 | void clearSide::show(void) { 1946 | if (fwd) { 1947 | if (index < int(strip.numPixels())) { 1948 | strip.setPixelColor(index, color); 1949 | if (index > 0) strip.setPixelColor(index-1, 0); 1950 | } 1951 | ++index; 1952 | complete = (index >= int(strip.numPixels())); 1953 | } else { 1954 | if (index >= 0) { 1955 | strip.setPixelColor(index, color); 1956 | if (index < int(strip.numPixels() - 1)) strip.setPixelColor(index+1, 0); 1957 | } 1958 | --index; 1959 | complete = (index < 0); 1960 | } 1961 | } 1962 | 1963 | // --------------------------------------------- Clear the strip from the center to both ends ----------------------------- 1964 | class clearCntr : public clr { 1965 | public: 1966 | clearCntr() {} 1967 | virtual void init(void); 1968 | virtual void show(void); 1969 | private: 1970 | uint32_t color; 1971 | int l, r; 1972 | bool fwd; 1973 | }; 1974 | 1975 | void clearCntr::init(void) { 1976 | complete = false; 1977 | color = Wheel(random(256)); 1978 | l = strip.numPixels() / 2; 1979 | r = l + 1; 1980 | } 1981 | 1982 | void clearCntr::show(void) { 1983 | if (r < int(strip.numPixels())) { 1984 | strip.setPixelColor(r, color); 1985 | if (r > 0) strip.setPixelColor(r-1, 0); 1986 | } 1987 | ++r; 1988 | if (l >= 0) { 1989 | strip.setPixelColor(l, color); 1990 | if (l < int(strip.numPixels() - 1)) strip.setPixelColor(l+1, 0); 1991 | } 1992 | --l; 1993 | complete = (l < 0); 1994 | } 1995 | 1996 | // --------------------------------------------- Clear the strip from the ether side -------------------------------------- 1997 | class clearFade : public clr { 1998 | public: 1999 | clearFade() {} 2000 | virtual void init(void) { complete = false; decrement = random(4, 16); } 2001 | virtual void show(void) { complete = clr::fadeAll(decrement); } 2002 | private: 2003 | byte decrement; 2004 | }; 2005 | 2006 | // --------------------------------------------- Clear the strip by 'eating' the pixels from the center ------------------- 2007 | class eatCntr : public clr { 2008 | public: 2009 | eatCntr() {} 2010 | virtual void init(void) { complete = false; remain = strip.numPixels()/2 + 1;} 2011 | virtual void show(void); 2012 | private: 2013 | int remain; 2014 | }; 2015 | 2016 | void eatCntr::show(void) { 2017 | int n = strip.numPixels(); 2018 | int c = n / 2; 2019 | for (int i = c; i > 0; --i) { 2020 | uint32_t c = strip.getPixelColor(i-1); 2021 | strip.setPixelColor(i, c); 2022 | } 2023 | for (int i = c; i < n-1; ++i) { 2024 | uint32_t c = strip.getPixelColor(i+1); 2025 | strip.setPixelColor(i, c); 2026 | } 2027 | strip.setPixelColor(0, 0); 2028 | strip.setPixelColor(n-1, 0); 2029 | --remain; 2030 | complete = (remain <= 0); 2031 | } 2032 | 2033 | //---------------------------------------------- Clear the strip by deviding it by 2 ------------------------------------ 2034 | class clearHalf : public clr { 2035 | public: 2036 | clearHalf() {} 2037 | virtual void init(void); 2038 | virtual void show(void); 2039 | private: 2040 | int one_step; 2041 | }; 2042 | 2043 | void clearHalf::init(void) { 2044 | complete = false; 2045 | one_step = strip.numPixels() / 2; 2046 | } 2047 | 2048 | void clearHalf::show(void) { 2049 | for (uint16_t i = 0; i < strip.numPixels(); i += one_step) { 2050 | if (i > 0 || (one_step == 1)) strip.setPixelColor(i, 0); 2051 | } 2052 | complete = ((one_step >>= 1) == 0); 2053 | } 2054 | 2055 | //---------------------------------------------- Shuffle the animation in the random order -------------------------------- 2056 | class shuffle { 2057 | public: 2058 | shuffle(byte a_size) { 2059 | for (byte i = 0; i < a_size; ++i) index[i] = i; 2060 | curr = num_anim = a_size; 2061 | } 2062 | byte next(void); 2063 | private: 2064 | void randomize(void); 2065 | byte index[35]; // The maximum number of animations 2066 | byte num_anim; // The active animation number 2067 | byte curr; 2068 | }; 2069 | 2070 | byte shuffle::next(void) { 2071 | if (curr >= num_anim) randomize(); 2072 | return index[curr++]; 2073 | } 2074 | 2075 | void shuffle::randomize(void) { 2076 | for (byte i = 0; i < num_anim*2; ++i) { 2077 | byte p1 = random(num_anim); 2078 | byte p2 = random(num_anim); 2079 | if (p1 != p2) { 2080 | byte t = index[p2]; 2081 | index[p2] = index[p1]; 2082 | index[p1] = t; 2083 | } 2084 | } 2085 | curr = 0; 2086 | } 2087 | 2088 | // --------------------------------------------- The sequence manager ----------------------------------------------------- 2089 | class MANAGER : public shuffle { 2090 | public: 2091 | MANAGER(animation* a[], byte a_size, clr* c[], byte clr_size) : shuffle(a_size) { 2092 | anims = a; 2093 | clearance = c; 2094 | num_clr = clr_size; 2095 | stp = 0; 2096 | do_clear = false; 2097 | aIndex = 0; 2098 | } 2099 | void init(void); 2100 | void show(void); 2101 | void menu(void) { stp_period --; if (stp_period < 1) stp_period = 1; } 2102 | void menu_l(void) { initClear(); } 2103 | void incr(void) { stp_period ++; if (stp_period > 20) stp_period = 20; } 2104 | private: 2105 | void initClear(void); 2106 | bool isClean(void); 2107 | animation** anims; 2108 | clr** clearance; 2109 | byte num_clr; 2110 | uint32_t stp = 0; 2111 | uint16_t stp_period; 2112 | uint16_t clr_stp_period; 2113 | uint32_t next; 2114 | byte aIndex; 2115 | animation* a; 2116 | clr* c; 2117 | bool do_clear; // Whether cleaning the strip 2118 | }; 2119 | 2120 | void MANAGER::init(void) { 2121 | if (!anims[aIndex]->do_clear) { 2122 | aIndex = shuffle::next(); 2123 | // aIndex = 34; 2124 | a = anims[aIndex]; 2125 | 2126 | uint32_t period = a->show_time; 2127 | period = random(period, period * 3); // time in 10-seconds intervals 2128 | period *= 10000; // Now time in ms 2129 | next = millis() + period; 2130 | } 2131 | 2132 | a = anims[aIndex]; 2133 | uint16_t min_stp = a->min_p * 10; 2134 | uint16_t max_stp = a->max_p * 10; 2135 | stp_period = random(min_stp, max_stp+1); 2136 | stp = 0; 2137 | 2138 | strip.clear(); 2139 | a->do_clear = false; 2140 | a->init(); 2141 | strip.show(); 2142 | a->do_clear = false; 2143 | } 2144 | 2145 | void MANAGER::show(void) { 2146 | uint32_t ms = millis(); 2147 | if (!do_clear && (ms > next) && a->complete) { // The current animation is timed out 2148 | if (isClean()) 2149 | init(); 2150 | else 2151 | initClear(); 2152 | } 2153 | 2154 | if (ms < stp) { delay(1); return; } 2155 | if (do_clear) 2156 | stp = ms + clr_stp_period; 2157 | else 2158 | stp = ms + stp_period; 2159 | 2160 | if (do_clear) { 2161 | if (c->isComplete()) { 2162 | do_clear = false; 2163 | if (ms > next) a->do_clear = false; // It is too late to continue the animation 2164 | init(); 2165 | } else 2166 | c->show(); // Keep running clear session till it ends 2167 | } else { 2168 | if (a->do_clear) initClear(); 2169 | a->show(); 2170 | } 2171 | strip.show(); 2172 | } 2173 | 2174 | void MANAGER::initClear(void) { 2175 | do_clear = true; // Start clearing sequence 2176 | byte ni = random(num_clr); 2177 | c = clearance[ni]; 2178 | c->init(); 2179 | stp = 0; 2180 | clr_stp_period = random(3, 10) * 10; 2181 | } 2182 | 2183 | bool MANAGER::isClean(void) { 2184 | for (uint16_t i = 0; i < strip.numPixels(); ++i) 2185 | if (strip.getPixelColor(i)) return false; 2186 | return true; 2187 | } 2188 | 2189 | //================================ Ent of class definitions =============================================================== 2190 | colorWipe cWipe; 2191 | colorWalk cWalk; 2192 | randomCreep cCreep; 2193 | rainbow cRainbow; 2194 | rainCycle cRainCycle; 2195 | rainFull cRainFull; 2196 | colorWave cWave; 2197 | lightUp lUp; 2198 | sparks sRnd; 2199 | rndFade rFade; 2200 | centerRun cRun; 2201 | shineSeven cSeven; 2202 | walkSeven wSeven; 2203 | flashSeven fSeven; 2204 | shineFlash cFlash; 2205 | mergeOne mOne; 2206 | mergeWave mWave; 2207 | collideOne cOne; 2208 | neoFire cFire; 2209 | evenOdd cEvenOdd; 2210 | collMdl cCollMdl; 2211 | collEnd cCollEnd; 2212 | rainBlend cBlend; 2213 | swing cSwing; 2214 | swingSingle cSwingS; 2215 | randomFill rFill; 2216 | singleWave sWave; 2217 | worms cWorms; 2218 | interfer cInterf; 2219 | toward cToward; 2220 | towardRain rToward; 2221 | lghtHouse lHouse; 2222 | rndDrops cDrops; 2223 | solCreep sCreep; 2224 | theatChase tChase; 2225 | 2226 | clearSide clrSide; 2227 | clearCntr clrCntr; 2228 | clearFade clrFade; 2229 | eatCntr clrEat; 2230 | clearHalf clrHalf; 2231 | animation* anims[] = { 2232 | &cWipe, &cWalk, &cCreep, &cRainbow, &cRainCycle, &cRainFull, &cWave, &lUp, &sRnd, &rFade, 2233 | &cCollEnd, &cRun, &cSeven, &mOne, &mWave, &cOne, &cFire, &cEvenOdd, &rFill, &cCollMdl, 2234 | &cBlend, &cSwing, &cSwingS, &cFlash, &sWave, &cWorms, &cInterf, &cToward, &rToward, &lHouse, 2235 | &cDrops, &wSeven, &fSeven, &sCreep, &tChase 2236 | }; 2237 | clr* clearance[] = { &clrSide, &clrCntr, &clrFade, &clrEat, &clrHalf }; 2238 | const byte num_anim = sizeof(anims) / sizeof(animation*); 2239 | const byte num_clr = sizeof(clearance) / sizeof(clr*); 2240 | 2241 | MANAGER mgr(anims, num_anim, clearance, num_clr); 2242 | 2243 | void setup() { 2244 | //Serial.begin(9600); 2245 | 2246 | uint32_t rnd = 0; 2247 | for (byte i = A0; i < A4; ++i) { 2248 | pinMode(i, INPUT); 2249 | rnd <<= 6; 2250 | rnd += analogRead(i); 2251 | } 2252 | randomSeed(rnd); 2253 | 2254 | // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket 2255 | #if defined (__AVR_ATtiny85__) 2256 | if (F_CPU == 16000000) clock_prescale_set(clock_div_1); 2257 | #endif 2258 | 2259 | strip.begin(); 2260 | strip.setBrightness(NEO_BRGHT); 2261 | strip.show(); // Initialize all pixels to 'off' 2262 | mgr.init(); 2263 | 2264 | } 2265 | 2266 | void loop() { 2267 | mgr.show(); 2268 | } 2269 | --------------------------------------------------------------------------------