// interrupts? as per: https://github.com/FastLED/FastLED/issues/306 #define FASTLED_ALLOW_INTERRUPTS 0 #include "FastLED.h" #include #include #include #include "OmEspHelpers.h" #include "OmLine.h" #include "OmNtp.h" #include "OmLog.h" #include "Patterns.h" #define DATA_PIN D3 #define LED_COUNT 300 CRGB leds[LED_COUNT]; OmLine s1(leds, LED_COUNT); OmWebServer s; OmWebPages p; OmNtp ntp; CHSV originalOrange(14, 255, 23); // using omHsvToRgb CHSV aColor = originalOrange; PThrob1 pThrob1; PSolid pSolid; PFader pFader; PSomeDots pSomeDots; POneDotPings pOneDotPings; int timeZone = -8; int forceMinute = -1; 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 hsvAction(const char *page, const char *item, int value, int ref1, void *ref2) { switch(ref1) { case 1: aColor.h = value; break; case 2: aColor.s = value; break; case 3: aColor.v = value; break; } pThrob1.mainColor = aColor; pThrob1.throbbedColor = aColor; pThrob1.throbbedColor.h ^= 16; pThrob1.throbbedColor.s ^= 16; pThrob1.throbbedColor.v ^= 16; } 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(); } void footerProc(OmXmlWriter &w, int ref1, void *ref2) { w.addElement("hr"); p.renderPageButton(w, "Main"); p.renderPageButton(w, "Colors"); p.renderPageButton(w, "Setup"); p.renderPageButton(w, "_info"); p.renderPageButton(w, "_top"); } void triggerAction(const char *page, const char *item, int value, int ref1, void *ref2) { if(value) { if(ref1 == 1) { pSomeDots.newDots(); int hue = random(0, 255); int saturation = 240; int value = 30; pSomeDots.addDots(CHSV(hue, saturation, value), 3); pSomeDots.addDots(CHSV(hue + 128, saturation, value), 3); pSomeDots.applyDots(); pFader.pattern2 = &pSomeDots; } else if(ref1 == 2) { pSolid.color = CRGB(random(0,50), random(0,50), random(0,50)); pFader.pattern2 = &pSolid; } else if(ref1 == 3) { pOneDotPings.newDots(random(5,20), CHSV(random(0,255), random(200,255), random(60,100)), CHSV(100,20,20)); pFader.pattern2 = &pOneDotPings; } pFader.trigger(); } } void setupAction(const char *page, const char *item, int value, int ref1, void *ref2) { switch(ref1) { case 2: // status led on s.setStatusLedPin(LED_BUILTIN); break; case 3: s.setStatusLedPin(-1); break; case 4: timeZone = value; ntp.setTimeZone(timeZone); break; case 5: forceMinute = value; break; } } void colorsAction(const char *page, const char *item, int value, int ref1, void *ref2) { switch(ref1) { #define COLOR_CASE(_ix, _k) \ case _ix: { \ pThrob1.mainColor = _k; \ CHSV k2 = _k; k2.h -= 14; k2.v /= 2; \ pThrob1.throbbedColor = k2; \ break; } COLOR_CASE(1, originalOrange); COLOR_CASE(2, CHSV(85,240, 80)); COLOR_CASE(3, CHSV(0,0,255)); COLOR_CASE(4, CHSV(128, 200, 100)); COLOR_CASE(5, CHSV(42,255, 200)); COLOR_CASE(6, CHSV(14,255,255)); COLOR_CASE(7, CHSV(177,255,255)); } } void setup() { Serial.begin(115200); ntp.setTimeZone(timeZone); 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("twoColor", triggerAction, 1); p.addButton("solid", triggerAction, 2); p.addButton("blink", triggerAction, 3); p.addHtml(htmlProc); p.beginPage("Colors"); p.addButton("reset", colorsAction, 1); p.addButton("green", colorsAction, 2); p.addButton("white", colorsAction, 3); p.addButton("cyan", colorsAction, 4); p.addButton("yellow", colorsAction, 5); p.addButton("red", colorsAction, 6); p.addButton("blue", colorsAction, 7); p.beginPage("Setup"); p.addButton("status led on", setupAction, 2); p.addButton("status led off", setupAction, 3); p.addSlider(-12, +12, "time zone", setupAction, timeZone, 4); p.addSlider(-1, +60, "force minute", setupAction, -1, 5); p.setFooterProc(footerProc); s.setHandler(p); LEDS.addLeds(leds, LED_COUNT); pThrob1.init(&s1); pThrob1.mainColor = aColor; pThrob1.throbbedColor = pThrob1.mainColor; pThrob1.throbbedColor.h = 0; pThrob1.throbbedColor.s = 190; pThrob1.throbbedColor.h /= 2; pSolid.init(&s1); pSolid.color = CRGB(255,255,255); pSomeDots.init(&s1); pOneDotPings.init(&s1); pFader.init(&s1); pFader.pattern1 = &pThrob1; pFader.pattern2 = &pSolid; pFader.attack = 100; pFader.hold = 100; pFader.release = 100; } float x = 0; int ticks = 0; int lastMinute = -1; void loop() { delay(20); ticks++; s.tick(); ntp.tick(); { // See if a minute has passed. int hour, minute, second; bool got = ntp.getTime(hour, minute, second); if(got) { if(lastMinute < 0) lastMinute = minute; else { if(minute != lastMinute) { lastMinute = minute; if(minute == 1) colorsAction(0, 0, 0, 1, 0); // reset original color every minute:01 ok? if(forceMinute >= 0) minute = forceMinute; if(minute == 30) // on the half hour { pOneDotPings.newDots(random(2, 10), CHSV(random(0,255), random(100,255), 200), CHSV(100,20,20)); pFader.setEnvelope(400,500,700); pFader.pattern2 = &pOneDotPings; pFader.trigger(); } else if(minute % 5 == 0) // it's a minute multiple... { pSomeDots.newDots(); int hue = random(0, 255); int saturation = 240; int value = 30; pSomeDots.addDots(CHSV(hue, saturation, value), minute / 10); pSomeDots.addDots(CHSV(hue + random(60,100), saturation, value), minute % 10 ? 5 : 10); pSomeDots.applyDots(); pFader.pattern2 = &pSomeDots; pFader.setEnvelope(200,300,200); pFader.trigger(); } else { pSolid.color = CRGB(random(0,50), random(0,50), random(0,50)); pFader.pattern2 = &pSolid; pFader.setEnvelope(80,100,120); pFader.trigger(); } } } } } s1.clear(); for(int ix = 0; ix < LED_COUNT; ix++) omHsvToRgb(aColor.raw, leds[ix].raw); int pip = (ticks / 300) % LED_COUNT; leds[pip] = CHSV(100,200,200); s1.clear(); pFader.tickAndDraw(1.0);// ((ticks % 100) / 100.0); // s1.clear(); // pThrob1.tickAndDraw(1.0); LEDS.show(); }