// interrupts? as per: https://github.com/FastLED/FastLED/issues/306 #define FASTLED_ALLOW_INTERRUPTS 0 #include "FastLED.h" #include #include #include #include #include #include #include "OmEspHelpers.h" #include "OmNtp.h" #include "OmLog.h" #include "OmRing.h" #include "SomePatterns.h" #include "SomeTransitions.h" #include "SimplePool.h" #include "Fader.h" #include "Sequencer.h" #define DATA_PIN D3 #define LED_COUNT 300 CRGB leds[LED_COUNT]; // led 184 is the "frontmost" led in my room. Omring can use this info. OmRing ring(LED_COUNT, 184); OmRing ring2(LED_COUNT, 184); OmRing ringOutput(LED_COUNT, 184, leds); OmWebServer s; OmWebPages p; OmNtp ntp; Fader fader(&ringOutput); SimplePool transitions; SimplePool patterns; void connectionStatus(const char *ssid, bool trying, bool failure, bool success) { if (success) { String bonjourName = "omino-theatre";// + system_get_chip_id(); MDNS.begin(bonjourName.c_str()); OMLOG("Bonjour address: http://%s.local\n", bonjourName.c_str()); ntp.setWifiAvailable(true); } } void htmlProc(OmXmlWriter &w, int ref1, void *ref2) { w.addElement("hr"); w.beginElement("pre"); w.addContentF(" time: %s\n", ntp.getTimeString()); w.addContentF("uptime: %s\n", omTime(millis())); w.endElement(); } long startMillis = 0; bool isCycling = true; Sequencer *sequencer = NULL; // if not NULL, run a sequence. Else just keep tickling the fader or cycle. void beginSequence(Sequencer *aSequence) { sequencer = aSequence; if(sequencer) sequencer->begin(); } Sequencer initialSequence(&fader, &patterns, &transitions); // bright, fading to dark Sequencer funBrightPatterns(&fader, &patterns, &transitions); Sequencer allPatterns(&fader, &patterns, &transitions); void setPatternAction(const char *page, const char *item, int value, int ref1, void *ref2) { if (value == 0) return; // button-up we ignore. fader.transitionTo(patterns.getEntryByIndex(ref1), transitions.getEntryByIndex(0), 2300); isCycling = false; beginSequence(0); } void mainAction(const char *page, const char *item, int value, int ref1, void *ref2) { switch(ref1) { case 1: beginSequence(&allPatterns); break; case 2: beginSequence(&initialSequence); break; case 3: fader.transitionTo(patterns.getEntryByName("allOn"), transitions.getEntryByIndex(0), 2300); break; case 4: fader.transitionTo(patterns.getEntryByName("darkScreen"), transitions.getEntryByIndex(0), 2300); break; } } void sliderAction(const char *page, const char *item, int value, int ref1, void *ref2) { switch (ref1) { case 1: // status led on break; case 2: break; case 3: break; case 4: break; } } void setup() { // Set up the pattern & transition pools #define ADD(_where,_name,_type) _where.addEntry(_name, new _type(), new _type()) ADD(transitions, "fader", Fade); ADD(transitions, "wipe", Wipe); ADD(patterns, "clock", Clock1Pattern); ADD(patterns, "worms", ChasingWorms1); ADD(patterns, "dim", Dims1Pattern); ADD(patterns, "bars", Bars1); ADD(patterns, "fire", Fire1); ADD(patterns, "darkScreen", DarkScreen1); ADD(patterns, "oneDot", OneDot); ADD(patterns, "allOn", AllOn); ADD(patterns, "twinkleStars", TwinkleStars); // start out dark. fader.transitionTo(patterns.getEntryByName("twinkleStars"), transitions.getEntryByIndex(0), 0); initialSequence.addStepPattern(0, "bars", 500, CRGB(0,50,20), 9); initialSequence.addStepPattern(5000, "allOn", 1000, CRGB(0,200,0)); // all on, in the first moments initialSequence.addStepPattern(5000, "allOn", 1000, CRGB(0,0,200)); // all on, in the first moments initialSequence.addStepPattern(5000, "worms", 2000); initialSequence.addStepPattern(5000, "bars", 1000, CRGB(100,0,0), 5); // a few more patterns after the relative brightness initialSequence.addStepPattern(5000, "allOn", 1000, CRGB(100,100,100)); // all on, in the first moments // hold the brighter pattern for a good long time! initialSequence.addStepPattern(20000, "bars", 2000, CRGB(100,100,100), 20); initialSequence.addStepPattern(20000, "bars", 2000, CRGB(100,50,10), 100); initialSequence.addStepPattern(10000, "oneDot", 2000); initialSequence.addStepPattern(20000, "oneDot", 2000, CRGB(0,0,128)); initialSequence.addStepPattern(20000, "fire", 2000); initialSequence.addStepPattern(20000, "allOn", 2000, CRGB(0,0,50)); initialSequence.addStepPattern(20000, "darkScreen", 2000); #define MC(_p) allPatterns.addStepPattern(3000, #_p, 5000); allPatterns.addStepPattern(0, "worms", 5000); MC(bars) MC(fire) MC(darkScreen) MC(clock) MC(allOn) MC(twinkleStars) MC(dim) MC(oneDot) MC(worms) allPatterns.addStepJump(3000, 1); startMillis = millis(); Serial.begin(115200); LEDS.addLeds(leds, LED_COUNT); ntp.setTimeZone(-7); s.addWifi("omino transwarp", "9999999999"); s.addWifi("Idea Fab Labs", "vortexrings"); s.setStatusCallback(connectionStatus); s.setStatusLedPin(-1); // no blinking blue light. p.beginPage("Main"); p.addButton("cycle", mainAction, 1); p.addButton("bright", mainAction, 2); p.addButton("stay bright", mainAction, 3); p.addButton("stay dark", mainAction, 4); p.addHtml(htmlProc); p.beginPage("Patterns"); { int k = patterns.getCount(); for (int ix = 0; ix < k; ix++) p.addButton(patterns.getEntryName(ix), setPatternAction, ix); } p.beginPage("Sliders"); p.addSlider(0, 255, "r", sliderAction, 255, 1); p.addSlider(0, 255, "g", sliderAction, 255, 2); p.addSlider(0, 255, "b", sliderAction, 255, 3); p.addSlider(-100, +100, "t", sliderAction, 255, 4); s.setHandler(p); beginSequence(&initialSequence); } int ticks = 0; long lastMillis = 0; enum GENERAL_MODE { GM_BRIGHT, GM_DARK, }; std::vector brightList{"worms", "bars"}; void loop() { delay(10); ticks++; long now = millis() - startMillis; if(sequencer) sequencer->tick(); else { // old cycling code int interval = 47000; int k0 = lastMillis / interval; int k1 = now / interval; if (k0 != k1 && isCycling) { const char *patternName = "x"; int s = patterns.getCount(); k0 %= s + 1; if (k0 != s) patternName = patterns.getEntryName(k0); Pattern *p = patterns.getEntryByName(patternName); Transition *f = transitions.getEntryByName("fader"); fader.transitionTo(p, f, 5000); } } lastMillis = now; s.tick(); ntp.tick(); fader.tick(); LEDS.show(); }