diff --git a/lib/WebSockets/src/WebSocketsServer.cpp b/lib/WebSockets/src/WebSocketsServer.cpp index 39d8d3e2..ec6928ea 100644 --- a/lib/WebSockets/src/WebSocketsServer.cpp +++ b/lib/WebSockets/src/WebSocketsServer.cpp @@ -25,6 +25,14 @@ #include "WebSockets.h" #include "WebSocketsServer.h" +#ifdef ESP32 +#if defined __has_include +#if __has_include("soc/wdev_reg.h") +#include "soc/wdev_reg.h" +#endif // __has_include +#endif // defined __has_include +#endif + WebSocketsServerCore::WebSocketsServerCore(const String & origin, const String & protocol) { _origin = origin; _protocol = protocol; @@ -65,6 +73,7 @@ WebSocketsServerCore::~WebSocketsServerCore() { } WebSocketsServer::~WebSocketsServer() { + delete _server; } /** @@ -82,9 +91,13 @@ void WebSocketsServerCore::begin(void) { #ifdef ESP8266 randomSeed(RANDOM_REG32); +#elif defined(ESP32) && defined(WDEV_RND_REG) + randomSeed(REG_READ(WDEV_RND_REG)); #elif defined(ESP32) #define DR_REG_RNG_BASE 0x3ff75144 randomSeed(READ_PERI_REG(DR_REG_RNG_BASE)); +#elif defined(ARDUINO_ARCH_RP2040) + randomSeed(rp2040.hwrand32()); #else // TODO find better seed randomSeed(millis()); @@ -400,7 +413,7 @@ bool WebSocketsServerCore::clientIsConnected(uint8_t num) { return clientIsConnected(client); } -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) /** * get an IP for a client * @param num uint8_t client id @@ -432,8 +445,16 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { client = &_clients[i]; - // state is not connected or tcp connection is lost - if(!clientIsConnected(client)) { + // look for match to existing socket before creating a new one + if(clientIsConnected(client)) { +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100) + // Check to see if it is the same socket - if so, return it + if(client->tcp->getSocketNumber() == TCPclient->getSocketNumber()) { + return client; + } +#endif + } else { + // state is not connected or tcp connection is lost client->tcp = TCPclient; #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) @@ -445,7 +466,7 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT); #endif client->status = WSC_HEADER; -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) #ifndef NODEBUG_WEBSOCKETS IPAddress ip = client->tcp->remoteIP(); #endif @@ -527,7 +548,7 @@ void WebSocketsServerCore::dropNativeClient(WSclient_t * client) { } if(client->tcp) { if(client->tcp->connected()) { -#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32) +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_RP2040) client->tcp->flush(); #endif client->tcp->stop(); @@ -546,7 +567,7 @@ void WebSocketsServerCore::dropNativeClient(WSclient_t * client) { * @param client WSclient_t * ptr to the client struct */ void WebSocketsServerCore::clientDisconnect(WSclient_t * client) { -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) if(client->isSSL && client->ssl) { if(client->ssl->connected()) { client->ssl->flush(); @@ -620,7 +641,7 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc if(!client) { // no free space to handle client -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) #ifndef NODEBUG_WEBSOCKETS IPAddress ip = tcpClient->remoteIP(); #endif @@ -633,6 +654,7 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc client = &dummy; client->tcp = tcpClient; dropNativeClient(client); + return nullptr; } WEBSOCKETS_YIELD(); @@ -644,12 +666,12 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc * Handle incoming Connection Request */ void WebSocketsServer::handleNewClients(void) { -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) while(_server->hasClient()) { #endif - // store new connection - WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available()); +// store new connection + WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->accept()); if(!tcpClient) { DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!"); return; @@ -657,7 +679,7 @@ void WebSocketsServer::handleNewClients(void) { handleNewClient(tcpClient); -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) } #endif } @@ -928,7 +950,7 @@ void WebSocketsServer::begin(void) { void WebSocketsServer::close(void) { WebSocketsServerCore::close(); -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) _server->close(); #elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) _server->end(); diff --git a/lib/WebSockets/src/WebSocketsServer.h b/lib/WebSockets/src/WebSocketsServer.h index a8472a5b..5000f577 100644 --- a/lib/WebSockets/src/WebSocketsServer.h +++ b/lib/WebSockets/src/WebSocketsServer.h @@ -90,7 +90,7 @@ class WebSocketsServerCore : protected WebSockets { void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount); void disableHeartbeat(); -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) IPAddress remoteIP(uint8_t num); #endif @@ -241,4 +241,4 @@ class WebSocketsServer : public WebSocketsServerCore { WEBSOCKETS_NETWORK_SERVER_CLASS * _server; }; -#endif /* WEBSOCKETSSERVER_H_ */ +#endif /* WEBSOCKETSSERVER_H_ */ \ No newline at end of file diff --git a/src/Main.cpp b/src/Main.cpp index 99221627..cf82ef14 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -250,7 +250,9 @@ void setup() { // сброс WDT #if defined(ESP32) //SerialPrint("i", "Task", "reset wdt"); + #if !defined(esp32c6_4mb) && !defined(esp32c6_8mb) //TODO esp32-c6 переписать esp_task_wdt_init esp_task_wdt_reset(); + #endif #endif // сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение) if (needSaveValues) { @@ -287,8 +289,8 @@ void setup() { nullptr, true); // test - Serial.println("-------test start--------"); - Serial.println("--------test end---------"); + //Serial.println("-------test start--------"); + //Serial.println("--------test end---------"); stopErrorMarker(SETUPLAST_ERRORMARKER); #if defined(RESTART_DEBUG_INFO) diff --git a/src/StandWebServer.cpp b/src/StandWebServer.cpp index 8a2453c3..8c16cc24 100644 --- a/src/StandWebServer.cpp +++ b/src/StandWebServer.cpp @@ -159,7 +159,7 @@ void handleStatus() { } void handleLocalOTA() { - upgrade_firmware(3, "local"); + upgrade_firmware(3,""); } #ifdef ESP32 diff --git a/src/UpgradeFirm.cpp b/src/UpgradeFirm.cpp index a9a74307..6b3baa30 100644 --- a/src/UpgradeFirm.cpp +++ b/src/UpgradeFirm.cpp @@ -3,6 +3,9 @@ updateFirm update; void upgrade_firmware(int type, String path) { + if (path == ""){ + path = getBinPath(); + } putUserDataToRam(); // сбросим файл статуса последнего обновления writeFile("ota.json", "{}"); @@ -44,9 +47,7 @@ bool upgradeFS(String path) { SerialPrint("E", F("Update"), F("FS Path error")); saveUpdeteStatus("fs", PATH_ERROR); return ret; - } else if (path == "local"){ - path = getBinPath(); - } + } #ifdef ESP8266 ESPhttpUpdate.rebootOnUpdate(false); t_httpUpdate_return retFS = ESPhttpUpdate.updateFS(wifiClient, path + "/littlefs.bin"); @@ -88,9 +89,7 @@ bool upgradeBuild(String path) { SerialPrint("E", F("Update"), F("Build Path error")); saveUpdeteStatus("build", PATH_ERROR); return ret; - } else if (path == "local"){ - path = getBinPath(); - } + } #if defined(esp8266_4mb) || defined(esp8266_16mb) || defined(esp8266_1mb) || defined(esp8266_1mb_ota) || defined(esp8266_2mb) || defined(esp8266_2mb_ota) ESPhttpUpdate.rebootOnUpdate(false); t_httpUpdate_return retBuild = ESPhttpUpdate.update(wifiClient, path + "/firmware.bin"); @@ -134,15 +133,29 @@ const String getBinPath() { String path = "error"; int targetVersion = 400; //HACKFUCK local OTA version in PrepareServer.py String serverip; -// if (jsonRead(errorsHeapJson, F("chver"), targetVersion)) { - if (targetVersion >= 400) { + if (jsonRead(errorsHeapJson, F("chver"), targetVersion)) { + if (targetVersion >= 400) + { + if (jsonRead(settingsFlashJson, F("serverip"), serverip)) + { + if (serverip != "") + { + path = jsonReadStr(settingsFlashJson, F("serverip")) + "/iotm/" + String(FIRMWARE_NAME) + "/" + String(targetVersion) + "/" ; + } + } + } + } + else if (targetVersion >= 400) + { if (jsonRead(settingsFlashJson, F("serverlocal"), serverip)) { - if (serverip != "") { + if (serverip != "") + { path = jsonReadStr(settingsFlashJson, F("serverlocal")) + "/iotm/" + String(FIRMWARE_NAME) + "/" + String(targetVersion) + "/"; } } } -// } + + SerialPrint("i", F("Update"), "server local: " + path); return path; } diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 18cfe1e4..ad3e6bc5 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -435,9 +435,9 @@ void sendFileToWsByFrames(const String& filename, const String& header, const St continuation = true; } - Serial.println(String(i) + ") " + "ws: " + String(client_id) + " fr sz: " - + String(size) + " fin: " + String(fin) + " cnt: " + - String(continuation)); +// Serial.println(String(i) + ") " + "ws: " + String(client_id) + " fr sz: " +// + String(size) + " fin: " + String(fin) + " cnt: " + +// String(continuation)); #ifdef ASYNC_WEB_SOCKETS if (client_id == -1) { //ws.broadcastBIN(frameBuf, size, fin, continuation); diff --git a/src/modules/display/GyverLAMP/GyverLAMP.cpp b/src/modules/display/GyverLAMP/GyverLAMP.cpp new file mode 100644 index 00000000..9f1f8b7c --- /dev/null +++ b/src/modules/display/GyverLAMP/GyverLAMP.cpp @@ -0,0 +1,1309 @@ +#include "Global.h" +#include "classes/IoTItem.h" +#include "FastLED.h" +#include "effects.h" +#include "matrix.h" +extern IoTGpio IoTgpio; + +class GyverLAMP : public IoTItem +{ +private: + unsigned long prevmillis = 0; + String curEffect; + +public: + //======================================================================================================= + // setup() + GyverLAMP(String parameters) : IoTItem(parameters) + { + jsonRead(parameters, F("speed"), _speed); + jsonRead(parameters, F("dalay"), _dalay); + jsonRead(parameters, F("brightness"), _brightness); + // jsonRead(parameters, F("x_size"), _x_size); + // jsonRead(parameters, F("y_size"), _y_size); + + LEDS.setBrightness(_brightness); // ограничить максимальную яркость + LEDS.addLeds(leds, LED_COUNT); // настрйоки для нашей ленты (ленты на WS2811, WS2812, WS2812B) + one_color_all(0, 0, 0); // погасить все светодиоды + LEDS.show(); + } + + //======================================================================================================= + // doByInterval() + void doByInterval() + { + } + + //======================================================================================================= + // loop() + void loop() + { + + // yield(); + + if (millis() - prevmillis > _dalay) + { + + prevmillis = millis(); + thisdelay = _speed; + + if (curEffect == "rainbow_fade") + { + // rainbow_fade(); + ihue++; + if (ihue > 255) + { + ihue = 0; + } + for (int idex = 0; idex < LED_COUNT; idex++) + { + leds[idex] = CHSV(ihue, thissat, 255); + } + LEDS.show(); + } + if (curEffect == "rainbow_loop") + { + // rainbow_loop(); + idex++; + ihue = ihue + thisstep; + if (idex >= LED_COUNT) + { + idex = 0; + } + if (ihue > 255) + { + ihue = 0; + } + leds[idex] = CHSV(ihue, thissat, 255); + LEDS.show(); + } + if (curEffect == "random_burst") + { + // random_burst(); + idex = random(0, LED_COUNT); + ihue = random(0, 255); + leds[idex] = CHSV(ihue, thissat, 255); + LEDS.show(); + } + if (curEffect == "color_bounce") + { + // color_bounce(); + if (bouncedirection == 0) + { + idex = idex + 1; + if (idex == LED_COUNT) + { + bouncedirection = 1; + idex = idex - 1; + } + } + if (bouncedirection == 1) + { + idex = idex - 1; + if (idex == 0) + { + bouncedirection = 0; + } + } + for (int i = 0; i < LED_COUNT; i++) + { + if (i == idex) + { + leds[i] = CHSV(thishue, thissat, 255); + } + else + { + leds[i] = CHSV(0, 0, 0); + } + } + LEDS.show(); + } + if (curEffect == "color_bounceFADE") + { + // color_bounceFADE(); + if (bouncedirection == 0) + { + idex = idex + 1; + if (idex == LED_COUNT) + { + bouncedirection = 1; + idex = idex - 1; + } + } + if (bouncedirection == 1) + { + idex = idex - 1; + if (idex == 0) + { + bouncedirection = 0; + } + } + int iL1 = adjacent_cw(idex); + int iL2 = adjacent_cw(iL1); + int iL3 = adjacent_cw(iL2); + int iR1 = adjacent_ccw(idex); + int iR2 = adjacent_ccw(iR1); + int iR3 = adjacent_ccw(iR2); + for (int i = 0; i < LED_COUNT; i++) + { + if (i == idex) + { + leds[i] = CHSV(thishue, thissat, 255); + } + else if (i == iL1) + { + leds[i] = CHSV(thishue, thissat, 150); + } + else if (i == iL2) + { + leds[i] = CHSV(thishue, thissat, 80); + } + else if (i == iL3) + { + leds[i] = CHSV(thishue, thissat, 20); + } + else if (i == iR1) + { + leds[i] = CHSV(thishue, thissat, 150); + } + else if (i == iR2) + { + leds[i] = CHSV(thishue, thissat, 80); + } + else if (i == iR3) + { + leds[i] = CHSV(thishue, thissat, 20); + } + else + { + leds[i] = CHSV(0, 0, 0); + } + } + LEDS.show(); + } + if (curEffect == "ems_lightsONE") + { + // ems_lightsONE(); + idex++; + if (idex >= LED_COUNT) + { + idex = 0; + } + int idexR = idex; + int idexB = antipodal_index(idexR); + int thathue = (thishue + 160) % 255; + for (int i = 0; i < LED_COUNT; i++) + { + if (i == idexR) + { + leds[i] = CHSV(thishue, thissat, 255); + } + else if (i == idexB) + { + leds[i] = CHSV(thathue, thissat, 255); + } + else + { + leds[i] = CHSV(0, 0, 0); + } + } + LEDS.show(); + } + if (curEffect == "ems_lightsALL") + { + // ems_lightsALL(); + idex++; + if (idex >= LED_COUNT) + { + idex = 0; + } + int idexR = idex; + int idexB = antipodal_index(idexR); + int thathue = (thishue + 160) % 255; + leds[idexR] = CHSV(thishue, thissat, 255); + leds[idexB] = CHSV(thathue, thissat, 255); + LEDS.show(); + } + if (curEffect == "flicker") + { + flicker(); + } + + if (curEffect == "pulse_one_color_all") + { + // pulse_one_color_all(); + if (bouncedirection == 0) + { + ibright++; + if (ibright >= 255) + { + bouncedirection = 1; + } + } + if (bouncedirection == 1) + { + ibright = ibright - 1; + if (ibright <= 1) + { + bouncedirection = 0; + } + } + for (int idex = 0; idex < LED_COUNT; idex++) + { + leds[idex] = CHSV(thishue, thissat, ibright); + } + LEDS.show(); + } + if (curEffect == "pulse_one_color_all_rev") + { + // pulse_one_color_all_rev(); + if (bouncedirection == 0) + { + isat++; + if (isat >= 255) + { + bouncedirection = 1; + } + } + if (bouncedirection == 1) + { + isat = isat - 1; + if (isat <= 1) + { + bouncedirection = 0; + } + } + for (int idex = 0; idex < LED_COUNT; idex++) + { + leds[idex] = CHSV(thishue, isat, 255); + } + LEDS.show(); + } + if (curEffect == "fade_vertical") + { + // fade_vertical(); + idex++; + if (idex > TOP_INDEX) + { + idex = 0; + } + int idexA = idex; + int idexB = horizontal_index(idexA); + ibright = ibright + 10; + if (ibright > 255) + { + ibright = 0; + } + leds[idexA] = CHSV(thishue, thissat, ibright); + leds[idexB] = CHSV(thishue, thissat, ibright); + LEDS.show(); + } + if (curEffect == "rule30") + { + // rule30(); + if (bouncedirection == 0) + { + random_red(); + bouncedirection = 1; + } + copy_led_array(); + int iCW; + int iCCW; + int y = 100; + for (int i = 0; i < LED_COUNT; i++) + { + iCW = adjacent_cw(i); + iCCW = adjacent_ccw(i); + if (ledsX[iCCW][0] > y && ledsX[i][0] > y && ledsX[iCW][0] > y) + { + leds[i].r = 0; + } + if (ledsX[iCCW][0] > y && ledsX[i][0] > y && ledsX[iCW][0] <= y) + { + leds[i].r = 0; + } + if (ledsX[iCCW][0] > y && ledsX[i][0] <= y && ledsX[iCW][0] > y) + { + leds[i].r = 0; + } + if (ledsX[iCCW][0] > y && ledsX[i][0] <= y && ledsX[iCW][0] <= y) + { + leds[i].r = 255; + } + if (ledsX[iCCW][0] <= y && ledsX[i][0] > y && ledsX[iCW][0] > y) + { + leds[i].r = 255; + } + if (ledsX[iCCW][0] <= y && ledsX[i][0] > y && ledsX[iCW][0] <= y) + { + leds[i].r = 255; + } + if (ledsX[iCCW][0] <= y && ledsX[i][0] <= y && ledsX[iCW][0] > y) + { + leds[i].r = 255; + } + if (ledsX[iCCW][0] <= y && ledsX[i][0] <= y && ledsX[iCW][0] <= y) + { + leds[i].r = 0; + } + } + LEDS.show(); + } + if (curEffect == "random_march") + { + // random_march(); + copy_led_array(); + int iCCW; + leds[0] = CHSV(random(0, 255), 255, 255); + for (int idex = 1; idex < LED_COUNT; idex++) + { + iCCW = adjacent_ccw(idex); + leds[idex].r = ledsX[iCCW][0]; + leds[idex].g = ledsX[iCCW][1]; + leds[idex].b = ledsX[iCCW][2]; + } + LEDS.show(); + } + if (curEffect == "rwb_march") + { + // rwb_march(); + copy_led_array(); + int iCCW; + idex++; + if (idex > 2) + { + idex = 0; + } + switch (idex) + { + case 0: + leds[0].r = 255; + leds[0].g = 0; + leds[0].b = 0; + break; + case 1: + leds[0].r = 255; + leds[0].g = 255; + leds[0].b = 255; + break; + case 2: + leds[0].r = 0; + leds[0].g = 0; + leds[0].b = 255; + break; + } + for (int i = 1; i < LED_COUNT; i++) + { + iCCW = adjacent_ccw(i); + leds[i].r = ledsX[iCCW][0]; + leds[i].g = ledsX[iCCW][1]; + leds[i].b = ledsX[iCCW][2]; + } + LEDS.show(); + } + if (curEffect == "radiation") + { + // radiation(); + int N3 = int(LED_COUNT / 3); + int N6 = int(LED_COUNT / 6); + int N12 = int(LED_COUNT / 12); + for (int i = 0; i < N6; i++) + { //-HACKY, I KNOW... + tcount = tcount + .02; + if (tcount > 3.14) + { + tcount = 0.0; + } + ibright = int(sin(tcount) * 255); + int j0 = (i + LED_COUNT - N12) % LED_COUNT; + int j1 = (j0 + N3) % LED_COUNT; + int j2 = (j1 + N3) % LED_COUNT; + leds[j0] = CHSV(thishue, thissat, ibright); + leds[j1] = CHSV(thishue, thissat, ibright); + leds[j2] = CHSV(thishue, thissat, ibright); + } + LEDS.show(); + } + if (curEffect == "color_loop_vardelay") + { + // color_loop_vardelay(); + idex++; + if (idex > LED_COUNT) + { + idex = 0; + } + int di = abs(TOP_INDEX - idex); + int t = constrain((10 / di) * 10, 10, 500); + for (int i = 0; i < LED_COUNT; i++) + { + if (i == idex) + { + leds[i] = CHSV(0, thissat, 255); + } + else + { + leds[i].r = 0; + leds[i].g = 0; + leds[i].b = 0; + } + } + LEDS.show(); + } + if (curEffect == "white_temps") + { + // white_temps(); + int N9 = int(LED_COUNT / 9); + for (int i = 0; i < LED_COUNT; i++) + { + if (i >= 0 && i < N9) + { + leds[i].r = 255; //-CANDLE - 1900 + leds[i].g = 147; + leds[i].b = 41; + } + if (i >= N9 && i < N9 * 2) + { + leds[i].r = 255; //-40W TUNG - 2600 + leds[i].g = 197; + leds[i].b = 143; + } + if (i >= N9 * 2 && i < N9 * 3) + { + leds[i].r = 255; //-100W TUNG - 2850 + leds[i].g = 214; + leds[i].b = 170; + } + if (i >= N9 * 3 && i < N9 * 4) + { + leds[i].r = 255; //-HALOGEN - 3200 + leds[i].g = 241; + leds[i].b = 224; + } + if (i >= N9 * 4 && i < N9 * 5) + { + leds[i].r = 255; //-CARBON ARC - 5200 + leds[i].g = 250; + leds[i].b = 244; + } + if (i >= N9 * 5 && i < N9 * 6) + { + leds[i].r = 255; //-HIGH NOON SUN - 5400 + leds[i].g = 255; + leds[i].b = 251; + } + if (i >= N9 * 6 && i < N9 * 7) + { + leds[i].r = 255; //-DIRECT SUN - 6000 + leds[i].g = 255; + leds[i].b = 255; + } + if (i >= N9 * 7 && i < N9 * 8) + { + leds[i].r = 201; //-OVERCAST SKY - 7000 + leds[i].g = 226; + leds[i].b = 255; + } + if (i >= N9 * 8 && i < LED_COUNT) + { + leds[i].r = 64; //-CLEAR BLUE SKY - 20000 + leds[i].g = 156; + leds[i].b = 255; + } + } + LEDS.show(); + } + if (curEffect == "sin_bright_wave") + { + sin_bright_wave(); + } + if (curEffect == "pop_horizontal") + { + // pop_horizontal(); + int ix; + if (bouncedirection == 0) + { + bouncedirection = 1; + ix = idex; + } + else if (bouncedirection == 1) + { + bouncedirection = 0; + ix = horizontal_index(idex); + idex++; + if (idex > TOP_INDEX) + { + idex = 0; + } + } + for (int i = 0; i < LED_COUNT; i++) + { + if (i == ix) + { + leds[i] = CHSV(thishue, thissat, 255); + } + else + { + leds[i].r = 0; + leds[i].g = 0; + leds[i].b = 0; + } + } + LEDS.show(); + } + if (curEffect == "quad_bright_curve") + { + // quad_bright_curve(); + int ax; + for (int x = 0; x < LED_COUNT; x++) + { + if (x <= TOP_INDEX) + { + ax = x; + } + else if (x > TOP_INDEX) + { + ax = LED_COUNT - x; + } + int a = 1; + int b = 1; + int c = 0; + int iquad = -(ax * ax * a) + (ax * b) + c; //-ax2+bx+c + int hquad = -(TOP_INDEX * TOP_INDEX * a) + (TOP_INDEX * b) + c; + ibright = int((float(iquad) / float(hquad)) * 255); + leds[x] = CHSV(thishue, thissat, ibright); + } + LEDS.show(); + } + if (curEffect == "flame") + { + flame(); + } + if (curEffect == "rainbow_vertical") + { + // rainbow_vertical(); + idex++; + if (idex > TOP_INDEX) + { + idex = 0; + } + ihue = ihue + thisstep; + if (ihue > 255) + { + ihue = 0; + } + int idexA = idex; + int idexB = horizontal_index(idexA); + leds[idexA] = CHSV(ihue, thissat, 255); + leds[idexB] = CHSV(ihue, thissat, 255); + LEDS.show(); + } + if (curEffect == "pacman") + { + // pacman(); + int s = int(LED_COUNT / 4); + lcount++; + if (lcount > 5) + { + lcount = 0; + } + if (lcount == 0) + { + for (int i = 0; i < LED_COUNT; i++) + { + set_color_led(i, 255, 255, 0); + } + } + if (lcount == 1 || lcount == 5) + { + for (int i = 0; i < LED_COUNT; i++) + { + set_color_led(i, 255, 255, 0); + } + leds[s].r = 0; + leds[s].g = 0; + leds[s].b = 0; + } + if (lcount == 2 || lcount == 4) + { + for (int i = 0; i < LED_COUNT; i++) + { + set_color_led(i, 255, 255, 0); + } + leds[s - 1].r = 0; + leds[s - 1].g = 0; + leds[s - 1].b = 0; + leds[s].r = 0; + leds[s].g = 0; + leds[s].b = 0; + leds[s + 1].r = 0; + leds[s + 1].g = 0; + leds[s + 1].b = 0; + } + if (lcount == 3) + { + for (int i = 0; i < LED_COUNT; i++) + { + set_color_led(i, 255, 255, 0); + } + leds[s - 2].r = 0; + leds[s - 2].g = 0; + leds[s - 2].b = 0; + leds[s - 1].r = 0; + leds[s - 1].g = 0; + leds[s - 1].b = 0; + leds[s].r = 0; + leds[s].g = 0; + leds[s].b = 0; + leds[s + 1].r = 0; + leds[s + 1].g = 0; + leds[s + 1].b = 0; + leds[s + 2].r = 0; + leds[s + 2].g = 0; + leds[s + 2].b = 0; + } + LEDS.show(); + } + if (curEffect == "random_color_pop") + { + // random_color_pop(); + idex = random(0, LED_COUNT); + ihue = random(0, 255); + one_color_all(0, 0, 0); + leds[idex] = CHSV(ihue, thissat, 255); + LEDS.show(); + } + if (curEffect == "ems_lightsSTROBE") + { + ems_lightsSTROBE(); + } + if (curEffect == "Strobe") + { + Strobe(R, G, B, 10, 50, _speed); + } + + if (curEffect == "BouncingBalls") + { + BouncingBalls(R, G, B, 3); + } + if (curEffect == "BouncingColoredBalls") + { + byte colors[3][3] = {{0xff, 0, 0}, + {0xff, 0xff, 0xff}, + {0, 0, 0xff}}; + + BouncingColoredBalls(3, colors); + } + + if (curEffect == "rgb_propeller") + { + // rgb_propeller(); + idex++; + int ghue = (thishue + 80) % 255; + int bhue = (thishue + 160) % 255; + int N3 = int(LED_COUNT / 3); + int N6 = int(LED_COUNT / 6); + int N12 = int(LED_COUNT / 12); + for (int i = 0; i < N3; i++) + { + int j0 = (idex + i + LED_COUNT - N12) % LED_COUNT; + int j1 = (j0 + N3) % LED_COUNT; + int j2 = (j1 + N3) % LED_COUNT; + leds[j0] = CHSV(thishue, thissat, 255); + leds[j1] = CHSV(ghue, thissat, 255); + leds[j2] = CHSV(bhue, thissat, 255); + } + LEDS.show(); + } + if (curEffect == "kitt") + { + kitt(); + } + if (curEffect == "matrix") + { + // matrix(); + int rand = random(0, 100); + if (rand > 90) + { + leds[0] = CHSV(thishue, thissat, 255); + } + else + { + leds[0] = CHSV(thishue, thissat, 0); + } + copy_led_array(); + for (int i = 1; i < LED_COUNT; i++) + { + leds[i].r = ledsX[i - 1][0]; + leds[i].g = ledsX[i - 1][1]; + leds[i].b = ledsX[i - 1][2]; + } + LEDS.show(); + } + if (curEffect == "new_rainbow_loop") + { + // new_rainbow_loop(); + ihue -= 1; + fill_rainbow(leds, LED_COUNT, ihue); + LEDS.show(); + } + if (curEffect == "strip_march_ccw") + { + // strip_march_ccw(); + copy_led_array(); + int iCW; + for (int i = 0; i < LED_COUNT; i++) + { + iCW = adjacent_cw(i); + leds[i].r = ledsX[iCW][0]; + leds[i].g = ledsX[iCW][1]; + leds[i].b = ledsX[iCW][2]; + } + LEDS.show(); + } + if (curEffect == "strip_march_cw") + { + // strip_march_cw(); + copy_led_array(); + int iCCW; + for (int i = 0; i < LED_COUNT; i++) + { + iCCW = adjacent_ccw(i); + leds[i].r = ledsX[iCCW][0]; + leds[i].g = ledsX[iCCW][1]; + leds[i].b = ledsX[iCCW][2]; + } + LEDS.show(); + } + if (curEffect == "colorWipe") + { + colorWipe(R, G, B, thisdelay); + } + if (curEffect == "CylonBounce") + { + CylonBounce(R, G, B, 4, 10, thisdelay); + } + if (curEffect == "Fire") + { + // Fire(55, 120, thisdelay); + static byte heat[LED_COUNT]; + int cooldown; + int Cooling = 55, Sparking = 120; + // Step 1. Cool down every cell a little + for (int i = 0; i < LED_COUNT; i++) + { + cooldown = random(0, ((Cooling * 10) / LED_COUNT) + 2); + + if (cooldown > heat[i]) + { + heat[i] = 0; + } + else + { + heat[i] = heat[i] - cooldown; + } + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for (int k = LED_COUNT - 1; k >= 2; k--) + { + heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3; + } + + // Step 3. Randomly ignite new 'sparks' near the bottom + if (random(255) < Sparking) + { + int y = random(7); + heat[y] = heat[y] + random(160, 255); + // heat[y] = random(160,255); + } + + // Step 4. Convert heat to LED colors + for (int j = 0; j < LED_COUNT; j++) + { + setPixelHeatColor(j, heat[j]); + } + + FastLED.show(); + } + if (curEffect == "NewKITT") + { + NewKITT(0xff, 0, 0, 8, 10, thisdelay); + } + if (curEffect == "rainbowCycle") + { + rainbowCycle(thisdelay); + } + if (curEffect == "TwinkleRandom") + { + TwinkleRandom(20, thisdelay, 1); + } + if (curEffect == "RunningLights") + { + RunningLights(0xff, 0xff, 0x00, thisdelay); + } + if (curEffect == "Sparkle") + { + Sparkle(random(255), random(255), random(60), _speed); + } + if (curEffect == "SnowSparkle") + { + SnowSparkle(0, 0, 0, 20, random(100, 1000)); + } + if (curEffect == "theaterChase") + { + theaterChase(0xff, 0, 0, _speed); + } + if (curEffect == "theaterChaseRainbow") + { + theaterChaseRainbow(_speed); + } + + if (curEffect == "demo_modeA") + { + demo_modeA(); + } + if (curEffect == "demo_modeB") + { + demo_modeB(); + } + if (curEffect == "meteorRain") + { + meteorRain(R, G, B, 10, 64, true, _speed); + } + + // матрицы + // *********** "дыхание" яркостью *********** + if (curEffect == "brightnessRoutine") + { + brightnessRoutine(); + } + // *********** снегопад 2.0 *********** + if (curEffect == "snowRoutine") + { + snowRoutine(); + } + // ***************************** БЛУДНЫЙ КУБИК ***************************** + if (curEffect == "ballRoutine") + { + ballRoutine(); + } + // *********** радуга заливка *********** + if (curEffect == "rainbowRoutine") + { + rainbowRoutine(); + } + // *********** радуга дигональная *********** + if (curEffect == "rainbowDiagonalRoutine") + { + rainbowDiagonalRoutine(); + } + // *********** радуга активных светодиодов (рисунка) *********** + if (curEffect == "rainbowColorsRoutine") + { + rainbowColorsRoutine(); + } + // ********************** огонь ********************** + if (curEffect == "fireRoutine") + { + fireRoutine(); + } + // **************** МАТРИЦА ***************** + if (curEffect == "matrixRoutine") + { + matrixRoutine(); + } + // ********************* ЗВЕЗДОПАД ****************** + if (curEffect == "starfallRoutine") + { + starfallRoutine(); + } + // рандомные гаснущие вспышки + if (curEffect == "sparklesRoutine") + { + sparklesRoutine(); + } + // ----------------------------- СВЕТЛЯКИ ------------------------------ + if (curEffect == "lightersRoutine") + { + lightersRoutine(); + } + // ------------- ПЕЙНТБОЛ ------------- + if (curEffect == "lightBallsRoutine") + { + lightBallsRoutine(); + } + // ------------- ВОДОВОРОТ ------------- + if (curEffect == "swirlRoutine") + { + swirlRoutine(); + } + // ------------- крутящаяся радуга матрица ------------- + if (curEffect == "rainbow_loop_matrix") + { + idex++; + ihue = ihue + thisstep; + if (idex >= LED_COUNT) + { + idex = 0; + } + if (ihue > 255) + { + ihue = 0; + } + + for (byte i = 0; i < WIDTH; i++) + { + CHSV thisColor = CHSV(ihue, thissat, 255); + for (byte j = 0; j < HEIGHT; j++) + drawPixelXY(i, j, thisColor); // leds[getPixelNumber(i, j)] = thisColor; + } + } + + FastLED.show(); + } + } + + IoTValue + execute(String command, std::vector ¶m) + { + + if (command == "effect") + { + curEffect = "none"; + + ///////////////////////////////////// + if (param[0].valS == "rainbow_fade") + { + curEffect = "rainbow_fade"; + } + if (param[0].valS == "rainbow_loop") + { + curEffect = "rainbow_loop"; + } + if (param[0].valS == "random_burst") + { + curEffect = "random_burst"; + } + if (param[0].valS == "color_bounce") + { + curEffect = "color_bounce"; + } + if (param[0].valS == "color_bounceFADE") + { + curEffect = "color_bounceFADE"; + } + if (param[0].valS == "ems_lightsONE") + { + curEffect = "ems_lightsONE"; + } + if (param[0].valS == "ems_lightsALL") + { + curEffect = "ems_lightsALL"; + } + if (param[0].valS == "pulse_one_color_all") + { + curEffect = "pulse_one_color_all"; + } + if (param[0].valS == "pulse_one_color_all_rev") + { + curEffect = "pulse_one_color_all_rev"; + } + if (param[0].valS == "fade_vertical") + { + curEffect = "fade_vertical"; + } + if (param[0].valS == "rule30") + { + curEffect = "rule30"; + } + if (param[0].valS == "random_march") + { + curEffect = "random_march"; + } + if (param[0].valS == "rwb_march") + { + curEffect = "rwb_march"; + } + if (param[0].valS == "radiation") + { + curEffect = "radiation"; + } + if (param[0].valS == "color_loop_vardelay") + { + curEffect = "color_loop_vardelay"; + } + if (param[0].valS == "white_temps") + { + curEffect = "white_temps"; + } + if (param[0].valS == "sin_bright_wave") + { + curEffect = "sin_bright_wave"; + } + if (param[0].valS == "pop_horizontal") + { + curEffect = "pop_horizontal"; + } + if (param[0].valS == "quad_bright_curve") + { + curEffect = "quad_bright_curve"; + } + if (param[0].valS == "flame") + { + curEffect = "flame"; + } + if (param[0].valS == "rainbow_vertical") + { + curEffect = "rainbow_vertical"; + } + if (param[0].valS == "pacman") + { + curEffect = "pacman"; + } + if (param[0].valS == "random_color_pop") + { + curEffect = "random_color_pop"; + } + if (param[0].valS == "ems_lightsSTROBE") + { + curEffect = "ems_lightsSTROBE"; + } + if (param[0].valS == "rgb_propeller") + { + curEffect = "rgb_propeller"; + } + if (param[0].valS == "kitt") + { + curEffect = "kitt"; + } + if (param[0].valS == "matrix") + { + curEffect = "matrix"; + } + if (param[0].valS == "new_rainbow_loop") + { + curEffect = "new_rainbow_loop"; + } + if (param[0].valS == "strip_march_ccw") + { + curEffect = "strip_march_ccw"; + } + if (param[0].valS == "strip_march_cw") + { + curEffect = "strip_march_cw"; + } + if (param[0].valS == "colorWipe") + { + curEffect = "colorWipe"; + } + if (param[0].valS == "CylonBounce") + { + curEffect = "CylonBounce"; + } + if (param[0].valS == "Fire") + { + curEffect = "Fire"; + } + if (param[0].valS == "NewKITT") + { + curEffect = "NewKITT"; + } + if (param[0].valS == "rainbowCycle") + { + curEffect = "rainbowCycle"; + } + if (param[0].valS == "TwinkleRandom") + { + curEffect = "TwinkleRandom"; + } + if (param[0].valS == "RunningLights") + { + curEffect = "RunningLights"; + } + if (param[0].valS == "Sparkle") + { + curEffect = "Sparkle"; + } + if (param[0].valS == "SnowSparkle") + { + curEffect = "SnowSparkle"; + } + if (param[0].valS == "theaterChase") + { + curEffect = "theaterChase"; + } + if (param[0].valS == "theaterChaseRainbow") + { + curEffect = "theaterChaseRainbow"; + } + if (param[0].valS == "Strobe") + { + curEffect = "Strobe"; + } + if (param[0].valS == "BouncingBalls") + { + curEffect = "BouncingBalls"; + } + if (param[0].valS == "BouncingColoredBalls") + { + curEffect = "BouncingColoredBalls"; + } + if (param[0].valS == "demo_modeA") + { + curEffect = "demo_modeA"; + } + if (param[0].valS == "demo_modeB") + { + curEffect = "demo_modeB"; + } + if (param[0].valS == "meteorRain") + { + curEffect = "meteorRain"; + } + + // матрицы + + // *********** "дыхание" яркостью *********** + if (param[0].valS == "brightnessRoutine") + { + curEffect = "brightnessRoutine"; + } + // *********** снегопад 2.0 *********** + if (param[0].valS == "snowRoutine") + { + curEffect = "snowRoutine"; + } + // ***************************** БЛУДНЫЙ КУБИК ***************************** + if (param[0].valS == "ballRoutine") + { + curEffect = "ballRoutine"; + } + // *********** радуга заливка *********** + if (param[0].valS == "rainbowRoutine") + { + curEffect = "rainbowRoutine"; + } + // *********** радуга дигональная *********** + if (param[0].valS == "rainbowDiagonalRoutine") + { + curEffect = "rainbowDiagonalRoutine"; + } + // *********** радуга активных светодиодов (рисунка) *********** + if (param[0].valS == "rainbowColorsRoutine") + { + curEffect = "rainbowColorsRoutine"; + } + // ********************** огонь ********************** + if (param[0].valS == "fireRoutine") + { + curEffect = "fireRoutine"; + } + // **************** МАТРИЦА ***************** + if (param[0].valS == "matrixRoutine") + { + curEffect = "matrixRoutine"; + } + // ********************* ЗВЕЗДОПАД ****************** + if (param[0].valS == "starfallRoutine") + { + curEffect = "starfallRoutine"; + } + // рандомные гаснущие вспышки + if (param[0].valS == "sparklesRoutine") + { + curEffect = "sparklesRoutine"; + } + // ----------------------------- СВЕТЛЯКИ ------------------------------ + if (param[0].valS == "lightersRoutine") + { + curEffect = "lightersRoutine"; + } + // ------------- ПЕЙНТБОЛ ------------- + if (param[0].valS == "lightBallsRoutine") + { + curEffect = "lightBallsRoutine"; + } + // ------------- ВОДОВОРОТ ------------- + if (param[0].valS == "swirlRoutine") + { + curEffect = "swirlRoutine"; + } + // ------------- крутящаяся радуга матрица ------------- + if (param[0].valS == "rainbow_loop_matrix") + { + curEffect = "rainbow_loop_matrix"; + } + + /////////////////////////////////////////////////// + } + else if (command == "brightness") + { + _brightness = param[0].valD; + LEDS.setBrightness(_brightness); + LEDS.show(); + } + else if (command == "speed") + { + _speed = param[0].valD; + } + else if (command == "dalay") + { + _dalay = param[0].valD; + } + else if (command == "color") + { + R = param[0].valD; + G = param[1].valD; + B = param[2].valD; + setAll(R, G, B); + LEDS.show(); + } + else if (command == "Off") + { + curEffect = "none"; + setAll(0, 0, 0); + LEDS.show(); + } + else if (command == "On") + { + curEffect = "none"; + + if (param.size() == 3) + { + R = param[0].valD; + G = param[1].valD; + B = param[2].valD; + setAll(R, G, B); + } + else + { + setAll(R, G, B); + } + LEDS.show(); + } + + return {}; + } + void setValue(const IoTValue &Value, bool genEvent = true) + { + value = Value; + _brightness = map(value.valD, 1, 1024, 1, 100); + LEDS.setBrightness(_brightness); + regEvent(value.valD, "GyverLAMP", false, genEvent); + // setAll(R, G, B); + LEDS.show(); + } + ~GyverLAMP(){}; +}; + +void *getAPI_GyverLAMP(String subtype, String param) +{ + if (subtype == F("GyverLAMP")) + { + return new GyverLAMP(param); + } + else + { + return nullptr; + } +} diff --git a/src/modules/display/GyverLAMP/config.h b/src/modules/display/GyverLAMP/config.h new file mode 100644 index 00000000..5fa713c4 --- /dev/null +++ b/src/modules/display/GyverLAMP/config.h @@ -0,0 +1,9 @@ + +// матрица +#define WIDTH 16 // ширина матрицы +#define HEIGHT 16 // высота матрицы +#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) +#define NUM_LEDS WIDTH *HEIGHT *SEGMENTS +// лента +#define LED_COUNT NUM_LEDS // число светодиодов в кольце/ленте +#define LED_DT 13 // пин, куда подключен DIN ленты \ No newline at end of file diff --git a/src/modules/display/GyverLAMP/effects.h b/src/modules/display/GyverLAMP/effects.h new file mode 100644 index 00000000..811f2b71 --- /dev/null +++ b/src/modules/display/GyverLAMP/effects.h @@ -0,0 +1,1833 @@ +#include "config.h" +CRGB leds[NUM_LEDS]; +// ---------------СЛУЖЕБНЫЕ ПЕРЕМЕННЫЕ----------------- +int _brightness; +int _speed, _dalay; +// int _x_size, _y_size; +int R = 255, G = 255, B = 255; +int BOTTOM_INDEX = 0; // светодиод начала отсчёта +int TOP_INDEX = int(LED_COUNT / 2); +int EVENODD = LED_COUNT % 2; +int ledsX[LED_COUNT][3]; //-ARRAY FOR COPYING WHATS IN THE LED STRIP CURRENTLY (FOR CELL-AUTOMATA, MARCH, ETC) + +int thisdelay = 20; //-FX LOOPS DELAY VAR +int thisstep = 10; //-FX LOOPS DELAY VAR +int thishue = 0; //-FX LOOPS DELAY VAR +int thissat = 255; //-FX LOOPS DELAY VAR + +int thisindex = 0; +int thisRED = 0; +int thisGRN = 0; +int thisBLU = 0; + +int idex = 0; //-LED INDEX (0 to LED_COUNT-1 +int ihue = 0; //-HUE (0-255) +int ibright = 0; //-BRIGHTNESS (0-255) +int isat = 0; //-SATURATION (0-255) +int bouncedirection = 0; //-SWITCH FOR COLOR BOUNCE (0-1) +float tcount = 0.0; //-INC VAR FOR SIN LOOPS +int lcount = 0; //-ANOTHER COUNTING VAR + +volatile boolean changeFlag; +// цвета мячиков для режима +byte ballColors[3][3] = { + {0xff, 0, 0}, + {0xff, 0xff, 0xff}, + {0, 0, 0xff}}; + +//------------------------------------- UTILITY FXNS -------------------------------------- +//---SET THE COLOR OF A SINGLE RGB LED +void set_color_led(int adex, int cred, int cgrn, int cblu) +{ + leds[adex].setRGB(cred, cgrn, cblu); +} + +//---FIND INDEX OF HORIZONAL OPPOSITE LED +int horizontal_index(int i) +{ + //-ONLY WORKS WITH INDEX < TOPINDEX + if (i == BOTTOM_INDEX) + { + return BOTTOM_INDEX; + } + if (i == TOP_INDEX && EVENODD == 1) + { + return TOP_INDEX + 1; + } + if (i == TOP_INDEX && EVENODD == 0) + { + return TOP_INDEX; + } + return LED_COUNT - i; +} + +//---FIND INDEX OF ANTIPODAL OPPOSITE LED +int antipodal_index(int i) +{ + int iN = i + TOP_INDEX; + if (i >= TOP_INDEX) + { + iN = (i + TOP_INDEX) % LED_COUNT; + } + return iN; +} + +//---FIND ADJACENT INDEX CLOCKWISE +int adjacent_cw(int i) +{ + int r; + if (i < LED_COUNT - 1) + { + r = i + 1; + } + else + { + r = 0; + } + return r; +} + +//---FIND ADJACENT INDEX COUNTER-CLOCKWISE +int adjacent_ccw(int i) +{ + int r; + if (i > 0) + { + r = i - 1; + } + else + { + r = LED_COUNT - 1; + } + return r; +} + +void copy_led_array() +{ + for (int i = 0; i < LED_COUNT; i++) + { + ledsX[i][0] = leds[i].r; + ledsX[i][1] = leds[i].g; + ledsX[i][2] = leds[i].b; + } +} + +void setPixel(int Pixel, byte red, byte green, byte blue) +{ + leds[Pixel].r = red; + leds[Pixel].g = green; + leds[Pixel].b = blue; +} +void one_color_all(int cred, int cgrn, int cblu) +{ //-SET ALL LEDS TO ONE COLOR + for (int i = 0; i < LED_COUNT; i++) + { + leds[i].setRGB(cred, cgrn, cblu); + } +} +void setAll(byte red, byte green, byte blue) +{ + + for (int i = 0; i < LED_COUNT; i++) + { + setPixel(i, red, green, blue); + } + + FastLED.show(); +} + +boolean safeDelay(int delTime) +{ + uint32_t thisTime = millis(); + while (millis() - thisTime <= delTime) + { + if (changeFlag) + { + changeFlag = false; + return true; + } + } + return false; +} +//------------------------LED EFFECT FUNCTIONS------------------------ + +void one_color_allHSV(int ahue) +{ //-SET ALL LEDS TO ONE COLOR (HSV) + for (int i = 0; i < LED_COUNT; i++) + { + leds[i] = CHSV(ahue, thissat, 255); + } +} + +void rainbow_fade() +{ //-m2-FADE ALL LEDS THROUGH HSV RAINBOW + ihue++; + if (ihue > 255) + { + ihue = 0; + } + for (int idex = 0; idex < LED_COUNT; idex++) + { + leds[idex] = CHSV(ihue, thissat, 255); + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void rainbow_loop() +{ //-m3-LOOP HSV RAINBOW + idex++; + ihue = ihue + thisstep; + if (idex >= LED_COUNT) + { + idex = 0; + } + if (ihue > 255) + { + ihue = 0; + } + leds[idex] = CHSV(ihue, thissat, 255); + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void random_burst() +{ //-m4-RANDOM INDEX/COLOR + idex = random(0, LED_COUNT); + ihue = random(0, 255); + leds[idex] = CHSV(ihue, thissat, 255); + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void color_bounce() +{ //-m5-BOUNCE COLOR (SINGLE LED) + if (bouncedirection == 0) + { + idex = idex + 1; + if (idex == LED_COUNT) + { + bouncedirection = 1; + idex = idex - 1; + } + } + if (bouncedirection == 1) + { + idex = idex - 1; + if (idex == 0) + { + bouncedirection = 0; + } + } + for (int i = 0; i < LED_COUNT; i++) + { + if (i == idex) + { + leds[i] = CHSV(thishue, thissat, 255); + } + else + { + leds[i] = CHSV(0, 0, 0); + } + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void color_bounceFADE() +{ //-m6-BOUNCE COLOR (SIMPLE MULTI-LED FADE) + if (bouncedirection == 0) + { + idex = idex + 1; + if (idex == LED_COUNT) + { + bouncedirection = 1; + idex = idex - 1; + } + } + if (bouncedirection == 1) + { + idex = idex - 1; + if (idex == 0) + { + bouncedirection = 0; + } + } + int iL1 = adjacent_cw(idex); + int iL2 = adjacent_cw(iL1); + int iL3 = adjacent_cw(iL2); + int iR1 = adjacent_ccw(idex); + int iR2 = adjacent_ccw(iR1); + int iR3 = adjacent_ccw(iR2); + for (int i = 0; i < LED_COUNT; i++) + { + if (i == idex) + { + leds[i] = CHSV(thishue, thissat, 255); + } + else if (i == iL1) + { + leds[i] = CHSV(thishue, thissat, 150); + } + else if (i == iL2) + { + leds[i] = CHSV(thishue, thissat, 80); + } + else if (i == iL3) + { + leds[i] = CHSV(thishue, thissat, 20); + } + else if (i == iR1) + { + leds[i] = CHSV(thishue, thissat, 150); + } + else if (i == iR2) + { + leds[i] = CHSV(thishue, thissat, 80); + } + else if (i == iR3) + { + leds[i] = CHSV(thishue, thissat, 20); + } + else + { + leds[i] = CHSV(0, 0, 0); + } + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void ems_lightsONE() +{ //-m7-EMERGENCY LIGHTS (TWO COLOR SINGLE LED) + idex++; + if (idex >= LED_COUNT) + { + idex = 0; + } + int idexR = idex; + int idexB = antipodal_index(idexR); + int thathue = (thishue + 160) % 255; + for (int i = 0; i < LED_COUNT; i++) + { + if (i == idexR) + { + leds[i] = CHSV(thishue, thissat, 255); + } + else if (i == idexB) + { + leds[i] = CHSV(thathue, thissat, 255); + } + else + { + leds[i] = CHSV(0, 0, 0); + } + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void ems_lightsALL() +{ //-m8-EMERGENCY LIGHTS (TWO COLOR SOLID) + idex++; + if (idex >= LED_COUNT) + { + idex = 0; + } + int idexR = idex; + int idexB = antipodal_index(idexR); + int thathue = (thishue + 160) % 255; + leds[idexR] = CHSV(thishue, thissat, 255); + leds[idexB] = CHSV(thathue, thissat, 255); + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void flicker() +{ //-m9-FLICKER EFFECT + int random_bright = random(0, 255); + int random_delay = random(10, 100); + int random_bool = random(0, random_bright); + if (random_bool < 10) + { + for (int i = 0; i < LED_COUNT; i++) + { + leds[i] = CHSV(thishue, thissat, random_bright); + } + LEDS.show(); + if (safeDelay(random_delay)) + return; + } +} + +void pulse_one_color_all() +{ //-m10-PULSE BRIGHTNESS ON ALL LEDS TO ONE COLOR + if (bouncedirection == 0) + { + ibright++; + if (ibright >= 255) + { + bouncedirection = 1; + } + } + if (bouncedirection == 1) + { + ibright = ibright - 1; + if (ibright <= 1) + { + bouncedirection = 0; + } + } + for (int idex = 0; idex < LED_COUNT; idex++) + { + leds[idex] = CHSV(thishue, thissat, ibright); + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void pulse_one_color_all_rev() +{ //-m11-PULSE SATURATION ON ALL LEDS TO ONE COLOR + if (bouncedirection == 0) + { + isat++; + if (isat >= 255) + { + bouncedirection = 1; + } + } + if (bouncedirection == 1) + { + isat = isat - 1; + if (isat <= 1) + { + bouncedirection = 0; + } + } + for (int idex = 0; idex < LED_COUNT; idex++) + { + leds[idex] = CHSV(thishue, isat, 255); + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void fade_vertical() +{ //-m12-FADE 'UP' THE LOOP + idex++; + if (idex > TOP_INDEX) + { + idex = 0; + } + int idexA = idex; + int idexB = horizontal_index(idexA); + ibright = ibright + 10; + if (ibright > 255) + { + ibright = 0; + } + leds[idexA] = CHSV(thishue, thissat, ibright); + leds[idexB] = CHSV(thishue, thissat, ibright); + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} +//? +void random_red() +{ // QUICK 'N DIRTY RANDOMIZE TO GET CELL AUTOMATA STARTED + int temprand; + for (int i = 0; i < LED_COUNT; i++) + { + temprand = random(0, 100); + if (temprand > 50) + { + leds[i].r = 255; + } + if (temprand <= 50) + { + leds[i].r = 0; + } + leds[i].b = 0; + leds[i].g = 0; + } + LEDS.show(); +} + +void rule30() +{ //-m13-1D CELLULAR AUTOMATA - RULE 30 (RED FOR NOW) + if (bouncedirection == 0) + { + random_red(); + bouncedirection = 1; + } + copy_led_array(); + int iCW; + int iCCW; + int y = 100; + for (int i = 0; i < LED_COUNT; i++) + { + iCW = adjacent_cw(i); + iCCW = adjacent_ccw(i); + if (ledsX[iCCW][0] > y && ledsX[i][0] > y && ledsX[iCW][0] > y) + { + leds[i].r = 0; + } + if (ledsX[iCCW][0] > y && ledsX[i][0] > y && ledsX[iCW][0] <= y) + { + leds[i].r = 0; + } + if (ledsX[iCCW][0] > y && ledsX[i][0] <= y && ledsX[iCW][0] > y) + { + leds[i].r = 0; + } + if (ledsX[iCCW][0] > y && ledsX[i][0] <= y && ledsX[iCW][0] <= y) + { + leds[i].r = 255; + } + if (ledsX[iCCW][0] <= y && ledsX[i][0] > y && ledsX[iCW][0] > y) + { + leds[i].r = 255; + } + if (ledsX[iCCW][0] <= y && ledsX[i][0] > y && ledsX[iCW][0] <= y) + { + leds[i].r = 255; + } + if (ledsX[iCCW][0] <= y && ledsX[i][0] <= y && ledsX[iCW][0] > y) + { + leds[i].r = 255; + } + if (ledsX[iCCW][0] <= y && ledsX[i][0] <= y && ledsX[iCW][0] <= y) + { + leds[i].r = 0; + } + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void random_march() +{ //-m14-RANDOM MARCH CCW + copy_led_array(); + int iCCW; + leds[0] = CHSV(random(0, 255), 255, 255); + for (int idex = 1; idex < LED_COUNT; idex++) + { + iCCW = adjacent_ccw(idex); + leds[idex].r = ledsX[iCCW][0]; + leds[idex].g = ledsX[iCCW][1]; + leds[idex].b = ledsX[iCCW][2]; + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void rwb_march() +{ //-m15-R,W,B MARCH CCW + copy_led_array(); + int iCCW; + idex++; + if (idex > 2) + { + idex = 0; + } + switch (idex) + { + case 0: + leds[0].r = 255; + leds[0].g = 0; + leds[0].b = 0; + break; + case 1: + leds[0].r = 255; + leds[0].g = 255; + leds[0].b = 255; + break; + case 2: + leds[0].r = 0; + leds[0].g = 0; + leds[0].b = 255; + break; + } + for (int i = 1; i < LED_COUNT; i++) + { + iCCW = adjacent_ccw(i); + leds[i].r = ledsX[iCCW][0]; + leds[i].g = ledsX[iCCW][1]; + leds[i].b = ledsX[iCCW][2]; + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void radiation() +{ //-m16-SORT OF RADIATION SYMBOLISH- + int N3 = int(LED_COUNT / 3); + int N6 = int(LED_COUNT / 6); + int N12 = int(LED_COUNT / 12); + for (int i = 0; i < N6; i++) + { //-HACKY, I KNOW... + tcount = tcount + .02; + if (tcount > 3.14) + { + tcount = 0.0; + } + ibright = int(sin(tcount) * 255); + int j0 = (i + LED_COUNT - N12) % LED_COUNT; + int j1 = (j0 + N3) % LED_COUNT; + int j2 = (j1 + N3) % LED_COUNT; + leds[j0] = CHSV(thishue, thissat, ibright); + leds[j1] = CHSV(thishue, thissat, ibright); + leds[j2] = CHSV(thishue, thissat, ibright); + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void color_loop_vardelay() +{ //-m17-COLOR LOOP (SINGLE LED) w/ VARIABLE DELAY + idex++; + if (idex > LED_COUNT) + { + idex = 0; + } + int di = abs(TOP_INDEX - idex); + int t = constrain((10 / di) * 10, 10, 500); + for (int i = 0; i < LED_COUNT; i++) + { + if (i == idex) + { + leds[i] = CHSV(0, thissat, 255); + } + else + { + leds[i].r = 0; + leds[i].g = 0; + leds[i].b = 0; + } + } + LEDS.show(); + if (safeDelay(t)) + return; +} + +void white_temps() +{ //-m18-SHOW A SAMPLE OF BLACK BODY RADIATION COLOR TEMPERATURES + int N9 = int(LED_COUNT / 9); + for (int i = 0; i < LED_COUNT; i++) + { + if (i >= 0 && i < N9) + { + leds[i].r = 255; //-CANDLE - 1900 + leds[i].g = 147; + leds[i].b = 41; + } + if (i >= N9 && i < N9 * 2) + { + leds[i].r = 255; //-40W TUNG - 2600 + leds[i].g = 197; + leds[i].b = 143; + } + if (i >= N9 * 2 && i < N9 * 3) + { + leds[i].r = 255; //-100W TUNG - 2850 + leds[i].g = 214; + leds[i].b = 170; + } + if (i >= N9 * 3 && i < N9 * 4) + { + leds[i].r = 255; //-HALOGEN - 3200 + leds[i].g = 241; + leds[i].b = 224; + } + if (i >= N9 * 4 && i < N9 * 5) + { + leds[i].r = 255; //-CARBON ARC - 5200 + leds[i].g = 250; + leds[i].b = 244; + } + if (i >= N9 * 5 && i < N9 * 6) + { + leds[i].r = 255; //-HIGH NOON SUN - 5400 + leds[i].g = 255; + leds[i].b = 251; + } + if (i >= N9 * 6 && i < N9 * 7) + { + leds[i].r = 255; //-DIRECT SUN - 6000 + leds[i].g = 255; + leds[i].b = 255; + } + if (i >= N9 * 7 && i < N9 * 8) + { + leds[i].r = 201; //-OVERCAST SKY - 7000 + leds[i].g = 226; + leds[i].b = 255; + } + if (i >= N9 * 8 && i < LED_COUNT) + { + leds[i].r = 64; //-CLEAR BLUE SKY - 20000 + leds[i].g = 156; + leds[i].b = 255; + } + } + LEDS.show(); + delay(100); +} +//?? +void sin_bright_wave() +{ //-m19-BRIGHTNESS SINE WAVE + for (int i = 0; i < LED_COUNT; i++) + { + tcount = tcount + .1; + if (tcount > 3.14) + { + tcount = 0.0; + } + ibright = int(sin(tcount) * 255); + leds[i] = CHSV(thishue, thissat, ibright); + LEDS.show(); + if (safeDelay(thisdelay)) + return; + } +} + +void pop_horizontal() +{ //-m20-POP FROM LEFT TO RIGHT UP THE RING + int ix; + if (bouncedirection == 0) + { + bouncedirection = 1; + ix = idex; + } + else if (bouncedirection == 1) + { + bouncedirection = 0; + ix = horizontal_index(idex); + idex++; + if (idex > TOP_INDEX) + { + idex = 0; + } + } + for (int i = 0; i < LED_COUNT; i++) + { + if (i == ix) + { + leds[i] = CHSV(thishue, thissat, 255); + } + else + { + leds[i].r = 0; + leds[i].g = 0; + leds[i].b = 0; + } + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void quad_bright_curve() +{ //-m21-QUADRATIC BRIGHTNESS CURVER + int ax; + for (int x = 0; x < LED_COUNT; x++) + { + if (x <= TOP_INDEX) + { + ax = x; + } + else if (x > TOP_INDEX) + { + ax = LED_COUNT - x; + } + int a = 1; + int b = 1; + int c = 0; + int iquad = -(ax * ax * a) + (ax * b) + c; //-ax2+bx+c + int hquad = -(TOP_INDEX * TOP_INDEX * a) + (TOP_INDEX * b) + c; + ibright = int((float(iquad) / float(hquad)) * 255); + leds[x] = CHSV(thishue, thissat, ibright); + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} +//?? +void flame() +{ //-m22-FLAMEISH EFFECT + int idelay = random(0, 35); + float hmin = 0.1; + float hmax = 45.0; + float hdif = hmax - hmin; + int randtemp = random(0, 3); + float hinc = (hdif / float(TOP_INDEX)) + randtemp; + int ihue = hmin; + for (int i = 0; i <= TOP_INDEX; i++) + { + ihue = ihue + hinc; + leds[i] = CHSV(ihue, thissat, 255); + int ih = horizontal_index(i); + leds[ih] = CHSV(ihue, thissat, 255); + leds[TOP_INDEX].r = 255; + leds[TOP_INDEX].g = 255; + leds[TOP_INDEX].b = 255; + LEDS.show(); + if (safeDelay(idelay)) + return; + } +} + +void rainbow_vertical() +{ //-m23-RAINBOW 'UP' THE LOOP + idex++; + if (idex > TOP_INDEX) + { + idex = 0; + } + ihue = ihue + thisstep; + if (ihue > 255) + { + ihue = 0; + } + int idexA = idex; + int idexB = horizontal_index(idexA); + leds[idexA] = CHSV(ihue, thissat, 255); + leds[idexB] = CHSV(ihue, thissat, 255); + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void pacman() +{ //-m24-REALLY TERRIBLE PACMAN CHOMPING EFFECT + int s = int(LED_COUNT / 4); + lcount++; + if (lcount > 5) + { + lcount = 0; + } + if (lcount == 0) + { + for (int i = 0; i < LED_COUNT; i++) + { + set_color_led(i, 255, 255, 0); + } + } + if (lcount == 1 || lcount == 5) + { + for (int i = 0; i < LED_COUNT; i++) + { + set_color_led(i, 255, 255, 0); + } + leds[s].r = 0; + leds[s].g = 0; + leds[s].b = 0; + } + if (lcount == 2 || lcount == 4) + { + for (int i = 0; i < LED_COUNT; i++) + { + set_color_led(i, 255, 255, 0); + } + leds[s - 1].r = 0; + leds[s - 1].g = 0; + leds[s - 1].b = 0; + leds[s].r = 0; + leds[s].g = 0; + leds[s].b = 0; + leds[s + 1].r = 0; + leds[s + 1].g = 0; + leds[s + 1].b = 0; + } + if (lcount == 3) + { + for (int i = 0; i < LED_COUNT; i++) + { + set_color_led(i, 255, 255, 0); + } + leds[s - 2].r = 0; + leds[s - 2].g = 0; + leds[s - 2].b = 0; + leds[s - 1].r = 0; + leds[s - 1].g = 0; + leds[s - 1].b = 0; + leds[s].r = 0; + leds[s].g = 0; + leds[s].b = 0; + leds[s + 1].r = 0; + leds[s + 1].g = 0; + leds[s + 1].b = 0; + leds[s + 2].r = 0; + leds[s + 2].g = 0; + leds[s + 2].b = 0; + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void random_color_pop() +{ //-m25-RANDOM COLOR POP + idex = random(0, LED_COUNT); + ihue = random(0, 255); + one_color_all(0, 0, 0); + leds[idex] = CHSV(ihue, thissat, 255); + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} +//?? +void ems_lightsSTROBE() +{ //-m26-EMERGENCY LIGHTS (STROBE LEFT/RIGHT) + int thishue = 0; + int thathue = (thishue + 160) % 255; + for (int x = 0; x < 5; x++) + { + for (int i = 0; i < TOP_INDEX; i++) + { + leds[i] = CHSV(thishue, thissat, 255); + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; + one_color_all(0, 0, 0); + LEDS.show(); + if (safeDelay(thisdelay)) + return; + } + for (int x = 0; x < 5; x++) + { + for (int i = TOP_INDEX; i < LED_COUNT; i++) + { + leds[i] = CHSV(thathue, thissat, 255); + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; + one_color_all(0, 0, 0); + LEDS.show(); + if (safeDelay(thisdelay)) + return; + } +} + +void rgb_propeller() +{ //-m27-RGB PROPELLER + idex++; + int ghue = (thishue + 80) % 255; + int bhue = (thishue + 160) % 255; + int N3 = int(LED_COUNT / 3); + int N6 = int(LED_COUNT / 6); + int N12 = int(LED_COUNT / 12); + for (int i = 0; i < N3; i++) + { + int j0 = (idex + i + LED_COUNT - N12) % LED_COUNT; + int j1 = (j0 + N3) % LED_COUNT; + int j2 = (j1 + N3) % LED_COUNT; + leds[j0] = CHSV(thishue, thissat, 255); + leds[j1] = CHSV(ghue, thissat, 255); + leds[j2] = CHSV(bhue, thissat, 255); + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} +//?? +void kitt() +{ //-m28-KNIGHT INDUSTIES 2000 + int rand = random(0, TOP_INDEX); + for (int i = 0; i < rand; i++) + { + leds[TOP_INDEX + i] = CHSV(thishue, thissat, 255); + leds[TOP_INDEX - i] = CHSV(thishue, thissat, 255); + LEDS.show(); + if (safeDelay(thisdelay / rand)) + return; + } + for (int i = rand; i > 0; i--) + { + leds[TOP_INDEX + i] = CHSV(thishue, thissat, 0); + leds[TOP_INDEX - i] = CHSV(thishue, thissat, 0); + LEDS.show(); + if (safeDelay(thisdelay / rand)) + return; + } +} + +void matrix() +{ //-m29-ONE LINE MATRIX + int rand = random(0, 100); + if (rand > 90) + { + leds[0] = CHSV(thishue, thissat, 255); + } + else + { + leds[0] = CHSV(thishue, thissat, 0); + } + copy_led_array(); + for (int i = 1; i < LED_COUNT; i++) + { + leds[i].r = ledsX[i - 1][0]; + leds[i].g = ledsX[i - 1][1]; + leds[i].b = ledsX[i - 1][2]; + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void strip_march_cw() +{ //-m50-MARCH STRIP CW + copy_led_array(); + int iCW; + for (int i = 0; i < LED_COUNT; i++) + { + iCW = adjacent_cw(i); + leds[i].r = ledsX[iCW][0]; + leds[i].g = ledsX[iCW][1]; + leds[i].b = ledsX[iCW][2]; + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void strip_march_ccw() +{ //-m51-MARCH STRIP CCW + copy_led_array(); + int iCCW; + for (int i = 0; i < LED_COUNT; i++) + { + iCCW = adjacent_ccw(i); + leds[i].r = ledsX[iCCW][0]; + leds[i].g = ledsX[iCCW][1]; + leds[i].b = ledsX[iCCW][2]; + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void new_rainbow_loop() +{ //-m88-RAINBOW FADE FROM FAST_SPI2 + ihue -= 1; + fill_rainbow(leds, LED_COUNT, ihue); + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} + +void demo_modeB() +{ + int r = 10; + one_color_all(0, 0, 0); + LEDS.show(); + thisdelay = 35; + for (int i = 0; i < r * 10; i++) + { + random_color_pop(); + } + for (int i = 0; i < r / 2; i++) + { + ems_lightsSTROBE(); + } + thisdelay = 50; + for (int i = 0; i < r * 10; i++) + { + rgb_propeller(); + } + one_color_all(0, 0, 0); + LEDS.show(); + thisdelay = 100; + thishue = 0; + for (int i = 0; i < r * 3; i++) + { + kitt(); + } + one_color_all(0, 0, 0); + LEDS.show(); + thisdelay = 30; + thishue = 95; + for (int i = 0; i < r * 25; i++) + { + matrix(); + } + one_color_all(0, 0, 0); + LEDS.show(); +} +void demo_modeA() +{ + int r = 10; + thisdelay = 20; + thisstep = 10; + thishue = 0; + thissat = 255; + one_color_all(255, 255, 255); + LEDS.show(); + if (safeDelay(1200)) + return; + for (int i = 0; i < r * 25; i++) + { + rainbow_fade(); + } + for (int i = 0; i < r * 20; i++) + { + rainbow_loop(); + } + for (int i = 0; i < r * 20; i++) + { + random_burst(); + } + for (int i = 0; i < r * 12; i++) + { + color_bounce(); + } + thisdelay = 40; + for (int i = 0; i < r * 12; i++) + { + color_bounceFADE(); + } + for (int i = 0; i < r * 6; i++) + { + ems_lightsONE(); + } + for (int i = 0; i < r * 5; i++) + { + ems_lightsALL(); + } + thishue = 160; + thissat = 50; + for (int i = 0; i < r * 40; i++) + { + flicker(); + } + one_color_all(0, 0, 0); + LEDS.show(); + thisdelay = 15; + thishue = 0; + thissat = 255; + for (int i = 0; i < r * 50; i++) + { + pulse_one_color_all(); + } + for (int i = 0; i < r * 40; i++) + { + pulse_one_color_all_rev(); + } + thisdelay = 60; + thishue = 180; + for (int i = 0; i < r * 5; i++) + { + fade_vertical(); + } + random_red(); + thisdelay = 100; + for (int i = 0; i < r * 5; i++) + { + rule30(); + } + thisdelay = 40; + for (int i = 0; i < r * 8; i++) + { + random_march(); + } + thisdelay = 80; + for (int i = 0; i < r * 5; i++) + { + rwb_march(); + } + one_color_all(0, 0, 0); + ; + LEDS.show(); + thisdelay = 60; + thishue = 95; + for (int i = 0; i < r * 15; i++) + { + radiation(); + } + for (int i = 0; i < r * 15; i++) + { + color_loop_vardelay(); + } + for (int i = 0; i < r * 5; i++) + { + white_temps(); + } + thisdelay = 35; + thishue = 180; + for (int i = 0; i < r; i++) + { + sin_bright_wave(); + } + thisdelay = 100; + thishue = 0; + for (int i = 0; i < r * 5; i++) + { + pop_horizontal(); + } + thisdelay = 100; + thishue = 180; + for (int i = 0; i < r * 4; i++) + { + quad_bright_curve(); + } + one_color_all(0, 0, 0); + LEDS.show(); + for (int i = 0; i < r * 3; i++) + { + flame(); + } + thisdelay = 50; + for (int i = 0; i < r * 10; i++) + { + pacman(); + } + thisdelay = 50; + thisstep = 15; + for (int i = 0; i < r * 12; i++) + { + rainbow_vertical(); + } + thisdelay = 100; + for (int i = 0; i < r * 3; i++) + { + strip_march_ccw(); + } + for (int i = 0; i < r * 3; i++) + { + strip_march_cw(); + } + demo_modeB(); + thisdelay = 5; + for (int i = 0; i < r * 120; i++) + { + new_rainbow_loop(); + } + one_color_all(255, 0, 0); + LEDS.show(); + if (safeDelay(1200)) + return; + one_color_all(0, 255, 0); + LEDS.show(); + if (safeDelay(1200)) + return; + one_color_all(0, 0, 255); + LEDS.show(); + if (safeDelay(1200)) + return; + one_color_all(255, 255, 0); + LEDS.show(); + if (safeDelay(1200)) + return; + one_color_all(0, 255, 255); + LEDS.show(); + if (safeDelay(1200)) + return; + one_color_all(255, 0, 255); + LEDS.show(); + if (safeDelay(1200)) + return; +} +//?? +//-----------------------------плавное заполнение цветом----------------------------------------- +void colorWipe(byte red, byte green, byte blue, int SpeedDelay) +{ + for (uint16_t i = 0; i < LED_COUNT; i++) + { + setPixel(i, red, green, blue); + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } +} +//?? +//-----------------------------------бегающие светодиоды----------------------------------- +void CylonBounce(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) +{ + + for (int i = 0; i < LED_COUNT - EyeSize - 2; i++) + { + setAll(0, 0, 0); + setPixel(i, red / 10, green / 10, blue / 10); + for (int j = 1; j <= EyeSize; j++) + { + setPixel(i + j, red, green, blue); + } + setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10); + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } + + if (safeDelay(ReturnDelay)) + return; + + for (int i = LED_COUNT - EyeSize - 2; i > 0; i--) + { + setAll(0, 0, 0); + setPixel(i, red / 10, green / 10, blue / 10); + for (int j = 1; j <= EyeSize; j++) + { + setPixel(i + j, red, green, blue); + } + setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10); + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } + + if (safeDelay(ReturnDelay)) + return; +} + +//---------------------------------линейный огонь------------------------------------- + +void setPixelHeatColor(int Pixel, byte temperature) +{ + // Scale 'heat' down from 0-255 to 0-191 + byte t192 = round((temperature / 255.0) * 191); + + // calculate ramp up from + byte heatramp = t192 & 0x3F; // 0..63 + heatramp <<= 2; // scale up to 0..252 + + // figure out which third of the spectrum we're in: + if (t192 > 0x80) + { // hottest + setPixel(Pixel, 255, 255, heatramp); + } + else if (t192 > 0x40) + { // middle + setPixel(Pixel, 255, heatramp, 0); + } + else + { // coolest + setPixel(Pixel, heatramp, 0, 0); + } +} +void Fire(int Cooling, int Sparking, int SpeedDelay) +{ + static byte heat[LED_COUNT]; + int cooldown; + + // Step 1. Cool down every cell a little + for (int i = 0; i < LED_COUNT; i++) + { + cooldown = random(0, ((Cooling * 10) / LED_COUNT) + 2); + + if (cooldown > heat[i]) + { + heat[i] = 0; + } + else + { + heat[i] = heat[i] - cooldown; + } + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for (int k = LED_COUNT - 1; k >= 2; k--) + { + heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3; + } + + // Step 3. Randomly ignite new 'sparks' near the bottom + if (random(255) < Sparking) + { + int y = random(7); + heat[y] = heat[y] + random(160, 255); + // heat[y] = random(160,255); + } + + // Step 4. Convert heat to LED colors + for (int j = 0; j < LED_COUNT; j++) + { + setPixelHeatColor(j, heat[j]); + } + + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; +} + +//-------------------------------newKITT--------------------------------------- + +void CenterToOutside(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) +{ + for (int i = ((LED_COUNT - EyeSize) / 2); i >= 0; i--) + { + setAll(0, 0, 0); + + setPixel(i, red / 10, green / 10, blue / 10); + for (int j = 1; j <= EyeSize; j++) + { + setPixel(i + j, red, green, blue); + } + setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10); + + setPixel(LED_COUNT - i, red / 10, green / 10, blue / 10); + for (int j = 1; j <= EyeSize; j++) + { + setPixel(LED_COUNT - i - j, red, green, blue); + } + setPixel(LED_COUNT - i - EyeSize - 1, red / 10, green / 10, blue / 10); + + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } + if (safeDelay(ReturnDelay)) + return; +} + +void OutsideToCenter(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) +{ + for (int i = 0; i <= ((LED_COUNT - EyeSize) / 2); i++) + { + setAll(0, 0, 0); + + setPixel(i, red / 10, green / 10, blue / 10); + for (int j = 1; j <= EyeSize; j++) + { + setPixel(i + j, red, green, blue); + } + setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10); + + setPixel(LED_COUNT - i, red / 10, green / 10, blue / 10); + for (int j = 1; j <= EyeSize; j++) + { + setPixel(LED_COUNT - i - j, red, green, blue); + } + setPixel(LED_COUNT - i - EyeSize - 1, red / 10, green / 10, blue / 10); + + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } + if (safeDelay(ReturnDelay)) + return; +} + +void LeftToRight(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) +{ + for (int i = 0; i < LED_COUNT - EyeSize - 2; i++) + { + setAll(0, 0, 0); + setPixel(i, red / 10, green / 10, blue / 10); + for (int j = 1; j <= EyeSize; j++) + { + setPixel(i + j, red, green, blue); + } + setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10); + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } + if (safeDelay(ReturnDelay)) + return; +} + +void RightToLeft(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) +{ + for (int i = LED_COUNT - EyeSize - 2; i > 0; i--) + { + setAll(0, 0, 0); + setPixel(i, red / 10, green / 10, blue / 10); + for (int j = 1; j <= EyeSize; j++) + { + setPixel(i + j, red, green, blue); + } + setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10); + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } + if (safeDelay(ReturnDelay)) + return; +} +void NewKITT(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) +{ + RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); + LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); + OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); + CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); + LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); + RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); + OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); + CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); +} + +//-------------------------------rainbowCycle--------------------------------------- +//?? +byte *Wheel(byte WheelPos) +{ + static byte c[3]; + + if (WheelPos < 85) + { + c[0] = WheelPos * 3; + c[1] = 255 - WheelPos * 3; + c[2] = 0; + } + else if (WheelPos < 170) + { + WheelPos -= 85; + c[0] = 255 - WheelPos * 3; + c[1] = 0; + c[2] = WheelPos * 3; + } + else + { + WheelPos -= 170; + c[0] = 0; + c[1] = WheelPos * 3; + c[2] = 255 - WheelPos * 3; + } + + return c; +} + +void rainbowCycle(int SpeedDelay) +{ + byte *c; + uint16_t i, j; + + for (j = 0; j < 256 * 5; j++) + { // 5 cycles of all colors on wheel + for (i = 0; i < LED_COUNT; i++) + { + c = Wheel(((i * 256 / LED_COUNT) + j) & 255); + setPixel(i, *c, *(c + 1), *(c + 2)); + } + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } +} +//?? +//-------------------------------TwinkleRandom--------------------------------------- +void TwinkleRandom(int Count, int SpeedDelay, boolean OnlyOne) +{ + setAll(0, 0, 0); + + for (int i = 0; i < Count; i++) + { + setPixel(random(LED_COUNT), random(0, 255), random(0, 255), random(0, 255)); + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + if (OnlyOne) + { + setAll(0, 0, 0); + } + } + + if (safeDelay(SpeedDelay)) + return; +} + +//-------------------------------RunningLights--------------------------------------- +void RunningLights(byte red, byte green, byte blue, int WaveDelay) +{ + int Position = 0; + + for (int i = 0; i < LED_COUNT * 2; i++) + { + Position++; // = 0; //Position + Rate; + for (int i = 0; i < LED_COUNT; i++) + { + // sine wave, 3 offset waves make a rainbow! + // float level = sin(i+Position) * 127 + 128; + // setPixel(i,level,0,0); + // float level = sin(i+Position) * 127 + 128; + setPixel(i, ((sin(i + Position) * 127 + 128) / 255) * red, + ((sin(i + Position) * 127 + 128) / 255) * green, + ((sin(i + Position) * 127 + 128) / 255) * blue); + } + + FastLED.show(); + if (safeDelay(WaveDelay)) + return; + } +} + +//-------------------------------Sparkle--------------------------------------- +void Sparkle(byte red, byte green, byte blue, int SpeedDelay) +{ + int Pixel = random(LED_COUNT); + setPixel(Pixel, red, green, blue); + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + setPixel(Pixel, 0, 0, 0); +} + +//-------------------------------SnowSparkle--------------------------------------- +void SnowSparkle(byte red, byte green, byte blue, int SparkleDelay, int SpeedDelay) +{ + setAll(red, green, blue); + + int Pixel = random(LED_COUNT); + setPixel(Pixel, 0xff, 0xff, 0xff); + FastLED.show(); + if (safeDelay(SparkleDelay)) + return; + setPixel(Pixel, red, green, blue); + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; +} +//?? +//-------------------------------theaterChase--------------------------------------- +void theaterChase(byte red, byte green, byte blue, int SpeedDelay) +{ + for (int j = 0; j < 10; j++) + { // do 10 cycles of chasing + for (int q = 0; q < 3; q++) + { + for (int i = 0; i < LED_COUNT; i = i + 3) + { + setPixel(i + q, red, green, blue); // turn every third pixel on + } + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + for (int i = 0; i < LED_COUNT; i = i + 3) + { + setPixel(i + q, 0, 0, 0); // turn every third pixel off + } + } + } +} + +//-------------------------------theaterChaseRainbow--------------------------------------- +void theaterChaseRainbow(int SpeedDelay) +{ + byte *c; + + for (int j = 0; j < 256; j++) + { // cycle all 256 colors in the wheel + for (int q = 0; q < 3; q++) + { + for (int i = 0; i < LED_COUNT; i = i + 3) + { + c = Wheel((i + j) % 255); + setPixel(i + q, *c, *(c + 1), *(c + 2)); // turn every third pixel on + } + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + for (int i = 0; i < LED_COUNT; i = i + 3) + { + setPixel(i + q, 0, 0, 0); // turn every third pixel off + } + } + } +} +//?? +//-------------------------------Strobe--------------------------------------- +void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause) +{ + for (int j = 0; j < StrobeCount; j++) + { + setAll(red, green, blue); + FastLED.show(); + if (safeDelay(FlashDelay)) + return; + setAll(0, 0, 0); + FastLED.show(); + if (safeDelay(FlashDelay)) + return; + } + + if (safeDelay(EndPause)) + return; +} + +//-------------------------------BouncingBalls--------------------------------------- +void BouncingBalls(byte red, byte green, byte blue, int BallCount) +{ + float Gravity = -9.81; + int StartHeight = 1; + + float Height[BallCount]; + float ImpactVelocityStart = sqrt(-2 * Gravity * StartHeight); + float ImpactVelocity[BallCount]; + float TimeSinceLastBounce[BallCount]; + int Position[BallCount]; + long ClockTimeSinceLastBounce[BallCount]; + float Dampening[BallCount]; + + for (int i = 0; i < BallCount; i++) + { + ClockTimeSinceLastBounce[i] = millis(); + Height[i] = StartHeight; + Position[i] = 0; + ImpactVelocity[i] = ImpactVelocityStart; + TimeSinceLastBounce[i] = 0; + Dampening[i] = 0.90 - float(i) / pow(BallCount, 2); + } + + while (true) + { + if (changeFlag) + { + changeFlag = false; + return; + } + for (int i = 0; i < BallCount; i++) + { + TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i]; + Height[i] = 0.5 * Gravity * pow(TimeSinceLastBounce[i] / 1000, 2.0) + ImpactVelocity[i] * TimeSinceLastBounce[i] / 1000; + + if (Height[i] < 0) + { + Height[i] = 0; + ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i]; + ClockTimeSinceLastBounce[i] = millis(); + + if (ImpactVelocity[i] < 0.01) + { + ImpactVelocity[i] = ImpactVelocityStart; + } + } + Position[i] = round(Height[i] * (LED_COUNT - 1) / StartHeight); + } + + for (int i = 0; i < BallCount; i++) + { + setPixel(Position[i], red, green, blue); + } + FastLED.show(); + setAll(0, 0, 0); + } +} + +//-------------------------------BouncingColoredBalls--------------------------------------- +void BouncingColoredBalls(int BallCount, byte colors[][3]) +{ + float Gravity = -9.81; + int StartHeight = 1; + + float Height[BallCount]; + float ImpactVelocityStart = sqrt(-2 * Gravity * StartHeight); + float ImpactVelocity[BallCount]; + float TimeSinceLastBounce[BallCount]; + int Position[BallCount]; + long ClockTimeSinceLastBounce[BallCount]; + float Dampening[BallCount]; + + for (int i = 0; i < BallCount; i++) + { + ClockTimeSinceLastBounce[i] = millis(); + Height[i] = StartHeight; + Position[i] = 0; + ImpactVelocity[i] = ImpactVelocityStart; + TimeSinceLastBounce[i] = 0; + Dampening[i] = 0.90 - float(i) / pow(BallCount, 2); + } + + while (true) + { + if (changeFlag) + { + changeFlag = false; + return; + } + for (int i = 0; i < BallCount; i++) + { + TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i]; + Height[i] = 0.5 * Gravity * pow(TimeSinceLastBounce[i] / 1000, 2.0) + ImpactVelocity[i] * TimeSinceLastBounce[i] / 1000; + + if (Height[i] < 0) + { + Height[i] = 0; + ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i]; + ClockTimeSinceLastBounce[i] = millis(); + + if (ImpactVelocity[i] < 0.01) + { + ImpactVelocity[i] = ImpactVelocityStart; + } + } + Position[i] = round(Height[i] * (LED_COUNT - 1) / StartHeight); + } + + for (int i = 0; i < BallCount; i++) + { + setPixel(Position[i], colors[i][0], colors[i][1], colors[i][2]); + } + FastLED.show(); + setAll(0, 0, 0); + } +} + +//-----------Meteor Rain------- +void fadeToBlack(int ledNo, byte fadeValue) +{ +#ifdef ADAFRUIT_NEOPIXEL_H + // NeoPixel + uint32_t oldColor; + uint8_t r, g, b; + int value; + + oldColor = strip.getPixelColor(ledNo); + r = (oldColor & 0x00ff0000UL) >> 16; + g = (oldColor & 0x0000ff00UL) >> 8; + b = (oldColor & 0x000000ffUL); + + r = (r <= 10) ? 0 : (int)r - (r * fadeValue / 256); + g = (g <= 10) ? 0 : (int)g - (g * fadeValue / 256); + b = (b <= 10) ? 0 : (int)b - (b * fadeValue / 256); + + strip.setPixelColor(ledNo, r, g, b); +#endif +#ifndef ADAFRUIT_NEOPIXEL_H + // FastLED + leds[ledNo].fadeToBlackBy(fadeValue); +#endif +} +void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) +{ + setAll(0, 0, 0); + + for (int i = 0; i < NUM_LEDS + NUM_LEDS; i++) + { + + // fade brightness all LEDs one step + for (int j = 0; j < NUM_LEDS; j++) + { + if ((!meteorRandomDecay) || (random(10) > 5)) + { + fadeToBlack(j, meteorTrailDecay); + } + } + + // draw meteor + for (int j = 0; j < meteorSize; j++) + { + if ((i - j < NUM_LEDS) && (i - j >= 0)) + { + setPixel(i - j, red, green, blue); + } + } + + FastLED.show(); + if (safeDelay(SpeedDelay)) + return; + } +} diff --git a/src/modules/display/GyverLAMP/matrix.h b/src/modules/display/GyverLAMP/matrix.h new file mode 100644 index 00000000..ce102bf1 --- /dev/null +++ b/src/modules/display/GyverLAMP/matrix.h @@ -0,0 +1,770 @@ +#include "utility.h" + +byte hue; +boolean loadingFlag = true; +// **************** НАСТРОЙКИ ЭФФЕКТОВ **************** +// эффект "синусоиды" - ОТКЛЮЧЕН +#define WAVES_AMOUNT 2 // количество синусоид + +// эффект "шарики" +#define BALLS_AMOUNT 3 // количество "шариков" +#define CLEAR_PATH 1 // очищать путь +#define BALL_TRACK 1 // (0 / 1) - вкл/выкл следы шариков +#define DRAW_WALLS 0 // режим с рисованием препятствий для шаров (не работает на ESP и STM32) +#define TRACK_STEP 70 // длина хвоста шарика (чем больше цифра, тем хвост короче) + +// эффект "квадратик" +#define BALL_SIZE 3 // размер шара +#define RANDOM_COLOR 1 // случайный цвет при отскоке + +// эффект "огонь" +#define SPARKLES 1 // вылетающие угольки вкл выкл +#define HUE_ADD 0 // добавка цвета в огонь (от 0 до 230) - меняет весь цвет пламени + +// эффект "кометы" +#define TAIL_STEP 100 // длина хвоста кометы +#define SATURATION 150 // насыщенность кометы (от 0 до 255) +#define STAR_DENSE 60 // количество (шанс появления) комет + +// эффект "конфетти" +#define DENSE 3 // плотность конфетти +#define BRIGHT_STEP 70 // шаг уменьшения яркости + +// эффект "снег" +#define SNOW_DENSE 10 // плотность снегопада + +// эффект "Светляки" +#define LIGHTERS_AM 35 // количество светляков + +uint32_t globalColor = 0xffffff; // Цвет рисования при запуске белый +unsigned char matrixValue[8][16]; +unsigned char line[WIDTH]; +int pcnt = 0; +int effectSpeed = _speed; // скрость изменения эффекта +uint8_t USE_SEGMENTS = 1; +uint8_t BorderWidth = 0; +uint8_t dir_mx, seg_num, seg_size, seg_offset; +uint16_t XY(uint8_t, uint8_t); // __attribute__ ((weak)); + +// эффекты матрицы + +// *********** "дыхание" яркостью *********** +boolean brightnessDirection; +byte breathBrightness; // Яркость эффекта "Дыхание" +byte globalBrightness = _brightness; +void brightnessRoutine() +{ + if (brightnessDirection) + { + breathBrightness += 2; + if (breathBrightness > globalBrightness - 1) + { + brightnessDirection = false; + } + } + else + { + breathBrightness -= 2; + if (breathBrightness < 1) + { + brightnessDirection = true; + } + } + FastLED.setBrightness(breathBrightness); +} + +// *********** снегопад 2.0 *********** +void snowRoutine() +{ + + // сдвигаем всё вниз + for (byte x = 0; x < WIDTH; x++) + { + for (byte y = 0; y < HEIGHT - 1; y++) + { + drawPixelXY(x, y, getPixColorXY(x, y + 1)); + } + } + + for (byte x = 0; x < WIDTH; x++) + { + // заполняем случайно верхнюю строку + // а также не даём двум блокам по вертикали вместе быть + if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, SNOW_DENSE) == 0)) + drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); + else + drawPixelXY(x, HEIGHT - 1, 0x000000); + } +} + +// ***************************** БЛУДНЫЙ КУБИК ***************************** +int coordB[2]; +int8_t vectorB[2]; +CRGB ballColor; + +void ballRoutine() +{ + if (loadingFlag) + { + for (byte i = 0; i < 2; i++) + { + coordB[i] = WIDTH / 2 * 10; + vectorB[i] = random(8, 20); + ballColor = CHSV(random(0, 9) * 28, 255, 255); + } + + loadingFlag = false; + } + for (byte i = 0; i < 2; i++) + { + coordB[i] += vectorB[i]; + if (coordB[i] < 0) + { + coordB[i] = 0; + vectorB[i] = -vectorB[i]; + if (RANDOM_COLOR) + ballColor = CHSV(random(0, 9) * 28, 255, 255); + // vectorB[i] += random(0, 6) - 3; + } + } + if (coordB[0] > (WIDTH - BALL_SIZE) * 10) + { + coordB[0] = (WIDTH - BALL_SIZE) * 10; + vectorB[0] = -vectorB[0]; + if (RANDOM_COLOR) + ballColor = CHSV(random(0, 9) * 28, 255, 255); + // vectorB[0] += random(0, 6) - 3; + } + if (coordB[1] > (HEIGHT - BALL_SIZE) * 10) + { + coordB[1] = (HEIGHT - BALL_SIZE) * 10; + vectorB[1] = -vectorB[1]; + if (RANDOM_COLOR) + ballColor = CHSV(random(0, 9) * 28, 255, 255); + // vectorB[1] += random(0, 6) - 3; + } + FastLED.clear(); + for (byte i = 0; i < BALL_SIZE; i++) + for (byte j = 0; j < BALL_SIZE; j++) + leds[getPixelNumber(coordB[0] / 10 + i, coordB[1] / 10 + j)] = ballColor; +} + +// *********** радуга заливка *********** +void rainbowRoutine() +{ + + hue += 3; + for (byte i = 0; i < WIDTH; i++) + { + CHSV thisColor = CHSV((byte)(hue + i * float(255 / WIDTH)), 255, 255); + for (byte j = 0; j < HEIGHT; j++) + drawPixelXY(i, j, thisColor); // leds[getPixelNumber(i, j)] = thisColor; + } +} + +// *********** радуга дигональная *********** +void rainbowDiagonalRoutine() +{ + + hue += 3; + for (byte x = 0; x < WIDTH; x++) + { + for (byte y = 0; y < HEIGHT; y++) + { + CHSV thisColor = CHSV((byte)(hue + (float)(WIDTH / HEIGHT * x + y) * (float)(255 / 100)), 255, 255); + drawPixelXY(x, y, thisColor); // leds[getPixelNumber(i, j)] = thisColor; + } + } +} + +// *********** радуга активных светодиодов (рисунка) *********** +void rainbowColorsRoutine() +{ + hue++; + for (byte i = 0; i < WIDTH; i++) + { + CHSV thisColor = CHSV((byte)(hue + i * float(255 / WIDTH)), 255, 255); + for (byte j = 0; j < HEIGHT; j++) + if (getPixColor(getPixelNumber(i, j)) > 0) + drawPixelXY(i, j, thisColor); + } +} + +// ****************************** ОГОНЬ ****************************** +// ********************** огонь ********************** +// these values are substracetd from the generated values to give a shape to the animation +const unsigned char valueMask[8][16] PROGMEM = { + {32, 0, 0, 0, 0, 0, 0, 32, 32, 0, 0, 0, 0, 0, 0, 32}, + {64, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 64}, + {96, 32, 0, 0, 0, 0, 32, 96, 96, 32, 0, 0, 0, 0, 32, 96}, + {128, 64, 32, 0, 0, 32, 64, 128, 128, 64, 32, 0, 0, 32, 64, 128}, + {160, 96, 64, 32, 32, 64, 96, 160, 160, 96, 64, 32, 32, 64, 96, 160}, + {192, 128, 96, 64, 64, 96, 128, 192, 192, 128, 96, 64, 64, 96, 128, 192}, + {255, 160, 128, 96, 96, 128, 160, 255, 255, 160, 128, 96, 96, 128, 160, 255}, + {255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255}}; + +// these are the hues for the fire, +// should be between 0 (red) to about 25 (yellow) +const unsigned char hueMask[8][16] PROGMEM = { + {1, 11, 19, 25, 25, 22, 11, 1, 1, 11, 19, 25, 25, 22, 11, 1}, + {1, 8, 13, 19, 25, 19, 8, 1, 1, 8, 13, 19, 25, 19, 8, 1}, + {1, 8, 13, 16, 19, 16, 8, 1, 1, 8, 13, 16, 19, 16, 8, 1}, + {1, 5, 11, 13, 13, 13, 5, 1, 1, 5, 11, 13, 13, 13, 5, 1}, + {1, 5, 11, 11, 11, 11, 5, 1, 1, 5, 11, 11, 11, 11, 5, 1}, + {0, 1, 5, 8, 8, 5, 1, 0, 0, 1, 5, 8, 8, 5, 1, 0}, + {0, 0, 1, 5, 5, 1, 0, 0, 0, 0, 1, 5, 5, 1, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}}; +// Randomly generate the next line (matrix row) + +void generateLine() +{ + for (uint8_t x = 0; x < WIDTH; x++) + { + line[x] = random(64, 255); + } +} + +// shift all values in the matrix up one row + +void shiftUp() +{ + for (uint8_t y = HEIGHT - 1; y > 0; y--) + { + for (uint8_t x = 0; x < WIDTH; x++) + { + uint8_t newX = x; + if (x > 15) + newX = x % 16; + if (y > 7) + continue; + matrixValue[y][newX] = matrixValue[y - 1][newX]; + } + } + + for (uint8_t x = 0; x < WIDTH; x++) + { + uint8_t newX = x; + if (x > 15) + newX = x % 16; + matrixValue[0][newX] = line[newX]; + } +} + +// draw a frame, interpolating between 2 "key frames" +// @param pcnt percentage of interpolation + +void drawFrame(int pcnt) +{ + int nextv; + + // each row interpolates with the one before it + for (unsigned char y = HEIGHT - 1; y > 0; y--) + { + for (unsigned char x = 0; x < WIDTH; x++) + { + uint8_t newX = x; + if (x > 15) + newX = x % 16; + if (y < 8) + { + nextv = + (((100.0 - pcnt) * matrixValue[y][newX] + pcnt * matrixValue[y - 1][newX]) / 100.0) - pgm_read_byte(&(valueMask[y][newX])); + + CRGB color = CHSV( + HUE_ADD + pgm_read_byte(&(hueMask[y][newX])), // H + 255, // S + (uint8_t)max(0, nextv) // V + ); + + leds[getPixelNumber(x, y)] = color; + } + else if (y == 8 && SPARKLES) + { + if (random(0, 20) == 0 && getPixColorXY(x, y - 1) != 0) + drawPixelXY(x, y, getPixColorXY(x, y - 1)); + else + drawPixelXY(x, y, 0); + } + else if (SPARKLES) + { + + // старая версия для яркости + if (getPixColorXY(x, y - 1) > 0) + drawPixelXY(x, y, getPixColorXY(x, y - 1)); + else + drawPixelXY(x, y, 0); + } + } + } + + // first row interpolates with the "next" line + for (unsigned char x = 0; x < WIDTH; x++) + { + uint8_t newX = x; + if (x > 15) + newX = x % 16; + CRGB color = CHSV( + HUE_ADD + pgm_read_byte(&(hueMask[0][newX])), // H + 255, // S + (uint8_t)(((100.0 - pcnt) * matrixValue[0][newX] + pcnt * line[newX]) / 100.0) // V + ); + // leds[getPixelNumber(newX, 0)] = color; // На форуме пишут что это ошибка - вместо newX должно быть x, иначе + leds[getPixelNumber(x, 0)] = color; // на матрицах шире 16 столбцов нижний правый угол неработает + } +} +void fireRoutine() +{ + if (loadingFlag) + { + + loadingFlag = false; + FastLED.clear(); + generateLine(); + memset(matrixValue, 0, sizeof(matrixValue)); + } + if (pcnt >= 100) + { + shiftUp(); + generateLine(); + pcnt = 0; + } + drawFrame(pcnt); + pcnt += 30; +} + +// **************** МАТРИЦА ***************** +void matrixRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + + FastLED.clear(); + } + for (byte x = 0; x < WIDTH; x++) + { + // заполняем случайно верхнюю строку + uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); + if (thisColor == 0) + drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, 10) == 0)); + else if (thisColor < 0x002000) + drawPixelXY(x, HEIGHT - 1, 0); + else + drawPixelXY(x, HEIGHT - 1, thisColor - 0x002000); + } + + // сдвигаем всё вниз + for (byte x = 0; x < WIDTH; x++) + { + for (byte y = 0; y < HEIGHT - 1; y++) + { + drawPixelXY(x, y, getPixColorXY(x, y + 1)); + } + } +} + +// ********************* ЗВЕЗДОПАД ****************** +void fadePixel(byte i, byte j, byte step) +{ // новый фейдер + int pixelNum = getPixelNumber(i, j); + if (getPixColor(pixelNum) == 0) + return; + + if (leds[pixelNum].r >= 30 || + leds[pixelNum].g >= 30 || + leds[pixelNum].b >= 30) + { + leds[pixelNum].fadeToBlackBy(step); + } + else + { + leds[pixelNum] = 0; + } +} +// функция плавного угасания цвета для всех пикселей +void fader(byte step) +{ + for (byte i = 0; i < WIDTH; i++) + { + for (byte j = 0; j < HEIGHT; j++) + { + fadePixel(i, j, step); + } + } +} + +void starfallRoutine() +{ + + // заполняем головами комет левую и верхнюю линию + for (byte i = HEIGHT / 2; i < HEIGHT; i++) + { + if (getPixColorXY(0, i) == 0 && (random(0, STAR_DENSE) == 0) && getPixColorXY(0, i + 1) == 0 && getPixColorXY(0, i - 1) == 0) + leds[getPixelNumber(0, i)] = CHSV(random(0, 200), SATURATION, 255); + } + for (byte i = 0; i < WIDTH / 2; i++) + { + if (getPixColorXY(i, HEIGHT - 1) == 0 && (random(0, STAR_DENSE) == 0) && getPixColorXY(i + 1, HEIGHT - 1) == 0 && getPixColorXY(i - 1, HEIGHT - 1) == 0) + leds[getPixelNumber(i, HEIGHT - 1)] = CHSV(random(0, 200), SATURATION, 255); + } + + // сдвигаем по диагонали + for (byte y = 0; y < HEIGHT - 1; y++) + { + for (byte x = WIDTH - 1; x > 0; x--) + { + drawPixelXY(x, y, getPixColorXY(x - 1, y + 1)); + } + } + + // уменьшаем яркость левой и верхней линии, формируем "хвосты" + for (byte i = HEIGHT / 2; i < HEIGHT; i++) + { + fadePixel(0, i, TAIL_STEP); + } + for (byte i = 0; i < WIDTH / 2; i++) + { + fadePixel(i, HEIGHT - 1, TAIL_STEP); + } +} + +// рандомные гаснущие вспышки +void sparklesRoutine() +{ + + for (byte i = 0; i < DENSE; i++) + { + byte x = random(0, WIDTH); + byte y = random(0, HEIGHT); + if (getPixColorXY(x, y) == 0) + leds[getPixelNumber(x, y)] = CHSV(random(0, 255), 255, 255); + } + fader(BRIGHT_STEP); +} + +// ----------------------------- СВЕТЛЯКИ ------------------------------ +int lightersPos[2][LIGHTERS_AM]; +int8_t lightersSpeed[2][LIGHTERS_AM]; +CHSV lightersColor[LIGHTERS_AM]; +byte loopCounter; + +int angle[LIGHTERS_AM]; +int speedV[LIGHTERS_AM]; +int8_t angleSpeed[LIGHTERS_AM]; + +void lightersRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + randomSeed(millis()); + for (byte i = 0; i < LIGHTERS_AM; i++) + { + lightersPos[0][i] = random(0, WIDTH * 10); + lightersPos[1][i] = random(0, HEIGHT * 10); + lightersSpeed[0][i] = random(-10, 10); + lightersSpeed[1][i] = random(-10, 10); + lightersColor[i] = CHSV(random(0, 255), 255, 255); + } + } + FastLED.clear(); + if (++loopCounter > 20) + loopCounter = 0; + for (byte i = 0; i < map(LIGHTERS_AM, 0, 255, 5, 150); i++) + { + if (loopCounter == 0) + { // меняем скорость каждые 255 отрисовок + lightersSpeed[0][i] += random(-3, 4); + lightersSpeed[1][i] += random(-3, 4); + lightersSpeed[0][i] = constrain(lightersSpeed[0][i], -20, 20); + lightersSpeed[1][i] = constrain(lightersSpeed[1][i], -20, 20); + } + + lightersPos[0][i] += lightersSpeed[0][i]; + lightersPos[1][i] += lightersSpeed[1][i]; + + if (lightersPos[0][i] < 0) + lightersPos[0][i] = (WIDTH - 1) * 10; + if (lightersPos[0][i] >= WIDTH * 10) + lightersPos[0][i] = 0; + + if (lightersPos[1][i] < 0) + { + lightersPos[1][i] = 0; + lightersSpeed[1][i] = -lightersSpeed[1][i]; + } + if (lightersPos[1][i] >= (HEIGHT - 1) * 10) + { + lightersPos[1][i] = (HEIGHT - 1) * 10; + lightersSpeed[1][i] = -lightersSpeed[1][i]; + } + drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]); + } +} + +// ------------- ПЕЙНТБОЛ ------------- + +void lightBallsRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + + FastLED.clear(); // очистить + dir_mx = WIDTH > HEIGHT ? 0 : 1; // 0 - квадратные сегменты расположены горизонтально, 1 - вертикально + seg_num = dir_mx == 0 ? (WIDTH / HEIGHT) : (HEIGHT / WIDTH); // вычисляем количество сегментов, умещающихся на матрице + seg_size = dir_mx == 0 ? HEIGHT : WIDTH; // Размер квадратного сегмента (высота и ширина равны) + seg_offset = ((dir_mx == 0 ? WIDTH : HEIGHT) - seg_size * seg_num) / (seg_num + 1); // смещение от края матрицы и между сегментами + BorderWidth = 0; + } + + // Apply some blurring to whatever's already on the matrix + // Note that we never actually clear the matrix, we just constantly + // blur it repeatedly. Since the blurring is 'lossy', there's + // an automatic trend toward black -- by design. + uint8_t blurAmount = dim8_raw(beatsin8(2, 64, 100)); + blur2d(leds, WIDTH, HEIGHT, blurAmount); + + // The color of each point shifts over time, each at a different speed. + uint32_t ms = millis(); + int16_t idx; + + byte cnt = map(effectSpeed, 0, 255, 1, 4); + + if (USE_SEGMENTS != 0) + { + // Для неквадратных - вычленяем квадратные сегменты, которые равномерно распределяем по ширине / высоте матрицы + uint8_t i = beatsin8(91, 0, seg_size - BorderWidth - 1); + uint8_t j = beatsin8(109, 0, seg_size - BorderWidth - 1); + uint8_t k = beatsin8(73, 0, seg_size - BorderWidth - 1); + uint8_t m = beatsin8(123, 0, seg_size - BorderWidth - 1); + + uint8_t d1 = ms / 29; + uint8_t d2 = ms / 41; + uint8_t d3 = ms / 73; + uint8_t d4 = ms / 97; + + for (uint8_t ii = 0; ii < seg_num; ii++) + { + delay(0); // Для предотвращения ESP8266 Watchdog Timer + uint8_t cx = dir_mx == 0 ? (seg_offset * (ii + 1) + seg_size * ii) : 0; + uint8_t cy = dir_mx == 0 ? 0 : (seg_offset * (ii + 1) + seg_size * ii); + uint8_t color_shift = ii * 50; + if (cnt <= 1) + { + idx = XY(i + cx, j + cy); + leds[idx] += CHSV(color_shift + d1, 200U, 255U); + } + if (cnt <= 2) + { + idx = XY(j + cx, k + cy); + leds[idx] += CHSV(color_shift + d2, 200U, 255U); + } + if (cnt <= 3) + { + idx = XY(k + cx, m + cy); + leds[idx] += CHSV(color_shift + d3, 200U, 255U); + } + if (cnt <= 4) + { + idx = XY(m + cx, i + cy); + leds[idx] += CHSV(color_shift + d4, 200U, 255U); + } + + // При соединении матрицы из угла вверх или вниз почему-то слева и справа узора остаются полосы, которые + // не гаснут обычным blur - гасим полоски левой и правой стороны дополнительно. + // При соединении из угла влево или вправо или на неквадратных матрицах такого эффекта не наблюдается + for (byte i2 = cy; i2 < cy + seg_size; i2++) + { + fadePixel(cx + BorderWidth, i2, 15); + fadePixel(cx + seg_size - BorderWidth - 1, i2, 15); + } + } + } + else + { + uint8_t i = beatsin8(91, BorderWidth, WIDTH - BorderWidth - 1); + uint8_t j = beatsin8(109, BorderWidth, HEIGHT - BorderWidth - 1); + uint8_t k = beatsin8(73, BorderWidth, WIDTH - BorderWidth - 1); + uint8_t m = beatsin8(123, BorderWidth, HEIGHT - BorderWidth - 1); + + if (cnt <= 1) + { + idx = XY(i, j); + leds[idx] += CHSV(ms / 29, 200U, 255U); + } + if (cnt <= 2) + { + idx = XY(k, j); + leds[idx] += CHSV(ms / 41, 200U, 255U); + } + if (cnt <= 3) + { + idx = XY(k, m); + leds[idx] += CHSV(ms / 73, 200U, 255U); + } + if (cnt <= 4) + { + idx = XY(i, m); + leds[idx] += CHSV(ms / 97, 200U, 255U); + } + + if (WIDTH == HEIGHT) + { + // При соединении матрицы из угла вверх или вниз почему-то слева и справа узора остаются полосы, которые + // не гаснут обычным blur - гасим полоски левой и правой стороны дополнительно. + // При соединении из угла влево или вправо или на неквадратных матрицах такого эффекта не наблюдается + for (byte i = 0; i < HEIGHT; i++) + { + fadePixel(0, i, 15); + fadePixel(WIDTH - 1, i, 15); + } + } + } +} +// ------------- ВОДОВОРОТ ------------- + +void swirlRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + + FastLED.clear(); // очистить + dir_mx = WIDTH > HEIGHT ? 0 : 1; // 0 - квадратные сегменты расположены горизонтально, 1 - вертикально + seg_num = dir_mx == 0 ? (WIDTH / HEIGHT) : (HEIGHT / WIDTH); // вычисляем количество сегментов, умещающихся на матрице + seg_size = dir_mx == 0 ? HEIGHT : WIDTH; // Размер квадратного сегмента (высота и ширина равны) + seg_offset = ((dir_mx == 0 ? WIDTH : HEIGHT) - seg_size * seg_num) / (seg_num + 1); // смещение от края матрицы и между сегментами + BorderWidth = seg_num == 1 ? 0 : 1; + } + + // Apply some blurring to whatever's already on the matrix + // Note that we never actually clear the matrix, we just constantly + // blur it repeatedly. Since the blurring is 'lossy', there's + // an automatic trend toward black -- by design. + uint8_t blurAmount = dim8_raw(beatsin8(2, 64, 100)); + blur2d(leds, WIDTH, HEIGHT, blurAmount); + + uint32_t ms = millis(); + int16_t idx; + + if (USE_SEGMENTS != 0) + { + // Use two out-of-sync sine waves + uint8_t i = beatsin8(41, 0, seg_size - BorderWidth - 1); + uint8_t j = beatsin8(27, 0, seg_size - BorderWidth - 1); + + // Also calculate some reflections + uint8_t ni = (seg_size - 1) - i; + uint8_t nj = (seg_size - 1) - j; + + uint8_t d1 = ms / 11; + uint8_t d2 = ms / 13; + uint8_t d3 = ms / 17; + uint8_t d4 = ms / 29; + uint8_t d5 = ms / 37; + uint8_t d6 = ms / 41; + + for (uint8_t ii = 0; ii < seg_num; ii++) + { + delay(0); // Для предотвращения ESP8266 Watchdog Timer + uint8_t cx = dir_mx == 0 ? (seg_offset * (ii + 1) + seg_size * ii) : 0; + uint8_t cy = dir_mx == 0 ? 0 : (seg_offset * (ii + 1) + seg_size * ii); + uint8_t color_shift = ii * 50; + + // The color of each point shifts over time, each at a different speed. + idx = XY(i + cx, j + cy); + leds[idx] += CHSV(color_shift + d1, 200, 192); + idx = XY(ni + cx, nj + cy); + leds[idx] += CHSV(color_shift + d2, 200, 192); + idx = XY(i + cx, nj + cy); + leds[idx] += CHSV(color_shift + d3, 200, 192); + idx = XY(ni + cx, j + cy); + leds[idx] += CHSV(color_shift + d4, 200, 192); + idx = XY(j + cx, i + cy); + leds[idx] += CHSV(color_shift + d5, 200, 192); + idx = XY(nj + cx, ni + cy); + leds[idx] += CHSV(color_shift + d6, 200, 192); + + // При соединении матрицы из угла вверх или вниз почему-то слева и справа узора остаются полосы, которые + // не гаснут обычным blur - гасим полоски левой и правой стороны дополнительно. + // При соединении из угла влево или вправо или на неквадратных матрицах такого эффекта не наблюдается + for (byte i2 = cy; i2 < cy + seg_size; i2++) + { + fadePixel(cx, i2, 15); + fadePixel(cx + BorderWidth, i2, 15); + fadePixel(cx + seg_size - 1, i2, 15); + fadePixel(cx + seg_size - BorderWidth - 1, i2, 15); + } + } + } + else + { + // Use two out-of-sync sine waves + uint8_t i = beatsin8(41, BorderWidth, WIDTH - BorderWidth - 1); + uint8_t j = beatsin8(27, BorderWidth, HEIGHT - BorderWidth - 1); + + // Also calculate some reflections + uint8_t ni = (WIDTH - 1) - i; + uint8_t nj = (HEIGHT - 1) - j; + + // The color of each point shifts over time, each at a different speed. + idx = XY(i, j); + leds[idx] += CHSV(ms / 11, 200, 192); + idx = XY(ni, nj); + leds[idx] += CHSV(ms / 13, 200, 192); + idx = XY(i, nj); + leds[idx] += CHSV(ms / 17, 200, 192); + idx = XY(ni, j); + leds[idx] += CHSV(ms / 29, 200, 192); + + if (HEIGHT == WIDTH) + { + // для квадратных матриц - 6 точек создают более красивую картину + idx = XY(j, i); + leds[idx] += CHSV(ms / 37, 200, 192); + idx = XY(nj, ni); + leds[idx] += CHSV(ms / 41, 200, 192); + + // При соединении матрицы из угла вверх или вниз почему-то слева и справа узора остаются полосы, которые + // не гаснут обычным blur - гасим полоски левой и правой стороны дополнительно. + // При соединении из угла влево или вправо или на неквадратных матрицах такого эффекта не наблюдается + for (byte i = 0; i < HEIGHT; i++) + { + fadePixel(0, i, 15); + fadePixel(WIDTH - 1, i, 15); + } + } + } +} + +uint16_t XY(uint8_t x, uint8_t y) +{ + return getPixelNumber(x, y); +} + +//--------------------крутящаяся радуга матрица------------------ + +void rainbow_loop_matrix() +{ //-m3-LOOP HSV RAINBOW + idex++; + ihue = ihue + thisstep; + if (idex >= LED_COUNT) + { + idex = 0; + } + if (ihue > 255) + { + ihue = 0; + } + + for (byte i = 0; i < WIDTH; i++) + { + CHSV thisColor = CHSV(ihue, thissat, 255); + for (byte j = 0; j < HEIGHT; j++) + drawPixelXY(i, j, thisColor); // leds[getPixelNumber(i, j)] = thisColor; + } + LEDS.show(); + if (safeDelay(thisdelay)) + return; +} \ No newline at end of file diff --git a/src/modules/display/GyverLAMP/modinfo.json b/src/modules/display/GyverLAMP/modinfo.json new file mode 100644 index 00000000..d5aff0d6 --- /dev/null +++ b/src/modules/display/GyverLAMP/modinfo.json @@ -0,0 +1,40 @@ +{ + "menuSection": "screens", + "configItem": [ + { + "global": 0, + "name": "GyverLAMP", + "type": "Reading", + "subtype": "GyverLAMP", + "id": "GyverLAMP", + "widget": "range", + "page": "Кнопки", + "descr": "GyverLAMP", + "needSave": 0, + "brightness": "10", + "speed": 30, + "dalay": 10000 + } + ], + "about": { + "authorName": "", + "authorContact": "", + "authorGit": "", + "exampleURL": "", + "specialThanks": "", + "moduleName": "GyverLAMP", + "moduleVersion": "1", + "moduleDesc": "xxx", + "propInfo": {}, + "funcInfo": [] + }, + "defActive": false, + "usedLibs": { + "esp32*": [ + "fastled/FastLED@^3.5.0" + ], + "esp82*": [ + "fastled/FastLED@^3.5.0" + ] + } +} \ No newline at end of file diff --git a/src/modules/display/GyverLAMP/utility.h b/src/modules/display/GyverLAMP/utility.h new file mode 100644 index 00000000..fff2d740 --- /dev/null +++ b/src/modules/display/GyverLAMP/utility.h @@ -0,0 +1,92 @@ +#include "config.h" +#define MATRIX_TYPE 0 +// #define NUM_LEDS LED_COUNT + +// **************** НАСТРОЙКА МАТРИЦЫ **************** +#if (CONNECTION_ANGLE == 0 && STRIP_DIRECTION == 0) +#define _WIDTH WIDTH +#define THIS_X x +#define THIS_Y y + +#elif (CONNECTION_ANGLE == 0 && STRIP_DIRECTION == 1) +#define _WIDTH HEIGHT +#define THIS_X y +#define THIS_Y x + +#elif (CONNECTION_ANGLE == 1 && STRIP_DIRECTION == 0) +#define _WIDTH WIDTH +#define THIS_X x +#define THIS_Y (HEIGHT - y - 1) + +#elif (CONNECTION_ANGLE == 1 && STRIP_DIRECTION == 3) +#define _WIDTH HEIGHT +#define THIS_X (HEIGHT - y - 1) +#define THIS_Y x + +#elif (CONNECTION_ANGLE == 2 && STRIP_DIRECTION == 2) +#define _WIDTH WIDTH +#define THIS_X (WIDTH - x - 1) +#define THIS_Y (HEIGHT - y - 1) + +#elif (CONNECTION_ANGLE == 2 && STRIP_DIRECTION == 3) +#define _WIDTH HEIGHT +#define THIS_X (HEIGHT - y - 1) +#define THIS_Y (WIDTH - x - 1) + +#elif (CONNECTION_ANGLE == 3 && STRIP_DIRECTION == 2) +#define _WIDTH WIDTH +#define THIS_X (WIDTH - x - 1) +#define THIS_Y y + +#elif (CONNECTION_ANGLE == 3 && STRIP_DIRECTION == 1) +#define _WIDTH HEIGHT +#define THIS_X y +#define THIS_Y (WIDTH - x - 1) + +#else +#define _WIDTH WIDTH +#define THIS_X x +#define THIS_Y y +#pragma message "Wrong matrix parameters! Set to default" + +#endif + +// получить номер пикселя в ленте по координатам +uint16_t getPixelNumber(int8_t x, int8_t y) +{ + if ((THIS_Y % 2 == 0) || MATRIX_TYPE) + { // если чётная строка + return (THIS_Y * _WIDTH + THIS_X); + } + else + { // если нечётная строка + return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); + } +} +// функция отрисовки точки по координатам X Y +void drawPixelXY(int8_t x, int8_t y, CRGB color) +{ + + if (x < 0 || x > WIDTH - 1 || y < 0 || y > HEIGHT - 1) + return; + int thisPixel = getPixelNumber(x, y) * SEGMENTS; + for (byte i = 0; i < SEGMENTS; i++) + { + leds[thisPixel + i] = color; + } + //FastLED.show(); +} +// функция получения цвета пикселя по его номеру +uint32_t getPixColor(int thisSegm) +{ + int thisPixel = thisSegm * SEGMENTS; + if (thisPixel < 0 || thisPixel > NUM_LEDS - 1) + return 0; + return (((uint32_t)leds[thisPixel].r << 16) | ((long)leds[thisPixel].g << 8) | (long)leds[thisPixel].b); +} + +// функция получения цвета пикселя в матрице по его координатам +uint32_t getPixColorXY(int8_t x, int8_t y) +{ + return getPixColor(getPixelNumber(x, y)); +} diff --git a/src/modules/exec/IoTServo/modinfo.json b/src/modules/exec/IoTServo/modinfo.json index b5184c51..ec50f810 100644 --- a/src/modules/exec/IoTServo/modinfo.json +++ b/src/modules/exec/IoTServo/modinfo.json @@ -50,7 +50,7 @@ } ] }, - "defActive": true, + "defActive": false, "usedLibs": { "esp32*": [ "https://github.com/RoboticsBrno/ServoESP32#v1.0.3" diff --git a/src/modules/exec/Pwm8266/modinfo.json b/src/modules/exec/Pwm8266/modinfo.json index 98163426..02a13034 100644 --- a/src/modules/exec/Pwm8266/modinfo.json +++ b/src/modules/exec/Pwm8266/modinfo.json @@ -38,7 +38,7 @@ "freq": "Частота" } }, - "defActive": true, + "defActive": false, "usedLibs": { "esp82*": [] } diff --git a/src/modules/sensors/Ble/modinfo.json b/src/modules/sensors/Ble/modinfo.json index c4cb3106..f51d0618 100644 --- a/src/modules/sensors/Ble/modinfo.json +++ b/src/modules/sensors/Ble/modinfo.json @@ -64,7 +64,13 @@ }, "defActive": false, "usedLibs": { - "esp32*": [ + "esp32c62_4mb": [ + "https://github.com/h2zero/NimBLE-Arduino#c6-build" + ], + "esp32c62_8mb": [ + "https://github.com/h2zero/NimBLE-Arduino#c6-build" + ], + "esp32_4mb3f": [ "https://github.com/Mit4el/NimBLE-Arduino.git" ], "esp32s2_4mb": [ diff --git a/src/modules/virtual/UpdateServer/UpdateServer.cpp b/src/modules/virtual/UpdateServer/UpdateServer.cpp new file mode 100644 index 00000000..b9f6b75a --- /dev/null +++ b/src/modules/virtual/UpdateServer/UpdateServer.cpp @@ -0,0 +1,27 @@ +#include "Global.h" +#include "classes/IoTItem.h" + +class UpdateServer : public IoTItem { + public: + UpdateServer(String parameters) : IoTItem(parameters) {} + + void onModuleOrder(String &key, String &value) { + if (key == "startUpdateAll") { + upgrade_firmware(3, value); + } else if (key == "startUpdateFS") { + upgrade_firmware(2, value); + } else if (key == "startUpdateFW") { + upgrade_firmware(1, value); + } + } + + ~UpdateServer() {}; +}; + +void* getAPI_UpdateServer(String subtype, String param) { + if (subtype == F("UpdateServer")) { + return new UpdateServer(param); + } else { + return nullptr; + } +} diff --git a/src/modules/virtual/UpdateServer/modinfo.json b/src/modules/virtual/UpdateServer/modinfo.json new file mode 100644 index 00000000..c4b8fc70 --- /dev/null +++ b/src/modules/virtual/UpdateServer/modinfo.json @@ -0,0 +1,41 @@ +{ + "menuSection": "virtual_elments", + "configItem": [ + { + "global": 0, + "name": "Свой сервер обновлений", + "type": "Reading", + "subtype": "UpdateServer", + "id": "UpdateServer", + "widget": "", + "page": "", + "descr": "", + "btn-startUpdateAll": "http://192.168.11.112/iotm/esp8266_4mb/400", + "btn-startUpdateFS": "http://192.168.11.112/iotm/esp8266_4mb/400", + "btn-startUpdateFW": "http://192.168.11.112/iotm/esp8266_4mb/400" + } + ], + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "exampleURL": "https://iotmanager.org/", + "specialThanks": "", + "moduleName": "UpdateServer", + "moduleVersion": "1.0", + "usedRam": { + "esp32_4mb": 15, + "esp8266_4mb": 15 + }, + "title": "Свой сервер обновлений", + "moduleDesc": "Модуль для получения прошивки из своего сервера обновлений.", + "propInfo": { + "btn-startUpdate": "Кнопка запуска процесса обновления из указанного URL" + } + }, + "defActive": true, + "usedLibs": { + "esp32*": [], + "esp82*": [] + } +} \ No newline at end of file diff --git a/src/utils/WiFiUtils.cpp b/src/utils/WiFiUtils.cpp index bd44849d..429b5164 100644 --- a/src/utils/WiFiUtils.cpp +++ b/src/utils/WiFiUtils.cpp @@ -96,7 +96,9 @@ void routerConnect() } #if defined(ESP32) //SerialPrint("i", "Task", "Resetting WDT..."); + #if !defined(esp32c6_4mb) && !defined(esp32c6_8mb) //TODO esp32-c6 переписать esp_task_wdt_init esp_task_wdt_reset(); + #endif #endif Serial.print("."); delay(1000);