From ce236374a1d8c146f96f09b2cc060a3d294279ac Mon Sep 17 00:00:00 2001 From: Dmytro Korniienko Date: Thu, 21 Nov 2019 12:24:38 +0200 Subject: [PATCH 1/4] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=20=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5,=20=D0=B4=D0=B5=D0=BC=D0=BE-=D1=80=D0=B5?= =?UTF-8?q?=D0=B6=D0=B8=D0=BC,=2017=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=20?= =?UTF-8?q?=D0=BB=D0=B0=D0=BC=D0=BF=D1=8B=20=D1=83=D0=BB=D1=83=D1=87=D1=88?= =?UTF-8?q?=D0=B5=D0=BD,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B2=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D0=BE=20=D0=BB=D0=BE=D0=BD=D0=B3-=D0=BD=D0=B0?= =?UTF-8?q?=D0=B6=D0=B0=D1=82=D0=B8=D1=8E,=20=D0=BF=D0=BE=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=B1=D0=BB-=D0=BA=D0=BB=D0=B8=D0=BA=D1=83,=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B2=D1=8B=D0=B1=D0=BE?= =?UTF-8?q?=D1=80=20=D0=B2=D0=B5=D1=80=D1=82=D0=B8=D0=BA=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE/=D0=B3=D0=BE=D1=80=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B8?= =?UTF-8?q?=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D1=80=D0=B0.=20+=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B7=D0=BD=D1=8B=D0=B5=20=D0=B1=D0=B0=D0=B3=20?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=D1=8B=20=D0=BE=D1=82=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=20=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81?= =?UTF-8?q?=D0=B8=D0=B8=20(:=20*=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D1=8C=D1=82=D0=B5=20=D0=BF=D0=B8=D0=BD=D1=8B,=20=D0=BD=D0=B0?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B8=20=D1=8F=D1=80=D0=BA?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8=20=D0=B8=20=D1=82=D0=BE=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=20=D0=BF=D1=80=D0=BE=D1=88=D0=B8?= =?UTF-8?q?=D0=B2=D0=BA=D0=BE=D0=B9,=20=D0=BF=D0=BE=20=D0=B2=D0=BE=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=81=D0=B0=D0=BC/=D0=BF=D0=BE=D0=B6=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20-=20=D0=B8=D1=89=D0=B8=D1=82?= =?UTF-8?q?=D0=B5=20=D0=BC=D0=B5=D0=BD=D1=8F=20=D1=82=D1=83=D1=82:=20https?= =?UTF-8?q?://community.alexgyver.ru/threads/wifi-lampa-budilnik-obsuzhden?= =?UTF-8?q?ie-proekta.1411?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GyverLamp_v1.4_Arduino_v1.0.ino | 54 ++++- .../GyverLamp_v1.4_Arduino_v1.0/button.ino | 172 ++++++++++++++-- .../effectTicker.ino | 192 ++++++++++++------ .../GyverLamp_v1.4_Arduino_v1.0/effects.ino | 6 +- 4 files changed, 333 insertions(+), 91 deletions(-) diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/GyverLamp_v1.4_Arduino_v1.0.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/GyverLamp_v1.4_Arduino_v1.0.ino index 3d8bf1e..2bb917f 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/GyverLamp_v1.4_Arduino_v1.0.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/GyverLamp_v1.4_Arduino_v1.0.ino @@ -18,13 +18,19 @@ // ============= НАСТРОЙКИ ============= +#define DEBUG 1 +#define VERTGAUGE 1 // вертикальный/горизонтальный индикатор +#define DEMOTIME 5 // в секундах +#define RANDOM_DEMO 1 // 0,1 - включить рандомный выбор режима + //// -------- РАССВЕТ ------- //#define DAWN_BRIGHT 200 // макс. яркость рассвета //#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут // ---------- МАТРИЦА --------- -#define BRIGHTNESS 40 // стандартная маскимальная яркость (0-255) -#define CURRENT_LIMIT 2000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит +#define BRIGHTNESS 255 // стандартная маскимальная яркость (0-255) +#define MIN17BRIGHTNESS 50 // минимальная яркость 17 режима, белая лампа (0-100) для исключения нерабочей зоны +#define CURRENT_LIMIT 2600 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит #define WIDTH 16 // ширина матрицы #define HEIGHT 16 // высота матрицы @@ -82,7 +88,8 @@ int8_t currentMode = 17; boolean loadingFlag = true; boolean ONflag = true; byte numHold; -unsigned long numHold_Timer = 0; +unsigned long numHold_Timer = 0UL; +unsigned long userTimer = 0UL; //uint32_t eepromTimer; //boolean settChanged = false; // Конфетти, Огонь, Радуга верт., Радуга гориз., Смена цвета, @@ -91,6 +98,10 @@ unsigned long numHold_Timer = 0; // colorRoutine, snowRoutine, полосы "Матрица" unsigned char matrixValue[8][16]; +byte xStep; +byte xCol; +byte yStep; +byte yCol; void setup() { @@ -107,6 +118,43 @@ void setup() { Serial.begin(9600); Serial.println(); + xStep = WIDTH / 4; + xCol = 4; + if(xStep<2) { + xStep = WIDTH / 3; + xCol = 3; + } else if(xStep<2) { + xStep = WIDTH / 2; + xCol = 2; + } else if(xStep<2) { + xStep = 1; + xCol = 1; + } + + yStep = HEIGHT / 4; + yCol = 4; + if(yStep<2) { + yStep = HEIGHT / 3; + yCol = 3; + } else if(yStep<2) { + yStep = HEIGHT / 2; + yCol = 2; + } else if(yStep<2) { + yStep = 1; + yCol = 1; + } + + #ifdef DEBUG + Serial.print("xStep: "); + Serial.print(xStep); + Serial.print(" xCol:"); + Serial.println(xCol); + Serial.print("yStep: "); + Serial.print(yStep); + Serial.print(" yCol:"); + Serial.println(yCol); + #endif + if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР currentMode = EEPROM.read(1); for (byte x = 0; x < MODE_AMOUNT; x++) { diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/button.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/button.ino index cd87c85..f839ee6 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/button.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/button.ino @@ -1,10 +1,69 @@ boolean brightDirection, speedDirection, scaleDirection; //byte numHold; +void debugPrint(){ + Serial.print(numHold); + Serial.print(" brightness:"); + Serial.print(modes[currentMode].brightness); + Serial.print(" speed:"); + Serial.print(modes[currentMode].speed); + Serial.print(" scale:"); + Serial.print(modes[currentMode].scale); + Serial.print(" numHold_Timer:"); + Serial.println(numHold_Timer); +} + +void changeDirection(byte numHold){ + switch(numHold){ + case 0: case 1: brightDirection = !brightDirection; break; + case 2: speedDirection = !speedDirection; break; + case 3: scaleDirection = !scaleDirection; break; + } + numHold_Timer = millis(); +} + void buttonTick() { touch.tick(); + + if (!ONflag) { // Обработка из выключенного состояния + #ifdef DEBUG + if(touch.isPress()) + Serial.println("Off state"); + #endif + + if (touch.isDouble()) { // Демо-режим, с переключением каждые 30 секунд для двойного клика в выключенном состоянии + numHold = 254; + currentMode = random(0, 255)%17; // 17 скипаем + //modes[currentMode].brightness = BRIGHTNESS/2; // в половину яркости + FastLED.setBrightness(modes[currentMode].brightness); + ONflag = true; + userTimer = millis(); // момент включения для таймаута в DEMOTIME + numHold_Timer = millis(); + //brightDirection = 0; // на уменьшение + changePower(); + #ifdef DEBUG + Serial.print("Demo mode: "); + Serial.println(currentMode); + #endif + } + + if (touch.isHolded()) { + #ifdef DEBUG + Serial.println("Holdeded from offed state"); + #endif + currentMode = 17; + modes[currentMode].brightness = BRIGHTNESS; + FastLED.setBrightness(modes[currentMode].brightness); + numHold = 255; + ONflag = true; + userTimer = millis(); // момент включения для таймаута в переключения в режим регулировки яркости + numHold_Timer = millis(); + brightDirection = 0; // на уменьшение + changePower(); + } + } - if (touch.isSingle()) { + if (touch.isSingle()) { // Включение/выключение одиночным // if (dawnFlag) { // //manualOff = true; // dawnFlag = false; @@ -12,19 +71,32 @@ void buttonTick() { // FastLED.setBrightness(modes[currentMode].brightness); // changePower(); // } else + // Serial.println("Single click"); { if (ONflag) { ONflag = false; + #ifdef DEBUG + Serial.println("Off lamp"); + #endif changePower(); } else { ONflag = true; - changePower(); + #ifdef DEBUG + Serial.println("On lamp"); + debugPrint(); // отладка + #endif + //FastLED.setBrightness(modes[currentMode].brightness); + //changePower(); } } } if (ONflag) { // если включено if (touch.isDouble()) { + #ifdef DEBUG + Serial.println("Double click"); + //debugPrint(); // отладка + #endif if (++currentMode >= MODE_AMOUNT) currentMode = 0; FastLED.setBrightness(modes[currentMode].brightness); loadingFlag = true; @@ -33,6 +105,10 @@ if (ONflag) { // если включено delay(1); } if (touch.isTriple()) { + #ifdef DEBUG + Serial.println("Triple click"); + //debugPrint(); // отладка + #endif if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; FastLED.setBrightness(modes[currentMode].brightness); loadingFlag = true; @@ -41,7 +117,7 @@ if (ONflag) { // если включено delay(1); } - if ((touch.hasClicks()) && (touch.getClicks() == 5)) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров // && (touch.hasClicks()) + if ((touch.hasClicks()) && (touch.getClicks() == 5)) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров // && (touch.hasClicks()) if (EEPROM.read(0) != 102) EEPROM.write(0, 102); if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов @@ -57,32 +133,51 @@ if (ONflag) { // если включено changePower(); } - if (touch.isHolded()) { // изменение яркости при удержании кнопки - brightDirection = !brightDirection; - numHold = 1; + if (touch.isHolded() && numHold != 255) { // изменение яркости при удержании кнопки + if(modes[currentMode].brightness == BRIGHTNESS && numHold == 1){ + brightDirection = 0; + } else if (modes[currentMode].brightness <= 1 && numHold == 1){ + brightDirection = 1; + } else + changeDirection(numHold); + if(!numHold || numHold==254) + numHold = 1; } if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки - speedDirection = !speedDirection; - numHold = 2; + if(modes[currentMode].speed == 255 && numHold == 2){ + speedDirection = 0; + } else if (modes[currentMode].speed <= 1 && numHold == 2){ + speedDirection = 1; + } else + changeDirection(numHold); + if(!numHold) + numHold = 2; } if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки - scaleDirection = !scaleDirection; - numHold = 3; + if(modes[currentMode].scale == 255 && numHold == 3){ + scaleDirection = 0; + } else if (modes[currentMode].scale <= 1 && numHold == 3){ + scaleDirection = 1; + } else + changeDirection(numHold); + if(!numHold) + numHold = 3; } if (touch.isStep()) { -// Serial.print(numHold); -// Serial.print(" brightness:"); -// Serial.print(modes[currentMode].brightness); -// Serial.print(" speed:"); -// Serial.print(modes[currentMode].speed); -// Serial.print(" scale:"); -// Serial.println(modes[currentMode].scale); - if (numHold != 0) numHold_Timer = millis(); loadingFlag = true; + #ifdef DEBUG + debugPrint(); // отладка + #endif + if (numHold != 0 && numHold != 255) { + numHold_Timer = millis(); + loadingFlag = true; + } + switch (numHold) { case 1: + case 254: // if (brightDirection) { // if (modes[currentMode].brightness < 10) modes[currentMode].brightness += 1; // else if (modes[currentMode].brightness < 250) modes[currentMode].brightness += 5; @@ -92,7 +187,10 @@ if (ONflag) { // если включено // else if (modes[currentMode].brightness > 1) modes[currentMode].brightness -= 1; // else modes[currentMode].brightness = 1; // } - modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , 255); + if(currentMode==17) + modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), MIN17BRIGHTNESS , BRIGHTNESS); + else + modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , BRIGHTNESS); // byte x = sqrt(modes[currentMode].brightness); // for (byte y = 0; y < HEIGHT - 1; y++) { // if (x < y) drawPixelXY(1, y, CHSV(10,200,200)); @@ -127,10 +225,40 @@ if (ONflag) { // если включено break; } } - if ((millis() - numHold_Timer) > numHold_Time) { - numHold = 0; - numHold_Timer = millis(); + + if ((millis() - userTimer) > numHold_Time && numHold>=250) { + if(numHold == 255){ + numHold = 1; + userTimer = millis(); + numHold_Timer = millis(); + } + } + + if ((millis() - numHold_Timer) > numHold_Time && !touch.isHolded() && numHold<250) { + numHold = 0; + numHold_Timer = millis(); + } + + if((millis() - userTimer > DEMOTIME*1000) && (numHold == 254)){ + //FastLED.clear(); + //delay(2); + for(byte i = 250; i>10; i-=10){ + fader(30); + FastLED.delay(33); + //FastLED.show(); + } + + if(RANDOM_DEMO) + currentMode = random(0, 255)%17; // 17 скипаем + else + currentMode=(currentMode+1)%17; // 17 скипаем и идем по наростанию + #ifdef DEBUG + Serial.print("Demo mode: "); + Serial.println(currentMode); + #endif + userTimer = millis(); } + FastLED.setBrightness(modes[currentMode].brightness); //settChanged = true; } diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/effectTicker.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/effectTicker.ino index aab079d..4d04b64 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/effectTicker.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/effectTicker.ino @@ -4,76 +4,140 @@ byte ind; void effectsTick() { // if (!dawnFlag) { - if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { + if (millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { effTimer = millis(); - switch (currentMode) { - case 0: sparklesRoutine(); - break; - case 1: fireRoutine(); - break; - case 2: rainbowVertical(); - break; - case 3: rainbowHorizontal(); - break; - case 4: colorsRoutine(); - break; - case 5: madnessNoise(); - break; - case 6: cloudNoise(); - break; - case 7: lavaNoise(); - break; - case 8: plasmaNoise(); - break; - case 9: rainbowNoise(); - break; - case 10: rainbowStripeNoise(); - break; - case 11: zebraNoise(); - break; - case 12: forestNoise(); - break; - case 13: oceanNoise(); - break; - case 14: colorRoutine(); - break; - case 15: snowRoutine(); - break; - case 16: matrixRoutine(); - break; - case 17: whiteLamp(); - // case 17: lightersRoutine(); - break; - } - switch (numHold) { // индикатор уровня яркости/скорости/масштаба - case 1: - ind = sqrt(modes[currentMode].brightness + 1); - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) drawPixelXY(0, y, CHSV(10, 255, 255)); - else drawPixelXY(0, y, 0); - } - break; - case 2: - ind = sqrt(modes[currentMode].speed - 1); - for (byte y = 0; y <= HEIGHT ; y++) { - if (ind <= y) drawPixelXY(0, 15 - y, CHSV(100, 255, 255)); - else drawPixelXY(0, 15 - y, 0); - } - break; - case 3: - ind = sqrt(modes[currentMode].scale + 1); - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) drawPixelXY(0, y, CHSV(150, 255, 255)); - else drawPixelXY(0, y, 0); - } - break; - + if(ONflag){ + switch (currentMode) { + case 0: sparklesRoutine(); + break; + case 1: fireRoutine(); + break; + case 2: rainbowVertical(); + break; + case 3: rainbowHorizontal(); + break; + case 4: colorsRoutine(); + break; + case 5: madnessNoise(); + break; + case 6: cloudNoise(); + break; + case 7: lavaNoise(); + break; + case 8: plasmaNoise(); + break; + case 9: rainbowNoise(); + break; + case 10: rainbowStripeNoise(); + break; + case 11: zebraNoise(); + break; + case 12: forestNoise(); + break; + case 13: oceanNoise(); + break; + case 14: colorRoutine(); + break; + case 15: snowRoutine(); + break; + case 16: matrixRoutine(); + break; + case 17: whiteLamp(); + // case 17: lightersRoutine(); + break; + } + if(VERTGAUGE) + GaugeShowVertical(); + else + GaugeShowHorizontal(); } FastLED.show(); } } } +void GaugeShowVertical() { + switch (numHold) { // индикатор уровня яркости/скорости/масштаба + case 1: + if(currentMode==17) + ind = sqrt((255.0/(BRIGHTNESS-MIN17BRIGHTNESS))*(modes[currentMode].brightness-MIN17BRIGHTNESS) + 1); // привести к полной шкале + else + ind = sqrt((255.0/BRIGHTNESS)*modes[currentMode].brightness + 1); // привести к полной шкале + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) + drawPixelXY(x, y, CHSV(10, 255, 255)); + else + drawPixelXY(x, y, 0); + } + } + break; + case 2: + ind = sqrt(modes[currentMode].speed - 1); + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y <= HEIGHT ; y++) { + if (ind <= y) + drawPixelXY(x, HEIGHT-1-y, CHSV(100, 255, 255)); + else + drawPixelXY(x, HEIGHT-1-y, 0); + } + } + break; + case 3: + ind = sqrt(modes[currentMode].scale + 1); + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) + drawPixelXY(x, y, CHSV(150, 255, 255)); + else + drawPixelXY(x, y, 0); + } + } + break; + } +} + +void GaugeShowHorizontal() { + switch (numHold) { // индикатор уровня яркости/скорости/масштаба + case 1: + if(currentMode==17) + ind = sqrt((255.0/(BRIGHTNESS-MIN17BRIGHTNESS))*(modes[currentMode].brightness-MIN17BRIGHTNESS) + 1); // привести к полной шкале + else + ind = sqrt((255.0/BRIGHTNESS)*modes[currentMode].brightness + 1); // привести к полной шкале + for (byte y = 0; y <= yCol*(yStep-1) ; y+=yStep) { + for (byte x = 0; x < WIDTH ; x++) { + if (ind > x) + drawPixelXY((x+y)%WIDTH, y, CHSV(10, 255, 255)); + else + drawPixelXY((x+y)%WIDTH, y, 0); + } + } + break; + case 2: + ind = sqrt(modes[currentMode].speed - 1); + for (byte y = 0; y <= yCol*(yStep-1) ; y+=yStep) { + for (byte x = 0; x <= WIDTH ; x++) { + if (ind < x) + drawPixelXY((WIDTH-x+y)%WIDTH, y, CHSV(100, 255, 255)); + else + drawPixelXY((WIDTH-x+y)%WIDTH, y, 0); + } + } + break; + case 3: + ind = sqrt(modes[currentMode].scale + 1); + for (byte y = 0; y <= yCol*(yStep-1) ; y+=yStep) { + for (byte x = 0; x < WIDTH ; x++) { + if (ind > x) + drawPixelXY((x+y)%WIDTH, y, CHSV(150, 255, 255)); + else + drawPixelXY((x+y)%WIDTH, y, 0); + } + } + break; + } +} + void changePower() { // плавное включение/выключение if (ONflag) { effectsTick(); @@ -86,7 +150,7 @@ void changePower() { // плавное включение/выключени delay(2); FastLED.show(); } else { - effectsTick(); + //effectsTick(); for (int i = modes[currentMode].brightness; i > 8; i -= 8) { FastLED.setBrightness(i); delay(1); diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/effects.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/effects.ino index 8fdb101..ed2cccc 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/effects.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/effects.ino @@ -184,7 +184,8 @@ void colorsRoutine() { // --------------------------------- ЦВЕТ ------------------------------------ void colorRoutine() { for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); + //leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); + leds[i] = CHSV(modes[14].speed*(modes[14].scale/16+1), 255, 255); } } @@ -231,7 +232,8 @@ void matrixRoutine() { // ------------------------------ БЕЛАЯ ЛАМПА ------------------------------ void whiteLamp() { for (byte y = 0; y < (HEIGHT / 2); y++) { - CHSV color = CHSV(100, 1, constrain(modes[17].brightness - (long)modes[17].speed * modes[17].brightness / 255 * y / 2, 1, 255)); + CHSV color = CHSV(56, modes[17].scale, constrain(modes[17].brightness - (long)modes[17].speed * modes[17].brightness / BRIGHTNESS * y / 2, 1, 255)); + //CHSV color = CHSV(100, 1, constrain(modes[17].brightness - (long)modes[17].speed * modes[17].brightness / BRIGHTNESS * y / 2, 1, 255)); for (byte x = 0; x < WIDTH; x++) { drawPixelXY(x, y + 8, color); drawPixelXY(x, 7 - y, color); From 5af1d6a68f4070474e012e8dbd3fe07ec3513481 Mon Sep 17 00:00:00 2001 From: Stepko/ Date: Tue, 13 Oct 2020 19:38:34 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A1=D0=BF=D0=B5=D1=86=D0=B8=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=B0=D1=8F=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20kDn=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * v1.2 Перевод на оригинальную библиотеку GyverButton. * Update README.md * Update README.md * Update README.md * Update README.md * Update button.ino * Add files via upload * Update README.md * Add files via upload * Light version * Light version * Add files via upload * Update README.md * Add files via upload * Add files via upload * Update README.md * Add files via upload * Add files via upload * Update README.md * Add files via upload Co-authored-by: Norovl --- ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino | 54 + ArduinoLamp_v1.4/Constants.h | 31 + ArduinoLamp_v1.4/button.ino | 92 + ArduinoLamp_v1.4/effectTicker.ino | 94 + ArduinoLamp_v1.4/effects.ino | 507 ++++ ArduinoLamp_v1.4/noiseEffects.ino | 269 +++ ArduinoLamp_v1.4/utility.ino | 192 ++ ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino | 54 + ArduinoLamp_v1.5/Constants.h | 36 + ArduinoLamp_v1.5/bitmap2.h | 61 + ArduinoLamp_v1.5/button.ino | 93 + ArduinoLamp_v1.5/effectTicker.ino | 108 + ArduinoLamp_v1.5/effects.ino | 2063 +++++++++++++++++ ArduinoLamp_v1.5/noiseEffects.ino | 283 +++ ArduinoLamp_v1.5/utility.ino | 195 ++ GyverButtonOld/GyverButton.rar | Bin 0 -> 3454 bytes GyverButtonOld/GyverButtonOld.cpp | 199 ++ GyverButtonOld/GyverButtonOld.h | 107 + .../Gbutton_example/Gbutton_example.ino | 50 + .../Gbutton_example_auto.ino | 53 + .../Gbutton_interrupt/Gbutton_interrupt.ino | 48 + .../Gbutton_timer_interrupt.ino | 51 + .../examples/_1-2-3-click/_1-2-3-click.ino | 20 + .../examples/_5_buttons/_5_buttons.ino | 34 + .../_5_buttons_auto/_5_buttons_auto.ino | 34 + .../analogKeyboard/analogKeyboard.ino | 32 + .../examples/increment/increment.ino | 41 + .../examples/many_clicks/many_clicks.ino | 19 + GyverButtonOld/keywords.txt | 48 + GyverButtonOld/old_version.rar | Bin 0 -> 8826 bytes GyverButtonOld/old_version/GyverButton.cpp | 119 + GyverButtonOld/old_version/GyverButton.h | 57 + .../Gbutton_example/Gbutton_example.ino | 46 + .../Gbutton_timer_interrupt.ino | 56 + .../examples/_1-2-3-click/_1-2-3-click.ino | 20 + .../examples/_5_buttons/_5_buttons.ino | 34 + .../examples/increment/increment.ino | 46 + .../examples/many_clicks/many_clicks.ino | 20 + GyverButtonOld/old_version/keywords.txt | 31 + GyverButtonOld/old_version/readme.txt | 13 + .../GyverLamp_v1.4_Arduino_v1.0.ino | 152 ++ GyverLamp_v1.4_Arduino_v1.0kDn/button.ino | 223 ++ .../effectTicker.ino | 115 + GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino | 158 ++ .../noiseEffects.ino | 194 ++ GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino | 128 + README.md | 21 +- .../GyverLamp_v1.4_Arduino_v1.2.ino | 127 + .../GyverLamp_v1.4_Arduino_v1.2/button.ino | 110 + .../effectTicker.ino | 99 + .../GyverLamp_v1.4_Arduino_v1.2/effects.ino | 292 +++ .../noiseEffects.ino | 205 ++ .../GyverLamp_v1.4_Arduino_v1.2/utility.ino | 87 + 53 files changed, 7206 insertions(+), 15 deletions(-) create mode 100644 ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino create mode 100644 ArduinoLamp_v1.4/Constants.h create mode 100644 ArduinoLamp_v1.4/button.ino create mode 100644 ArduinoLamp_v1.4/effectTicker.ino create mode 100644 ArduinoLamp_v1.4/effects.ino create mode 100644 ArduinoLamp_v1.4/noiseEffects.ino create mode 100644 ArduinoLamp_v1.4/utility.ino create mode 100644 ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino create mode 100644 ArduinoLamp_v1.5/Constants.h create mode 100644 ArduinoLamp_v1.5/bitmap2.h create mode 100644 ArduinoLamp_v1.5/button.ino create mode 100644 ArduinoLamp_v1.5/effectTicker.ino create mode 100644 ArduinoLamp_v1.5/effects.ino create mode 100644 ArduinoLamp_v1.5/noiseEffects.ino create mode 100644 ArduinoLamp_v1.5/utility.ino create mode 100644 GyverButtonOld/GyverButton.rar create mode 100644 GyverButtonOld/GyverButtonOld.cpp create mode 100644 GyverButtonOld/GyverButtonOld.h create mode 100644 GyverButtonOld/examples/Gbutton_example/Gbutton_example.ino create mode 100644 GyverButtonOld/examples/Gbutton_example_auto/Gbutton_example_auto.ino create mode 100644 GyverButtonOld/examples/Gbutton_interrupt/Gbutton_interrupt.ino create mode 100644 GyverButtonOld/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino create mode 100644 GyverButtonOld/examples/_1-2-3-click/_1-2-3-click.ino create mode 100644 GyverButtonOld/examples/_5_buttons/_5_buttons.ino create mode 100644 GyverButtonOld/examples/_5_buttons_auto/_5_buttons_auto.ino create mode 100644 GyverButtonOld/examples/analogKeyboard/analogKeyboard.ino create mode 100644 GyverButtonOld/examples/increment/increment.ino create mode 100644 GyverButtonOld/examples/many_clicks/many_clicks.ino create mode 100644 GyverButtonOld/keywords.txt create mode 100644 GyverButtonOld/old_version.rar create mode 100644 GyverButtonOld/old_version/GyverButton.cpp create mode 100644 GyverButtonOld/old_version/GyverButton.h create mode 100644 GyverButtonOld/old_version/examples/Gbutton_example/Gbutton_example.ino create mode 100644 GyverButtonOld/old_version/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino create mode 100644 GyverButtonOld/old_version/examples/_1-2-3-click/_1-2-3-click.ino create mode 100644 GyverButtonOld/old_version/examples/_5_buttons/_5_buttons.ino create mode 100644 GyverButtonOld/old_version/examples/increment/increment.ino create mode 100644 GyverButtonOld/old_version/examples/many_clicks/many_clicks.ino create mode 100644 GyverButtonOld/old_version/keywords.txt create mode 100644 GyverButtonOld/old_version/readme.txt create mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/GyverLamp_v1.4_Arduino_v1.0.ino create mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/button.ino create mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/effectTicker.ino create mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino create mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/noiseEffects.ino create mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino create mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/GyverLamp_v1.4_Arduino_v1.2.ino create mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/button.ino create mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/effectTicker.ino create mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/effects.ino create mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/noiseEffects.ino create mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/utility.ino diff --git a/ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino b/ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino new file mode 100644 index 0000000..9000450 --- /dev/null +++ b/ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino @@ -0,0 +1,54 @@ +/* + Скетч к проекту "Многофункциональный RGB светильник" + Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ + Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ + Автор: AlexGyver, AlexGyver Technologies, 2019(Портировал на Ардуино Norovl(+ эффекты, демо от stepko365) + https://AlexGyver.ru/ +*/ +// ---------------- БИБЛИОТЕКИ ----------------- +#include +#include +#include +//----------------- ----------------- +#include "Constants.h" +// ----------------- ПЕРЕМЕННЫЕ ------------------ +static const byte maxDim = max(WIDTH, HEIGHT); +struct { byte Brightness = 10; byte Speed = 30; byte Scale = 10; } modes[MODE_AMOUNT]; //настройки эффекта по умолчанию +int8_t currentMode = 10; +boolean loadingFlag = true; +boolean ONflag = true; +byte numHold; +unsigned long numHold_Timer = 0; +unsigned char matrixValue[8][16]; + + +void setup() { + // ЛЕНТА + FastLED.addLeds(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/; + FastLED.setBrightness(BRIGHTNESS); + if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); + FastLED.clear(); + FastLED.show(); + + touch.setStepTimeout(100); + touch.setClickTimeout(500); + + //Serial.begin(9600); + //Serial.println(); + + if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР + currentMode = EEPROM.read(1); + for (byte x = 0; x < MODE_AMOUNT; x++) { + modes[x].Brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) + modes[x].Speed = EEPROM.read(x * 3 + 12); + modes[x].Scale = EEPROM.read(x * 3 + 13); + } + + } +} + +void loop() { + effectsTick(); + buttonTick(); + demo(); +} diff --git a/ArduinoLamp_v1.4/Constants.h b/ArduinoLamp_v1.4/Constants.h new file mode 100644 index 0000000..6bec6d7 --- /dev/null +++ b/ArduinoLamp_v1.4/Constants.h @@ -0,0 +1,31 @@ +// ============= НАСТРОЙКИ ============= +// ---------- МАТРИЦА --------- +#define BRIGHTNESS 10 // стандартная маскимальная яркость (0-255) +#define CURRENT_LIMIT 1000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит + +#define WIDTH 16 // ширина матрицы +#define HEIGHT 16 // высота матрицы + +#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB + +#define MATRIX_TYPE 1 // тип матрицы: 0 - зигзаг, 1 - параллельная +#define CONNECTION_ANGLE 1 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний +#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз +// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" +// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ + +#define numHold_Time (1*1000) // время отображения индикатора уровня яркости/скорости/масштаба + +// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= +#define LED_PIN 6 // пин ленты +#define BTN_PIN 2 +#define MODE_AMOUNT 28 //кол-во эффектов +#define NUM_LEDS WIDTH * HEIGHT +#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) +// ------------------- ТИПЫ -------------------- +CRGB leds[NUM_LEDS]; +GButton touch(BTN_PIN, HIGH_PULL, NORM_OPEN); //если сенсорна кнопка LOW_PULL +#define RANDOM_DEMO 1 // 0,1 - включить рандомный выбор режима +#define DEMOTIMELIMIT ( 1 * 20UL * 1000UL) // минуты/секунды/милисекунды время задержка между эффектами +uint32_t DemTimer = 0UL; // тут будет храниться время следующего переключения эффекта +bool isDemo = false; diff --git a/ArduinoLamp_v1.4/button.ino b/ArduinoLamp_v1.4/button.ino new file mode 100644 index 0000000..7681dec --- /dev/null +++ b/ArduinoLamp_v1.4/button.ino @@ -0,0 +1,92 @@ +boolean brightDirection, speedDirection, scaleDirection; + +void buttonTick() { + touch.tick(); + + if (touch.isSingle()) { + { + if (ONflag) { + ONflag = false; + changePower(); + } else { + ONflag = true; + changePower(); + } + } + } + +if (ONflag) { // если включено + if (touch.isDouble()) { + if (++currentMode >= MODE_AMOUNT) currentMode = 0; + FastLED.setBrightness(modes[currentMode].Brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + if (touch.isTriple()) { + if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; + FastLED.setBrightness(modes[currentMode].Brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + if (touch.hasClicks()) + if (touch.getClicks() == 5) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров + if (EEPROM.read(0) != 102) EEPROM.write(0, 102); + if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект + for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов + if (EEPROM.read(x * 3 + 11) != modes[x].Brightness) EEPROM.write(x * 3 + 11, modes[x].Brightness); + if (EEPROM.read(x * 3 + 12) != modes[x].Speed) EEPROM.write(x * 3 + 12, modes[x].Speed); + if (EEPROM.read(x * 3 + 13) != modes[x].Scale) EEPROM.write(x * 3 + 13, modes[x].Scale); + } + // индикация сохранения + ONflag = false; + changePower(); + delay(200); + ONflag = true; + changePower(); + } + else if (touch.getClicks() == 4){ // если было четырёхкратное нажатие на кнопку, то переключаем демо + isDemo = !isDemo; + DemTimer = 0UL;} + + + if (touch.isHolded()) { // изменение яркости при удержании кнопки + brightDirection = !brightDirection; + numHold = 1; + } + + if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки + speedDirection = !speedDirection; + numHold = 2; + } + + if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки + scaleDirection = !scaleDirection; + numHold = 3; + } + + if (touch.isStep()) { + if (numHold != 0) numHold_Timer = millis(); loadingFlag = true; + switch (numHold) { + case 1: + modes[currentMode].Brightness = constrain(modes[currentMode].Brightness + (modes[currentMode].Brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , 255); + break; + case 2: + modes[currentMode].Speed = constrain(modes[currentMode].Speed + (modes[currentMode].Speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); + break; + + case 3: + modes[currentMode].Scale = constrain(modes[currentMode].Scale + (modes[currentMode].Scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); + break; + } + } + if ((millis() - numHold_Timer) > numHold_Time) { + numHold = 0; + numHold_Timer = millis(); + } + FastLED.setBrightness(modes[currentMode].Brightness); + } +} diff --git a/ArduinoLamp_v1.4/effectTicker.ino b/ArduinoLamp_v1.4/effectTicker.ino new file mode 100644 index 0000000..f1326b6 --- /dev/null +++ b/ArduinoLamp_v1.4/effectTicker.ino @@ -0,0 +1,94 @@ +uint32_t effTimer; +byte ind; +void effectsTick() { { if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 17) ? modes[currentMode].Speed : 50) ) {effTimer = millis(); switch (currentMode) { +//|номер |название функции эффекта |тоже надо| + case 0 : sparklesRoutine(); break; + case 1 : fireRoutine(); break; + case 3 : rainbowVertical(); break; + case 4 : rainbowHorizontal(); break; + case 5 : rainbowDiagonalRoutine(); break; + case 6 : madnessNoise(); break; + case 7 : cloudNoise(); break; + case 8 : lavaNoise(); break; + case 9 : plasmaNoise(); break; + case 10: rainbowNoise(); break; + case 11: rainbowStripeNoise(); break; + case 12: zebraNoise(); break; + case 13: forestNoise(); break; + case 14: oceanNoise(); break; + case 15: heatNoise(); break; + case 16: smokeNoise(); break; + case 18: colorRoutine(); break; + case 19: colorsRoutine(); break; + case 20: whiteLamp(); break; + case 21: matrixRoutine(); break; + case 22: snowRoutine(); break; + case 23: stormRoutine2(true); break; + case 24: stormRoutine2(false); break; + case 25: ballRoutine(); break; + case 26: ballsRoutine(); break; + case 27: MunchRoutine(); break; +} + switch (numHold) { // индикатор уровня яркости/скорости/масштаба + case 1: + ind = sqrt(modes[currentMode].Brightness + 1); + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) drawPixelXY(0, y, CHSV(10, 255, 255)); + else drawPixelXY(0, y, 0); + } + break; + case 2: + ind = sqrt(modes[currentMode].Speed - 1); + for (byte y = 0; y <= HEIGHT ; y++) { + if (ind <= y) drawPixelXY(0, 15 - y, CHSV(100, 255, 255)); + else drawPixelXY(0, 15 - y, 0); + } + break; + case 3: + ind = sqrt(modes[currentMode].Scale + 1); + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) drawPixelXY(0, y, CHSV(150, 255, 255)); + else drawPixelXY(0, y, 0); + } + break; + + } + FastLED.show(); + } + } +} + +void changePower() { // плавное включение/выключение + if (ONflag) { + effectsTick(); + for (int i = 0; i < modes[currentMode].Brightness; i += 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.setBrightness(modes[currentMode].Brightness); + delay(2); + FastLED.show(); + } else { + effectsTick(); + for (int i = modes[currentMode].Brightness; i > 8; i -= 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.clear(); + delay(2); + FastLED.show(); + } +} + + void demo(){ + if (isDemo && ONflag && millis() >= DemTimer){ + if(RANDOM_DEMO) + currentMode = random8(MODE_AMOUNT); // если нужен следующий случайный эффект + else + currentMode = currentMode + 1U < MODE_AMOUNT ? currentMode + 1U : 0U; // если нужен следующий по списку эффект + FastLED.clear(); + DemTimer = millis() + DEMOTIMELIMIT; + loadingFlag = true;} +} diff --git a/ArduinoLamp_v1.4/effects.ino b/ArduinoLamp_v1.4/effects.ino new file mode 100644 index 0000000..aab879b --- /dev/null +++ b/ArduinoLamp_v1.4/effects.ino @@ -0,0 +1,507 @@ +// ================================= ЭФФЕКТЫ ==================================== +uint8_t wrapX(int8_t x){ + return (x + WIDTH)%WIDTH; +} +uint8_t wrapY(int8_t y){ + return (y + HEIGHT)%HEIGHT; +} +uint8_t step; // какой-нибудь счётчик кадров или постедовательностей операций +uint8_t pcnt; +uint8_t line[WIDTH]; +uint8_t deltaValue; // просто повторно используемая переменная +uint8_t shiftHue[HEIGHT]; +uint8_t shiftValue[HEIGHT]; +// палитра для типа реалистичного водопада (если ползунок Масштаб выставить на 100) +extern const TProgmemRGBPalette16 WaterfallColors_p FL_PROGMEM = {0x000000, 0x060707, 0x101110, 0x151717, 0x1C1D22, 0x242A28, 0x363B3A, 0x313634, 0x505552, 0x6B6C70, 0x98A4A1, 0xC1C2C1, 0xCACECF, 0xCDDEDD, 0xDEDFE0, 0xB2BAB9}; +CRGB _pulse_color; +void blurScreen(fract8 blur_amount, CRGB *LEDarray = leds) +{ + blur2d(LEDarray, WIDTH, HEIGHT, blur_amount); +} +const TProgmemRGBPalette16 *palette_arr[] = { + &PartyColors_p, + &OceanColors_p, + &LavaColors_p, + &HeatColors_p, + &WaterfallColors_p, + &CloudColors_p, + &ForestColors_p, + &RainbowColors_p, + &RainbowStripeColors_p +}; +const TProgmemRGBPalette16 *curPalette = palette_arr[0]; +void setCurrentPalette() { + if (modes[currentMode].Scale > 100U) modes[currentMode].Scale = 100U; // чтобы не было проблем при прошивке без очистки памяти + curPalette = palette_arr[(uint8_t)(modes[currentMode].Scale / 100.0F * ((sizeof(palette_arr) / sizeof(TProgmemRGBPalette16 *)) - 0.01F))]; +} +// --------------------------------- конфетти ------------------------------------ +#define FADE_OUT_SPEED (70U) // скорость затухания +void sparklesRoutine() +{ + for (uint8_t i = 0; i < modes[currentMode].Scale; i++) + { + uint8_t x = random(0U, WIDTH); + uint8_t y = random(0U, HEIGHT); + if (getPixColorXY(x, y) == 0U) + { + leds[XY(x, y)] = CHSV(random(0U, 255U), 255U, 255U); + } + } + fader(FADE_OUT_SPEED); +} +// функция плавного угасания цвета для всех пикселей +void fader(uint8_t step) +{ + for (uint8_t i = 0U; i < WIDTH; i++) + { + for (uint8_t j = 0U; j < HEIGHT; j++) + { + fadePixel(i, j, step); + } + } +} +void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер +{ + int32_t pixelNum = XY(i, j); + if (getPixColor(pixelNum) == 0U) return; + + if (leds[pixelNum].r >= 30U || + leds[pixelNum].g >= 30U || + leds[pixelNum].b >= 30U) + { + leds[pixelNum].fadeToBlackBy(step); + } + else + { + leds[pixelNum] = 0U; + } +} +// -------------------------------------- огонь --------------------------------------------- +#define SPARKLES 1 // вылетающие угольки вкл выкл +//these values are substracetd from the generated values to give a shape to the animation +const unsigned char valueMask[8][16] PROGMEM = { + {0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 }, + {0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 }, + {0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 }, + {0 , 32 , 64 , 128, 128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 128, 64 , 32 , 0 }, + {32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 }, + {64 , 96 , 128, 192, 192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128, 96 , 64 }, + {96 , 128, 160, 255, 255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160, 128, 96 }, + {128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128} +}; + +//these are the hues for the fire, +//should be between 0 (red) to about 25 (yellow) +const unsigned char hueMask[8][16] PROGMEM = { + {25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25 }, + {25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19 }, + {19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16 }, + {13, 13, 5 , 1 , 1 , 5 , 11, 13, 13, 13, 5 , 1 , 1 , 5 , 11, 13 }, + {11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11 }, + {8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 }, + {5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 }, + {1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } +}; + +void fireRoutine() { + if (loadingFlag) { + loadingFlag = false; + //FastLED.clear(); + generateLine(); + } + if (pcnt >= 100) { + shiftUp(); + generateLine(); + pcnt = 0; + } + drawFrame(pcnt); + pcnt += 25; +} + +// Случайным образом генерирует следующую линию (matrix row) + +void generateLine() { + for (uint8_t x = 0; x < WIDTH; x++) { + line[x] = random(127, 255); + } +} + +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 - 15; + 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 - 15; + matrixValue[0][newX] = line[newX]; + } +} + +// рисует кадр, интерполируя между 2 "ключевых кадров" +// параметр pcnt - процент интерполяции + +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 - 15; + 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( + modes[currentMode].Scale * 2.5 + 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); + + } + } + } + + //Перавя стрка интерполируется со следующей "next" линией + for (unsigned char x = 0; x < WIDTH; x++) { + uint8_t newX = x; + if (x > 15) newX = x - 15; + CRGB color = CHSV( + modes[currentMode].Scale * 2.5 + 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; + } +} +// ---------------------------------------- радуга ------------------------------------------ +byte hue; +void rainbowVertical() { + hue += 2; + for (byte j = 0; j < HEIGHT; j++) { + CHSV thisColor = CHSV((byte)(hue + j * modes[currentMode].Scale), 255, 255); + for (byte i = 0; i < WIDTH; i++) + drawPixelXY(i, j, thisColor); + } +} +void rainbowHorizontal() { + hue += 2; + for (byte i = 0; i < WIDTH; i++) { + CHSV thisColor = CHSV((byte)(hue + i * modes[currentMode].Scale), 255, 255); + for (byte j = 0; j < HEIGHT; j++) + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; + } +} +void rainbowDiagonalRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + FastLED.clear(); + } + + hue += 8; + for (uint8_t i = 0U; i < WIDTH; i++) + { + for (uint8_t j = 0U; j < HEIGHT; j++) + { + float twirlFactor = 3.0F * (modes[currentMode].Scale / 100.0F); // на сколько оборотов будет закручена матрица, [0..3] + CRGB thisColor = CHSV((uint8_t)(hue + ((float)WIDTH / HEIGHT * i + j * twirlFactor) * ((float)255 / maxDim)), 255, 255); + drawPixelXY(i, j, thisColor); + } + } +} +// ---------------------------------------- ЦВЕТА ----------------------------- +void colorsRoutine() { + hue += modes[currentMode].Scale; + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = CHSV(hue, 255, 255); + } +} + +// --------------------------------- ЦВЕТ ------------------------------------ +void colorRoutine() { + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = CHSV(modes[currentMode].Scale * 2.5, modes[currentMode].Speed * 2.5, 255); + } +} + +// ------------------------------ снегопад 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, modes[currentMode].Scale) == 0)) + drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); + else + drawPixelXY(x, HEIGHT - 1, 0x000000); + } +} + +// ------------------------------ МАТРИЦА ------------------------------ +void matrixRoutine() { + for (byte x = 0; x < WIDTH; x++) { + // заполняем случайно верхнюю строку + uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); + if (thisColor == 0) + drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, modes[currentMode].Scale) == 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 whiteLamp() { + for (byte y = 0; y < (HEIGHT / 2); y++) { + CHSV color = CHSV(100, 1, constrain(modes[currentMode].Brightness - (long)modes[currentMode].Speed * modes[currentMode].Brightness / 255 * y / 2, 1, 255)); + for (byte x = 0; x < WIDTH; x++) { + drawPixelXY(x, y + 8, color); + drawPixelXY(x, 7 - y, color); + } + } +} +//--------------------------Шторм,Метель------------------------- +#define e_sns_DENSE (32U) // плотность снега - меньше = плотнее +void stormRoutine2(bool isColored) +{ + // заполняем головами комет + uint8_t Saturation = 0U; // цвет хвостов + uint8_t e_TAIL_STEP = 127U; // длина хвоста + if (isColored) + Saturation = modes[currentMode].Scale * 2.55; + else + { + e_TAIL_STEP = 255U - modes[currentMode].Scale * 2.55; + } + for (int8_t x = 0U; x < WIDTH - 1U; x++) // fix error i != 0U + { + if (!random8(e_sns_DENSE) && + !getPixColorXY(wrapX(x), HEIGHT - 1U) && + !getPixColorXY(wrapX(x + 1U), HEIGHT - 1U) && + !getPixColorXY(wrapX(x - 1U), HEIGHT - 1U)) + { + drawPixelXY(x, HEIGHT - 1U, CHSV(random8(), Saturation, random8(64U, 255U))); + } + } + + // сдвигаем по диагонали + for (int8_t y = 0U; y < HEIGHT - 1U; y++) + { + for (int8_t x = 0; x < WIDTH; x++) + { + drawPixelXY(wrapX(x + 1U), y, getPixColorXY(x, y + 1U)); + } + } + + // уменьшаем яркость верхней линии, формируем "хвосты" + for (int8_t i = 0U; i < WIDTH; i++) + { + fadePixel(i, HEIGHT - 1U, e_TAIL_STEP); + } +} +//-------------------------Блуждающий кубик----------------------- +#define RANDOM_COLOR (1U) // случайный цвет при отскоке +int16_t coordB[2U]; +int8_t vectorB[2U]; +CRGB ballColor; +//int8_t deltaValue; //ballSize; + +void ballRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + //FastLED.clear(); + + for (uint8_t i = 0U; i < 2U; i++) + { + coordB[i] = WIDTH / 2 * 10; + vectorB[i] = random(8, 20); + } + deltaValue = map(modes[currentMode].Scale * 2.55, 0U, 255U, 2U, max((uint8_t)min(WIDTH, HEIGHT) / 3, 2)); + ballColor = CHSV(random(0, 9) * 28, 255U, 255U); +// _pulse_color = CHSV(random(0, 9) * 28, 255U, 255U); + } + +// if (!(modes[currentMode].Scale & 0x01)) +// { +// hue += (modes[currentMode].Scale - 1U) % 11U * 8U + 1U; + +// ballColor = CHSV(hue, 255U, 255U); +// } + + if ((modes[currentMode].Scale & 0x01)) + for (uint8_t i = 0U; i < deltaValue; i++) + for (uint8_t j = 0U; j < deltaValue; j++) + leds[XY(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = _pulse_color; + + for (uint8_t i = 0U; i < 2U; 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, 255U, 255U); // if (RANDOM_COLOR && (modes[currentMode].Scale & 0x01)) + //vectorB[i] += random(0, 6) - 3; + } + } + if (coordB[0U] > (int16_t)((WIDTH - deltaValue) * 10)) + { + coordB[0U] = (WIDTH - deltaValue) * 10; + vectorB[0U] = -vectorB[0U]; + if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U); + //vectorB[0] += random(0, 6) - 3; + } + if (coordB[1U] > (int16_t)((HEIGHT - deltaValue) * 10)) + { + coordB[1U] = (HEIGHT - deltaValue) * 10; + vectorB[1U] = -vectorB[1U]; + if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U); + //vectorB[1] += random(0, 6) - 3; + } + +// if (modes[currentMode].Scale & 0x01) +// dimAll(135U); +// dimAll(255U - (modes[currentMode].Scale - 1U) % 11U * 24U); +// else + FastLED.clear(); + + for (uint8_t i = 0U; i < deltaValue; i++) + for (uint8_t j = 0U; j < deltaValue; j++) + leds[XY(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = ballColor; +} + +//-------------------Светлячки со шлейфом---------------------------- +#define BALLS_AMOUNT (3U) // количество "шариков" +#define CLEAR_PATH (1U) // очищать путь +#define BALL_TRACK (1U) // (0 / 1) - вкл/выкл следы шариков +#define TRACK_STEP (70U) // длина хвоста шарика (чем больше цифра, тем хвост короче) +int16_t coord[BALLS_AMOUNT][2U]; +int8_t vector[BALLS_AMOUNT][2U]; +CRGB ballColors[BALLS_AMOUNT]; +void ballsRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + + for (uint8_t j = 0U; j < BALLS_AMOUNT; j++) + { + int8_t sign; + // забиваем случайными данными + coord[j][0U] = WIDTH / 2 * 10; + random(0, 2) ? sign = 1 : sign = -1; + vector[j][0U] = random(4, 15) * sign; + coord[j][1U] = HEIGHT / 2 * 10; + random(0, 2) ? sign = 1 : sign = -1; + vector[j][1U] = random(4, 15) * sign; + //ballColors[j] = CHSV(random(0, 9) * 28, 255U, 255U); + // цвет зависит от масштаба + ballColors[j] = CHSV((modes[currentMode].Scale * (j + 1)) % 256U, 255U, 255U); + } + } + + if (!BALL_TRACK) // режим без следов шариков + { + FastLED.clear(); + } + else // режим со следами + { + fader(TRACK_STEP); + } + + // движение шариков + for (uint8_t j = 0U; j < BALLS_AMOUNT; j++) + { + // движение шариков + for (uint8_t i = 0U; i < 2U; i++) + { + coord[j][i] += vector[j][i]; + if (coord[j][i] < 0) + { + coord[j][i] = 0; + vector[j][i] = -vector[j][i]; + } + } + + if (coord[j][0U] > (int16_t)((WIDTH - 1) * 10)) + { + coord[j][0U] = (WIDTH - 1) * 10; + vector[j][0U] = -vector[j][0U]; + } + if (coord[j][1U] > (int16_t)((HEIGHT - 1) * 10)) + { + coord[j][1U] = (HEIGHT - 1) * 10; + vector[j][1U] = -vector[j][1U]; + } + leds[XY(coord[j][0U] / 10, coord[j][1U] / 10)] = ballColors[j]; + } +} + +//-----------------Эффект Вышиванка------------- +byte count = 0; +byte dir = 1; +byte flip = 0; +byte generation = 0; +void MunchRoutine() { if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + for (byte x = 0; x < WIDTH; x++) { + for (byte y = 0; y < HEIGHT; y++) { + leds[XY(x, y)] = (x ^ y ^ flip) < count ? ColorFromPalette(*curPalette, ((x ^ y) << 4) + generation) : CRGB::Black; + } + } + + count += dir; + + if (count <= 0 || count >= WIDTH) { + dir = -dir; + } + + if (count <= 0) { + if (flip == 0) + flip = 7; + else + flip = 0; + } + + generation++; +} diff --git a/ArduinoLamp_v1.4/noiseEffects.ino b/ArduinoLamp_v1.4/noiseEffects.ino new file mode 100644 index 0000000..de459ef --- /dev/null +++ b/ArduinoLamp_v1.4/noiseEffects.ino @@ -0,0 +1,269 @@ +// ************* НАСТРОЙКИ ************* +// The 16 bit version of our coordinates +static uint16_t x; +static uint16_t y; +static uint16_t z; + +uint16_t speed = 20; // speed is set dynamically once we've started up +uint16_t scale = 30; // scale is set dynamically once we've started up + +// This is the array that we keep our computed noise values in +#define MAX_DIMENSION (max(WIDTH, HEIGHT)) +#if (WIDTH > HEIGHT) +uint8_t noise[WIDTH][WIDTH]; +#else +uint8_t noise[HEIGHT][HEIGHT]; +#endif + +CRGBPalette16 pPalette; + +// This function sets up a palette of black and blue stripes, +// using code. Since the palette is effectively an array of +// sixteen CRGB colors, the various fill_* functions can be used +// to set them up. +void SetupPalette() +{ + // 'black out' all 16 palette entries... + fill_solid( pPalette, 16, CHSV(modes[currentMode].Scale * 2.5,255, 75)); + + for(uint8_t i = 0; i < 6; i++) { + pPalette[i] = CHSV(modes[currentMode].Scale * 2.5, 255, 255); + } +} + + +CRGBPalette16 currentPalette(PartyColors_p); +uint8_t colorLoop = 1; +uint8_t ihue = 0; + +void madnessNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + } + fillnoise8(); + for (uint8_t i = 0; i < WIDTH; i++) + { + for (uint8_t j = 0; j < HEIGHT; j++) + { + CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); + leds[XY(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); + } + } + ihue += 1; +} + +void rainbowNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = RainbowColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 1; + } + fillNoiseLED(0.125,0.0625,1); +} + +void rainbowStripeNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = RainbowStripeColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 1; + } + fillNoiseLED(0.125,0.0625,1); +} + +void zebraNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + // 'black out' all 16 palette entries... + fill_solid(currentPalette, 16, CRGB::Black); + // and set every fourth one to white. + currentPalette[0] = CRGB::White; + currentPalette[4] = CRGB::White; + currentPalette[8] = CRGB::White; + currentPalette[12] = CRGB::White; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 1; + } + fillNoiseLED(0.125,0.0625,1); +} + +void forestNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = ForestColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(0.125,0.0625,1); +} + +void oceanNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = OceanColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + + fillNoiseLED(0.125,0.0625,1); +} + +void plasmaNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = PartyColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 1; + } + fillNoiseLED(0.125,0.0625,1); +} + +void cloudNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = CloudColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(0.125,0.0625,1); +} + +void lavaNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = LavaColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(0.125,0.0625,1); +} + +void heatNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = HeatColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(1,0,0.125); +} + +void smokeNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = WaterfallColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(1,0,0.125); +} +// ************* СЛУЖЕБНЫЕ ************* +void fillNoiseLED(byte x_dir, byte y_dir, byte z_dir) +{ + uint8_t dataSmoothing = 0; + if (speed < 50) + { + dataSmoothing = 200 - (speed * 4); + } + for (uint8_t i = 0; i < MAX_DIMENSION; i++) + { + int32_t ioffset = scale * i; + for (uint8_t j = 0; j < MAX_DIMENSION; j++) + { + int32_t joffset = scale * j; + + uint8_t data = inoise8(x + ioffset, y + joffset, z); + + data = qsub8(data, 16); + data = qadd8(data, scale8(data, 39)); + + if (dataSmoothing) + { + uint8_t olddata = noise[i][j]; + uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); + data = newdata; + } + + noise[i][j] = data; + } + } + z += speed*z_dir; + x -= speed*x_dir; + y += speed*y_dir; + + for (uint8_t i = 0; i < WIDTH; i++) + { + for (uint8_t j = 0; j < HEIGHT; j++) + { + uint8_t index = noise[j][i]; + uint8_t bri = noise[i][j]; + // if this palette is a 'loop', add a slowly-changing base value + if ( colorLoop) + { + index += ihue; + } + // brighten up, as the color palette itself often contains the + // light/dark dynamic range desired + if ( bri > 127 ) + { + bri = 255; + } + else + { + bri = dim8_raw( bri * 2); + } + CRGB color = ColorFromPalette( currentPalette, index, bri); + leds[XY(i, j)] = color; + } + } + ihue += 1; +} + +void fillnoise8() +{ + for (uint8_t i = 0; i < MAX_DIMENSION; i++) + { + int32_t ioffset = scale * i; + for (uint8_t j = 0; j < MAX_DIMENSION; j++) + { + int32_t joffset = scale * j; + noise[i][j] = inoise8(x + ioffset, y + joffset, z); + } + } + z -= speed; +} diff --git a/ArduinoLamp_v1.4/utility.ino b/ArduinoLamp_v1.4/utility.ino new file mode 100644 index 0000000..be238e9 --- /dev/null +++ b/ArduinoLamp_v1.4/utility.ino @@ -0,0 +1,192 @@ +// служебные функции + +// залить все +void fillAll(CRGB color) { + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = color; + } +} + +// функция отрисовки точки по координатам 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; + } +} + +// функция получения цвета пикселя по его номеру +uint32_t getPixColor(uint32_t thisSegm) +{ + uint32_t thisPixel = thisSegm * SEGMENTS; + if (thisPixel > NUM_LEDS - 1) return 0; + return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b); +} + +// функция получения цвета пикселя в матрице по его координатам +uint32_t getPixColorXY(uint8_t x, uint8_t y) +{ + return getPixColor(XY(x, y)); +} + +// **************** НАСТРОЙКА МАТРИЦЫ **************** +#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 XY(uint8_t x, uint8_t y) +{ + if (!(THIS_Y & 0x01) || MATRIX_TYPE) // Even rows run forwards + return (THIS_Y * _WIDTH + THIS_X); + else + return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); // Odd rows run backwards +} + +// оставлено для совместимости со эффектами из старых прошивок +uint16_t getPixelNumber(uint8_t x, uint8_t y) +{ + return XY(x, y); +} + +// Gamma коррекция (Defalt Gamma = 2.8) +const uint8_t PROGMEM gammaR[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, + 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, + 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, + 33, 34, 35, 36, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 46, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 80, + 81, 83, 84, 85, 87, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, + 104, 105, 107, 109, 110, 112, 113, 115, 116, 118, 120, 121, 123, 125, 127, 128, + 130, 132, 134, 135, 137, 139, 141, 143, 145, 146, 148, 150, 152, 154, 156, 158, + 160, 162, 164, 166, 168, 170, 172, 174, 177, 179, 181, 183, 185, 187, 190, 192, + 194, 196, 199, 201, 203, 206, 208, 210, 213, 215, 218, 220, 223, 225, 227, 230 +}; + +const uint8_t PROGMEM gammaG[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, + 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, + 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, + 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, + 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, + 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114, + 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142, + 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175, + 177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, + 215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255 +}; + +const uint8_t PROGMEM gammaB[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 12, 13, + 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, + 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, + 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40, + 40, 41, 42, 43, 44, 44, 45, 46, 47, 48, 49, 50, 51, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 70, + 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, + 90, 92, 93, 94, 96, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 112, + 113, 115, 116, 118, 119, 121, 122, 124, 126, 127, 129, 131, 132, 134, 136, 137, + 139, 141, 143, 144, 146, 148, 150, 152, 153, 155, 157, 159, 161, 163, 165, 167, + 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 196, 198, 200 +}; + +// гамма-коррекция (более натуральные цвета) +uint32_t gammaCorrection(uint32_t color) { + byte r = (color >> 16) & 0xFF; // Extract the RR byte + byte g = (color >> 8) & 0xFF; // Extract the GG byte + byte b = color & 0xFF; // Extract the BB byte + + r = pgm_read_byte(&gammaR[r]); + g = pgm_read_byte(&gammaG[g]); + b = pgm_read_byte(&gammaB[b]); + + uint32_t newColor = ((long)(r & 0xff) << 16) + ((long)(g & 0xff) << 8) + ((long)b & 0xff); + return newColor; +} + +// gamma correction для expandColor +static const uint8_t PROGMEM +gamma5[] = { + 0x00, 0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, + 0x0e, 0x11, 0x14, 0x18, 0x1d, 0x22, 0x28, 0x2e, + 0x36, 0x3d, 0x46, 0x4f, 0x59, 0x64, 0x6f, 0x7c, + 0x89, 0x97, 0xa6, 0xb6, 0xc7, 0xd9, 0xeb, 0xff +}, +gamma6[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, + 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x12, 0x13, + 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x20, 0x22, 0x25, + 0x27, 0x2a, 0x2d, 0x30, 0x33, 0x37, 0x3a, 0x3e, + 0x41, 0x45, 0x49, 0x4d, 0x52, 0x56, 0x5b, 0x5f, + 0x64, 0x69, 0x6e, 0x74, 0x79, 0x7f, 0x85, 0x8b, + 0x91, 0x97, 0x9d, 0xa4, 0xab, 0xb2, 0xb9, 0xc0, + 0xc7, 0xcf, 0xd6, 0xde, 0xe6, 0xee, 0xf7, 0xff +}; + +// преобразовать цвет из 16 битного в 24 битный +static uint32_t expandColor(uint16_t color) { + return ((uint32_t)pgm_read_byte(&gamma5[ color >> 11 ]) << 16) | + ((uint32_t)pgm_read_byte(&gamma6[(color >> 5) & 0x3F]) << 8) | + pgm_read_byte(&gamma5[ color & 0x1F]); +} diff --git a/ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino b/ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino new file mode 100644 index 0000000..23e07c1 --- /dev/null +++ b/ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino @@ -0,0 +1,54 @@ +/* + Скетч к проекту "Многофункциональный RGB светильник" + Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ + Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ + Автор: AlexGyver, AlexGyver Technologies, 2019(Портировал на Ардуино Norovl(+ эффекты,демо stepko365) + https://AlexGyver.ru/ +*/ +// ---------------- БИБЛИОТЕКИ ----------------- +#include +#include +#include +//----------------- ----------------- +#include "bitmap2.h" +#include "Constants.h" +// ----------------- ПЕРЕМЕННЫЕ ------------------ +static const byte maxDim = max(WIDTH, HEIGHT); +int8_t currentMode = 10; +boolean loadingFlag = true; +boolean ONflag = true; +byte numHold; +unsigned long numHold_Timer = 0; +unsigned char matrixValue[8][16]; + + +void setup() { + // ЛЕНТА + FastLED.addLeds(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/; + FastLED.setBrightness(BRIGHTNESS); + if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); + FastLED.clear(); + FastLED.show(); + + touch.setStepTimeout(100); + touch.setClickTimeout(500); + + //Serial.begin(9600); + //Serial.println(); + + if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР + currentMode = EEPROM.read(1); + for (byte x = 0; x < MODE_AMOUNT; x++) { + modes[x].Brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) + modes[x].Speed = EEPROM.read(x * 3 + 12); + modes[x].Scale = EEPROM.read(x * 3 + 13); + } + + } +} + +void loop() { + effectsTick(); + buttonTick(); + demo(); +} diff --git a/ArduinoLamp_v1.5/Constants.h b/ArduinoLamp_v1.5/Constants.h new file mode 100644 index 0000000..427640f --- /dev/null +++ b/ArduinoLamp_v1.5/Constants.h @@ -0,0 +1,36 @@ +// ============= НАСТРОЙКИ ============= +// ---------- МАТРИЦА --------- +#define BRIGHTNESS 10 // стандартная маскимальная яркость (0-255) +#define CURRENT_LIMIT 1000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит + +#define WIDTH 8 // ширина матрицы +#define HEIGHT 8 // высота матрицы + +#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB + +#define MATRIX_TYPE 1 // тип матрицы: 0 - зигзаг, 1 - параллельная +#define CONNECTION_ANGLE 1 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний +#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз +// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" +// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ + +#define numHold_Time (1*1000) // время отображения индикатора уровня яркости/скорости/масштаба + +// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= +#define LED_PIN 6 // пин ленты +#define BTN_PIN 2 +#define MODE_AMOUNT 36 //кол-во эффектов +#define NUM_LEDS WIDTH * HEIGHT +#define SEGMENTS 1// диодов в одном "пикселе" (для создания матрицы из кусков ленты) +// ------------------- ТИПЫ -------------------- +CRGB leds[NUM_LEDS]; +GButton touch(BTN_PIN, HIGH_PULL, NORM_OPEN); //если сенсорна кнопка LOW_PULL +struct { + byte Brightness = 10; + byte Speed = 30; + byte Scale = 10; +} modes[MODE_AMOUNT]; //настройки эффекта по умолчанию +#define DEMOTIMELIMIT ( 1 * 20UL * 1000UL) // минуты/секунды/милисекунды время задержка между эффектами +#define RANDOM_DEMO 0 // 0,1 - включить рандомный выбор режима +uint32_t DemTimer = 0UL; // тут будет храниться время следующего переключения эффекта +bool isDemo = false; diff --git a/ArduinoLamp_v1.5/bitmap2.h b/ArduinoLamp_v1.5/bitmap2.h new file mode 100644 index 0000000..6de330d --- /dev/null +++ b/ArduinoLamp_v1.5/bitmap2.h @@ -0,0 +1,61 @@ +static const uint16_t framesArray[6][8][8] PROGMEM = {{ + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xFFDE, 0xF813, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, + {0x0000, 0x0000, 0xFF3B, 0xDC90, 0x0000, 0xFF3B, 0x0000, 0x0000}, + {0x0000, 0x0000, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90, 0xFF3B, 0xDC90}, + {0x0000, 0x0000, 0x0000, 0xFF3B, 0xFF3B, 0xFF3B, 0xFF3B, 0x0000}, + {0x0000, 0xF813, 0xF813, 0xFFEE, 0x7EBF, 0x7EBF, 0xFE60, 0x0000}, + {0xFFDE, 0x0000, 0x7EBF, 0x7EBF, 0x7EBF, 0x7EBF, 0x6354, 0xC59A}, + {0x0000, 0x0000, 0xC2F4, 0x0000, 0x0000, 0xDC90, 0x0000, 0x0000} + }, + { + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xFFDE, 0xF813, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, + {0x0000, 0x0000, 0xFF3B, 0xDC90, 0x0000, 0xFF3B, 0x0000, 0x0000}, + {0x0000, 0x0000, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90, 0xFF3B, 0xDC90}, + {0x0000, 0xF813, 0xF813, 0xFF3B, 0xFF3B, 0xFF3B, 0xFF3B, 0x0000}, + {0xFFDE, 0x0000, 0xF813, 0xFFEE, 0x7EBF, 0x7EBF, 0xFE60, 0xFFDE}, + {0x0000, 0xC2F4, 0x7EBF, 0x7EBF, 0x7EBF, 0x7EBF, 0x6354, 0x0000}, + {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDC90, 0x0000} + }, + { + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xFFDE, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, + {0x0000, 0x0000, 0xDC90, 0xFF3B, 0xDC90, 0x0000, 0xFF3B, 0x0000}, + {0x0000, 0x0000, 0xDC90, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90, 0xFF3B}, + {0x0000, 0x0000, 0x0000, 0xDC90, 0xFF3B, 0xFF3B, 0xFF3B, 0x0000}, + {0x0000, 0x0000, 0xF813, 0xF813, 0xFFEE, 0x7EBF, 0x6354, 0x0000}, + {0x0000, 0x0000, 0xF813, 0xFFDE, 0x7EBF, 0x7EBF, 0x6354, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xDC90, 0xDC90, 0xC2F4, 0x0000, 0x0000} + }, + { + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, + {0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xDC90, 0x0000, 0x0000}, + {0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90}, + {0x0000, 0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xFF3B, 0x0000}, + {0x0000, 0x0000, 0x7EBF, 0xF813, 0xF813, 0xFFEE, 0x6354, 0x0000}, + {0x0000, 0x0000, 0x7EBF, 0x7EBF, 0xF813, 0xF813, 0xFFDE, 0x0000}, + {0x0000, 0x0000, 0xDC90, 0x0000, 0x0000, 0xC2F4, 0x0000, 0x0000} + }, + { + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, + {0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xDC90, 0x0000, 0x0000}, + {0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90}, + {0x0000, 0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xFF3B, 0x0000}, + {0x0000, 0x0000, 0x7EBF, 0xF813, 0xF813, 0xFFEE, 0x6354, 0xFFDE}, + {0x0000, 0xDC90, 0x7EBF, 0x7EBF, 0x7EBF, 0xF813, 0xF813, 0x0000}, + {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xC2F4, 0x0000} + }, + { + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xFFDE, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, + {0x0000, 0x0000, 0xDC90, 0xFF3B, 0xDC90, 0x0000, 0xFF3B, 0x0000}, + {0x0000, 0x0000, 0xDC90, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90, 0xFF3B}, + {0x0000, 0x0000, 0x0000, 0xDC90, 0xFF3B, 0xFF3B, 0xFF3B, 0x0000}, + {0x0000, 0x0000, 0xF813, 0xF813, 0xFFEE, 0x7EBF, 0x6354, 0x0000}, + {0x0000, 0x0000, 0xF813, 0xFFDE, 0x7EBF, 0x7EBF, 0x6354, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xDC90, 0xDC90, 0xC2F4, 0x0000, 0x0000} + } +}; diff --git a/ArduinoLamp_v1.5/button.ino b/ArduinoLamp_v1.5/button.ino new file mode 100644 index 0000000..52aa994 --- /dev/null +++ b/ArduinoLamp_v1.5/button.ino @@ -0,0 +1,93 @@ +boolean brightDirection, speedDirection, scaleDirection; + +void buttonTick() { + touch.tick(); + + if (touch.isSingle()) { + { + if (ONflag) { + ONflag = false; + changePower(); + } else { + ONflag = true; + changePower(); + } + } + } + + if (ONflag) { // если включено + if (touch.isDouble()) { + if (++currentMode >= MODE_AMOUNT) currentMode = 0; + FastLED.setBrightness(modes[currentMode].Brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + if (touch.isTriple()) { + if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; + FastLED.setBrightness(modes[currentMode].Brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + if (touch.hasClicks()) + if (touch.getClicks() == 5) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров + if (EEPROM.read(0) != 102) EEPROM.write(0, 102); + if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект + for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов + if (EEPROM.read(x * 3 + 11) != modes[x].Brightness) EEPROM.write(x * 3 + 11, modes[x].Brightness); + if (EEPROM.read(x * 3 + 12) != modes[x].Speed) EEPROM.write(x * 3 + 12, modes[x].Speed); + if (EEPROM.read(x * 3 + 13) != modes[x].Scale) EEPROM.write(x * 3 + 13, modes[x].Scale); + } + // индикация сохранения + ONflag = false; + changePower(); + delay(200); + ONflag = true; + changePower(); + } + else if (touch.getClicks() == 4) { // если было четырёхкратное нажатие на кнопку, то переключаем демо + isDemo = !isDemo; + DemTimer = 0UL; + } + + + if (touch.isHolded()) { // изменение яркости при удержании кнопки + brightDirection = !brightDirection; + numHold = 1; + } + + if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки + speedDirection = !speedDirection; + numHold = 2; + } + + if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки + scaleDirection = !scaleDirection; + numHold = 3; + } + + if (touch.isStep()) { + if (numHold != 0) numHold_Timer = millis(); loadingFlag = true; + switch (numHold) { + case 1: + modes[currentMode].Brightness = constrain(modes[currentMode].Brightness + (modes[currentMode].Brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , 255); + break; + case 2: + modes[currentMode].Speed = constrain(modes[currentMode].Speed + (modes[currentMode].Speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); + break; + + case 3: + modes[currentMode].Scale = constrain(modes[currentMode].Scale + (modes[currentMode].Scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); + break; + } + } + if ((millis() - numHold_Timer) > numHold_Time) { + numHold = 0; + numHold_Timer = millis(); + } + FastLED.setBrightness(modes[currentMode].Brightness); + } +} diff --git a/ArduinoLamp_v1.5/effectTicker.ino b/ArduinoLamp_v1.5/effectTicker.ino new file mode 100644 index 0000000..efb4d27 --- /dev/null +++ b/ArduinoLamp_v1.5/effectTicker.ino @@ -0,0 +1,108 @@ +uint32_t effTimer; +byte ind; +void effectsTick() { + { + if (ONflag && millis() - effTimer >= ((currentMode < 6 || currentMode > 21) ? modes[currentMode].Speed : 50) ) { + effTimer = millis(); switch (currentMode) { + //|номер |название функции эффекта |тоже надо| + case 0 : sparklesRoutine(); break; + case 1 : fireRoutine(); break; + case 2 : rainbowVertical(); break; + case 3 : rainbowHorizontal(); break; + case 4 : rainbowDiagonalRoutine(); break; + case 5 : WaveRoutine(); break; + case 6 : BBallsRoutine(); break; + case 7 : SinusoidRoutine(); break; + case 8 : MetaBallsRoutine(); break; + case 9 : PrismataRoutine(); break; + case 10: madnessNoise(); break; + case 11: cloudNoise(); break; + case 12: lavaNoise(); break; + case 13: plasmaNoise(); break; + case 14: rainbowNoise(); break; + case 15: rainbowStripeNoise(); break; + case 16: zebraNoise(); break; + case 17: forestNoise(); break; + case 18: oceanNoise(); break; + case 19: heatNoise(); break; + case 20: smokeNoise(); break; + case 21: lavLampNoise(); break; + case 22: colorRoutine(); break; + case 23: colorsRoutine(); break; + case 24: RainRoutine(); break; + case 25: stormRoutine2(true); break; + case 26: stormRoutine2(false); break; + case 27: ballRoutine(); break; + case 28: ballsRoutine(); break; + case 29: fire2012WithPalette(); break; + case 30: lightersRoutine(); break; + case 31: pulseRoutine(1); break; + case 32: ringsRoutine(); break; + case 33: starRoutine(); break; + case 34: MunchRoutine(); break; + + } + switch (numHold) { // индикатор уровня яркости/скорости/масштаба + case 1: + ind = sqrt(modes[currentMode].Brightness + 1); + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) drawPixelXY(y, 0, CHSV(10, 255, 255)); + else drawPixelXY(y, 0, 0); + } + break; + case 2: + ind = sqrt(modes[currentMode].Speed + 1); + for (byte y = 0; y <= HEIGHT ; y++) { + if (ind <= y) drawPixelXY(y, 0, CHSV(100, 255, 255)); + else drawPixelXY(y, 0, 0); + } + break; + case 3: + ind = sqrt(modes[currentMode].Scale + 1); + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) drawPixelXY(y, 0, CHSV(150, 255, 255)); + else drawPixelXY(y, 0, 0); + } + break; + + } + FastLED.show(); + } + } +} + +void changePower() { // плавное включение/выключение + if (ONflag) { + effectsTick(); + for (int i = 0; i < modes[currentMode].Brightness; i += 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.setBrightness(modes[currentMode].Brightness); + delay(2); + FastLED.show(); + } else { + effectsTick(); + for (int i = modes[currentMode].Brightness; i > 8; i -= 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.clear(); + delay(2); + FastLED.show(); + } +} + +void demo() { + if (isDemo && ONflag && millis() >= DemTimer) { + if (RANDOM_DEMO) + currentMode = random8(MODE_AMOUNT); // если нужен следующий случайный эффект + else + currentMode = currentMode + 1U < MODE_AMOUNT ? currentMode + 1U : 0U; // если нужен следующий по списку эффект + FastLED.clear(); + DemTimer = millis() + DEMOTIMELIMIT; + loadingFlag = true; + } +} diff --git a/ArduinoLamp_v1.5/effects.ino b/ArduinoLamp_v1.5/effects.ino new file mode 100644 index 0000000..02b7a21 --- /dev/null +++ b/ArduinoLamp_v1.5/effects.ino @@ -0,0 +1,2063 @@ +// ================================= ЭФФЕКТЫ ==================================== +uint8_t wrapX(int8_t x) { + return (x + WIDTH) % WIDTH; +} +uint8_t wrapY(int8_t y) { + return (y + HEIGHT) % HEIGHT; +} +uint8_t deltaHue, deltaHue2; // ещё пара таких же, когда нужно много +uint8_t step; // какой-нибудь счётчик кадров или постедовательностей операций +uint8_t pcnt; +uint8_t line[WIDTH]; +uint8_t deltaValue; // просто повторно используемая переменная +#define NUM_LAYERSMAX 2 +uint8_t noise3d[NUM_LAYERSMAX][WIDTH][HEIGHT]; +uint8_t shiftHue[HEIGHT]; +uint8_t shiftValue[HEIGHT]; + +// палитра для типа реалистичного водопада (если ползунок Масштаб выставить на 100) +extern const TProgmemRGBPalette16 WaterfallColors_p FL_PROGMEM = {0x000000, 0x060707, 0x101110, 0x151717, 0x1C1D22, 0x242A28, 0x363B3A, 0x313634, 0x505552, 0x6B6C70, 0x98A4A1, 0xC1C2C1, 0xCACECF, 0xCDDEDD, 0xDEDFE0, 0xB2BAB9}; +// добавлено изменение текущей палитры (используется во многих эффектах ниже для бегунка Масштаб) +const TProgmemRGBPalette16 *palette_arr[] = { + &PartyColors_p, + &OceanColors_p, + &LavaColors_p, + &HeatColors_p, + &WaterfallColors_p, + &CloudColors_p, + &ForestColors_p, + &RainbowColors_p, + &RainbowStripeColors_p +}; +const TProgmemRGBPalette16 *curPalette = palette_arr[0]; +void setCurrentPalette() { + if (modes[currentMode].Scale > 100U) modes[currentMode].Scale = 100U; // чтобы не было проблем при прошивке без очистки памяти + curPalette = palette_arr[(uint8_t)(modes[currentMode].Scale / 100.0F * ((sizeof(palette_arr) / sizeof(TProgmemRGBPalette16 *)) - 0.01F))]; +} +CRGB _pulse_color; +void blurScreen(fract8 blur_amount, CRGB *LEDarray = leds) +{ + blur2d(LEDarray, WIDTH, HEIGHT, blur_amount); +} +void dimAll(uint8_t value) { + for (uint16_t i = 0; i < NUM_LEDS; i++) { + leds[i].nscale8(value); //fadeToBlackBy + } +} +void drawPixelXYF(float x, float y, CRGB color) +{ + // extract the fractional parts and derive their inverses + uint8_t xx = (x - (int)x) * 255, yy = (y - (int)y) * 255, ix = 255 - xx, iy = 255 - yy; + // calculate the intensities for each affected pixel + #define WU_WEIGHT(a,b) ((uint8_t) (((a)*(b)+(a)+(b))>>8)) + uint8_t wu[4] = {WU_WEIGHT(ix, iy), WU_WEIGHT(xx, iy), + WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)}; + // multiply the intensities by the colour, and saturating-add them to the pixels + for (uint8_t i = 0; i < 4; i++) { + int16_t xn = x + (i & 1), yn = y + ((i >> 1) & 1); + CRGB clr = getPixColorXY(xn, yn); + clr.r = qadd8(clr.r, (color.r * wu[i]) >> 8); + clr.g = qadd8(clr.g, (color.g * wu[i]) >> 8); + clr.b = qadd8(clr.b, (color.b * wu[i]) >> 8); + drawPixelXY(xn, yn, clr); + } +} + +void drawCircleF(float x0, float y0, float radius, CRGB color){ + float x = 0, y = radius, error = 0; + float delta = 1 - 2 * radius; + + while (y >= 0) { + drawPixelXYF(x0 + x, y0 + y, color); + drawPixelXYF(x0 + x, y0 - y, color); + drawPixelXYF(x0 - x, y0 + y, color); + drawPixelXYF(x0 - x, y0 - y, color); + error = 2 * (delta + y) - 1; + if (delta < 0 && error <= 0) { + ++x; + delta += 2 * x + 1; + continue; + } + error = 2 * (delta - x) - 1; + if (delta > 0 && error > 0) { + --y; + delta += 1 - 2 * y; + continue; + } + ++x; + delta += 2 * (x - y); + --y; + } +} + +// --------------------------------- конфетти ------------------------------------ +#define FADE_OUT_SPEED (70U) // скорость затухания +void sparklesRoutine() +{ + for (uint8_t i = 0; i < modes[currentMode].Scale; i++) + { + uint8_t x = random(0U, WIDTH); + uint8_t y = random(0U, HEIGHT); + if (getPixColorXY(x, y) == 0U) + { + leds[XY(x, y)] = CHSV(random(0U, 255U), 255U, 255U); + } + } + fader(FADE_OUT_SPEED); +} +// функция плавного угасания цвета для всех пикселей +void fader(uint8_t step) +{ + for (uint8_t i = 0U; i < WIDTH; i++) + { + for (uint8_t j = 0U; j < HEIGHT; j++) + { + fadePixel(i, j, step); + } + } +} +void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер +{ + int32_t pixelNum = XY(i, j); + if (getPixColor(pixelNum) == 0U) return; + + if (leds[pixelNum].r >= 30U || + leds[pixelNum].g >= 30U || + leds[pixelNum].b >= 30U) + { + leds[pixelNum].fadeToBlackBy(step); + } + else + { + leds[pixelNum] = 0U; + } +} +// -------------------------------------- огонь --------------------------------------------- +#define SPARKLES 0 // вылетающие угольки вкл выкл +//these values are substracetd from the generated values to give a shape to the animation +const unsigned char valueMask[8][16] PROGMEM = { + {0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 }, + {0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 }, + {0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 }, + {0 , 32 , 64 , 128, 128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 128, 64 , 32 , 0 }, + {32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 }, + {64 , 96 , 128, 192, 192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128, 96 , 64 }, + {96 , 128, 160, 255, 255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160, 128, 96 }, + {128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128} +}; + +//these are the hues for the fire, +//should be between 0 (red) to about 25 (yellow) +const unsigned char hueMask[8][16] PROGMEM = { + {25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25 }, + {25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19 }, + {19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16 }, + {13, 13, 5 , 1 , 1 , 5 , 11, 13, 13, 13, 5 , 1 , 1 , 5 , 11, 13 }, + {11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11 }, + {8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 }, + {5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 }, + {1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } +}; +void fireRoutine() { + if (loadingFlag) { + loadingFlag = false; + //FastLED.clear(); + generateLine(); + } + if (pcnt >= 100) { + shiftUp(); + generateLine(); + pcnt = 0; + } + drawFrame(pcnt); + pcnt += 25; +} + +// Случайным образом генерирует следующую линию (matrix row) + +void generateLine() { + for (uint8_t x = 0; x < WIDTH; x++) { + line[x] = random(127, 255); + } +} + +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 - 15; + 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 - 15; + matrixValue[0][newX] = line[newX]; + } +} + +// рисует кадр, интерполируя между 2 "ключевых кадров" +// параметр pcnt - процент интерполяции + +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 - 15; + 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( + modes[currentMode].Scale * 2.5 + 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); + + } + } + } + + //Перавя стрка интерполируется со следующей "next" линией + for (unsigned char x = 0; x < WIDTH; x++) { + uint8_t newX = x; + if (x > 15) newX = x - 15; + CRGB color = CHSV( + modes[currentMode].Scale * 2.5 + 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; + } +} +// ---------------------------------------- радуга ------------------------------------------ +byte hue; byte hue2; +void rainbowVertical() { + hue += 2; + for (byte j = 0; j < HEIGHT; j++) { + CHSV thisColor = CHSV((byte)(hue + j * modes[currentMode].Scale), 255, 255); + for (byte i = 0; i < WIDTH; i++) + drawPixelXY(i, j, thisColor); + } +} +void rainbowHorizontal() { + hue += 2; + for (byte i = 0; i < WIDTH; i++) { + CHSV thisColor = CHSV((byte)(hue + i * modes[currentMode].Scale), 255, 255); + for (byte j = 0; j < HEIGHT; j++) + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; + } +} +void rainbowDiagonalRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + FastLED.clear(); + } + + hue += 8; + for (uint8_t i = 0U; i < WIDTH; i++) + { + for (uint8_t j = 0U; j < HEIGHT; j++) + { + float twirlFactor = 3.0F * (modes[currentMode].Scale / 100.0F); // на сколько оборотов будет закручена матрица, [0..3] + CRGB thisColor = CHSV((uint8_t)(hue + ((float)WIDTH / HEIGHT * i + j * twirlFactor) * ((float)255 / maxDim)), 255, 255); + drawPixelXY(i, j, thisColor); + } + } +} +// ---------------------------------------- ЦВЕТА ----------------------------- +void colorsRoutine() { + hue += modes[currentMode].Scale; + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = CHSV(hue, 255, 255); + } +} + +// --------------------------------- ЦВЕТ ------------------------------------ +void colorRoutine() { + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = CHSV(modes[currentMode].Scale * 2.5, modes[currentMode].Speed * 2.5, 255); + } +} + +// ------------------------------ снегопад 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, modes[currentMode].Scale) == 0)) + drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); + else + drawPixelXY(x, HEIGHT - 1, 0x000000); + } + } +*/ +// ------------------------------ МАТРИЦА ------------------------------ +/*void matrixRoutine() { + for (byte x = 0; x < WIDTH; x++) { + // заполняем случайно верхнюю строку + uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); + if (thisColor == 0) + drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, modes[currentMode].Scale) == 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 whiteLamp() { + for (byte y = 0; y < (HEIGHT / 2); y++) { + CHSV color = CHSV(100, 1, constrain(modes[currentMode].Brightness - (long)modes[currentMode].Speed * modes[currentMode].Brightness / 255 * y / 2, 1, 255)); + for (byte x = 0; x < WIDTH; x++) { + drawPixelXY(x, y + 8, color); + drawPixelXY(x, 7 - y, color); + } + } + }*/ +//--------------------------Шторм,Метель------------------------- +#define e_sns_DENSE (32U) // плотность снега - меньше = плотнее +void stormRoutine2(bool isColored) +{ + // заполняем головами комет + uint8_t Saturation = 0U; // цвет хвостов + uint8_t e_TAIL_STEP = 127U; // длина хвоста + if (isColored) + Saturation = modes[currentMode].Scale * 2.55; + else + { + e_TAIL_STEP = 255U - modes[currentMode].Scale * 2.55; + } + for (int8_t x = 0U; x < WIDTH - 1U; x++) // fix error i != 0U + { + if (!random8(e_sns_DENSE) && + !getPixColorXY(wrapX(x), HEIGHT - 1U) && + !getPixColorXY(wrapX(x + 1U), HEIGHT - 1U) && + !getPixColorXY(wrapX(x - 1U), HEIGHT - 1U)) + { + drawPixelXY(x, HEIGHT - 1U, CHSV(random8(), Saturation, random8(64U, 255U))); + } + } + + // сдвигаем по диагонали + for (int8_t y = 0U; y < HEIGHT - 1U; y++) + { + for (int8_t x = 0; x < WIDTH; x++) + { + drawPixelXY(wrapX(x + 1U), y, getPixColorXY(x, y + 1U)); + } + } + + // уменьшаем яркость верхней линии, формируем "хвосты" + for (int8_t i = 0U; i < WIDTH; i++) + { + fadePixel(i, HEIGHT - 1U, e_TAIL_STEP); + } +} +//------------------Синусоид3----------------------- +//Stefan Petrick +void SinusoidRoutine() +{ + const uint8_t semiHeightMajor = HEIGHT / 2 + (HEIGHT % 2); + const uint8_t semiWidthMajor = WIDTH / 2 + (WIDTH % 2) ; + float e_s3_Speed = 0.004 * modes[currentMode].Speed + 0.015; // Speed of the movement along the Lissajous curves + float e_s3_size = 3 * (float)modes[currentMode].Scale / 100.0 + 2; // amplitude of the curves + + float time_shift = float(millis() % (uint32_t)(30000 * (1.0 / ((float)modes[currentMode].Speed / 255)))); + + for (uint8_t y = 0; y < HEIGHT; y++) { + for (uint8_t x = 0; x < WIDTH; x++) { + CRGB color; + + float cx = y + float(e_s3_size * (sinf (float(e_s3_Speed * 0.003 * time_shift)))) - semiHeightMajor; // the 8 centers the middle on a 16x16 + float cy = x + float(e_s3_size * (cosf (float(e_s3_Speed * 0.0022 * time_shift)))) - semiWidthMajor; + float v = 127 * (1 + sinf ( sqrtf ( ((cx * cx) + (cy * cy)) ) )); + color.r = v; + + cx = x + float(e_s3_size * (sinf (e_s3_Speed * float(0.0021 * time_shift)))) - semiWidthMajor; + cy = y + float(e_s3_size * (cosf (e_s3_Speed * float(0.002 * time_shift)))) - semiHeightMajor; + v = 127 * (1 + sinf ( sqrtf ( ((cx * cx) + (cy * cy)) ) )); + color.b = v; + + cx = x + float(e_s3_size * (sinf (e_s3_Speed * float(0.0041 * time_shift)))) - semiWidthMajor; + cy = y + float(e_s3_size * (cosf (e_s3_Speed * float(0.0052 * time_shift)))) - semiHeightMajor; + v = 127 * (1 + sinf ( sqrtf ( ((cx * cx) + (cy * cy)) ) )); + color.g = v; + drawPixelXY(x, y, color); + } + } +} +//-------------------------Метаболз------------------- +//Stefan Petrick +void MetaBallsRoutine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + + float Speed = modes[currentMode].Speed / 127.0; + + // get some 2 random moving points + uint8_t x2 = inoise8(millis() * Speed, 25355, 685 ) / WIDTH; + uint8_t y2 = inoise8(millis() * Speed, 355, 11685 ) / HEIGHT; + + uint8_t x3 = inoise8(millis() * Speed, 55355, 6685 ) / WIDTH; + uint8_t y3 = inoise8(millis() * Speed, 25355, 22685 ) / HEIGHT; + + // and one Lissajou function + uint8_t x1 = beatsin8(23 * Speed, 0, 15); + uint8_t y1 = beatsin8(28 * Speed, 0, 15); + + for (uint8_t y = 0; y < HEIGHT; y++) { + for (uint8_t x = 0; x < WIDTH; x++) { + + // calculate distances of the 3 points from actual pixel + // and add them together with weightening + uint8_t dx = abs(x - x1); + uint8_t dy = abs(y - y1); + uint8_t dist = 2 * sqrt((dx * dx) + (dy * dy)); + + dx = abs(x - x2); + dy = abs(y - y2); + dist += sqrt((dx * dx) + (dy * dy)); + + dx = abs(x - x3); + dy = abs(y - y3); + dist += sqrt((dx * dx) + (dy * dy)); + + // inverse result + //byte color = modes[currentMode].Speed * 10 / dist; + byte color = 1000U / dist; + + // map color between thresholds + if (color > 0 and color < 60) { + if (modes[currentMode].Scale == 100U) + drawPixelXY(x, y, CHSV(color * 9, 255, 255));// это оригинальный цвет эффекта + else + drawPixelXY(x, y, ColorFromPalette(*curPalette, color * 9)); + } else { + if (modes[currentMode].Scale == 100U) + drawPixelXY(x, y, CHSV(0, 255, 255)); // в оригинале центральный глаз почему-то крвсный + else + drawPixelXY(x, y, ColorFromPalette(*curPalette, 0U)); + } + // show the 3 points, too + drawPixelXY(x1, y1, CRGB(255, 255, 255)); + drawPixelXY(x2, y2, CRGB(255, 255, 255)); + drawPixelXY(x3, y3, CRGB(255, 255, 255)); + } + } +} + +// ============= ЭФФЕКТ ВОЛНЫ =============== +// https://github.com/pixelmatix/aurora/blob/master/PatternWave.h +// Адаптация от (c) SottNick + +byte waveThetaUpdate = 0; +byte waveThetaUpdateFrequency = 0; +byte waveTheta = 0; + +byte hueUpdate = 0; +byte hueUpdateFrequency = 0; +// byte hue = 0; будем использовать сдвиг от эффектов Радуга + +byte waveRotation = 0; +uint8_t waveScale = 256 / WIDTH; +uint8_t waveCount = 1; + +void WaveRoutine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + + //waveRotation = random(0, 4);// теперь вместо этого регулятор Масштаб + waveRotation = (modes[currentMode].Scale - 1) / 25U; + //waveCount = random(1, 3);// теперь вместо этого чётное/нечётное у регулятора Скорость + waveCount = modes[currentMode].Speed % 2; + //waveThetaUpdateFrequency = random(1, 2); + //hueUpdateFrequency = random(1, 6); + } + + dimAll(254); + + int n = 0; + + switch (waveRotation) { + case 0: + for (uint8_t x = 0; x < WIDTH; x++) { + n = quadwave8(x * 2 + waveTheta) / waveScale; + drawPixelXY(x, n, ColorFromPalette(*curPalette, hue + x)); + if (waveCount != 1) + drawPixelXY(x, HEIGHT - 1 - n, ColorFromPalette(*curPalette, hue + x)); + } + break; + + case 1: + for (uint8_t y = 0; y < HEIGHT; y++) { + n = quadwave8(y * 2 + waveTheta) / waveScale; + drawPixelXY(n, y, ColorFromPalette(*curPalette, hue + y)); + if (waveCount != 1) + drawPixelXY(WIDTH - 1 - n, y, ColorFromPalette(*curPalette, hue + y)); + } + break; + + case 2: + for (uint8_t x = 0; x < WIDTH; x++) { + n = quadwave8(x * 2 - waveTheta) / waveScale; + drawPixelXY(x, n, ColorFromPalette(*curPalette, hue + x)); + if (waveCount != 1) + drawPixelXY(x, HEIGHT - 1 - n, ColorFromPalette(*curPalette, hue + x)); + } + break; + + case 3: + for (uint8_t y = 0; y < HEIGHT; y++) { + n = quadwave8(y * 2 - waveTheta) / waveScale; + drawPixelXY(n, y, ColorFromPalette(*curPalette, hue + y)); + if (waveCount != 1) + drawPixelXY(WIDTH - 1 - n, y, ColorFromPalette(*curPalette, hue + y)); + } + break; + } + + + if (waveThetaUpdate >= waveThetaUpdateFrequency) { + waveThetaUpdate = 0; + waveTheta++; + } + else { + waveThetaUpdate++; + } + + if (hueUpdate >= hueUpdateFrequency) { + hueUpdate = 0; + hue++; + } + else { + hueUpdate++; + } + + blurScreen(10); // @Palpalych советует делать размытие. вот в этом эффекте его явно не хватает... +} + +//-------------------------Блуждающий кубик----------------------- +#define RANDOM_COLOR (1U) // случайный цвет при отскоке +int16_t coordB[2U]; +int8_t vectorB[2U]; +CRGB ballColor; +//int8_t deltaValue; //ballSize; + +void ballRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + //FastLED.clear(); + + for (uint8_t i = 0U; i < 2U; i++) + { + coordB[i] = WIDTH / 2 * 10; + vectorB[i] = random(8, 20); + } + deltaValue = map(modes[currentMode].Scale * 2.55, 0U, 255U, 2U, max((uint8_t)min(WIDTH, HEIGHT) / 3, 2)); + ballColor = CHSV(random(0, 9) * 28, 255U, 255U); + // _pulse_color = CHSV(random(0, 9) * 28, 255U, 255U); + } + + // if (!(modes[currentMode].Scale & 0x01)) + // { + // hue += (modes[currentMode].Scale - 1U) % 11U * 8U + 1U; + + // ballColor = CHSV(hue, 255U, 255U); + // } + + if ((modes[currentMode].Scale & 0x01)) + for (uint8_t i = 0U; i < deltaValue; i++) + for (uint8_t j = 0U; j < deltaValue; j++) + leds[XY(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = _pulse_color; + + for (uint8_t i = 0U; i < 2U; 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, 255U, 255U); // if (RANDOM_COLOR && (modes[currentMode].Scale & 0x01)) + //vectorB[i] += random(0, 6) - 3; + } + } + if (coordB[0U] > (int16_t)((WIDTH - deltaValue) * 10)) + { + coordB[0U] = (WIDTH - deltaValue) * 10; + vectorB[0U] = -vectorB[0U]; + if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U); + //vectorB[0] += random(0, 6) - 3; + } + if (coordB[1U] > (int16_t)((HEIGHT - deltaValue) * 10)) + { + coordB[1U] = (HEIGHT - deltaValue) * 10; + vectorB[1U] = -vectorB[1U]; + if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U); + //vectorB[1] += random(0, 6) - 3; + } + + // if (modes[currentMode].Scale & 0x01) + // dimAll(135U); + // dimAll(255U - (modes[currentMode].Scale - 1U) % 11U * 24U); + //else + FastLED.clear(); + + for (uint8_t i = 0U; i < deltaValue; i++) + for (uint8_t j = 0U; j < deltaValue; j++) + leds[XY(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = ballColor; +} + +//-------------------Светлячки со шлейфом---------------------------- +#define BALLS_AMOUNT (3U) // количество "шариков" +#define CLEAR_PATH (1U) // очищать путь +#define TRACK_STEP (130U) // длина хвоста шарика (чем больше цифра, тем хвост короче) +int16_t coord[BALLS_AMOUNT][2U]; +int8_t vector[BALLS_AMOUNT][2U]; +CRGB ballColors[BALLS_AMOUNT]; +void ballsRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + + for (uint8_t j = 0U; j < BALLS_AMOUNT; j++) + { + int8_t sign; + // забиваем случайными данными + coord[j][0U] = WIDTH / 2 * 10; + random(0, 2) ? sign = 1 : sign = -1; + vector[j][0U] = random(4, 15) * sign; + coord[j][1U] = HEIGHT / 2 * 10; + random(0, 2) ? sign = 1 : sign = -1; + vector[j][1U] = random(4, 15) * sign; + //ballColors[j] = CHSV(random(0, 9) * 28, 255U, 255U); + // цвет зависит от масштаба + ballColors[j] = CHSV((modes[currentMode].Scale * (j + 1)) % 256U, 255U, 255U); + } + } + + fader(TRACK_STEP); + + + // движение шариков + for (uint8_t j = 0U; j < BALLS_AMOUNT; j++) + { + // движение шариков + for (uint8_t i = 0U; i < 2U; i++) + { + coord[j][i] += vector[j][i]; + if (coord[j][i] < 0) + { + coord[j][i] = 0; + vector[j][i] = -vector[j][i]; + } + } + + if (coord[j][0U] > (int16_t)((WIDTH - 1) * 10)) + { + coord[j][0U] = (WIDTH - 1) * 10; + vector[j][0U] = -vector[j][0U]; + } + if (coord[j][1U] > (int16_t)((HEIGHT - 1) * 10)) + { + coord[j][1U] = (HEIGHT - 1) * 10; + vector[j][1U] = -vector[j][1U]; + } + leds[XY(coord[j][0U] / 10, coord[j][1U] / 10)] = ballColors[j]; + } +} + +//-------------------Водопад------------------------------ +#define COOLINGNEW 32 +#define SPARKINGNEW 80 +/*extern const TProgmemRGBPalette16 WaterfallColors4in1_p FL_PROGMEM = {CRGB::Black, CRGB::DarkSlateGray, CRGB::DimGray, CRGB::LightSlateGray, CRGB::DimGray, CRGB::DarkSlateGray, CRGB::Silver, CRGB::Lavender, CRGB::Silver, CRGB::Azure, CRGB::LightGrey, CRGB::GhostWhite, CRGB::Silver, CRGB::White, CRGB::RoyalBlue}; + void fire2012WithPalette4in1() { + uint8_t rCOOLINGNEW = constrain((uint16_t)(modes[currentMode].Scale % 16) * 32 / HEIGHT + 16, 1, 255) ; + // Array of temperature readings at each simulation cell + //static byte heat[WIDTH][HEIGHT]; будет noise3d[0][WIDTH][HEIGHT] + + for (uint8_t x = 0; x < WIDTH; x++) { + // Step 1. Cool down every cell a little + for (unsigned int i = 0; i < HEIGHT; i++) { + //noise3d[0][x][i] = qsub8(noise3d[0][x][i], random8(0, ((rCOOLINGNEW * 10) / HEIGHT) + 2)); + noise3d[0][x][i] = qsub8(noise3d[0][x][i], random8(0, rCOOLINGNEW)); + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for (int k = HEIGHT - 1; k >= 2; k--) { + noise3d[0][x][k] = (noise3d[0][x][k - 1] + noise3d[0][x][k - 2] + noise3d[0][x][k - 2]) / 3; + } + + // Step 3. Randomly ignite new 'sparks' of heat near the bottom + if (random8() < SPARKINGNEW) { + int y = random8(2); + noise3d[0][x][y] = qadd8(noise3d[0][x][y], random8(160, 255)); + } + + // Step 4. Map from heat cells to LED colors + for (unsigned int j = 0; j < HEIGHT; j++) { + // Scale the heat value from 0-255 down to 0-240 + // for best results with color palettes. + byte colorindex = scale8(noise3d[0][x][j], 240); + if (modes[currentMode].Scale < 16) { // Lavafall + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(LavaColors_p, colorindex); + } else if (modes[currentMode].Scale < 32) { // Firefall + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(HeatColors_p, colorindex); + } else if (modes[currentMode].Scale < 48) { // Waterfall + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(WaterfallColors4in1_p, colorindex); + } else if (modes[currentMode].Scale < 64) { // Skyfall + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(CloudColors_p, colorindex); + } else if (modes[currentMode].Scale < 80) { // Forestfall + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(ForestColors_p, colorindex); + } else if (modes[currentMode].Scale < 96) { // Rainbowfall + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(RainbowColors_p, colorindex); + } else { // Aurora + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(RainbowStripeColors_p, colorindex); + } + } + } + }*/ +void fire2012WithPalette() { + // bool fire_water = modes[currentMode].Scale <= 50; + // uint8_t COOLINGNEW = fire_water ? modes[currentMode].Scale * 2 + 20 : (100 - modes[currentMode].Scale ) * 2 + 20 ; + // uint8_t COOLINGNEW = modes[currentMode].Scale * 2 + 20 ; + // Array of temperature readings at each simulation cell + //static byte heat[WIDTH][HEIGHT]; будет noise3d[0][WIDTH][HEIGHT] + + for (uint8_t x = 0; x < WIDTH; x++) { + // Step 1. Cool down every cell a little + for (int i = 0; i < HEIGHT; i++) { + noise3d[0][x][i] = qsub8(noise3d[0][x][i], random8(0, ((COOLINGNEW * 10) / HEIGHT) + 2)); + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for (int k = HEIGHT - 1; k >= 2; k--) { + noise3d[0][x][k] = (noise3d[0][x][k - 1] + noise3d[0][x][k - 2] + noise3d[0][x][k - 2]) / 3; + } + + // Step 3. Randomly ignite new 'sparks' of heat near the bottom + if (random8() < SPARKINGNEW) { + int y = random8(2); + noise3d[0][x][y] = qadd8(noise3d[0][x][y], random8(160, 255)); + } + + // Step 4. Map from heat cells to LED colors + for (int j = 0; j < HEIGHT; j++) { + // Scale the heat value from 0-255 down to 0-240 + // for best results with color palettes. + byte colorindex = scale8(noise3d[0][x][j], 240); + if (modes[currentMode].Scale == 100) + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(WaterfallColors_p, colorindex); + else + leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(CRGBPalette16( CRGB::Black, CHSV(modes[currentMode].Scale * 2.57, 255U, 255U) , CHSV(modes[currentMode].Scale * 2.57, 128U, 255U) , CRGB::White), colorindex);// 2.57 вместо 2.55, потому что 100 для белого цвета + //leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(fire_water ? HeatColors_p : OceanColors_p, colorindex); + } + } +} +//-----------------------Недо огонь--------------------------------------- +//stepko +#define FOR_i(from, to) for(int i = (from); i < (to); i++) +#define FOR_j(from, to) for(int j = (from); j < (to); j++) +unsigned int counter; +int STEP = modes[currentMode].Scale; //нужно виставить номер эффекта с пометкой false или любое число если не хотите Белого огня +void noiseWave(bool isColored) { +if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + FastLED.clear(); + + FOR_i(0, WIDTH) { + byte thisVal = sin8(STEP*counter*i); + byte thisMax = map(thisVal, 0, 255, 0, HEIGHT); + if (isColored) { + FOR_j(0, thisMax) { + CRGB color = (CRGB)ColorFromPalette(*curPalette, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND); + drawPixelXY(i, j, color);}} + else { + STEP = modes[currentMode].Scale; + FOR_j(0, thisMax) { + drawPixelXY(i, j, ColorFromPalette(WaterfallColors_p, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND)); + } + } + } + counter += 1; +} + +//----------------Gifка---------------------- +byte frameNum; + void animation1() { + frameNum++; + if (frameNum >= (framesArray)) frameNum = 0; + for (byte i = 0; i < 8; i++) + for (byte j = 0; j < 8; j++) + drawPixelXY(i, j, gammaCorrection(expandColor(pgm_read_word(&framesArray[frameNum][HEIGHT - j - 1][i])))); + } + + + +// -------------- эффект пульс ------------ +// Stefan Petrick's PULSE Effect mod by PalPalych for GyverLamp + +void drawCircle(int16_t x0, int16_t y0, uint16_t radius, const CRGB & color) { + int a = radius, b = 0; + int radiusError = 1 - a; + + if (radius == 0) { + drawPixelXY(x0, y0, color); + return; + } + + while (a >= b) { + drawPixelXY(a + x0, b + y0, color); + drawPixelXY(b + x0, a + y0, color); + drawPixelXY(-a + x0, b + y0, color); + drawPixelXY(-b + x0, a + y0, color); + drawPixelXY(-a + x0, -b + y0, color); + drawPixelXY(-b + x0, -a + y0, color); + drawPixelXY(a + x0, -b + y0, color); + drawPixelXY(b + x0, -a + y0, color); + b++; + if (radiusError < 0) + radiusError += 2 * b + 1; + else + { + a--; + radiusError += 2 * (b - a + 1); + } + } +} + +CRGBPalette16 palette; +uint8_t currentRadius = 4; +uint8_t pulse_centerX = random8(WIDTH - 5U) + 3U; +uint8_t pulse_centerY = random8(HEIGHT - 5U) + 3U; +//uint16_t _rc; вроде, не используется +//uint8_t _pulse_hue; заменено на deltaHue из общих переменных +//uint8_t _pulse_hueall; заменено на hue2 из общих переменных +//uint8_t _pulse_delta; заменено на deltaHue2 из общих переменных +//uint8_t pulse_hue; заменено на hue из общих переменных + +void pulseRoutine(uint8_t PMode) { + palette = RainbowColors_p; + const uint8_t limitSteps = 6U; + static const float fadeRate = 0.8; + + dimAll(248U); + uint8_t _sat; + if (step <= currentRadius) { + for (uint8_t i = 0; i < step; i++ ) { + uint8_t _dark = qmul8( 2U, cos8 (128U / (step + 1U) * (i + 1U))) ; + switch (PMode) { + case 1U: // 1 - случайные диски + deltaHue = hue; + _pulse_color = CHSV(deltaHue, 255U, _dark); + break; + case 2U: // 2...17 - перелив цвета дисков + deltaHue2 = modes[currentMode].Scale; + _pulse_color = CHSV(hue2, 255U, _dark); + break; + case 3U: // 18...33 - выбор цвета дисков + deltaHue = modes[currentMode].Scale * 2.55; + _pulse_color = CHSV(deltaHue, 255U, _dark); + break; + case 4U: // 34...50 - дискоцветы + deltaHue += modes[currentMode].Scale; + _pulse_color = CHSV(deltaHue, 255U, _dark); + break; + case 5U: // 51...67 - пузыри цветы + _sat = qsub8( 255U, cos8 (128U / (step + 1U) * (i + 1U))) ; + deltaHue += modes[currentMode].Scale; + _pulse_color = CHSV(deltaHue, _sat, _dark); + break; + case 6U: // 68...83 - выбор цвета пузырей + _sat = qsub8( 255U, cos8 (128U / (step + 1U) * (i + 1U))) ; + deltaHue = modes[currentMode].Scale * 2.55; + _pulse_color = CHSV(deltaHue, _sat, _dark); + break; + case 7U: // 84...99 - перелив цвета пузырей + _sat = qsub8( 255U, cos8 (128U / (step + 1U) * (i + 1U))) ; + deltaHue2 = modes[currentMode].Scale; + _pulse_color = CHSV(hue2, _sat, _dark); + break; + case 8U: // 100 - случайные пузыри + _sat = qsub8( 255U, cos8 (128U / (step + 1U) * (i + 1U))) ; + deltaHue = hue; + _pulse_color = CHSV(deltaHue, _sat, _dark); + break; + } + drawCircle(pulse_centerX, pulse_centerY, i, _pulse_color ); + } + } else { + pulse_centerX = random8(WIDTH - 5U) + 3U; + pulse_centerY = random8(HEIGHT - 5U) + 3U; + hue2 += deltaHue2; + hue = random8(0U, 255U); + currentRadius = random8(3U, 9U); + step = 0; + } + step++; +} +// ============= ЭФФЕКТ CНЕГ/МАТРИЦА/ДОЖДЬ =============== +// от @Shaitan +void RainRoutine() +{ + for (uint8_t x = 0U; x < WIDTH; x++) + { + // заполняем случайно верхнюю строку + CRGB thisColor = getPixColorXY(x, HEIGHT - 1U); + if ((uint32_t)thisColor == 0U) + { + if (random8(0, 50) == 0U) + { + if (modes[currentMode].Scale == 1) drawPixelXY(x, HEIGHT - 1U, CHSV(random(0, 9) * 28, 255U, 255U)); // Радужный дождь + else if (modes[currentMode].Scale >= 100) drawPixelXY(x, HEIGHT - 1U, 0xE0FFFF - 0x101010 * random(0, 4)); // Снег + else + drawPixelXY(x, HEIGHT - 1U, CHSV(modes[currentMode].Scale * 2.4 + random(0, 16), 255, 255)); // Цветной дождь + } + } + else + leds[XY(x, HEIGHT - 1U)] -= CHSV(0, 0, random(96, 128)); + } + // сдвигаем всё вниз + for (uint8_t x = 0U; x < WIDTH; x++) + { + for (uint8_t y = 0U; y < HEIGHT - 1U; y++) + { + drawPixelXY(x, y, getPixColorXY(x, y + 1U)); + } + } +} +// --------------------------- эффект спирали ---------------------- +/* + Aurora: https://github.com/pixelmatix/aurora + https://github.com/pixelmatix/aurora/blob/sm3.0-64x64/PatternSpiro.h + Copyright (c) 2014 Jason Coon + Неполная адаптация SottNick +*/ +byte spirotheta1 = 0; +byte spirotheta2 = 0; +// byte spirohueoffset = 0; // будем использовать переменную сдвига оттенка hue из эффектов Радуга + + +const uint8_t spiroradiusx = WIDTH / 4; +const uint8_t spiroradiusy = HEIGHT / 4; + +const uint8_t spirocenterX = WIDTH / 2-1; +const uint8_t spirocenterY = HEIGHT / 2-1; + +const uint8_t spirominx = spirocenterX - spiroradiusx; +const uint8_t spiromaxx = spirocenterX + spiroradiusx + 1; +const uint8_t spirominy = spirocenterY - spiroradiusy; +const uint8_t spiromaxy = spirocenterY + spiroradiusy + 1; + +uint8_t spirocount = 1; +uint8_t spirooffset = 256 / spirocount; +boolean spiroincrement = false; + +boolean spirohandledChange = false; + +uint8_t mapsin8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) { + uint8_t beatsin = sin8(theta); + uint8_t rangewidth = highest - lowest; + uint8_t Scaledbeat = scale8(beatsin, rangewidth); + uint8_t result = lowest + Scaledbeat; + return result; +} + +uint8_t mapcos8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) { + uint8_t beatcos = cos8(theta); + uint8_t rangewidth = highest - lowest; + uint8_t Scaledbeat = scale8(beatcos, rangewidth); + uint8_t result = lowest + Scaledbeat; + return result; +} + +uint8_t beatcos8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0) +{ + uint8_t beat = beat8(beats_per_minute, timebase); + uint8_t beatcos = cos8(beat + phase_offset); + uint8_t rangewidth = highest - lowest; + uint8_t scaledbeat = scale8(beatcos, rangewidth); + uint8_t result = lowest + scaledbeat; + return result; +} + +void spiroRoutine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + + blurScreen(5); + dimAll(255U - modes[currentMode].Speed / 10); + + boolean change = false; + + for (uint8_t i = 0; i < spirocount; i++) { + uint8_t x = mapsin8(spirotheta1 + i * spirooffset, spirominx, spiromaxx); + uint8_t y = mapcos8(spirotheta1 + i * spirooffset, spirominy, spiromaxy); + + uint8_t x2 = mapsin8(spirotheta2 + i * spirooffset, x - spiroradiusx, x + spiroradiusx); + uint8_t y2 = mapcos8(spirotheta2 + i * spirooffset, y - spiroradiusy, y + spiroradiusy); + + + //CRGB color = ColorFromPalette( PartyColors_p, (hue + i * spirooffset), 128U); // вообще-то палитра должна постоянно меняться, но до адаптации этого руки уже не дошли + //CRGB color = ColorFromPalette(*curPalette, hue + i * spirooffset, 128U); // вот так уже прикручена к бегунку Масштаба. за + //leds[XY(x2, y2)] += color; + if (x2 < WIDTH && y2 < HEIGHT) // добавил проверки. не знаю, почему эффект подвисает без них + leds[XY(x2, y2)] += (CRGB)ColorFromPalette(*curPalette, hue + i * spirooffset); + + if ((x2 == spirocenterX && y2 == spirocenterY) || + (x2 == spirocenterX && y2 == spirocenterY)) change = true; + } + + spirotheta2 += 2; + + EVERY_N_MILLIS(12) { + spirotheta1 += 1; + } + + EVERY_N_MILLIS(75) { + if (change && !spirohandledChange) { + spirohandledChange = true; + + if (spirocount >= WIDTH || spirocount == 1) spiroincrement = !spiroincrement; + + if (spiroincrement) { + if (spirocount >= 10) + spirocount *= 2; + else + spirocount += 1; + } + else { + if (spirocount > 4) + spirocount /= 2; + else + spirocount -= 1; + } + + spirooffset = 256 / spirocount; + } + + if (!change) spirohandledChange = false; + } + + EVERY_N_MILLIS(33) { + hue += 1; + } +} + + + void driftRoutine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + uint8_t dim = beatsin8(2, 230, 250); + dimAll(dim); + + for (int i = 2; i <= WIDTH / 2; i++) + { + CRGB color = (CRGB)ColorFromPalette(*curPalette,(i - 2) * (240 / (WIDTH / 2))); + + uint8_t x = beatcos8((spirocenterX + 1 - i) * 2, spirocenterX - i, spirocenterX + i); + uint8_t y = beatsin8((spirocenterY + 1 - i) * 2, spirocenterY - i, spirocenterY + i); + + drawPixelXY(x, y, color); + } + } + +void drift2Routine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + uint8_t dim = beatsin8(2, 170, 250); + dimAll(dim); + //FastLED.clear(); + + for (uint8_t i = 0; i < WIDTH; i++) + { + CRGB color; + + uint8_t x = 0; + uint8_t y = 0; + + if (i < spirocenterX) { + x = beatcos8((i + 1) * 20, i, WIDTH - i); + y = beatsin8((i + 1) * 20, i, HEIGHT - i); + color = (CRGB)ColorFromPalette(*curPalette, i * 14); + } + else + { + x = beatsin8((WIDTH - i) * 20, WIDTH - i, i + 1); + y = beatcos8((HEIGHT - i) * 20, HEIGHT - i, i + 1); + color = (CRGB)ColorFromPalette(*curPalette, (7 - i) * 14); + } + + drawPixelXY(x, y,color); + } +} + +/*void infinityRoutine() { //не очень + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + dimAll(255U - modes[currentMode].Speed / 10); + //FastLED.clear(); + + // the horizontal position of the head of the infinity sign + // oscillates from 0 to the maximum horizontal and back + int x = beatsin8(15, 1, WIDTH - 1); + + // the vertical position of the head oscillates + int y = (HEIGHT - 1) - beatsin8(30, HEIGHT / 4, ((HEIGHT / 4) * 3) - 1); + + // the hue oscillates from 0 to 255, overflowing back to 0 + hue++; + + CRGB color = (CRGB)ColorFromPalette(*curPalette, hue); + + drawPixelXY(x, y, color); + drawPixelXY(x - 1, y, color); +} +*/ + +byte theta = 0; +void radarRoutine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + dimAll(254); + + for (int offset = 0; offset < spirocenterX; offset++) { + byte hue = 255 - (offset * (256 / spirocenterX) + hue); + CRGB color = ColorFromPalette(*curPalette, hue); + uint8_t x = mapcos8(theta, offset, (WIDTH - 1) - offset); + uint8_t y = mapsin8(theta, offset, (HEIGHT - 1) - offset); + leds[XY(x, y)] = color; + + EVERY_N_MILLIS(25) { + theta += 2; + hue += 1; + } + } +} + +//-----------------Эффект Вышиванка------------- +byte count = 0; +byte dir = 1; +byte flip = 0; +byte generation = 0; +void MunchRoutine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + for (byte x = 0; x < WIDTH; x++) { + for (byte y = 0; y < HEIGHT; y++) { + leds[XY(x, y)] = (x ^ y ^ flip) < count ? ColorFromPalette(*curPalette, ((x ^ y) << 4) + generation) : CRGB::Black; + } + } + + count += dir; + + if (count <= 0 || count >= WIDTH) { + dir = -dir; + } + + if (count <= 0) { + if (flip == 0) + flip = 7; + else + flip = 0; + } + + generation++; +} + + + int time = 0; + + void PlasmaRoutine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + for (int x = 0; x < WIDTH; x++) { + for (int y = 0; y < HEIGHT; y++) { + int16_t v = 0; + uint8_t wibble = sin8(time); + v += sin16(x * wibble * 2 + time); + v += cos16(y * (128 - wibble) * 2 + time); + v += sin16(y * x * cos8(-time) / 2); + CRGB color = ColorFromPalette(*curPalette,(v >> 8) + 127); + drawPixelXY(x, y, color); + } + } + + time += 1; + + } +// ------------------------------ ЭФФЕКТ КОЛЬЦА / КОДОВЫЙ ЗАМОК ---------------------- +// (c) SottNick +// из-за повторного использоваия переменных от других эффектов теперь в этом коде невозможно что-то понять. +// поэтому для понимания придётся сперва заменить названия переменных на человеческие. но всё равно это песец, конечно. +//uint8_t deltaHue2; // максимальне количество пикселей в кольце (толщина кольца) от 1 до HEIGHT / 2 + 1 +//uint8_t deltaHue; // количество колец от 2 до HEIGHT +//uint8_t noise3d[1][1][HEIGHT]; // начальный оттенок каждого кольца (оттенка из палитры) 0-255 +//uint8_t shiftValue[HEIGHT]; // местоположение начального оттенка кольца 0-WIDTH-1 +//uint8_t shiftHue[HEIGHT]; // 4 бита на ringHueShift, 4 на ringHueShift2 +////ringHueShift[ringsCount]; // шаг градиета оттенка внутри кольца -8 - +8 случайное число +////ringHueShift2[ringsCount]; // обычная скорость переливания оттенка всего кольца -8 - +8 случайное число +//uint8_t deltaValue; // кольцо, которое в настоящий момент нужно провернуть +//uint8_t step; // оставшееся количество шагов, на которое нужно провернуть активное кольцо - случайное от WIDTH/5 до WIDTH-3 +//uint8_t hue, hue2; // количество пикселей в нижнем (hue) и верхнем (hue2) кольцах + +void ringsRoutine() { + uint8_t h, x, y; + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + + //deltaHue2 = (modes[currentMode].Scale - 1U) / 99.0 * (HEIGHT / 2 - 1U) + 1U; // толщина кольца в пикселях. если на весь бегунок масштаба (от 1 до HEIGHT / 2 + 1) + deltaHue2 = (modes[currentMode].Scale - 1U) % 11U + 1U; // толщина кольца от 1 до 11 для каждой из палитр + deltaHue = HEIGHT / deltaHue2 + ((HEIGHT % deltaHue2 == 0U) ? 0U : 1U); // количество колец + hue2 = deltaHue2 - (deltaHue2 * deltaHue - HEIGHT) / 2U; // толщина верхнего кольца. может быть меньше нижнего + hue = HEIGHT - hue2 - (deltaHue - 2U) * deltaHue2; // толщина нижнего кольца = всё оставшееся + for (uint8_t i = 0; i < deltaHue; i++) + { + noise3d[0][0][i] = random8(257U - WIDTH / 2U); // начальный оттенок кольца из палитры 0-255 за минусом длины кольца, делённой пополам + shiftHue[i] = random8(); + shiftValue[i] = 0U; //random8(WIDTH); само прокрутится постепенно + step = 0U; + //do { // песец конструкцию придумал бредовую + // step = WIDTH - 3U - random8((WIDTH - 3U) * 2U); само присвоится при первом цикле + //} while (step < WIDTH / 5U || step > 255U - WIDTH / 5U); + deltaValue = random8(deltaHue); + } + + } + for (uint8_t i = 0; i < deltaHue; i++) + { + if (i != deltaValue) // если это не активное кольцо + { + h = shiftHue[i] & 0x0F; // сдвигаем оттенок внутри кольца + if (h > 8U) + //noise3d[0][0][i] += (uint8_t)(7U - h); // с такой скоростью сдвиг оттенка от вращения кольца не отличается + noise3d[0][0][i]--; + else + //noise3d[0][0][i] += h; + noise3d[0][0][i]++; + } + else + { + if (step == 0) // если сдвиг активного кольца завершён, выбираем следующее + { + deltaValue = random8(deltaHue); + do { + step = WIDTH - 3U - random8((WIDTH - 3U) * 2U); // проворот кольца от хз до хз + } while (step < WIDTH / 5U || step > 255U - WIDTH / 5U); + } + else + { + if (step > 127U) + { + step++; + shiftValue[i] = (shiftValue[i] + 1U) % WIDTH; + } + else + { + step--; + shiftValue[i] = (shiftValue[i] - 1U + WIDTH) % WIDTH; + } + } + } + // отрисовываем кольца + h = (shiftHue[i] >> 4) & 0x0F; // берём шаг для градиента вутри кольца + if (h > 8U) + h = 7U - h; + for (uint8_t j = 0U; j < ((i == 0U) ? hue : ((i == deltaHue - 1U) ? hue2 : deltaHue2)); j++) // от 0 до (толщина кольца - 1) + { + y = i * deltaHue2 + j - ((i == 0U) ? 0U : deltaHue2 - hue); + // mod для чётных скоростей by @kostyamat - получается какая-то другая фигня. не стоит того + //for (uint8_t k = 0; k < WIDTH / ((modes[currentMode].Speed & 0x01) ? 2U : 4U); k++) // полукольцо для нечётных скоростей и четверть кольца для чётных + for (uint8_t k = 0; k < WIDTH / 2U; k++) // полукольцо + { + x = (shiftValue[i] + k) % WIDTH; // первая половина кольца + drawPixelXY(x, y, ColorFromPalette(*curPalette, noise3d[0][0][i] + k * h)); + x = (WIDTH - 1 + shiftValue[i] - k) % WIDTH; // вторая половина кольца (зеркальная первой) + + drawPixelXY(x, y, ColorFromPalette(*curPalette, noise3d[0][0][i] + k * h)); + } + if (WIDTH & 0x01) //(WIDTH % 2U > 0U) // если число пикселей по ширине матрицы нечётное, тогда не забываем и про среднее значение + { + x = (shiftValue[i] + WIDTH / 2U) % WIDTH; + drawPixelXY(x, y, ColorFromPalette(*curPalette, noise3d[0][0][i] + WIDTH / 2U * h)); + } + } + } +} + + +// ------------------------------ ЭФФЕКТ ЗВЁЗДЫ ---------------------- +// (c) SottNick +// производная от эффекта White Warp +// https://github.com/marcmerlin/NeoMatrix-FastLED-IR/blob/master/Table_Mark_Estes_Impl.h +// https://github.com/marcmerlin/FastLED_NeoMatrix_SmartMatrix_LEDMatrix_GFX_Demos/blob/master/LEDMatrix/Table_Mark_Estes/Table_Mark_Estes.ino +//int16_t pointy, blender = 128;//, laps, hue, steper, xblender, hhowmany, radius3, xpoffset[MATRIX_WIDTH * 3]; +#define STAR_BLENDER 128U // хз что это +#define CENTER_DRIFT_SPEED 6U // скорость перемещения плавающего центра возникновения звёзд +#define bballsMaxNUM (WIDTH * 2) +//, ringdelay;//, bringdelay, sumthum; +//int16_t shifty = 6;//, pattern = 0, poffset; +int16_t radius2;//, fpeed[WIDTH * 3], fcount[WIDTH * 3], fcountr[WIDTH * 3];//, xxx, yyy, dot = 3, rr, gg, bb, adjunct = 3; +//uint8_t fcolor[WIDTH * 3]; +uint16_t ccoolloorr; //, why1, why2, why3, eeks1, eeks2, eeks3, oldpattern, xhowmany, kk; +float driftx, drifty;//, locusx, locusy, xcen, ycen, yangle, xangle; +float cangle, sangle;//xfire[WIDTH * 3], yfire[WIDTH * 3], radius, xslope[MATRIX_WIDTH * 3], yslope[MATRIX_WIDTH * 3]; + +//Дополнительная функция построения линий +void DrawLine(int x1, int y1, int x2, int y2, CRGB color) +{ + int tmp; + int x, y; + int dx, dy; + int err; + int ystep; + + uint8_t swapxy = 0; + + if ( x1 > x2 ) dx = x1 - x2; else dx = x2 - x1; + if ( y1 > y2 ) dy = y1 - y2; else dy = y2 - y1; + + if ( dy > dx ) + { + swapxy = 1; + tmp = dx; dx = dy; dy = tmp; + tmp = x1; x1 = y1; y1 = tmp; + tmp = x2; x2 = y2; y2 = tmp; + } + if ( x1 > x2 ) + { + tmp = x1; x1 = x2; x2 = tmp; + tmp = y1; y1 = y2; y2 = tmp; + } + err = dx >> 1; + if ( y2 > y1 ) ystep = 1; else ystep = -1; + y = y1; + + for ( x = x1; x <= x2; x++ ) + { + if ( swapxy == 0 ) drawPixelXY(x, y, color); + else drawPixelXY(y, x, color); + err -= (uint8_t)dy; + if ( err < 0 ) + { + y += ystep; + err += dx; + } + } +} + +void drawstar(int16_t xlocl, int16_t ylocl, int16_t biggy, int16_t little, int16_t points, int16_t dangle, uint8_t koler)// random multipoint star +{ + // if (counter == 0) { // это, блин, вообще что за хрень была?! + // shifty = 3;//move quick + // } + radius2 = 255 / points; + for (int i = 0; i < points; i++) + { + //DrawLine(xlocl + ((little * (sin8(i * radius2 + radius2 / 2 - dangle) - 128.0)) / 128), ylocl + ((little * (cos8(i * radius2 + radius2 / 2 - dangle) - 128.0)) / 128), xlocl + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), ylocl + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), CHSV(koler , 255, 255)); + //DrawLine(xlocl + ((little * (sin8(i * radius2 - radius2 / 2 - dangle) - 128.0)) / 128), ylocl + ((little * (cos8(i * radius2 - radius2 / 2 - dangle) - 128.0)) / 128), xlocl + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), ylocl + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), CHSV(koler , 255, 255)); + // две строчки выше - рисуют звезду просто по оттенку, а две строчки ниже - берут цвет из текущей палитры + DrawLine(xlocl + ((little * (sin8(i * radius2 + radius2 / 2 - dangle) - 128.0)) / 128), ylocl + ((little * (cos8(i * radius2 + radius2 / 2 - dangle) - 128.0)) / 128), xlocl + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), ylocl + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), ColorFromPalette(*curPalette, koler)); + DrawLine(xlocl + ((little * (sin8(i * radius2 - radius2 / 2 - dangle) - 128.0)) / 128), ylocl + ((little * (cos8(i * radius2 - radius2 / 2 - dangle) - 128.0)) / 128), xlocl + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), ylocl + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), ColorFromPalette(*curPalette, koler)); + } +} + +uint8_t bballsCOLOR[bballsMaxNUM] ; // цвет звезды (используем повторно массив эффекта Мячики) +uint8_t bballsX[bballsMaxNUM] ; // количество углов в звезде (используем повторно массив эффекта Мячики) +int bballsPos[bballsMaxNUM] ; // задержка пуска звезды относительно счётчика (используем повторно массив эффекта Мячики) +uint8_t bballsNUM; // количество звёзд (используем повторно переменную эффекта Мячики) + +void starRoutine() { + //dimAll(255U - modes[currentMode].Scale * 2); + dimAll(89U); + //dimAll(myscale8(modes[currentMode].Scale)); + + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + + driftx = random8(4, WIDTH - 4);//set an initial location for the animation center + drifty = random8(4, HEIGHT - 4);// set an initial location for the animation center + + cangle = (sin8(random(25, 220)) - 128.0) / 128.0;//angle of movement for the center of animation gives a float value between -1 and 1 + sangle = (sin8(random(25, 220)) - 128.0) / 128.0;//angle of movement for the center of animation in the y direction gives a float value between -1 and 1 + //shifty = random (3, 12);//how often the drifter moves будет CENTER_DRIFT_SPEED = 6 + + //pointy = 7; теперь количество углов у каждой звезды своё + bballsNUM = (WIDTH + 6U) / 2U;//(modes[currentMode].Scale - 1U) / 99.0 * (bballsMaxNUM - 1U) + 1U; + if (bballsNUM > bballsMaxNUM) bballsNUM = bballsMaxNUM; + for (uint8_t num = 0; num < bballsNUM; num++) { + bballsX[num] = random8(3, 9);//pointy = random8(3, 9); // количество углов в звезде + bballsPos[num] = counter + (num << 2) + 1U;//random8(50);//modes[currentMode].Scale;//random8(50, 99); // задержка следующего пуска звезды + bballsCOLOR[num] = random8(); + } + + } + + + //hue++;//increment the color basis был общий оттенок на весь эффект. теперь у каждой звезды свой + //h = hue; //set h to the color basis + counter++; + if (driftx > (WIDTH - spirocenterX / 2U))//change directin of drift if you get near the right 1/4 of the screen + cangle = 0 - fabs(cangle); + if (driftx < spirocenterX / 2U)//change directin of drift if you get near the right 1/4 of the screen + cangle = fabs(cangle); + if (counter % CENTER_DRIFT_SPEED == 0) + driftx = driftx + cangle;//move the x center every so often + + if (drifty > ( HEIGHT - spirocenterY / 2U))// if y gets too big, reverse + sangle = 0 - fabs(sangle); + if (drifty < spirocenterY / 2U) // if y gets too small reverse + sangle = fabs(sangle); + if ((counter + CENTER_DRIFT_SPEED / 2U) % CENTER_DRIFT_SPEED == 0) + drifty = drifty + sangle;//move the y center every so often + + //по идее, не нужно равнять диапазоны плавающего центра. за них и так вылет невозможен + //driftx = constrain(driftx, spirocenterX - spirocenterX / 3, spirocenterX + spirocenterX / 3);//constrain the center, probably never gets evoked any more but was useful at one time to keep the graphics on the screen.... + //drifty = constrain(drifty, spirocenterY - spirocenterY / 3, spirocenterY + spirocenterY / 3); + + for (uint8_t num = 0; num < bballsNUM; num++) { + if (counter >= bballsPos[num])//(counter >= ringdelay) + { + if (counter - bballsPos[num] <= WIDTH + 5U) { //(counter - ringdelay <= WIDTH + 5){ + //drawstar(driftx , drifty, 2 * (counter - ringdelay), (counter - ringdelay), pointy, blender + h, h * 2 + 85); + drawstar(driftx , drifty, 2 * (counter - bballsPos[num]), (counter - bballsPos[num]), bballsX[num], STAR_BLENDER + bballsCOLOR[num], bballsCOLOR[num] * 2);//, h * 2 + 85);// что, бл, за 85?! + bballsCOLOR[num]++; + } + else + //bballsX[num] = random8(3, 9);//pointy = random8(3, 9); // количество углов в звезде + bballsPos[num] = counter + (bballsNUM << 1) + 1U;//random8(50, 99);//modes[currentMode].Scale;//random8(50, 99); // задержка следующего пуска звезды + } + } +} + + + + +// ============= ЭФФЕКТ ПРИЗМАТА =============== +// Prismata Loading Animation +// https://github.com/pixelmatix/aurora/blob/master/PatternPendulumWave.h +// Адаптация от (c) SottNick + +void PrismataRoutine() { + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + } + + EVERY_N_MILLIS(33) { + hue++; // используем переменную сдвига оттенка из функций радуги, чтобы не занимать память + } + FastLED.clear(); + + for (uint8_t x = 0; x < WIDTH; x++) + { + //uint8_t y = beatsin8(x + 1, 0, HEIGHT-1); // это я попытался распотрошить данную функцию до исходного кода и вставить в неё регулятор скорости + // вместо 28 в оригинале было 280, умножения на .Speed не было, а вместо >>17 было (<<8)>>24. короче, оригинальная скорость достигается при бегунке .Speed=20 + uint8_t beat = (GET_MILLIS() * (accum88(x + 1)) * 28 * modes[currentMode].Speed) >> 17; + uint8_t y = scale8(sin8(beat), HEIGHT - 1); + //и получилось!!! + + drawPixelXY(x, y, ColorFromPalette(*curPalette, x * 7 + hue)); + } +} +// ------------- светлячки -------------- +#define BALLS_AMOUNT2 (10U) // количество "cветлячков" +#define CLEAR_PATH2 (1U) // очищать путь +int16_t coord2[BALLS_AMOUNT2][2U]; +int8_t vector2[BALLS_AMOUNT2][2U]; +CRGB ballColors2[BALLS_AMOUNT2]; +void lightersRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + + for (uint8_t j = 0U; j < BALLS_AMOUNT2; j++) + { + int8_t sign2; + // забиваем случайными данными + coord2[j][0U] = WIDTH / 2 * 10; + random(0, 2) ? sign2 = 1 : sign2 = -1; + vector2[j][0U] = random(4, 15) * sign2; + coord2[j][1U] = HEIGHT / 2 * 10; + random(0, 2) ? sign2 = 1 : sign2 = -1; + vector2[j][1U] = random(4, 15) * sign2; + //ballColors[j] = CHSV(random(0, 9) * 28, 255U, 255U); + // цвет зависит от масштаба + ballColors2[j] = CHSV((modes[currentMode].Scale * (j + 1)) % 256U, 255U, 255U); + } + } + + + FastLED.clear(); + + // движение шариков + for (uint8_t j = 0U; j < BALLS_AMOUNT2; j++) + { + // движение шариков + for (uint8_t i = 0U; i < 2U; i++) + { + coord2[j][i] += vector2[j][i]; + if (coord2[j][i] < 0) + { + coord2[j][i] = 0; + vector2[j][i] = -vector2[j][i]; + } + } + + if (coord2[j][0U] > (int16_t)((WIDTH - 1) * 10)) + { + coord2[j][0U] = (WIDTH - 1) * 10; + vector2[j][0U] = -vector2[j][0U]; + } + if (coord2[j][1U] > (int16_t)((HEIGHT - 1) * 10)) + { + coord2[j][1U] = (HEIGHT - 1) * 10; + vector2[j][1U] = -vector2[j][1U]; + } + leds[XY(coord2[j][0U] / 10, coord2[j][1U] / 10)] = ballColors2[j]; + } +} + +// --------------------------- эффект мячики ---------------------- +// BouncingBalls2014 is a program that lets you animate an LED strip +// to look like a group of bouncing balls +// Daniel Wilson, 2014 +// https://github.com/githubcdr/Arduino/blob/master/bouncingballs/bouncingballs.ino +// With BIG thanks to the FastLED community! +// адаптация от SottNick +#define bballsGRAVITY (-9.81) // Downward (negative) acceleration of gravity in m/s^2 +#define bballsH0 (1) // Starting height, in meters, of the ball (strip length) +//#define bballsMaxNUM (WIDTH * 2) // максимальное количество мячиков прикручено при адаптации для бегунка Масштаб +//uint8_t bballsNUM; // Number of bouncing balls you want (recommend < 7, but 20 is fun in its own way) ... количество мячиков теперь задаётся бегунком, а не константой +//uint8_t bballsCOLOR[bballsMaxNUM] ; // прикручено при адаптации для разноцветных мячиков +//uint8_t bballsX[bballsMaxNUM] ; // прикручено при адаптации для распределения мячиков по радиусу лампы +bool bballsShift[bballsMaxNUM] ; // прикручено при адаптации для того, чтобы мячики не стояли на месте +float bballsVImpact0 = sqrt( -2 * bballsGRAVITY * bballsH0 ); // Impact velocity of the ball when it hits the ground if "dropped" from the top of the strip +float bballsVImpact[bballsMaxNUM] ; // As time goes on the impact velocity will change, so make an array to store those values +//uint16_t bballsPos[bballsMaxNUM] ; // The integer position of the dot on the strip (LED index) +long bballsTLast[bballsMaxNUM] ; // The clock time of the last ground strike +float bballsCOR[bballsMaxNUM] ; // Coefficient of Restitution (bounce damping) + +void BBallsRoutine() { + if (loadingFlag) + { + loadingFlag = false; + FastLED.clear(); + bballsNUM = (modes[currentMode].Scale - 1U) / 99.0 * (bballsMaxNUM - 1U) + 1U; + if (bballsNUM > bballsMaxNUM) bballsNUM = bballsMaxNUM; + for (uint8_t i = 0 ; i < bballsNUM ; i++) { // Initialize variables + bballsCOLOR[i] = random8(); + bballsX[i] = random8(0U, WIDTH); + bballsTLast[i] = millis(); + bballsPos[i] = 0U; // Balls start on the ground + bballsVImpact[i] = bballsVImpact0; // And "pop" up at vImpact0 + bballsCOR[i] = 0.90 - float(i) / pow(bballsNUM, 2); // это, видимо, прыгучесть. для каждого мячика уникальная изначально + bballsShift[i] = false; + hue2 = (modes[currentMode].Speed > 127U) ? 255U : 0U; // цветные или белые мячики + hue = (modes[currentMode].Speed == 128U) ? 255U : 254U - modes[currentMode].Speed % 128U * 2U; // скорость угасания хвостов 0 = моментально + } + } + + float bballsHi; + float bballsTCycle; + deltaHue++; // постепенное изменение оттенка мячиков (закомментировать строчку, если не нужно) + dimAll(hue); + for (uint8_t i = 0 ; i < bballsNUM ; i++) { + //leds[XY(bballsX[i], bballsPos[i])] = CRGB::Black; // off for the next loop around // теперь пиксели гасятся в dimAll() + + bballsTCycle = millis() - bballsTLast[i] ; // Calculate the time since the last time the ball was on the ground + + // A little kinematics equation calculates positon as a function of time, acceleration (gravity) and intial velocity + bballsHi = 0.5 * bballsGRAVITY * pow( bballsTCycle / 1000.0 , 2.0 ) + bballsVImpact[i] * bballsTCycle / 1000.0; + + if ( bballsHi < 0 ) { + bballsTLast[i] = millis(); + bballsHi = 0; // If the ball crossed the threshold of the "ground," put it back on the ground + bballsVImpact[i] = bballsCOR[i] * bballsVImpact[i] ; // and recalculate its new upward velocity as it's old velocity * COR + + if ( bballsVImpact[i] < 0.01 ) // If the ball is barely moving, "pop" it back up at vImpact0 + { + bballsCOR[i] = 0.90 - float(random(0U, 9U)) / pow(random(4U, 9U), 2); // сделал, чтобы мячики меняли свою прыгучесть каждый цикл + bballsShift[i] = bballsCOR[i] >= 0.89; // если мячик максимальной прыгучести, то разрешаем ему сдвинуться + bballsVImpact[i] = bballsVImpact0; + } + } + bballsPos[i] = round( bballsHi * (HEIGHT - 1) / bballsH0); // Map "h" to a "pos" integer index position on the LED strip + if (bballsShift[i] && (bballsPos[i] == HEIGHT - 1)) { // если мячик получил право, то пускай сдвинется на максимальной высоте 1 раз + bballsShift[i] = false; + if (bballsCOLOR[i] % 2 == 0) { // чётные налево, нечётные направо + if (bballsX[i] == 0U) bballsX[i] = WIDTH - 1U; + else --bballsX[i]; + } else { + if (bballsX[i] == WIDTH - 1U) bballsX[i] = 0U; + else ++bballsX[i]; + } + } + leds[XY(bballsX[i], bballsPos[i])] = CHSV(bballsCOLOR[i] + deltaHue, hue2, 255U); + } +} + +/*// ------------------------------ ЭФФЕКТ ПРЫГУНЫ ---------------------- + // стырено откуда-то by @obliterator + // https://github.com/DmytroKorniienko/FireLamp_JeeUI/blob/templ/src/effects.cpp + + //Leaper leapers[20]; + //вместо класса Leaper будем повторно использовать переменные из эффекта мячики + //float x, y; будет: + float leaperX[bballsMaxNUM]; + float leaperY[bballsMaxNUM]; + //float xd, yd; будет: + ////float bballsVImpact[bballsMaxNUM]; // As time goes on the impact velocity will change, so make an array to store those values + ////float bballsCOR[bballsMaxNUM]; // Coefficient of Restitution (bounce damping) + //CHSV color; будет: + ////uint8_t bballsCOLOR[bballsMaxNUM]; + + void LeapersRestart_leaper(uint8_t l) { + // leap up and to the side with some random component + bballsVImpact[l] = (1 * (float)random8(1, 100) / 100); + bballsCOR[l] = (2 * (float)random8(1, 100) / 100); + + // for variety, sometimes go 50% faster + if (random8() < 12) { + bballsVImpact[l] += bballsVImpact[l] * 0.5; + bballsCOR[l] += bballsCOR[l] * 0.5; + } + + // leap towards the centre of the screen + if (leaperX[l] > (WIDTH / 2)) { + bballsVImpact[l] = -bballsVImpact[l]; + } + } + + void LeapersMove_leaper(uint8_t l) { + #define GRAVITY 0.06 + #define SETTLED_THRESHOLD 0.1 + #define WALL_FRICTION 0.95 + #define WIND 0.95 // wind resistance + + leaperX[l] += bballsVImpact[l]; + leaperY[l] += bballsCOR[l]; + + // bounce off the floor and ceiling? + if (leaperY[l] < 0 || leaperY[l] > HEIGHT - 1) { + bballsCOR[l] = (-bballsCOR[l] * WALL_FRICTION); + bballsVImpact[l] = ( bballsVImpact[l] * WALL_FRICTION); + leaperY[l] += bballsCOR[l]; + if (leaperY[l] < 0) leaperY[l] = 0; + // settled on the floor? + if (leaperY[l] <= SETTLED_THRESHOLD && fabs(bballsCOR[l]) <= SETTLED_THRESHOLD) { + LeapersRestart_leaper(l); + } + } + + // bounce off the sides of the screen? + if (leaperX[l] <= 0 || leaperX[l] >= WIDTH - 1) { + bballsVImpact[l] = (-bballsVImpact[l] * WALL_FRICTION); + if (leaperX[l] <= 0) { + leaperX[l] = bballsVImpact[l]; + } else { + leaperX[l] = WIDTH - 1 - bballsVImpact[l]; + } + } + + bballsCOR[l] -= GRAVITY; + bballsVImpact[l] *= WIND; + bballsCOR[l] *= WIND; + } + + + void LeapersRoutine(){ + //unsigned num = map(Scale, 0U, 255U, 6U, sizeof(boids) / sizeof(*boids)); + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + //FastLED.clear(); + //bballsNUM = (modes[currentMode].Scale - 1U) / 99.0 * (bballsMaxNUM - 1U) + 1U; + bballsNUM = (modes[currentMode].Scale - 1U) % 11U / 10.0 * (bballsMaxNUM - 1U) + 1U; + if (bballsNUM > bballsMaxNUM) bballsNUM = bballsMaxNUM; + //if (bballsNUM < 2U) bballsNUM = 2U; + + for (uint8_t i = 0 ; i < bballsNUM ; i++) { + leaperX[i] = random8(WIDTH); + leaperY[i] = random8(HEIGHT); + + //curr->color = CHSV(random(1U, 255U), 255U, 255U); + bballsCOLOR[i] = random8(); + } + } + FastLED.clear(); + + for (uint8_t i = 0; i < bballsNUM; i++) { + LeapersMove_leaper(i); + //drawPixelXYF(leaperX[i], leaperY[i], CHSV(bballsCOLOR[i], 255U, 255U)); + drawPixelXYF(leaperX[i], leaperY[i], ColorFromPalette(*curPalette, bballsCOLOR[i])); + }; + + blurScreen(20); + }*/ + + #define PAUSE_MAX 7 // пропустить 7 кадров после завершения анимации сдвига ячеек + +//uint8_t noise3d[1][WIDTH][HEIGHT]; // тут используем только нулевую колонку и нулевую строку. просто для экономии памяти взяли существующий трёхмерный массив +//uint8_t hue2; // осталось шагов паузы +//uint8_t step; // текущий шаг сдвига (от 0 до deltaValue-1) +//uint8_t deltaValue; // всего шагов сдвига (до razmer? до (razmer?+1)*shtuk?) +//uint8_t deltaHue, deltaHue2; // глобальный X и глобальный Y нашего "кубика" +uint8_t razmerX, razmerY; // размеры ячеек по горизонтали / вертикали +uint8_t shtukX, shtukY; // количество ячеек по горизонтали / вертикали +uint8_t poleX, poleY; // размер всего поля по горизонтали / вертикали (в том числе 1 дополнительная пустая дорожка-разделитель с какой-то из сторон) +int8_t globalShiftX, globalShiftY; // нужно ли сдвинуть всё поле по окончаии цикла и в каком из направлений (-1, 0, +1) +bool seamlessX; // получилось ли сделать поле по Х бесшовным +bool krutimVertikalno; // направление вращения в данный момент + +void cube2dRoutine(){ + uint8_t x, y; + uint8_t anim0; // будем считать тут начальный пиксель для анимации сдвига строки/колонки + int8_t shift, kudaVse; // какое-то расчётное направление сдвига (-1, 0, +1) + CRGB color, color2; + + if (loadingFlag) + { + loadingFlag = false; + setCurrentPalette(); + FastLED.clear(); + + razmerX = (modes[currentMode].Scale - 1U) % 11U + 1U; // размер ячейки от 1 до 11 пикселей для каждой из 9 палитр + razmerY = razmerX; + if (modes[currentMode].Speed & 0x01) // по идее, ячейки не обязательно должны быть квадратными, поэтому можно тут поизвращаться + razmerY = (razmerY << 1U) + 1U; + + shtukY = HEIGHT / (razmerY + 1U); + if (shtukY < 2U) + shtukY = 2U; + y = HEIGHT / shtukY - 1U; + if (razmerY > y) + razmerY = y; + poleY = (razmerY + 1U) * shtukY; + shtukX = WIDTH / (razmerX + 1U); + if (shtukX < 2U) + shtukX = 2U; + x = WIDTH / shtukX - 1U; + if (razmerX > x) + razmerX = x; + poleX = (razmerX + 1U) * shtukX; + seamlessX = (poleX == WIDTH); + deltaHue = 0U; + deltaHue2 = 0U; + globalShiftX = 0; + globalShiftY = 0; + + for (uint8_t j = 0U; j < shtukY; j++) + { + y = j * (razmerY + 1U); // + deltaHue2 т.к. оно =0U + for (uint8_t i = 0U; i < shtukX; i++) + { + x = i * (razmerX + 1U); // + deltaHue т.к. оно =0U + if (modes[currentMode].Scale == 100U) + color = CHSV(45U, 0U, 128U + random8(128U)); + else + color = ColorFromPalette(*curPalette, random8()); + for (uint8_t k = 0U; k < razmerY; k++) + for (uint8_t m = 0U; m < razmerX; m++) + leds[XY(x+m, y+k)] = color; + } + } + step = 4U; // текущий шаг сдвига первоначально с перебором (от 0 до deltaValue-1) + deltaValue = 4U; // всего шагов сдвига (от razmer? до (razmer?+1) * shtuk?) + hue2 = 0U; // осталось шагов паузы + + //это лишнее обнуление + //krutimVertikalno = true; + //for (uint8_t i = 0U; i < shtukX; i++) + // noise3d[0][i][0] = 0U; + } + + //двигаем, что получилось... + if (hue2 == 0 && step < deltaValue) // если пауза закончилась, а цикл вращения ещё не завершён + { + step++; + if (krutimVertikalno) + { + for (uint8_t i = 0U; i < shtukX; i++) + { + x = (deltaHue + i * (razmerX + 1U)) % WIDTH; + if (noise3d[0][i][0] > 0) // в нулевой ячейке храним оставшееся количество ходов прокрутки + { + noise3d[0][i][0]--; + shift = noise3d[0][i][1] - 1; // в первой ячейке храним направление прокрутки + + if (globalShiftY == 0) + anim0 = (deltaHue2 == 0U) ? 0U : deltaHue2 - 1U; + else if (globalShiftY > 0) + anim0 = deltaHue2; + else + anim0 = deltaHue2 - 1U; + + if (shift < 0) // если крутим столбец вниз + { + color = leds[XY(x, anim0)]; // берём цвет от нижней строчки + for (uint8_t k = anim0; k < anim0+poleY-1; k++) + { + color2 = leds[XY(x,k+1)]; // берём цвет от строчки над нашей + for (uint8_t m = x; m < x + razmerX; m++) + leds[XY(m % WIDTH,k)] = color2; // копируем его на всю нашу строку + } + for (uint8_t m = x; m < x + razmerX; m++) + leds[XY(m % WIDTH,anim0+poleY-1)] = color; // цвет нижней строчки копируем на всю верхнюю + } + else if (shift > 0) // если крутим столбец вверх + { + color = leds[XY(x,anim0+poleY-1)]; // берём цвет от верхней строчки + for (uint8_t k = anim0+poleY-1; k > anim0 ; k--) + { + color2 = leds[XY(x,k-1)]; // берём цвет от строчки под нашей + for (uint8_t m = x; m < x + razmerX; m++) + leds[XY(m % WIDTH,k)] = color2; // копируем его на всю нашу строку + } + for (uint8_t m = x; m < x + razmerX; m++) + leds[XY(m % WIDTH, anim0)] = color; // цвет верхней строчки копируем на всю нижнюю + } + } + } + } + else + { + for (uint8_t j = 0U; j < shtukY; j++) + { + y = deltaHue2 + j * (razmerY + 1U); + if (noise3d[0][0][j] > 0) // в нулевой ячейке храним оставшееся количество ходов прокрутки + { + noise3d[0][0][j]--; + shift = noise3d[0][1][j] - 1; // в первой ячейке храним направление прокрутки + + if (seamlessX) + anim0 = 0U; + else if (globalShiftX == 0) + anim0 = (deltaHue == 0U) ? 0U : deltaHue - 1U; + else if (globalShiftX > 0) + anim0 = deltaHue; + else + anim0 = deltaHue - 1U; + + if (shift < 0) // если крутим строку влево + { + color = leds[XY(anim0, y)]; // берём цвет от левой колонки (левого пикселя) + for (uint8_t k = anim0; k < anim0+poleX-1; k++) + { + color2 = leds[XY(k+1, y)]; // берём цвет от колонки (пикселя) правее + for (uint8_t m = y; m < y + razmerY; m++) + leds[XY(k, m)] = color2; // копируем его на всю нашу колонку + } + for (uint8_t m = y; m < y + razmerY; m++) + leds[XY(anim0+poleX-1, m)] = color; // цвет левой колонки копируем на всю правую + } + else if (shift > 0) // если крутим столбец вверх + { + color = leds[XY(anim0+poleX-1, y)]; // берём цвет от правой колонки + for (uint8_t k = anim0+poleX-1; k > anim0 ; k--) + { + color2 = leds[XY(k-1, y)]; // берём цвет от колонки левее + for (uint8_t m = y; m < y + razmerY; m++) + leds[XY(k, m)] = color2; // копируем его на всю нашу колонку + } + for (uint8_t m = y; m < y + razmerY; m++) + leds[XY(anim0, m)] = color; // цвет правой колонки копируем на всю левую + } + } + } + } + + } + else if (hue2 != 0U) // пропускаем кадры после прокрутки кубика (делаем паузу) + hue2--; + + if (step >= deltaValue) // если цикл вращения завершён, меняем местами соответствующие ячейки (цвет в них) и точку первой ячейки + { + step = 0U; + hue2 = PAUSE_MAX; + //если часть ячеек двигалась на 1 пиксель, пододвигаем глобальные координаты начала + deltaHue2 = deltaHue2 + globalShiftY; //+= globalShiftY; + globalShiftY = 0; + //deltaHue += globalShiftX; для бесшовной не годится + deltaHue = (WIDTH + deltaHue + globalShiftX) % WIDTH; + globalShiftX = 0; + + //пришла пора выбрать следующие параметры вращения + kudaVse = 0; + krutimVertikalno = random8(2U); + if (krutimVertikalno) // идём по горизонтали, крутим по вертикали (столбцы двигаются) + { + for (uint8_t i = 0U; i < shtukX; i++) + { + noise3d[0][i][1] = random8(3); + shift = noise3d[0][i][1] - 1; // в первой ячейке храним направление прокрутки + if (kudaVse == 0) + kudaVse = shift; + else if (shift != 0 && kudaVse != shift) + kudaVse = 50; + } + deltaValue = razmerY + ((deltaHue2 - kudaVse >= 0 && deltaHue2 - kudaVse + poleY < (int)HEIGHT) ? random8(2U) : 1U); + +/* if (kudaVse == 0) // пытался сделать, чтобы при совпадении "весь кубик стоит" сдвинуть его весь на пиксель, но заколебался + { + deltaValue = razmerY; + kudaVse = (random8(2)) ? 1 : -1; + if (deltaHue2 - kudaVse < 0 || deltaHue2 - kudaVse + poleY >= (int)HEIGHT) + kudaVse = 0 - kudaVse; + } +*/ + if (deltaValue == razmerY) // значит полюбому kudaVse было = (-1, 0, +1) - и для нуля в том числе мы двигаем весь куб на 1 пиксель + { + globalShiftY = 1 - kudaVse; //временно на единичку больше, чем надо + for (uint8_t i = 0U; i < shtukX; i++) + if (noise3d[0][i][1] == 1U) // если ячейка никуда не планировала двигаться + { + noise3d[0][i][1] = globalShiftY; + noise3d[0][i][0] = 1U; // в нулевой ячейке храним количество ходов сдвига + } + else + noise3d[0][i][0] = deltaValue; // в нулевой ячейке храним количество ходов сдвига + globalShiftY--; + } + else + { + x = 0; + for (uint8_t i = 0U; i < shtukX; i++) + if (noise3d[0][i][1] != 1U) + { + y = random8(shtukY); + if (y > x) + x = y; + noise3d[0][i][0] = deltaValue * (x + 1U); // в нулевой ячейке храним количество ходов сдвига + } + deltaValue = deltaValue * (x + 1U); + } + + } + else // идём по вертикали, крутим по горизонтали (строки двигаются) + { + for (uint8_t j = 0U; j < shtukY; j++) + { + noise3d[0][1][j] = random8(3); + shift = noise3d[0][1][j] - 1; // в первой ячейке храним направление прокрутки + if (kudaVse == 0) + kudaVse = shift; + else if (shift != 0 && kudaVse != shift) + kudaVse = 50; + } + if (seamlessX) + deltaValue = razmerX + ((kudaVse < 50) ? random8(2U) : 1U); + else + deltaValue = razmerX + ((deltaHue - kudaVse >= 0 && deltaHue - kudaVse + poleX < (int)WIDTH) ? random8(2U) : 1U); + +/* if (kudaVse == 0) // пытался сделать, чтобы при совпадении "весь кубик стоит" сдвинуть его весь на пиксель, но заколебался + { + deltaValue = razmerX; + kudaVse = (random8(2)) ? 1 : -1; + if (deltaHue - kudaVse < 0 || deltaHue - kudaVse + poleX >= (int)WIDTH) + kudaVse = 0 - kudaVse; + } +*/ + if (deltaValue == razmerX) // значит полюбому kudaVse было = (-1, 0, +1) - и для нуля в том числе мы двигаем весь куб на 1 пиксель + { + globalShiftX = 1 - kudaVse; //временно на единичку больше, чем надо + for (uint8_t j = 0U; j < shtukY; j++) + if (noise3d[0][1][j] == 1U) // если ячейка никуда не планировала двигаться + { + noise3d[0][1][j] = globalShiftX; + noise3d[0][0][j] = 1U; // в нулевой ячейке храним количество ходов сдвига + } + else + noise3d[0][0][j] = deltaValue; // в нулевой ячейке храним количество ходов сдвига + globalShiftX--; + } + else + { + y = 0; + for (uint8_t j = 0U; j < shtukY; j++) + if (noise3d[0][1][j] != 1U) + { + x = random8(shtukX); + if (x > y) + y = x; + noise3d[0][0][j] = deltaValue * (x + 1U); // в нулевой ячейке храним количество ходов сдвига + } + deltaValue = deltaValue * (y + 1U); + } + } + } +} diff --git a/ArduinoLamp_v1.5/noiseEffects.ino b/ArduinoLamp_v1.5/noiseEffects.ino new file mode 100644 index 0000000..e2888a7 --- /dev/null +++ b/ArduinoLamp_v1.5/noiseEffects.ino @@ -0,0 +1,283 @@ +// ************* НАСТРОЙКИ ************* +// The 16 bit version of our coordinates +static uint16_t x; +static uint16_t y; +static uint16_t z; + +uint16_t speed = 20; // speed is set dynamically once we've started up +uint16_t scale = 30; // scale is set dynamically once we've started up + +// This is the array that we keep our computed noise values in +#define MAX_DIMENSION (max(WIDTH, HEIGHT)) +#if (WIDTH > HEIGHT) +uint8_t noise[WIDTH][WIDTH]; +#else +uint8_t noise[HEIGHT][HEIGHT]; +#endif + +CRGBPalette16 pPalette; + +// This function sets up a palette of black and blue stripes, +// using code. Since the palette is effectively an array of +// sixteen CRGB colors, the various fill_* functions can be used +// to set them up. +void SetupPalette() +{ + fill_solid( pPalette, 16, CHSV(modes[currentMode].Scale * 2.5, 255, 75)); + + for (uint8_t i = 0; i < 6; i++) { + pPalette[i] = CHSV(modes[currentMode].Scale * 2.5, 255, 255); + + } + } + + +CRGBPalette16 currentPalette(PartyColors_p); +uint8_t colorLoop = 1; +uint8_t ihue = 0; + +void madnessNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + } + fillnoise8(); + for (uint8_t i = 0; i < WIDTH; i++) + { + for (uint8_t j = 0; j < HEIGHT; j++) + { + CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); + leds[XY(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); + } + } + ihue += 1; +} + +void rainbowNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = RainbowColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 1; + } + fillNoiseLED(0.125, 0.0625, 1); +} + +void rainbowStripeNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = RainbowStripeColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 1; + } + fillNoiseLED(0.125, 0.0625, 1); +} + +void zebraNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + // 'black out' all 16 palette entries... + fill_solid(currentPalette, 16, CRGB::Black); + // and set every fourth one to white. + currentPalette[0] = CRGB::White; + currentPalette[4] = CRGB::White; + currentPalette[8] = CRGB::White; + currentPalette[12] = CRGB::White; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 1; + } + fillNoiseLED(0.125, 0.0625, 1); +} + +void forestNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = ForestColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(0.125, 0.0625, 1); +} + +void oceanNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = OceanColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + + fillNoiseLED(0.125, 0.0625, 1); +} + +void plasmaNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = PartyColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 1; + } + fillNoiseLED(0.125, 0.0625, 1); +} + +void cloudNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = CloudColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(0.125, 0.0625, 1); +} + +void lavaNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = LavaColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(0.125, 0.0625, 1); +} + +void heatNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = HeatColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(1, 0.625, 0.125); +} + +void smokeNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + currentPalette = WaterfallColors_p; + scale = modes[currentMode].Scale; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(1, 0.625, 0.125); +} + +void lavLampNoise() +{ + if (loadingFlag) + { + loadingFlag = false; + SetupPalette(); + currentPalette = pPalette; + scale = 30; + speed = modes[currentMode].Speed; + colorLoop = 0; + } + fillNoiseLED(1, 0, 0.125); +} +// ************* СЛУЖЕБНЫЕ ************* +void fillNoiseLED(byte x_dir, byte y_dir, byte z_dir) +{ + uint8_t dataSmoothing = 0; + if (speed < 50) + { + dataSmoothing = 200 - (speed * 4); + } + for (uint8_t i = 0; i < MAX_DIMENSION; i++) + { + int32_t ioffset = scale * i; + for (uint8_t j = 0; j < MAX_DIMENSION; j++) + { + int32_t joffset = scale * j; + + uint8_t data = inoise8(x + ioffset, y + joffset, z); + + data = qsub8(data, 16); + data = qadd8(data, scale8(data, 39)); + + if (dataSmoothing) + { + uint8_t olddata = noise[i][j]; + uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); + data = newdata; + } + + noise[i][j] = data; + } + } + z += speed * z_dir; + x -= speed * x_dir; + y += speed * y_dir; + + for (uint8_t i = 0; i < WIDTH; i++) + { + for (uint8_t j = 0; j < HEIGHT; j++) + { + uint8_t index = noise[j][i]; + uint8_t bri = noise[i][j]; + // if this palette is a 'loop', add a slowly-changing base value + if ( colorLoop) + { + index += ihue; + } + // brighten up, as the color palette itself often contains the + // light/dark dynamic range desired + if ( bri > 127 ) + { + bri = 255; + } + else + { + bri = dim8_raw( bri * 2); + } + CRGB color = ColorFromPalette( currentPalette, index, bri); + leds[XY(i, j)] = color; + } + } + ihue += 1; +} + +void fillnoise8() +{ + for (uint8_t i = 0; i < MAX_DIMENSION; i++) + { + int32_t ioffset = scale * i; + for (uint8_t j = 0; j < MAX_DIMENSION; j++) + { + int32_t joffset = scale * j; + noise[i][j] = inoise8(x + ioffset, y + joffset, z); + } + } + z -= speed; +} diff --git a/ArduinoLamp_v1.5/utility.ino b/ArduinoLamp_v1.5/utility.ino new file mode 100644 index 0000000..d9e167c --- /dev/null +++ b/ArduinoLamp_v1.5/utility.ino @@ -0,0 +1,195 @@ +// служебные функции + +// залить все +void fillAll(CRGB color) { + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = color; + } +} + +// функция отрисовки точки по координатам X Y +void drawPixelXY(uint8_t x, uint8_t y, CRGB color) +{ + if (x < 0 || x > (WIDTH - 1) || y < 0 || y > (HEIGHT - 1)) return; + uint32_t thisPixel = XY((uint8_t)x, (uint8_t)y) * SEGMENTS; + for (uint8_t i = 0; i < SEGMENTS; i++) + { + leds[thisPixel + i] = color; + } +} + + +// функция получения цвета пикселя по его номеру +uint32_t getPixColor(uint32_t thisSegm) +{ + uint32_t thisPixel = thisSegm * SEGMENTS; + if (thisPixel > NUM_LEDS - 1) return 0; + return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b); +} + +// функция получения цвета пикселя в матрице по его координатам +uint32_t getPixColorXY(uint8_t x, uint8_t y) +{ + return getPixColor(XY(x, y)); +} + +// **************** НАСТРОЙКА МАТРИЦЫ **************** +#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 XY(uint8_t x, uint8_t y) +{ + if (!(THIS_Y & 0x01) || MATRIX_TYPE) // Even rows run forwards + return (THIS_Y * _WIDTH + THIS_X); + else + return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); // Odd rows run backwards +} + +// оставлено для совместимости со эффектами из старых прошивок +uint16_t getPixelNumber(uint8_t x, uint8_t y) +{ + return XY(x, y); +} + + // Gamma коррекция (Defalt Gamma = 2.8) + const uint8_t PROGMEM gammaR[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, + 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, + 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, + 33, 34, 35, 36, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 46, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 80, + 81, 83, 84, 85, 87, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, + 104, 105, 107, 109, 110, 112, 113, 115, 116, 118, 120, 121, 123, 125, 127, 128, + 130, 132, 134, 135, 137, 139, 141, 143, 145, 146, 148, 150, 152, 154, 156, 158, + 160, 162, 164, 166, 168, 170, 172, 174, 177, 179, 181, 183, 185, 187, 190, 192, + 194, 196, 199, 201, 203, 206, 208, 210, 213, 215, 218, 220, 223, 225, 227, 230 + }; + + const uint8_t PROGMEM gammaG[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, + 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, + 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, + 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, + 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, + 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114, + 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142, + 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175, + 177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, + 215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255 + }; + + const uint8_t PROGMEM gammaB[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 12, 13, + 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, + 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, + 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40, + 40, 41, 42, 43, 44, 44, 45, 46, 47, 48, 49, 50, 51, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 70, + 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, + 90, 92, 93, 94, 96, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 112, + 113, 115, 116, 118, 119, 121, 122, 124, 126, 127, 129, 131, 132, 134, 136, 137, + 139, 141, 143, 144, 146, 148, 150, 152, 153, 155, 157, 159, 161, 163, 165, 167, + 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 196, 198, 200 + }; + + // гамма-коррекция (более натуральные цвета) + uint32_t gammaCorrection(uint32_t color) { + byte r = (color >> 16) & 0xFF; // Extract the RR byte + byte g = (color >> 8) & 0xFF; // Extract the GG byte + byte b = color & 0xFF; // Extract the BB byte + + r = pgm_read_byte(&gammaR[r]); + g = pgm_read_byte(&gammaG[g]); + b = pgm_read_byte(&gammaB[b]); + + uint32_t newColor = ((long)(r & 0xff) << 16) + ((long)(g & 0xff) << 8) + ((long)b & 0xff); + return newColor; + } + + // gamma correction для expandColor + static const uint8_t PROGMEM + gamma5[] = { + 0x00, 0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, + 0x0e, 0x11, 0x14, 0x18, 0x1d, 0x22, 0x28, 0x2e, + 0x36, 0x3d, 0x46, 0x4f, 0x59, 0x64, 0x6f, 0x7c, + 0x89, 0x97, 0xa6, 0xb6, 0xc7, 0xd9, 0xeb, 0xff + }, + gamma6[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, + 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x12, 0x13, + 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x20, 0x22, 0x25, + 0x27, 0x2a, 0x2d, 0x30, 0x33, 0x37, 0x3a, 0x3e, + 0x41, 0x45, 0x49, 0x4d, 0x52, 0x56, 0x5b, 0x5f, + 0x64, 0x69, 0x6e, 0x74, 0x79, 0x7f, 0x85, 0x8b, + 0x91, 0x97, 0x9d, 0xa4, 0xab, 0xb2, 0xb9, 0xc0, + 0xc7, 0xcf, 0xd6, 0xde, 0xe6, 0xee, 0xf7, 0xff + }; + + // преобразовать цвет из 16 битного в 24 битный + static uint32_t expandColor(uint16_t color) { + return ((uint32_t)pgm_read_byte(&gamma5[ color >> 11 ]) << 16) | + ((uint32_t)pgm_read_byte(&gamma6[(color >> 5) & 0x3F]) << 8) | + pgm_read_byte(&gamma5[ color & 0x1F]); + } diff --git a/GyverButtonOld/GyverButton.rar b/GyverButtonOld/GyverButton.rar new file mode 100644 index 0000000000000000000000000000000000000000..a0913fae148716451f406daea8c426c326a0a608 GIT binary patch literal 3454 zcmV-^4T17fVR9iF2LR8Ia{vGh000000002(RdgVLF900`000UR0006n(cTIrE#gic zGYZ*DGQaBvI(O%TZa6cv4>_^g(sDG*blmWrUDm9(e?j);OD zq)?M&HCRa&&4NM{N`c{hFUppxR3gwm7kB9DQXLW!M)PwwGdH3l!g?MiYi~H)<8L!3 z%)Xp&j~`0o=uPv9bJw1JmFZ2RT5`nnX>jl?$HucP)1{BS=!)u(f5C~>tx9&&LM&Y; z7_)OtqBtpM-7S(-@Z=MUEJ<>8HOZboS=OVima6Q>k!)+W(+tt;P0W#^A5egN5h=-~0Op_W2arS?Ob{=~ zOI!E{roHqxXefuliPFaf9#iE0poPk7r*p*zQj?GPC|dK$9mXKKk)$Jy*v2P+CvH&O za=}fYRhF4;$&m#9(Ore6-GDI7?hC_S>-iMca)}_w5(rAy52&_?eWEb3tedFSs^%FC z>aO}i8buLujSb^&<DsdOS2?1HFy|rWne>Za9DKP*Rd0+ zu#8As@!fGS7>{C;=y0g8j5DWfZh<=mE}Y&yhR&A?!`K`+T<9HA2&?bOzvae1`FxyA ztT$Pt=2F5+`%BWHM+Cb`q0KeM7%a3*OhR~9DVAh}&(9`ObTLM}Aw#roAG_uw7wE^X z#Hma#Qp9Y#5;vwf!QEd!9N}n~{%~3P3o~I1+?ig^i3x!Ll-_eUMu|t?UX9QN`|2R$ z{CnMCnirT;zqt+&XkxeL+(1uIoDf&G`C$i^3!X)Cspo-&o^T)(Ise=v&h^2m{NX`6 z>=s^`h)j%vH}-3xzDBv4=WF^#yDdh#fk2pXkQpG4;fT|hpuML@X7ZDZ;{D=H!=C8y z_ITj_-kf_}j2>UU&<`CJ0iDlWflT8e8@Dtq^pl6E*C~>SkZD5H2D|X?L{1vV>U#)H z-W?}%f`lwj#kp3YRXR%-0TfqUV6grI9T2ey_D(fT256;f6CbP$F2?y=<7=c1E~JdO z&<16e3*A(yXF5Rp!P@b*!ob;Ei;J9)8?2}VLdATPnt6nyFLLDJs(BwE$r&OD-m}lV zhP#(a8C@V>b%p@}l1BMj{WZ?t)Gn8yugKure2ww9_kDFI;eP;jL)xMEV3qNtadAQ# zu1Dckl>`Li`chAnXAuiT2bPxspbkY8K^X9Kv0II6@CC0of?JR#0_O`u_y#{ojQCx7 z(*!w6r{|2NOmydX!7~pu4Tl}$!VM;aC9JmEdY84004Cu0007% zpC6SaE#gicGYtSB0000-d3I%TLUnX>Z*DGV3>{Gr$kWZ8SGax^iB6W{a2qD>sj%JD zjR~?uqyb19I~oS?2DFWdykb#B5`gw>nt=ja-@hfk07ndl0LFMLen+Y|93yz&Dz5S6 z<~(9>o7f~ZnO9d;%K2Shc*TDRx%%xZReZX;N|o1VQeK?NOX;oK@@y|V@1VmIW=PeA z)C8r>UHMxIPPGeEx7m|ARS%4ti>voSg^ksPh@raOWvcq>v_JU=?MmBKS*yoae$sGS z3ftWEI=r@)udrzTb*PU%I^Uri**C$4;p*`$TZ-OrOV(Z?0M&FxKHDgJG)Rs*`Q|M= zUyc2Tp9oG=23)ock~ZwzWCMSz$ZLYyb&pxLsk*PQxNDTjBXJO7ZZ@88=cZi{h zL8VsdPT)ob1=={@>2hcQBY-Ca$2dfw`R<+*dou9DwcGcN>#}izq8dO3a!}%6Kw?Ep z*$GmGfx?uN9OhDd^@@oVktk}?c|#H$@SH-n|J0ool>(KiUE+M3;V3{9n@2?uZc7^h z0e{z`_KvT~*)oGdsbGj9TZB1{49ZQ>Vxpk3tNsH{B7tjqhoWcItNmh)HMWfwOxGd~ z4qB-wpG9H7S!TB3Nry4LuTmWP3IW=XR_o$WlMO-T&;!DwTXkav-r3SA88{?CS|=zQ zCr_|8(t*0;RpLocIio{WThLAMvMrF(5CJTm5~flEw0ld8dBl47HGjfMk6|Wglwj$A zLdxFkt&fWz9Ope~{ft=Md|Y_Z{cx+9Mm(D9ml#vnokB|xyrG2B zn>Sf)CMHOFYMCgtdMgr{v_#p)s;&KP@hQa2_}Hr+8DqzOwo= z*L+txa`WfBCvoNV-=wC@Un^Q&*X%xQ$H?iM7tHUDY^8mP%vjhZJMI|ymFI8p02%oY zp6uOtkfBMnH!`-Q8$$BJTGmj~0p7^*S;Fwf0c>_8F>3kvnHY)w#>Pys2-x?F=&6wd zndE}u=zz!cXu%=*sC1~^BPrXea`Q1xgfcJS+qOZ zz9aI8oB{XV&gj~*OWSnJ&G2{RX6JUZD~IQmZ(bhIq^F<2MCx~}^8&~m1wl?VyLp*$ zQYcB7s%_+8=vx1dR#kKy;YBc$x~pzynt))D4DFj*iP-tI{VBV~>;PTHrwt1l+Q*X{ zSbO!WuG#@@062if;2wN~Oza!ORxffDEIR%U#MyF|p1T=q=?e%+T;`HL)FzfvNTPrO zz-U?jnx*FpxGYsLOtRgG!sJb@5zt0_zZ&iC!=QE$K>%-mSG?ib#rHHgFdtqr z0Ez())%_SJ3-r(nVVO?@c`ydvuU{!ZqV zJXy9Hw$MYO=t3gYgb8_%gUcvBsDnHrtrwaBabDL_+LI+J70Z`7c`Qp8czbo;fH4Dc za+9bUtHysx*eZAHJ7LJG-AfT#fX`1Ej=Xe`c77rE@^dsYO8J>O8TqjVkV4@Z?u^db zDP1apJg*Un%bAQ5-y=Gh4zH?a(i=`AUBe*z&)@<`1U}%}BOGF|Cf!~U{^md`ql0{e zVH+e~KX+axAQc4Ag)_UqLON)bCOQ{kp)cPa~q3?<}z+u zfF%T-B=EYV(mc#uV^fa-xdLL~dcX{*mrfFIdb^|9=R?8p)&A=G&wa9qF1-Ruj)V>5 zM|w@Orm?Q5Ejd8|ZWau_?-KXnrq!Rr;D--$E??=MkhLtP9b6+h>^XA(kc3BawEp0j zrd;Ds=GOZ-F`8z1Pdvs#P_X&B`YCDZ!S5~6?AE>JVr8NDLocKbZ>?{Xt zsnYffx&nBbx?Hvb*zAD+xZ>Jn`i(amNd?&>?OHZM96992AFbABZ);!Yhi3;-Yi003)c zd3SGeWOFWbcytUEP{_~KK^JiTDWqw)WuFF6AVp6Ucqp!@i3X%5i!+II6$knc1Xzyf-wc+Y2iU(CZf`MRf>- zf9)jEz;q2dv6?OVF_jczq*It)$C6^Y4wjpoqx>Znk(;VDgJk^TO}F*_e-kMcA~_jK zsO=WbI0Y?ZtJjX|sdmQW`snBaA^1b1JUyCL<6-WHk{!(Bx+0n9uJZaIdK~yg2L)fz g3{Am=Z0}@^q(|6-Z;fPv#L~i-zoNuFdjLQO0OZ<~j{pDw literal 0 HcmV?d00001 diff --git a/GyverButtonOld/GyverButtonOld.cpp b/GyverButtonOld/GyverButtonOld.cpp new file mode 100644 index 0000000..aba8a17 --- /dev/null +++ b/GyverButtonOld/GyverButtonOld.cpp @@ -0,0 +1,199 @@ +#include "GyverButtonOld.h" +#include + +GButton::GButton(uint8_t pin) { + _PIN = pin; + GButton::init(); +} +GButton::GButton(uint8_t pin, boolean type, boolean dir) { + _PIN = pin; + GButton::init(); + GButton::setType(type); + flags.inv_state = dir; +} + +void GButton::init() { + _debounce = 60; + _timeout = 500; + _step_timeout = 400; + _click_timeout = 300; + flags.inv_state = NORM_OPEN; + flags.mode = false; + flags.type = false; + flags.tickMode = false; + GButton::setType(HIGH_PULL); +} + +void GButton::setDebounce(uint16_t debounce) { + _debounce = debounce; +} +void GButton::setTimeout(uint16_t timeout) { + _timeout = timeout; +} +void GButton::setClickTimeout(uint16_t timeout) { + _click_timeout = timeout; +} +void GButton::setStepTimeout(uint16_t step_timeout) { + _step_timeout = step_timeout; +} +void GButton::setType(boolean type) { + flags.type = type; + if (type) pinMode(_PIN, INPUT); + else pinMode(_PIN, INPUT_PULLUP); +} +void GButton::setDirection(boolean dir) { + flags.inv_state = dir; +} +void GButton::setTickMode(boolean tickMode) { + flags.tickMode = tickMode; +} + +boolean GButton::isPress() { + if (flags.tickMode) GButton::tick(); + if (flags.isPress_f) { + flags.isPress_f = false; + return true; + } else return false; +} +boolean GButton::isRelease() { + if (flags.tickMode) GButton::tick(); + if (flags.isRelease_f) { + flags.isRelease_f = false; + return true; + } else return false; +} +boolean GButton::isClick() { + if (flags.tickMode) GButton::tick(); + if (flags.isOne_f) { + flags.isOne_f = false; + return true; + } else return false; +} +boolean GButton::isHolded() { + if (flags.tickMode) GButton::tick(); + if (flags.isHolded_f == 1) { + flags.isHolded_f = 0; + return true; + } else return false; +} + +boolean GButton::isHolded2() { + if (flags.tickMode) GButton::tick(); + if (flags.isHolded_f == 2) { + flags.isHolded_f = 0; + return true; + } else return false; +} +boolean GButton::isHolded3() { + if (flags.tickMode) GButton::tick(); + if (flags.isHolded_f == 3) { + flags.isHolded_f = 0; + return true; + } else return false; +} +boolean GButton::isHold() { + if (flags.tickMode) GButton::tick(); + if (flags.step_flag) return true; + else return false; +} +boolean GButton::state() { + if (flags.tickMode) GButton::tick(); + return flags.btn_state; +} +boolean GButton::isSingle() { + if (flags.tickMode) GButton::tick(); + if (flags.counter_flag && last_counter == 1) { + flags.counter_flag = false; + return true; + } else return false; +} +boolean GButton::isDouble() { + if (flags.tickMode) GButton::tick(); + if (flags.counter_flag && last_counter == 2) { + flags.counter_flag = false; + return true; + } else return false; +} +boolean GButton::isTriple() { + if (flags.tickMode) GButton::tick(); + if (flags.counter_flag && last_counter == 3) { + flags.counter_flag = false; + return true; + } else return false; +} +boolean GButton::hasClicks() { + if (flags.tickMode) GButton::tick(); + if (flags.counter_flag) { + flags.counter_flag = false; + return true; + } else return false; +} +uint8_t GButton::getClicks() { + return last_counter; +} +boolean GButton::isStep() { + if (flags.tickMode) GButton::tick(); + if (flags.step_flag && (millis() - btn_timer >= _step_timeout)) { + btn_timer = millis(); + return true; + } + else return false; +} +void GButton::tick(boolean state) { + flags.mode = true; + flags.btn_state = state ^ flags.inv_state; + GButton::tick(); + flags.mode = false; +} +void GButton::tick() { + // + if (!flags.mode) flags.btn_state = !digitalRead(_PIN) ^ (flags.inv_state ^ flags.type); + + // + if (flags.btn_state && !flags.btn_flag) { + if (!flags.btn_deb) { + flags.btn_deb = true; + btn_timer = millis(); + } else { + if (millis() - btn_timer >= _debounce) { + flags.btn_flag = true; + flags.isPress_f = true; + flags.oneClick_f = true; + } + } + } else { + flags.btn_deb = false; + } + + // + if (!flags.btn_state && flags.btn_flag) { + flags.btn_flag = false; + if (!flags.hold_flag) btn_counter++; + flags.hold_flag = false; + flags.isRelease_f = true; + btn_timer = millis(); + flags.step_flag = false; + if (flags.oneClick_f) { + flags.oneClick_f = false; + flags.isOne_f = true; + } + } + + // + if (flags.btn_flag && flags.btn_state && (millis() - btn_timer >= _timeout) && !flags.hold_flag) { + flags.hold_flag = true; + flags.isHolded_f = btn_counter + 1; + btn_counter = 0; + last_counter = 0; + flags.step_flag = true; + flags.oneClick_f = false; + btn_timer = millis(); + } + + // + if ((millis() - btn_timer >= _click_timeout) && (btn_counter != 0)) { + last_counter = btn_counter; + btn_counter = 0; + flags.counter_flag = true; + } +} diff --git a/GyverButtonOld/GyverButtonOld.h b/GyverButtonOld/GyverButtonOld.h new file mode 100644 index 0000000..2216164 --- /dev/null +++ b/GyverButtonOld/GyverButtonOld.h @@ -0,0 +1,107 @@ +#ifndef GyverButtonOld_h +#define GyverButton_h +#include + +/* + GyverButton - библиотека для многофункциональной отработки нажатия кнопки. Возможности: + - Работа с нормально замкнутыми и нормально разомкнутыми кнопками + - Работа с подключением PULL_UP и PULL_DOWN + - Опрос кнопки с программным антидребезгом контактов + - Настраиваемое время антидребезга + - Отработка нажатия, удерживания, отпускания, клика по кнопке + - Настраиваемый таймаут удержания + - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) + - Отработка любого количества нажатий кнопки (функция возвращает количество нажатий) + - Настраиваемый таймаут повторного нажатия/удержания + - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени + - Возможность опрашивать не кнопку, а напрямую давать величину (все возможности библиотеки для матричных и резистивных клавиатур) + + Текущая версия: 2.12 от 18.03.2019: + - Поправлены баги при совместной работе методов опроса +*/ + +#pragma pack(push,1) +typedef struct +{ + bool btn_state: 1; + bool btn_deb: 1; + bool btn_flag: 1; + bool hold_flag: 1; + bool counter_flag: 1; + uint8_t isHolded_f: 3; + bool isRelease_f: 1; + bool isPress_f: 1; + bool step_flag: 1; + bool oneClick_f: 1; + bool isOne_f: 1; + bool inv_state: 1; + bool mode: 1; + bool type: 1; + bool tickMode: 1; +} GyverButtonFlags; +#pragma pack(pop) + +class GButton +{ + public: + GButton(uint8_t pin); // класс кнопки, принимает пин + + GButton(uint8_t pin, boolean type, boolean dir); // класс кнопки, принимает PIN пин, тип type (HIGH_PULL / LOW_PULL) и направление dir (NORM_OPEN / NORM_CLOSE) + // HIGH_PULL - кнопка подключена к GND, пин подтянут к VCC, pinMode - INPUT_PULLUP (по умолчанию) + // LOW_PULL - кнопка подключена к VCC, пин подтянут к GND, pinMode - INPUT + // NORM_OPEN - кнопка по умолчанию разомкнута (по умолчанию) + // NORM_CLOSE - кнопка по умолчанию замкнута + + void setDebounce(uint16_t debounce); // установка времени антидребезга (по умолчанию 80 мс) + void setTimeout(uint16_t timeout); // установка таймаута удержания (по умолчанию 300 мс) + void setClickTimeout(uint16_t timeout); // установка таймаута между кликами (по умолчанию 500 мс) + void setStepTimeout(uint16_t step_timeout); // установка таймаута между инкрементами (по умолчанию 400 мс) + void setType(boolean type); // установка типа кнопки (HIGH_PULL - подтянута к питанию, LOW_PULL - к gnd) + void setDirection(boolean dir); // установка направления (разомкнута/замкнута по умолчанию - NORM_OPEN, NORM_CLOSE) + + void setTickMode(boolean tickMode); // (MANUAL / AUTO) ручной или автоматический опрос кнопки функцией tick() + // MANUAL - нужно вызывать функцию tick() вручную + // AUTO - tick() входит во все остальные функции и опрашивается сама + + + void tick(); // опрос кнопки + void tick(boolean state); // опрос внешнего значения (0 нажато, 1 не нажато) (для матричных, резистивных клавиатур и джойстиков) + + boolean isPress(); // возвращает true при нажатии на кнопку. Сбрасывается после вызова + boolean isRelease(); // возвращает true при отпускании кнопки. Сбрасывается после вызова + boolean isClick(); // возвращает true при клике. Сбрасывается после вызова + boolean isHolded(); // возвращает true при удержании дольше timeout. Сбрасывается после вызова + boolean isHolded2(); // возвращает true при двойном нажатии и удержании дольше timeout. Сбрасывается после вызова + boolean isHolded3(); // возвращает true при тройном нажатии и удержании дольше timeout. Сбрасывается после вызова + boolean isHold(); // возвращает true при нажатой кнопке, не сбрасывается + boolean state(); // возвращает состояние кнопки + + boolean isSingle(); // возвращает true при одиночном клике. Сбрасывается после вызова + boolean isDouble(); // возвращает true при двойном клике. Сбрасывается после вызова + boolean isTriple(); // возвращает true при тройном клике. Сбрасывается после вызова + + boolean hasClicks(); // проверка на наличие кликов. Сбрасывается после вызова + uint8_t getClicks(); // вернуть количество кликов + + boolean isStep(); // возвращает true по таймеру setStepTimeout, смотри пример + + private: + void init(); + GyverButtonFlags flags; + uint8_t _PIN = 0; + uint16_t _debounce = 0; + uint16_t _timeout = 0; + uint16_t _click_timeout = 0; + uint16_t _step_timeout = 0; + uint8_t btn_counter = 0, last_counter = 0; + uint32_t btn_timer = 0; +}; + +#define HIGH_PULL 0 +#define LOW_PULL 1 +#define NORM_OPEN 0 +#define NORM_CLOSE 1 +#define MANUAL 0 +#define AUTO 1 + +#endif diff --git a/GyverButtonOld/examples/Gbutton_example/Gbutton_example.ino b/GyverButtonOld/examples/Gbutton_example/Gbutton_example.ino new file mode 100644 index 0000000..d1aefa4 --- /dev/null +++ b/GyverButtonOld/examples/Gbutton_example/Gbutton_example.ino @@ -0,0 +1,50 @@ +/* + Пример использования библиотеки GyverButton, все возможности в одном скетче. +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(PIN); +// GButton butt1(PIN, HIGH_PULL, NORM_OPEN); // можно инициализировать так + +int value = 0; + +void setup() { + Serial.begin(9600); + + butt1.setDebounce(50); // настройка антидребезга (по умолчанию 80 мс) + butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) + butt1.setClickTimeout(600); // настройка таймаута между кликами (по умолчанию 300 мс) + + // HIGH_PULL - кнопка подключена к GND, пин подтянут к VCC (PIN --- КНОПКА --- GND) + // LOW_PULL - кнопка подключена к VCC, пин подтянут к GND + butt1.setType(HIGH_PULL); + + // NORM_OPEN - нормально-разомкнутая кнопка + // NORM_CLOSE - нормально-замкнутая кнопка + butt1.setDirection(NORM_OPEN); +} + +void loop() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + + if (butt1.isClick()) Serial.println("Click"); // проверка на один клик + if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик + if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик + if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик + + if (butt1.hasClicks()) // проверка на наличие нажатий + Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий + + if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) + if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) + if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание + if (butt1.isHold()) Serial.println("Holding"); // проверка на удержание + //if (butt1.state()) Serial.println("Hold"); // возвращает состояние кнопки + + if (butt1.isStep()) { // если кнопка была удержана (это для инкремента) + value++; // увеличивать/уменьшать переменную value с шагом и интервалом + Serial.println(value); // для примера выведем в порт + } +} diff --git a/GyverButtonOld/examples/Gbutton_example_auto/Gbutton_example_auto.ino b/GyverButtonOld/examples/Gbutton_example_auto/Gbutton_example_auto.ino new file mode 100644 index 0000000..10e46b8 --- /dev/null +++ b/GyverButtonOld/examples/Gbutton_example_auto/Gbutton_example_auto.ino @@ -0,0 +1,53 @@ +/* + Пример использования библиотеки GyverButton, все возможности в одном скетче. +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(PIN); +// GButton butt1(PIN, HIGH_PULL, NORM_OPEN); // можно инициализировать так + +int value = 0; + +void setup() { + Serial.begin(9600); + + butt1.setDebounce(90); // настройка антидребезга (по умолчанию 80 мс) + butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) + + // HIGH_PULL - кнопка подключена к GND, пин подтянут к VCC (PIN --- КНОПКА --- GND) + // LOW_PULL - кнопка подключена к VCC, пин подтянут к GND + butt1.setType(HIGH_PULL); + + // NORM_OPEN - нормально-разомкнутая кнопка + // NORM_CLOSE - нормально-замкнутая кнопка + butt1.setDirection(NORM_OPEN); + + // MANUAL - нужно вызывать функцию tick() вручную + // AUTO - tick() входит во все остальные функции и опрашивается сама! + butt1.setTickMode(AUTO); +} + +void loop() { + // butt1.tick(); // не нужна, в этом режиме (AUTO) она входит в каждую функцию + + if (butt1.isClick()) Serial.println("Click"); // проверка на один клик + if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик + if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик + if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик + + if (butt1.hasClicks()) // проверка на наличие нажатий + Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий + + if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) + if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) + if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание + if (butt1.isHold()) Serial.println("Holding"); // проверка на удержание + //if (butt1.state()) Serial.println("Hold"); // возвращает состояние кнопки + + if (butt1.isStep()) { // если кнопка была удержана (это для инкремента) + value++; // увеличивать/уменьшать переменную value с шагом и интервалом + Serial.println(value); // для примера выведем в порт + } +} diff --git a/GyverButtonOld/examples/Gbutton_interrupt/Gbutton_interrupt.ino b/GyverButtonOld/examples/Gbutton_interrupt/Gbutton_interrupt.ino new file mode 100644 index 0000000..b529801 --- /dev/null +++ b/GyverButtonOld/examples/Gbutton_interrupt/Gbutton_interrupt.ino @@ -0,0 +1,48 @@ +/* + Пример использования библиотеки GyverButton, все возможности в одном скетче. + - Опрос кнопки с программным антидребезгом контактов + - Отработка нажатия, удерживания отпускания кнопки + - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) + - Отработка любого количества нажатий кнопки (функция возвращает число нажатий) + - Отработка нажатия и удержания кнопки + - Настраиваемый таймаут повторного нажатия/удержания + - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(PIN); +int value = 0; + +void setup() { + Serial.begin(9600); + attachInterrupt(1, isr, CHANGE); + + butt1.setDebounce(80); // настройка антидребезга (по умолчанию 80 мс) + butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) +} + +void isr() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться +} + +void loop() { + if (butt1.isClick()) Serial.println("Click"); // проверка на один клик + if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик + if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик + if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик + + if (butt1.hasClicks()) // проверка на наличие нажатий + Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий + + if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) + if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) + if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание + //if (butt1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки + + if (butt1.isStep()) { // если кнопка была удержана (это для инкремента) + value++; // увеличивать/уменьшать переменную value с шагом и интервалом + Serial.println(value); // для примера выведем в порт + } +} diff --git a/GyverButtonOld/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino b/GyverButtonOld/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino new file mode 100644 index 0000000..1db28f8 --- /dev/null +++ b/GyverButtonOld/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino @@ -0,0 +1,51 @@ +/* + Пример использования библиотеки GyverButton, все возможности в одном скетче. + - Опрос кнопки с программным антидребезгом контактов + - Отработка нажатия, удерживания отпускания кнопки + - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) + - Отработка любого количества нажатий кнопки (функция возвращает число нажатий) + - Отработка нажатия и удержания кнопки + - Настраиваемый таймаут повторного нажатия/удержания + - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени + Данный скетч показывает, как быть в сложном "не сквозном" коде с кучей delay и замкнутых циклов + Здесь кнопка опрашивается каждые 10 миллисекунд независимо от того, что происходит у вас в коде + Используется библиотека TimerOne https://github.com/PaulStoffregen/TimerOne +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +#include "TimerOne.h" +GButton butt1(PIN); +int value = 0; + +void setup() { + Serial.begin(9600); + + Timer1.initialize(10000); // установка таймера на каждые 10000 микросекунд (= 10 мс) + Timer1.attachInterrupt(timerIsr); // запуск таймера +} + +void timerIsr() { // прерывание таймера + butt1.tick(); // отработка теперь находится здесь +} + +void loop() { + if (butt1.isClick()) Serial.println("Click"); // проверка на один клик + if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик + if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик + if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик + + if (butt1.hasClicks()) // проверка на наличие нажатий + Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий + + if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) + if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) + if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание + //if (butt1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки + + if (butt1.isStep()) { // если кнопка была удержана (это для инкремента) + value++; // увеличивать/уменьшать переменную value с шагом и интервалом + Serial.println(value); // для примера выведем в порт + } +} diff --git a/GyverButtonOld/examples/_1-2-3-click/_1-2-3-click.ino b/GyverButtonOld/examples/_1-2-3-click/_1-2-3-click.ino new file mode 100644 index 0000000..a4118f5 --- /dev/null +++ b/GyverButtonOld/examples/_1-2-3-click/_1-2-3-click.ino @@ -0,0 +1,20 @@ +/* + Пример использования библиотеки GyverButton, 1- 2- 3- нажатие +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(PIN); + +void setup() { + Serial.begin(9600); +} + +void loop() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + + if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик + if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик + if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик +} diff --git a/GyverButtonOld/examples/_5_buttons/_5_buttons.ino b/GyverButtonOld/examples/_5_buttons/_5_buttons.ino new file mode 100644 index 0000000..edeec32 --- /dev/null +++ b/GyverButtonOld/examples/_5_buttons/_5_buttons.ino @@ -0,0 +1,34 @@ +/* + Пример использования библиотеки GyverButton, 5 кнопок +*/ + +#define BTN1 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN2 4 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN3 5 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN4 6 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN5 7 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(BTN1); +GButton butt2(BTN2); +GButton butt3(BTN3); +GButton butt4(BTN4); +GButton butt5(BTN5); + +void setup() { + Serial.begin(9600); +} + +void loop() { + butt1.tick(); + butt2.tick(); + butt3.tick(); + butt4.tick(); + butt5.tick(); + + if (butt1.isClick()) Serial.println("Button 1"); + if (butt2.isClick()) Serial.println("Button 2"); + if (butt3.isClick()) Serial.println("Button 3"); + if (butt4.isClick()) Serial.println("Button 4"); + if (butt5.isClick()) Serial.println("Button 5"); +} diff --git a/GyverButtonOld/examples/_5_buttons_auto/_5_buttons_auto.ino b/GyverButtonOld/examples/_5_buttons_auto/_5_buttons_auto.ino new file mode 100644 index 0000000..2fff75e --- /dev/null +++ b/GyverButtonOld/examples/_5_buttons_auto/_5_buttons_auto.ino @@ -0,0 +1,34 @@ +/* + Пример использования библиотеки GyverButton, 5 кнопок + Режим опроса - автоматический +*/ + +#define BTN1 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN2 4 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN3 5 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN4 6 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN5 7 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(BTN1); +GButton butt2(BTN2); +GButton butt3(BTN3); +GButton butt4(BTN4); +GButton butt5(BTN5); + +void setup() { + Serial.begin(9600); + butt1.setTickMode(AUTO); + butt2.setTickMode(AUTO); + butt3.setTickMode(AUTO); + butt4.setTickMode(AUTO); + butt5.setTickMode(AUTO); +} + +void loop() { + if (butt1.isClick()) Serial.println("Button 1"); + if (butt2.isClick()) Serial.println("Button 2"); + if (butt3.isClick()) Serial.println("Button 3"); + if (butt4.isClick()) Serial.println("Button 4"); + if (butt5.isClick()) Serial.println("Button 5"); +} diff --git a/GyverButtonOld/examples/analogKeyboard/analogKeyboard.ino b/GyverButtonOld/examples/analogKeyboard/analogKeyboard.ino new file mode 100644 index 0000000..490a2f7 --- /dev/null +++ b/GyverButtonOld/examples/analogKeyboard/analogKeyboard.ino @@ -0,0 +1,32 @@ +#include "GyverButton.h" + +// пин подключения не важен, лучше какой-нибудь ненужный +GButton myButt1(3, LOW_PULL, NORM_OPEN); +GButton myButt2(3, LOW_PULL, NORM_OPEN); +GButton myButt3(3, LOW_PULL, NORM_OPEN); + +void setup() { + Serial.begin(9600); +} + +void loop() { + int analog = analogRead(7); + //Serial.println(analog); + + myButt1.tick(analog < 860 && analog > 820); + myButt2.tick(analog < 740 && analog > 700); + myButt3.tick(analog < 650 && analog > 600); + + if (myButt1.isHolded()) { + Serial.println("hold 1"); + } + if (myButt2.isHolded()) { + Serial.println("hold 2"); + } + if (myButt3.isHolded()) { + Serial.println("hold 3"); + } + + delay(10); + +} diff --git a/GyverButtonOld/examples/increment/increment.ino b/GyverButtonOld/examples/increment/increment.ino new file mode 100644 index 0000000..d0ace38 --- /dev/null +++ b/GyverButtonOld/examples/increment/increment.ino @@ -0,0 +1,41 @@ +/* + Пример использования библиотеки GyverButton, управляем переменной value при помощи двух кнопок + Конструкция с isIncr делает увеличение/уменьшение переменной при нажатой кнопке с шагом по времени +*/ + +#define BTN1 2 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN2 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(BTN1); +GButton butt2(BTN2); +int value = 0; + +void setup() { + Serial.begin(9600); +} + +void loop() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + butt2.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + + if (butt1.isClick()) { // одиночное нажатие + value++; // инкремент + Serial.println(value); // для примера выведем в порт + } + + if (butt2.isClick()) { // одиночное нажатие + value--; // декремент + Serial.println(value); // для примера выведем в порт + } + + if (butt1.isStep()) { // обработчик удержания с шагами + value++; // увеличивать/уменьшать переменную value с шагом и интервалом! + Serial.println(value); // для примера выведем в порт + } + + if (butt2.isStep()) { // обработчик удержания с шагами + value--; // увеличивать/уменьшать переменную value с шагом и интервалом! + Serial.println(value); // для примера выведем в порт + } +} diff --git a/GyverButtonOld/examples/many_clicks/many_clicks.ino b/GyverButtonOld/examples/many_clicks/many_clicks.ino new file mode 100644 index 0000000..63d42e2 --- /dev/null +++ b/GyverButtonOld/examples/many_clicks/many_clicks.ino @@ -0,0 +1,19 @@ +/* + Пример использования библиотеки GyverButton, отработка любого количества нажатий +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#include "GyverButton.h" +GButton butt1(PIN); + +void setup() { + Serial.begin(9600); + butt1.setTimeout(400); // настройка таймаута на удержание и второй клик (по умолчанию 500 мс) +} + +void loop() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + + if (butt1.hasClicks()) // проверка на наличие нажатий + Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий +} diff --git a/GyverButtonOld/keywords.txt b/GyverButtonOld/keywords.txt new file mode 100644 index 0000000..e4173ba --- /dev/null +++ b/GyverButtonOld/keywords.txt @@ -0,0 +1,48 @@ +####################################### +# Syntax Coloring Map For GyverButton +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +GButton KEYWORD1 +GyverButtonOld KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +setDebounce KEYWORD2 +setTimeout KEYWORD2 +setStepTimeout KEYWORD2 +setClickTimeout KEYWORD2 +setType KEYWORD2 +setDirection KEYWORD2 +setTickMode KEYWORD2 + +tick KEYWORD2 +isPress KEYWORD2 +isRelease KEYWORD2 +isClick KEYWORD2 +isHolded KEYWORD2 +isHold KEYWORD2 +state KEYWORD2 + +hasClicks KEYWORD2 +getClicks KEYWORD2 +isSingle KEYWORD2 +isDouble KEYWORD2 +isTriple KEYWORD2 +isStep KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +HIGH_PULL LITERAL1 +LOW_PULL LITERAL1 +NORM_OPEN LITERAL1 +NORM_CLOSE LITERAL1 +MANUAL LITERAL1 +AUTO LITERAL1 \ No newline at end of file diff --git a/GyverButtonOld/old_version.rar b/GyverButtonOld/old_version.rar new file mode 100644 index 0000000000000000000000000000000000000000..661aae111ab419539b8aca49e94bdd4f736bc4cd GIT binary patch literal 8826 zcma)iWl$Z>y7k6_1b3HYL+}K5ceg-rcXxMpw~f2IyE_DTcY<#uK(KtAn^WhWI`@6= z{pMHCRQ0N{002mUKi3V&ku+8v5CjbXBq0I-kgM(O{0@!= zGDJ-508&x_z{b*0$JxlU_v&plL6rBQzAB%X=wJw&H#EPfCu7Uvmw zBRJT6;TWC%{I0vP+xF!(21=>Fn4c}nW>jT-CeM@lBL6U(OM!2eW%$T3wSl>qvk9%W z;xyA{Gu+MbeC#JHnw~T5Ih_Ept;IfMk6;VmiA@8Qko3I3$2M!;W!9>BLnddyltqb}X zQV9Z^XTJ6OM?QNAp!xo|0p;1<>;wuD@)rbACyOO7Jm7~xxlhNb%<+(YA3TgiJ8h?5 z&+~XnYliA0zB-WHIX^uRwv)OE7;H2wxUpUlHFk#8jpF5tSSHcQ(fh_Dl^UoNTBVgA zi3XfXS(H``s*lUbN7$K;J{D365K_Chn)6AN%EmD^jG}T2pX6z3`Rv|vDpRCs9FjyxE&MpaTW~$U}Lvw+bg`r9bv2{(sw>qnVYFy^fi+qmjM6lda>w zZ02Xr{k#Esv({vfIPdydA7f{;% zF;PsT6Z5?Yj?A#2_77Sj|!SwY5gGJ$I_O+Av*KC^oRx2AM zUWk`1i}ZSwbJv$Na%W|A^CkD1NOn^zBmr@z+%a*BsS^&!LxZQl(Vw$^g3gi;y|21Js2E=+pMVgxC37p5 zgWvDmPo5Fn_g5;UR+>tUdU%SUyt4&Md#H@axRYMttt*9`W@@(zyNW2 zMCC`7#U^E83XEorBoo|sX@^C6iNw2OI49|Dt(m(rlSIKyU(Wr8X_}DOIC~E~Fy$eo zXfs>+sOfErasAC-C{&GLE<+<6oM%n+(LM1c@vE|VdzqwIDvbK1yNAzbosZE}a^*kL zneBuOJWZu6k1AM-UnNU(Hn8(ZAEfesqz)c!A^U3-&=xaR$kF)#kq!nl$s+g6*u@N&UJhgXlYwSUiO69q+E>W;0 zb*+d#Ht?-MT!r{XvOlt|P7PA>B3_9K>A_3zKg^4gzf;vQ#%sO3yD zUJ5AF=)GjjZk>NnuS>c?y4W(SFbl}dsz8guj0w(l(|m(&?cc1@N{ScwL!Xh z<=pRg_JFA?k3)&~@=v>z{9-qi-uW{b`OeExaXk# zs66!HyFoJrQa%_{8qNZz0T)SWZugKa)4WQ#<`A#>63g;>0zf877=>Ges9QNUQl`HM z>R$Vlipxt>&$Z~+E2~`U=N#^lb8n||3PGH(+3nA&79iOm6O%hRRiws6w~xv63h5}0 z&YtUpRaOQv^F%lU41571OWw#-E~ipYq3yjGw3BzbfmiL=#tqs((J~MA?2<8a{Fclu zz&_`h66-RIt*&mwoI&SXD01xI_+Eye-@1e>fCmZySVnm356G#Yt>hjnqGnA}1ga-~Ug$3R z{q?w(Sh_=^omwJQ_Xpz=;~VwfTCV24XyhJOM3bjmp@D?OF$P?!q2UC4HV?HZXQRz> zE;%vUP2}xs>C}pF_%pw`805)7l}9MFdB4KzZ zA<}^q;U00r=c+5@Y@%K@9?U*|rLcx-N|FHzFT;uXyxE*+I8$W1YN2qPIg`bK;a(dw zlttRMLi1}`g@&)0Gm8lB_fv5w{)|}Y68tRSoXFHzen)}OdX}2 z)EshM(=2b-!rTfq*d8|O?Ye<4Sm@Wu@y*g9Q)hCu@6G!q3#5pT%7&rWsz%rX(I9vg zc-a%?0i;Vd0Du(dp_;r_W+#QwnWX**nO==+&IWMAki18Ga$O@xm4IecNZsps?G}hB zsuvYF;-`6kfnU%dM6S8PP78;agNM|ojbo5!8lgsSYROV>l{{Z+L4F#hYc3KzV&kpC z5dMA!iLu8$z7|D9KKQ1`;$qN`rZcsD!(V9EU7tS!Ie=}PYB^OMn?*+5pB&iU8ZUxn zcsZT;1n`d4I;zr-3s0cuZ1ORm2*%D(-k}Y{Ewl1?ql^aF_!nd!X*WJ> zw{}GN&sa#=QCDo}u8}}bA+E2Fx3#sE?=5|EQ*(23atql~5YWczH8ZLSgT5YomWFT2 zioQhjr%T+FnZFb1$SPTrs7ViKd{#CTNH`eN zD{!d?_~iNfQ<@wEJTX8+Kc$XTy_+818pOW9usEbefqQ$*QnaBGcl+z;Bil5KWL$d7 zr_a*BREKDOTYoY*NUU$%R!~f*v5D&vdvX+F!<#U-UnhSt!j9R9jGaW`X+s?lX%`R1m1 zqVYyWBE5ToPABoQsMo)*;m{x^5KG%d!=)vQp!`w2PR|HWBM7rnh>2!kyI+zkD$>~W zWVhTrbN;O^d9`}fdEkyKx_wJGb@9fX&r?8FztqF{Q~#Ojmf)7~rk9M5Zv{1O_l>St z(hdxvSYNZ8%C3lhLPaEK57$#EyQpS1MCROOW|rpizP<&C4X zxWuS^w9sbC3`R_OX&9d7JjIAX>*0Ti=H+ zj-L(Q()I13saRJ9s$C&n+>9VgUTSz(f#?jzM}Ru^0Bq09`4nChx0+8kWUE2x>+SQO17!wk-3l zSsOP`XDK=)t0OQi-0bUA|G#j7Mdwcf=Afzbui-y= zfF&b8zJcR#86M2(K-o+;WfCh@6{;{NOarECrn9we6+Ora6VReh{AQ2vOs624+|>R4 z?2);yu+`zqP0AMwFplQTG0$AqWdZ!nbVBDD@RP3WjWn|P1&D=)(l3=Sy%V;}C*kR6 zGiBqLZ{{ldeP_tSIFFp`Lu|Ek_$|MKtHLCkd$t*vTQG!Wh{I&fZs^Pk!VkV{!j4%N zSST)&R-t0t55X54IZfY3rtA}t-GN4Q7M?TQxY@ut5JZM{{EHYKY%_z@(SHc$3wzG3 z#JCJYz;sDm@KLq>7-eyr=!r9;ci_)XTC&hW3Ejvn-NhUxBqJb$o|b(PT*~#F*GEg6 zhpE0xPuqv9N6-3QzM(()tSHAJ-)T0`*)=UiCLG+7b+JDhinKg#*0hhQvfqqXI-2uI zY(vjzq)Q0-AaW7HAuUlF_>-1}mNH*Kgr0?-vR@&v zO|Icd_HFri03~lSzK4HXzI#UGhCjSyFf3vW6~cxPafV1H`ZuGQKsa)T>WkVU#>*6HX$@1Pc9@s~U)Xenx4&_k+-1qZj_jLiaI$geskies<5w}IlpD7q}wcf^@iaP`z6Y!|E z48w8|+*sn7KS|&gRn0B3&&yriECr}m;gP}CbCn!yrdTx zfNxH(BAYK!EUq1!bFFPtH6f6$M>T_QTKL){=i<*$8F@-qa{ZNRo}9UxJ<*#0hALX} zDSG<0a0xbmxjvrHX{YN+>@Wd0jUVSK13!EneZrM+Q>F$TjTS|eOxt&@Ayk(=_5&I7 z^sGlPpuc=}8na;mV!&J{Riw75lS_?`h3lb`(TZ|D*l3-$z5`UpUauTVADi#aOxPQ% z*^zgXO?M05J^h>|oQ}%wuT;haevC&+E=$Rx@Y3#bZ@&w~Ge`jMFt~P$itb`D?^bJ$ zqOu&LjhEBS7yQ;-W>Vi1G8=zI*h>h$-ZvOe?Vk+I1RUwawXsxx;OI6W;zi#@+i_&d zYP)7T$f<(o_Aq-O8xp9cbt@GYtnop}i;}1cGq@$j+3Uv%15NMl(Cdy5!3`j=7>~xL zr)T!}tY@*N#v5Me>gOe~;o7O-@oaOq8zdTA*EVH-Fp$@qpDQ0b=21sY8kAA^@S*oi zHIeE6e_YlxPor2BHecBRf>g4@EUrM zJZ2Rxim?DLSYN!1AgZ7pglZ}X7HvxTum}m|5`Z=-Z9)){Js--^5|q-;{5$q%{2R%+ z03C1pp;)*#l8bQUGyfqu-v3H+)3*@*ADf>}tR#=32NiNoO$@>vae3dsP~jY>(AW!e z(QC0Xj>@8+18{=Ek#KOB=v+PGV!rHq%j*syz1qKU3zqjidXzUWnydXj_M~mNIi)1I zIJur(qE<9DxghF2(x`H1vOalGj)eDPJT7_proJt5@;S0%1rMa=HYUs_ z=G3`u_i<9-j4MtlpEW5RlIDly(A1avA;Zad08K&KX|hUenbVx6ea&vW zs?I8f%g_+F56)BWzsLQcciJ!9kUrH~1a7bA-!t*aE>)B;BWsLB1w#t~wn7T5IIG z2LtmhBFU5J(F<=Bp>4S*R5z0(rOynT>4e`jx{5~~XVoSzt)BuyXkWzY&`qUr587va5 z?%`r?Q-uMqB}=tq?;{khZFj1ApSw$GiKWp;1{e|cB_$e29q|ZIxw@wr$2hkaYcskN zDxL#S4Xq-1c6;kiT4<}Q97qUzS8jKPN}K<|zm zOy5(nT`RBO6hluw6dP;eSv0FAl@nl0A?5tB`Q^?1CHMke>`hl|u@8wfO+E$^2<%om zae=6*sI4pUDQA6-cC!Xi!)_ak%4xXGgg*|EeET*T-^R?tnFb<8G-7BvqM^f7>pjFU7Z|&xF(bC!7p*TZh%;4}6k(J59Sx%kjXhj}7(?j6yE7 zq7pfeq3gL+1e1tMLzzXpj8L7YOp;|f6UUR*NYLjl-D=-xz{yCyrH8emH+0ki zS_t_3W>ui8w6R9u3}Cx$hvM+YiQ6tVrsgT)hOSesA^tht1{2j6C+?KsDd}k(;XSbG zR#-)vjS(;rjT;*MI9^F1@9Ox7Hq8JDu17J8|25Qvk~b26bSo&6v*C4&(O-~PkE61WKjPrps55`oXyTAa#AZ3 z1))>TlF5THu1XYC#i{BLHrpYm8zB*@jU+?-`_$kI0$2W#&&vx2rnhqpr`O5A5yN7x zw5Hy~M0K%oTQz4`9T7}ec}-FzoE-T*CjGcI@w{8f1POZns>keKi(YVUU#s>eD!9k5 zt7ELqM#yIBm~7%*Cf3xjzub^a;s4^iFh|HLmKEJ|=yB`<<=U*n?p1 z7^M~%G2oDj74#;y4V=SBG*0mLrQF7hqJk#abkWS5*x=3Y_DdXRdiLj_z6kNbIU?|G z`pvm@u0>H$LAkEx_Gi~u@u}JSE1lWe;2KwiZQ^(6qZmv3a}!y3s%o5#_TW3Y|mmwJB=soZ(YLeznd<(=wDOBdp}i9*r0{4G}PcFqT$ z%cQ4K;}jKM!h*muJ7L$k0+RNc*U+XZKmN$_LTclIme61Irsl(!#hfZj>YHP_t2C82 z`@_?@Cys5)2k$B)88}{PV)QcDWF_F{j{{!&92@vM-XU^0kH2-}lZp zOXR?85Wq@l6>p~8xUf5whIHkbRJmW;kVy(S#km&P0->!bVb|WVzK`eEhT`@7ZZ=_c zB9)83e2K`KvOnl#kk1mT#%8eGkfdHAL(>nL7xbL|gUd9B=N|uqECKiiU;1trCXq$Y zYR=%tC7q4MJ!#f$aeYI-P~TLjdcJo7@YsrUZ9B*g>$SrePxg|T^WIejzfEGqQOPAD4Epbc-)QN0%%X zw3~13Co4E^$4dP3w}Lk{{$nKJK_QFz1qeVT{r~%u001@(@&9f12Bh#;K(zli(0`oG z0l;a`{vg#iK%u_^B>sEAe}%dL@Pu6evdkNV$X`K_{yoIMMNt6o%VB`n+8c=IUxASQ zJ;=XD4FE8IKp+YI8;bB>p^*G9DF6CQ1%T}y0^iNQVQ~Bv2Ik*l0KoEPf!Ek?6Tke` V#P|O>5daqB@E_pu0Pw>C{vVaVQ_=tc literal 0 HcmV?d00001 diff --git a/GyverButtonOld/old_version/GyverButton.cpp b/GyverButtonOld/old_version/GyverButton.cpp new file mode 100644 index 0000000..35feee7 --- /dev/null +++ b/GyverButtonOld/old_version/GyverButton.cpp @@ -0,0 +1,119 @@ +#include "GyverButton.h" +#include + +GButton::GButton(uint8_t BUTT) { + _BUTT = BUTT; + _debounce = 80; + _timeout = 500; + _incr_timeout = 800; + step = 1; + pinMode (_BUTT, INPUT_PULLUP); +} + +void GButton::setDebounce(uint8_t debounce) { + _debounce = debounce; +} +void GButton::setTimeout(uint16_t timeout) { + _timeout = timeout; +} +void GButton::setIncrStep(int16_t incr_step) { + step = incr_step; +} +void GButton::setIncrTimeout(uint16_t incr_timeout) { + _incr_timeout = incr_timeout; +} + +boolean GButton::isPress() { + if (isPress_f) { + isPress_f = false; + return true; + } else return false; +} +boolean GButton::isRelease() { + if (isRelease_f) { + isRelease_f = false; + return true; + } else return false; +} +boolean GButton::isHolded() { + if (isHolded_f) { + isHolded_f = false; + return true; + } else return false; +} +boolean GButton::isHold() { + if (isHold_f) return true; + else return false; +} +boolean GButton::isSingle() { + if (counter_flag && last_counter == 1) { + counter_flag = false; + return true; + } else return false; +} +boolean GButton::isDouble() { + if (counter_flag && last_counter == 2) { + counter_flag = false; + return true; + } else return false; +} +boolean GButton::isTriple() { + if (counter_flag && last_counter == 3) { + counter_flag = false; + return true; + } else return false; +} +boolean GButton::hasClicks() { + if (counter_flag) { + counter_flag = false; + return true; + } else return false; +} +uint8_t GButton::getClicks() { + return last_counter; +} + +boolean GButton::isIncr() { + if (incr_flag) return true; + else return false; +} +int16_t GButton::getIncr(int16_t incr_value) { + if (isHold_f && (millis() - incr_timer > _incr_timeout)) { + incr_timer = millis(); + incr_flag = true; + return (incr_value + step); + } else return incr_value; +} + +void GButton::tick() { + btn_state = !digitalRead(_BUTT); + if (btn_state) isHold_f = true; + else isHold_f = false; + + if (btn_state && !btn_flag && (millis() - btn_timer > _debounce)) { + btn_flag = true; + btn_counter++; + btn_timer = millis(); + isPress_f = true; + } + if (!btn_state && btn_flag) { + btn_flag = false; + hold_flag = false; + isRelease_f = true; + btn_timer = millis(); + incr_flag = false; + } + if (btn_flag && btn_state && (millis() - btn_timer > _timeout) && !hold_flag) { + hold_flag = true; + btn_counter = 0; + isHolded_f = true; + incr_flag = true; + incr_timer = millis(); + } + + if ((millis() - btn_timer > _timeout) && (btn_counter != 0)) { + last_counter = btn_counter; + btn_counter = 0; + counter_flag = true; + } +} \ No newline at end of file diff --git a/GyverButtonOld/old_version/GyverButton.h b/GyverButtonOld/old_version/GyverButton.h new file mode 100644 index 0000000..913a6b5 --- /dev/null +++ b/GyverButtonOld/old_version/GyverButton.h @@ -0,0 +1,57 @@ +#ifndef GyverButton_h +#define GyverButton_h +#include + +/* +Текущая версия: 1.1 от 29.03.2018 +GyverButton - библиотека для полной отработки нажатия кнопки. Возможности: +Опрос кнопки с программным антидребезгом контактов +Отработка нажатия, удерживания отпускания кнопки +Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) +Отработка любого количества нажатий кнопки (функция возвращает число нажатий) +Отработка нажатия и удержания кнопки +Настраиваемый таймаут повторного нажатия/удержания +Функция изменения значения переменной с заданным шагом и заданным интервалом по времени +Пример использования в папке examples, показывает все возможности библиотеки +Отличия от oneBtton и подобных библиотек: методы библиотеки не создают новые функции, что упрощает применение в сотни раз +*/ + +class GButton +{ + public: + GButton(uint8_t BUTT); + void setDebounce(uint8_t debounce); + void setTimeout(uint16_t timeout); + void tick(); + + boolean isPress(); + boolean isRelease(); + boolean isHolded(); + boolean isHold(); + + boolean hasClicks(); + uint8_t getClicks(); + + boolean isSingle(); + boolean isDouble(); + boolean isTriple(); + + boolean isIncr(); + void setIncrStep(int16_t incr_step); + void setIncrTimeout(uint16_t incr_timeout); + int16_t getIncr(int16_t incr_value); + + int16_t step; + + private: + uint8_t _BUTT; + uint8_t _debounce; + uint16_t _timeout; + uint8_t btn_counter, last_counter; + boolean btn_state, btn_flag, hold_flag, counter_flag; + uint32_t btn_timer, incr_timer; + boolean isHold_f, isHolded_f, isRelease_f, isPress_f, incr_flag; + uint16_t _incr_timeout; +}; + +#endif \ No newline at end of file diff --git a/GyverButtonOld/old_version/examples/Gbutton_example/Gbutton_example.ino b/GyverButtonOld/old_version/examples/Gbutton_example/Gbutton_example.ino new file mode 100644 index 0000000..5d2771a --- /dev/null +++ b/GyverButtonOld/old_version/examples/Gbutton_example/Gbutton_example.ino @@ -0,0 +1,46 @@ +/* + Пример использования библиотеки GyverButton, все возможности в одном скетче. + - Опрос кнопки с программным антидребезгом контактов + - Отработка нажатия, удерживания отпускания кнопки + - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) + - Отработка любого количества нажатий кнопки (функция возвращает число нажатий) + - Отработка нажатия и удержания кнопки + - Настраиваемый таймаут повторного нажатия/удержания + - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(PIN); +int value = 0; + +void setup() { + Serial.begin(9600); + + butt1.setDebounce(50); // настройка антидребезга (по умолчанию 80 мс) + butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) + butt1.setIncrStep(2); // настройка инкремента, может быть отрицательным (по умолчанию 1) + butt1.setIncrTimeout(500); // настрйока интервала инкремента (по умолчанию 800 мс) +} + +void loop() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + + if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик + if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик + if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик + + if (butt1.hasClicks()) // проверка на наличие нажатий + Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий + + if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) + if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) + if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание + //if (butt1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки + + if (butt1.isIncr()) { // если кнопка была удержана (это для инкремента) + value = butt1.getIncr(value); // увеличивать/уменьшать переменную value с шагом и интервалом + Serial.println(value); // для примера выведем в порт + } +} diff --git a/GyverButtonOld/old_version/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino b/GyverButtonOld/old_version/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino new file mode 100644 index 0000000..4e654b0 --- /dev/null +++ b/GyverButtonOld/old_version/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino @@ -0,0 +1,56 @@ +/* + Пример использования библиотеки GyverButton, все возможности в одном скетче. + - Опрос кнопки с программным антидребезгом контактов + - Отработка нажатия, удерживания отпускания кнопки + - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) + - Отработка любого количества нажатий кнопки (функция возвращает число нажатий) + - Отработка нажатия и удержания кнопки + - Настраиваемый таймаут повторного нажатия/удержания + - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени + Данный скетч показывает, как быть в сложном "не сквозном" коде с кучей delay и замкнутых циклов + Здесь кнопка опрашивается каждые 10 миллисекунд независимо от того, что происходит у вас в коде + Используется библиотека TimerOne https://github.com/PaulStoffregen/TimerOne +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +#include "TimerOne.h" +GButton butt1(PIN); +int value = 0; + +void setup() { + Serial.begin(9600); + + Timer1.initialize(10000); // установка таймера на каждые 10000 микросекунд (= 10 мс) + Timer1.attachInterrupt(timerIsr); // запуск таймера + + butt1.setDebounce(50); // настройка антидребезга (по умолчанию 80 мс) + butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) + butt1.setIncrStep(2); // настройка инкремента, может быть отрицательным (по умолчанию 1) + butt1.setIncrTimeout(500); // настрйока интервала инкремента (по умолчанию 800 мс) +} + +void timerIsr() { // прерывание таймера + butt1.tick(); // отработка теперь находится здесь + // при добавлении кнопок, их .tick() нужно добавить сюда +} + +void loop() { + if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик + if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик + if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик + + if (butt1.hasClicks()) // проверка на наличие нажатий + Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий + + if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) + if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) + if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание + //if (butt1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки + + if (butt1.isIncr()) { // если кнопка была удержана (это для инкремента) + value = butt1.getIncr(value); // увеличивать/уменьшать переменную value с шагом и интервалом + Serial.println(value); // для примера выведем в порт + } +} diff --git a/GyverButtonOld/old_version/examples/_1-2-3-click/_1-2-3-click.ino b/GyverButtonOld/old_version/examples/_1-2-3-click/_1-2-3-click.ino new file mode 100644 index 0000000..6496dc5 --- /dev/null +++ b/GyverButtonOld/old_version/examples/_1-2-3-click/_1-2-3-click.ino @@ -0,0 +1,20 @@ +/* + Пример использования библиотеки GyverButton, 1- 2- 3- нажатие +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(PIN); + +void setup() { + Serial.begin(9600); +} + +void loop() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + + if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик + if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик + if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик +} diff --git a/GyverButtonOld/old_version/examples/_5_buttons/_5_buttons.ino b/GyverButtonOld/old_version/examples/_5_buttons/_5_buttons.ino new file mode 100644 index 0000000..a03fb24 --- /dev/null +++ b/GyverButtonOld/old_version/examples/_5_buttons/_5_buttons.ino @@ -0,0 +1,34 @@ +/* + Пример использования библиотеки GyverButton, 5 кнопок +*/ + +#define BTN1 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN2 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN3 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN4 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN5 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(BTN1); +GButton butt2(BTN2); +GButton butt3(BTN3); +GButton butt4(BTN4); +GButton butt5(BTN5); + +void setup() { + Serial.begin(9600); +} + +void loop() { + butt1.tick(); + butt2.tick(); + butt3.tick(); + butt4.tick(); + butt5.tick(); + + if (butt1.isSingle()) Serial.println("Button 1"); + if (butt2.isSingle()) Serial.println("Button 2"); + if (butt3.isSingle()) Serial.println("Button 3"); + if (butt4.isSingle()) Serial.println("Button 4"); + if (butt5.isSingle()) Serial.println("Button 5"); +} diff --git a/GyverButtonOld/old_version/examples/increment/increment.ino b/GyverButtonOld/old_version/examples/increment/increment.ino new file mode 100644 index 0000000..f342d92 --- /dev/null +++ b/GyverButtonOld/old_version/examples/increment/increment.ino @@ -0,0 +1,46 @@ +/* + Пример использования библиотеки GyverButton, управляем переменной value при помощи двух кнопок + Конструкция с isIncr делает увеличение/уменьшение переменной при нажатой кнопке с шагом по времени +*/ + +#define BTN1 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) +#define BTN2 4 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(BTN1); +GButton butt2(BTN2); +int value = 0; + +void setup() { + Serial.begin(9600); + butt1.setIncrStep(2); // настройка инкремента, может быть отрицательным (по умолчанию 1) + butt1.setIncrTimeout(500); // настрйока интервала инкремента (по умолчанию 800 мс) + + butt2.setIncrStep(-2); // настройка инкремента, может быть отрицательным (по умолчанию 1) + butt2.setIncrTimeout(500); // настрйока интервала инкремента (по умолчанию 800 мс) +} + +void loop() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + butt2.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + + if (butt1.isSingle()) { // одиночное нажатие + value += butt1.step; // изменить на шаг, указанный в setIncrStep + Serial.println(value); // для примера выведем в порт + } + + if (butt2.isSingle()) { // одиночное нажатие + value += butt2.step; // изменить на шаг, указанный в setIncrStep + Serial.println(value); // для примера выведем в порт + } + + if (butt1.isIncr()) { // если кнопка была удержана (это для инкремента) + value = butt1.getIncr(value); // увеличивать/уменьшать переменную value с шагом и интервалом! + Serial.println(value); // для примера выведем в порт + } + + if (butt2.isIncr()) { // если кнопка была удержана (это для инкремента) + value = butt2.getIncr(value); // увеличивать/уменьшать переменную value с шагом и интервалом! + Serial.println(value); // для примера выведем в порт + } +} diff --git a/GyverButtonOld/old_version/examples/many_clicks/many_clicks.ino b/GyverButtonOld/old_version/examples/many_clicks/many_clicks.ino new file mode 100644 index 0000000..58a92a5 --- /dev/null +++ b/GyverButtonOld/old_version/examples/many_clicks/many_clicks.ino @@ -0,0 +1,20 @@ +/* + Пример использования библиотеки GyverButton, отработка любого количества нажатий +*/ + +#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) + +#include "GyverButton.h" +GButton butt1(PIN); + +void setup() { + Serial.begin(9600); + butt1.setTimeout(300); // настройка таймаута на удержание и второй клик (по умолчанию 500 мс) +} + +void loop() { + butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться + + if (butt1.hasClicks()) // проверка на наличие нажатий + Serial.println(butt1.getClicks()); // получить (и вывести) количество нажатий +} diff --git a/GyverButtonOld/old_version/keywords.txt b/GyverButtonOld/old_version/keywords.txt new file mode 100644 index 0000000..525a6d7 --- /dev/null +++ b/GyverButtonOld/old_version/keywords.txt @@ -0,0 +1,31 @@ +####################################### +# Syntax Coloring Map For GyverButton +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +GButton KEYWORD1 +setDebounce KEYWORD1 +setTimeout KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +tick KEYWORD2 +isPress KEYWORD2 +isRelease KEYWORD2 +isHolded KEYWORD2 +isHold KEYWORD2 +hasClicks KEYWORD2 +getClicks KEYWORD2 +isSingle KEYWORD2 +isDouble KEYWORD2 +isTriple KEYWORD2 +isIncr KEYWORD2 +setIncrStep KEYWORD2 +setIncrTimeout KEYWORD2 +getIncr KEYWORD2 +step KEYWORD2 \ No newline at end of file diff --git a/GyverButtonOld/old_version/readme.txt b/GyverButtonOld/old_version/readme.txt new file mode 100644 index 0000000..faf75c4 --- /dev/null +++ b/GyverButtonOld/old_version/readme.txt @@ -0,0 +1,13 @@ +- **GyverButton (текущая 1.1)** - библиотека для полной отработки нажатия кнопки. Возможности: + + Класс **GButton (pin)** - указать пин, куда подключена кнопка (PIN --- КНОПКА --- GND) + + **setDebounce(time)** - время антидребезга (по умолчанию 80 мс) + + **setTimeout(time)** - таймаут на удержание/повторное нажатие (по умолчанию 500 мс) + + **tick()** - опрос кнопки с программным антидребезгом контактов + + **isPress(), isRelease(), isHolded(), isHold()** - отработка нажатия, удерживания отпускания кнопки + + **isSingle(), isDouble(), isTriple** - отработка одиночного, двойного и тройного нажатия (вынесено отдельно) + + **getClicks()** - отработка любого количества нажатий кнопки (функция возвращает число нажатий) + + **getIncr(value)** - функция изменения значения переменной с заданным шагом и заданным интервалом по времени + + **setIncrStep(step)** - настройка инкремента, может быть отрицательным (по умолчанию 1) + + **setIncrTimeout(time)** - настрйока интервала инкремента (по умолчанию 800 мс) + + Пример использования в папке examples, показывает все возможности библиотеки + + Отличия от oneBtton и подобных библиотек: методы библиотеки не создают новые функции, что упрощает применение в сотни раз \ No newline at end of file diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/GyverLamp_v1.4_Arduino_v1.0.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/GyverLamp_v1.4_Arduino_v1.0.ino new file mode 100644 index 0000000..0eeceda --- /dev/null +++ b/GyverLamp_v1.4_Arduino_v1.0kDn/GyverLamp_v1.4_Arduino_v1.0.ino @@ -0,0 +1,152 @@ +/* + Скетч к проекту "Многофункциональный RGB светильник" + Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ + Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/ + Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ + Автор: AlexGyver, AlexGyver Technologies, 2019 + https://AlexGyver.ru/ +*/ + +/* + Версия 1.4: + - Исправлен баг при смене режимов + - Исправлены тормоза в режиме точки доступа +*/ + +//// Ссылка для менеджера плат: +//// http://arduino.esp8266.com/stable/package_esp8266com_index.json + +// ============= НАСТРОЙКИ ============= + +//#define DEBUG // Дебаг(Нужен, расскоментируйте) +#define VERTGAUGE 0 // вертикальный/горизонтальный индикатор +#define DEMOTIME 5 // в секундах +#define RANDOM_DEMO 1 // 0,1 - включить рандомный выбор режима + +//// -------- РАССВЕТ ------- +//#define DAWN_BRIGHT 200 // макс. яркость рассвета +//#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут + +// ---------- МАТРИЦА --------- +#define BRIGHTNESS 255 // стандартная маскимальная яркость (0-255) +#define MINBRIGHTNESS 25 // минимальная яркость режимов (0-100) для исключения черной лампы +#define CURRENT_LIMIT 2600 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит + +#define WIDTH 16 // ширина матрицы +#define HEIGHT 16 // высота матрицы + +#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB + +#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная +#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний +#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз +// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" +// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ + +#define numHold_Time 1500 // время отображения индикатора уровня яркости/скорости/масштаба + +// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= +#define LED_PIN 2 // пин ленты +#define BTN_PIN 4 +#define MODE_AMOUNT 18 +#define NUM_LEDS WIDTH * HEIGHT +#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) + +// ---------------- БИБЛИОТЕКИ ----------------- +#include +#include +#include + +// ------------------- ТИПЫ -------------------- +CRGB leds[NUM_LEDS]; +GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); + +// ----------------- ПЕРЕМЕННЫЕ ------------------ + +static const byte maxDim = max(WIDTH, HEIGHT); +struct { + byte brightness = 50; + byte speed = 30; + byte scale = 10; +} modes[MODE_AMOUNT]; + + +int8_t currentMode = 17; +boolean loadingFlag = true; +boolean ONflag = true; +byte numHold; +unsigned long numHold_Timer = 0UL; +unsigned long userTimer = 0UL; +unsigned char matrixValue[8][16]; +byte xStep; +byte xCol; +byte yStep; +byte yCol; + +void setup() { + + // ЛЕНТА + FastLED.addLeds(leds, NUM_LEDS).setCorrection(0xFFB0F0); + FastLED.setBrightness(BRIGHTNESS); + if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); + FastLED.clear(); + FastLED.show(); + + touch.setStepTimeout(100); + touch.setClickTimeout(500); + + //Serial.begin(9600); + //Serial.println(); + + xStep = WIDTH / 4; + xCol = 4; + if(xStep<2) { + xStep = WIDTH / 3; + xCol = 3; + } else if(xStep<2) { + xStep = WIDTH / 2; + xCol = 2; + } else if(xStep<2) { + xStep = 1; + xCol = 1; + } + + yStep = HEIGHT / 4; + yCol = 4; + if(yStep<2) { + yStep = HEIGHT / 3; + yCol = 3; + } else if(yStep<2) { + yStep = HEIGHT / 2; + yCol = 2; + } else if(yStep<2) { + yStep = 1; + yCol = 1; + } + + #ifdef DEBUG + Serial.print("xStep: "); + Serial.print(xStep); + Serial.print(" xCol:"); + Serial.println(xCol); + Serial.print("yStep: "); + Serial.print(yStep); + Serial.print(" yCol:"); + Serial.println(yCol); + #endif + + if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР + currentMode = EEPROM.read(1); + for (byte x = 0; x < MODE_AMOUNT; x++) { + modes[x].brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) + modes[x].speed = EEPROM.read(x * 3 + 12); + modes[x].scale = EEPROM.read(x * 3 + 13); + } + + } +} + +void loop() { + effectsTick(); + buttonTick(); //yield(); +} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/button.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/button.ino new file mode 100644 index 0000000..a2e2a28 --- /dev/null +++ b/GyverLamp_v1.4_Arduino_v1.0kDn/button.ino @@ -0,0 +1,223 @@ +boolean brightDirection, speedDirection, scaleDirection; +//byte numHold; +#ifdef DEBUG +void debugPrint(){ + Serial.print(numHold); + Serial.print(F(" brightness:")); + Serial.print(modes[currentMode].brightness); + Serial.print(F(" speed:")); + Serial.print(modes[currentMode].speed); + Serial.print(F(" scale:")); + Serial.print(modes[currentMode].scale); + Serial.print(F(" numHold_Timer:")); + Serial.println(numHold_Timer); +} +#endif +void changeDirection(byte numHold){ + switch(numHold){ + case 0: case 1: brightDirection = !brightDirection; break; + case 2: speedDirection = !speedDirection; break; + case 3: scaleDirection = !scaleDirection; break; + } + numHold_Timer = millis(); +} + +void buttonTick() { + touch.tick(); + + if (!ONflag) { // Обработка из выключенного состояния + #ifdef DEBUG + if(touch.isPress()) + Serial.println(F("Off state")); + #endif + + if (touch.isDouble()) { // Демо-режим, с переключением каждые 30 секунд для двойного клика в выключенном состоянии + numHold = 254; + currentMode = random(0, 255)%17; // 17 скипаем + //modes[currentMode].brightness = BRIGHTNESS/2; // в половину яркости + FastLED.setBrightness(modes[currentMode].brightness); + ONflag = true; + userTimer = millis(); // момент включения для таймаута в DEMOTIME + numHold_Timer = millis(); + //brightDirection = 0; // на уменьшение + changePower(); + #ifdef DEBUG + Serial.print(F("Demo mode: ")); + Serial.println(currentMode); + #endif + } + + if (touch.isHolded()) { + #ifdef DEBUG + Serial.println(F("Holdeded from offed state")); + #endif + currentMode = 17; + modes[currentMode].brightness = BRIGHTNESS; + FastLED.setBrightness(modes[currentMode].brightness); + numHold = 255; + ONflag = true; + userTimer = millis(); // момент включения для таймаута в переключения в режим регулировки яркости + numHold_Timer = millis(); + brightDirection = 0; // на уменьшение + changePower(); + } + } + + if (touch.isSingle()) { // Включение/выключение одиночным + + { + if (ONflag) { + ONflag = false; + #ifdef DEBUG + Serial.println(F("Off lamp")); + #endif + changePower(); + } else { + ONflag = true; + #ifdef DEBUG + Serial.println(F("On lamp")); + debugPrint(); // отладка + #endif + + } + } + } + +if (ONflag) { // если включено + if (touch.isDouble()) { + #ifdef DEBUG + Serial.println(F("Double click")); + //debugPrint(); // отладка + #endif + if (++currentMode >= MODE_AMOUNT) currentMode = 0; + FastLED.setBrightness(modes[currentMode].brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + if (touch.isTriple()) { + #ifdef DEBUG + Serial.println(F("Triple click")); + //debugPrint(); // отладка + #endif + if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; + FastLED.setBrightness(modes[currentMode].brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + + if ((touch.hasClicks()) && (touch.getClicks() == 5)) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров // && (touch.hasClicks()) + if (EEPROM.read(0) != 102) EEPROM.write(0, 102); + if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект + for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов + if (EEPROM.read(x * 3 + 11) != modes[x].brightness) EEPROM.write(x * 3 + 11, modes[x].brightness); + if (EEPROM.read(x * 3 + 12) != modes[x].speed) EEPROM.write(x * 3 + 12, modes[x].speed); + if (EEPROM.read(x * 3 + 13) != modes[x].scale) EEPROM.write(x * 3 + 13, modes[x].scale); + } + // индикация сохранения + ONflag = false; + changePower(); + delay(200); + ONflag = true; + changePower(); + } + + if (touch.isHolded() && numHold != 255) { // изменение яркости при удержании кнопки + if(modes[currentMode].brightness == BRIGHTNESS && numHold == 1){ + brightDirection = 0; + } else if (modes[currentMode].brightness <= 1 && numHold == 1){ + brightDirection = 1; + } else + changeDirection(numHold); + if(!numHold || numHold==254) + numHold = 1; + } + + if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки + if(modes[currentMode].speed == 255 && numHold == 2){ + speedDirection = 0; + } else if (modes[currentMode].speed <= 1 && numHold == 2){ + speedDirection = 1; + } else + changeDirection(numHold); + if(!numHold) + numHold = 2; + } + + if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки + if(modes[currentMode].scale == 255 && numHold == 3){ + scaleDirection = 0; + } else if (modes[currentMode].scale <= 1 && numHold == 3){ + scaleDirection = 1; + } else + changeDirection(numHold); + if(!numHold) + numHold = 3; + } + + if (touch.isStep()) { + #ifdef DEBUG + debugPrint(); // отладка + #endif + if (numHold != 0 && numHold != 255) { + numHold_Timer = millis(); + loadingFlag = true; + } + + switch (numHold) { + case 1: + + modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), MINBRIGHTNESS , BRIGHTNESS); + break; + + case 2: + + modes[currentMode].speed = constrain(modes[currentMode].speed + (modes[currentMode].speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); + break; + + case 3: + + modes[currentMode].scale = constrain(modes[currentMode].scale + (modes[currentMode].scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); + break; + } + } + + if ((millis() - userTimer) > numHold_Time && numHold>=250) { + if(numHold == 255){ + numHold = 1; + userTimer = millis(); + numHold_Timer = millis(); + } + } + + if ((millis() - numHold_Timer) > numHold_Time && !touch.isHolded() && numHold<250) { + numHold = 0; + numHold_Timer = millis(); + } + + if((millis() - userTimer > DEMOTIME*1000) && (numHold == 254)){ + //FastLED.clear(); + //delay(2); + for(byte i = 250; i>10; i-=10){ + fader(30); + FastLED.delay(33); + //FastLED.show(); + } + + if(RANDOM_DEMO) + currentMode = random(0, 255)%17; // 17 скипаем + else + currentMode=(currentMode+1)%17; // 17 скипаем и идем по наростанию + #ifdef DEBUG + Serial.print(F("Demo mode: ")); + Serial.println(currentMode); + #endif + userTimer = millis(); + } + + FastLED.setBrightness(modes[currentMode].brightness); + } +} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/effectTicker.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/effectTicker.ino new file mode 100644 index 0000000..2a92161 --- /dev/null +++ b/GyverLamp_v1.4_Arduino_v1.0kDn/effectTicker.ino @@ -0,0 +1,115 @@ +uint32_t effTimer; +byte ind; + +void effectsTick() { + { + if (millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { + effTimer = millis(); + if(ONflag){ + switch (currentMode) { + case 0: sparklesRoutine(); + break; + case 1: rainbowVertical(); + break; + case 2: rainbowHorizontal(); + break; + case 3: Fire2020(); + break; + case 4: colorsRoutine(); + break; + case 5: madnessNoise(); + break; + case 6: cloudNoise(); + break; + case 7: lavaNoise(); + break; + case 8: plasmaNoise(); + break; + case 9: rainbowNoise(); + break; + case 10: rainbowStripeNoise(); + break; + case 11: zebraNoise(); + break; + case 12: forestNoise(); + break; + case 13: oceanNoise(); + break; + case 14: colorRoutine(); + break; + case 15: snowRoutine(); + break; + case 16: matrixRoutine(); + break; + case 17: whiteLampRoutine(); + break; + } + if(VERTGAUGE) + GaugeShowVertical(); + } + FastLED.show(); + } + } +} + +void GaugeShowVertical() { + switch (numHold) { // индикатор уровня яркости/скорости/масштаба + case 1: + ind = ind = sqrt(modes[currentMode].brightness + 1); + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) + drawPixelXY(x, y, CHSV(10, 255, 255)); + else + drawPixelXY(x, y, 0); + } + } + break; + case 2: + ind = sqrt(modes[currentMode].speed - 1); + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y <= HEIGHT ; y++) { + if (ind <= y) + drawPixelXY(x, HEIGHT-1-y, CHSV(100, 255, 255)); + else + drawPixelXY(x, HEIGHT-1-y, 0); + } + } + break; + case 3: + ind = sqrt(modes[currentMode].scale + 1); + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) + drawPixelXY(x, y, CHSV(150, 255, 255)); + else + drawPixelXY(x, y, 0); + } + } + break; + } +} + +void changePower() { // плавное включение/выключение + if (ONflag) { + effectsTick(); + for (int i = 0; i < modes[currentMode].brightness; i += 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.setBrightness(modes[currentMode].brightness); + delay(2); + FastLED.show(); + } else { + //effectsTick(); + for (int i = modes[currentMode].brightness; i > 8; i -= 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.clear(); + delay(2); + FastLED.show(); + } +} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino new file mode 100644 index 0000000..d2259ce --- /dev/null +++ b/GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino @@ -0,0 +1,158 @@ +// ================================= ЭФФЕКТЫ ==================================== +// --------------------------------- конфетти ------------------------------------ +#define FADE_OUT_SPEED (70U) // скорость затухания +void sparklesRoutine() +{ + for (uint8_t i = 0; i < modes[currentMode].scale; i++) + { + uint8_t x = random(0U, WIDTH); + uint8_t y = random(0U, HEIGHT); + if (getPixColorXY(x, y) == 0U) + { + drawPixelXY(x, y,CHSV(random(0U, 255U), 255U, 255U)); + } + } + fader(FADE_OUT_SPEED); +} +//----------------------Огонь-------------------- +void Fire2020() { + uint8_t speedy = map(modes[currentMode].speed, 1, 255, 255, 0); + uint8_t _scale = modes[currentMode].scale + 30; + + uint32_t a = millis(); + for (byte i = 0U; i < WIDTH; i++) { + for (float j = 0.; j < HEIGHT; j++) { + + drawPixelXY((WIDTH - 1) - i, (HEIGHT - 1) - j, ColorFromPalette(HeatColors_p/*myPal*/, qsub8(inoise8(i * _scale, j * _scale + a, a / speedy), abs8(j - (HEIGHT - 1)) * 255 / (HEIGHT - 1)), 255)); + } + } +} +byte hue; +// ---------------------------------------- радуга ------------------------------------------ +void rainbowVertical() { + hue += 2; + for (byte j = 0; j < HEIGHT; j++) { + CHSV thisColor = CHSV((byte)(hue + j * modes[currentMode].scale), 255, 255); + for (byte i = 0; i < WIDTH; i++) + drawPixelXY(i, j, thisColor); + } +} +void rainbowHorizontal() { + hue += 2; + for (byte i = 0; i < WIDTH; i++) { + CHSV thisColor = CHSV((byte)(hue + i * modes[currentMode].scale), 255, 255); + for (byte j = 0; j < HEIGHT; j++) + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; + } +} + +// ---------------------------------------- ЦВЕТА ------------------------------------------ +void colorsRoutine() { + hue += modes[currentMode].scale; + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = CHSV(hue, 255, 255); + } +} + +// --------------------------------- ЦВЕТ ------------------------------------ +void colorRoutine() { + for (int i = 0; i < NUM_LEDS; i++) { + //leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); + leds[i] = CHSV(modes[currentMode].speed*(modes[currentMode].scale/16+1), 255, 255); + } +} + +// ------------------------------ снегопад 2.0 -------------------------------- +void snowRoutine() { + shiftDown(); + + for (byte x = 0; x < WIDTH; x++) { + // заполняем случайно верхнюю строку + // а также не даём двум блокам по вертикали вместе быть + if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, modes[currentMode].scale) == 0)) + drawPixelXY(x, HEIGHT - 1U, 0xE0FFFF - 0x101010 * random(0, 4)); + else + drawPixelXY(x, HEIGHT - 1, 0x000000); + } +} +// ------------------------------ МАТРИЦА ------------------------------ +void matrixRoutine() +{ + for (uint8_t x = 0U; x < WIDTH; x++) + { + // обрабатываем нашу матрицу снизу вверх до второй сверху строчки + for (uint8_t y = 0U; y < HEIGHT - 1U; y++) + { + uint32_t thisColor = getPixColorXY(x, y); // берём цвет нашего пикселя + uint32_t upperColor = getPixColorXY(x, y + 1U); // берём цвет пикселя над нашим + if (upperColor >= 0x900000 && random(7 * HEIGHT) != 0U) // если выше нас максимальная яркость, игнорим этот факт с некой вероятностью или опускаем цепочку ниже + drawPixelXY(x, y, upperColor); + else if (thisColor == 0U && random((100 - modes[currentMode].scale) * HEIGHT) == 0U) // если наш пиксель ещё не горит, иногда зажигаем новые цепочки + //else if (thisColor == 0U && random((100 - modes[currentMode].Scale) * HEIGHT*3) == 0U) // для длинных хвостов + drawPixelXY(x, y, 0x9bf800); + else if (thisColor <= 0x050800) // если наш пиксель почти погас, стараемся сделать затухание медленней + { + if (thisColor >= 0x030000) + drawPixelXY(x, y, 0x020300); + else if (thisColor != 0U) + drawPixelXY(x, y, 0U); + } + else if (thisColor >= 0x900000) // если наш пиксель максимальной яркости, резко снижаем яркость + drawPixelXY(x, y, 0x558800); + else + drawPixelXY(x, y, thisColor - 0x0a1000); // в остальных случаях снижаем яркость на 1 уровень + //drawPixelXY(x, y, thisColor - 0x050800); // для длинных хвостов + } + // аналогично обрабатываем верхний ряд пикселей матрицы + uint32_t thisColor = getPixColorXY(x, HEIGHT - 1U); + if (thisColor == 0U) // если наш верхний пиксель не горит, заполняем его с вероятностью .Scale + { + if (random(100 - modes[currentMode].scale) == 0U) + drawPixelXY(x, HEIGHT - 1U, 0x9bf800); + } + else if (thisColor <= 0x050800) // если наш верхний пиксель почти погас, стараемся сделать затухание медленней + { + if (thisColor >= 0x030000) + drawPixelXY(x, HEIGHT - 1U, 0x020300); + else + drawPixelXY(x, HEIGHT - 1U, 0U); + } + else if (thisColor >= 0x900000) // если наш верхний пиксель максимальной яркости, резко снижаем яркость + drawPixelXY(x, HEIGHT - 1U, 0x558800); + else + drawPixelXY(x, HEIGHT - 1U, thisColor - 0x0a1000); // в остальных случаях снижаем яркость на 1 уровень + //drawPixelXY(x, HEIGHT - 1U, thisColor - 0x050800); // для длинных хвостов + } +} +// ------------------------------ БЕЛАЯ ЛАМПА ------------------------------ +void whiteLampRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + FastLED.clear(); + //delay(1); + + uint8_t centerY = (uint8_t)round(HEIGHT / 2.0F) - 1U;// max((uint8_t)round(HEIGHT / 2.0F) - 1, 0); нахрена тут максимум было вычислять? для ленты?! + uint8_t bottomOffset = (uint8_t)(!(HEIGHT & 0x01));// && (HEIGHT > 1)); и высота больше единицы. супер! // если высота матрицы чётная, линий с максимальной яркостью две, а линии с минимальной яркостью снизу будут смещены на один ряд + + uint8_t fullRows = centerY / 100.0 * modes[currentMode].scale; + uint8_t iPol = (centerY / 100.0 * modes[currentMode].scale - fullRows) * 255; + + for (int16_t y = centerY; y >= 0; y--) + { + CRGB color = CHSV( + 45U, // определяем тон + map(modes[currentMode].speed, 0U, 255U, 0U, 170U), // определяем насыщенность + y > (centerY - fullRows - 1) // определяем яркость + ? 255U // для центральных горизонтальных полос + : iPol * (y > centerY - fullRows - 2)); // для остальных горизонтальных полос яркость равна либо 255, либо 0 в зависимости от масштаба + + for (uint8_t x = 0U; x < WIDTH; x++) + { + drawPixelXY(x, y, color); // при чётной высоте матрицы максимально яркими отрисуются 2 центральных горизонтальных полосы + drawPixelXY(x, HEIGHT + bottomOffset - y - 2U, color); // при нечётной - одна, но дважды + } + } + } +} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/noiseEffects.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/noiseEffects.ino new file mode 100644 index 0000000..11f3c90 --- /dev/null +++ b/GyverLamp_v1.4_Arduino_v1.0kDn/noiseEffects.ino @@ -0,0 +1,194 @@ +// ******************* НАСТРОЙКИ ***************** +// ***************** ДЛЯ РАЗРАБОТЧИКОВ ****************** + +// The 16 bit version of our coordinates +static uint16_t x; +static uint16_t y; +static uint16_t z; + +uint16_t speed = 20; // speed is set dynamically once we've started up +uint16_t scale = 30; // scale is set dynamically once we've started up + +// This is the array that we keep our computed noise values in (это массив, в котором храним вычисленные значения шума) +#define MAX_DIMENSION (max(WIDTH, HEIGHT)) +#if (WIDTH > HEIGHT) +uint8_t noise[WIDTH][WIDTH]; +#else +uint8_t noise[HEIGHT][HEIGHT]; +#endif + +CRGBPalette16 currentPalette( PartyColors_p ); +uint8_t colorLoop = 1; +uint8_t ihue = 0; + +void madnessNoise() { + if (loadingFlag) { + loadingFlag = false; + scale = modes[5].scale; + speed = modes[5].speed; + } + fillnoise8(); + for (int i = 0; i < WIDTH; i++) { + for (int j = 0; j < HEIGHT; j++) { + CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); + } + } + ihue += 1; +} +void rainbowNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = RainbowColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void rainbowStripeNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = RainbowStripeColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void zebraNoise() { + if (loadingFlag) { + loadingFlag = false; + // 'black out' all 16 palette entries... + fill_solid( currentPalette, 16, CRGB::Black); + // and set every fourth one to white. + currentPalette[0] = CRGB::White; + currentPalette[4] = CRGB::White; + currentPalette[8] = CRGB::White; + currentPalette[12] = CRGB::White; + scale = modes[11].scale; + speed = modes[11].speed; + colorLoop = 1; + +// Serial.print(" speed:"); +// Serial.print(modes[currentMode].speed); +// Serial.print(" scale:"); +// Serial.println(modes[currentMode].scale); + } + fillNoiseLED(); +} +void forestNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = ForestColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 0; + } + fillNoiseLED(); +} +void oceanNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = OceanColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 0; + } + + fillNoiseLED(); +} +void plasmaNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = PartyColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void cloudNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = CloudColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 0; + } + fillNoiseLED(); +} +void lavaNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = LavaColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 0; + } + fillNoiseLED(); +} + +// ******************* СЛУЖЕБНЫЕ ******************* +void fillNoiseLED() { + uint8_t dataSmoothing = 0; + if ( speed < 50) { + dataSmoothing = 200 - (speed * 4); + } + for (int i = 0; i < MAX_DIMENSION; i++) { + int ioffset = scale * i; + for (int j = 0; j < MAX_DIMENSION; j++) { + int joffset = scale * j; + + uint8_t data = inoise8(x + ioffset, y + joffset, z); + + data = qsub8(data, 16); + data = qadd8(data, scale8(data, 39)); + + if ( dataSmoothing ) { + uint8_t olddata = noise[i][j]; + uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); + data = newdata; + } + + noise[i][j] = data; + } + } + z += speed; + + // apply slow drift to X and Y, just for visual variation. + x += speed / 8; + y -= speed / 16; + + for (int i = 0; i < WIDTH; i++) { + for (int j = 0; j < HEIGHT; j++) { + uint8_t index = noise[j][i]; + uint8_t bri = noise[i][j]; + // if this palette is a 'loop', add a slowly-changing base value + if ( colorLoop) { + index += ihue; + } + // brighten up, as the color palette itself often contains the + // light/dark dynamic range desired + if ( bri > 127 ) { + bri = 255; + } else { + bri = dim8_raw( bri * 2); + } + CRGB color = ColorFromPalette( currentPalette, index, bri); + drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color; + } + } + ihue += 1; +} + +void fillnoise8() { + for (int i = 0; i < MAX_DIMENSION; i++) { + int ioffset = scale * i; + for (int j = 0; j < MAX_DIMENSION; j++) { + int joffset = scale * j; + noise[i][j] = inoise8(x + ioffset, y + joffset, z); + } + } + z += speed; +} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino new file mode 100644 index 0000000..c481eb4 --- /dev/null +++ b/GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino @@ -0,0 +1,128 @@ +// служебные функции +// функция плавного угасания цвета для всех пикселей +void fader(uint8_t step) +{ + for (uint8_t i = 0U; i < WIDTH; i++) + { + for (uint8_t j = 0U; j < HEIGHT; j++) + { + fadePixel(i, j, step); + } + } +} +void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер +{ + int32_t pixelNum = XY(i, j); + if (getPixColor(pixelNum) == 0U) return; + + if (leds[pixelNum].r >= 30U || + leds[pixelNum].g >= 30U || + leds[pixelNum].b >= 30U) + { + leds[pixelNum].fadeToBlackBy(step); + } + else + { + leds[pixelNum] = 0U; + } +} +void shiftDown(){ + for (byte x = 0; x < WIDTH; x++) { + for (byte y = 0; y < HEIGHT - 1; y++) { + drawPixelXY(x, y, getPixColorXY(x, y + 1)); + }}} +// залить все +void fillAll(CRGB color) { + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = color; + } +} + + + +// функция отрисовки точки по координатам X Y +void drawPixelXY(uint8_t x, uint8_t y, CRGB color) +{ + if (x < 0 || x > (WIDTH - 1) || y < 0 || y > (HEIGHT - 1)) return; + uint32_t thisPixel = XY((uint8_t)x, (uint8_t)y) * SEGMENTS; + for (uint8_t i = 0; i < SEGMENTS; i++) + { + leds[thisPixel + i] = color; + } +} + +// функция получения цвета пикселя по его номеру +uint32_t getPixColor(uint32_t thisSegm) +{ + uint32_t thisPixel = thisSegm * SEGMENTS; + if (thisPixel > NUM_LEDS - 1) return 0; + return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b); +} +// функция получения цвета пикселя в матрице по его координатам +uint32_t getPixColorXY(uint8_t x, uint8_t y) +{ + return getPixColor(XY(x, y)); +} + +// **************** НАСТРОЙКА МАТРИЦЫ **************** +#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 XY(uint8_t x, uint8_t y) +{ + if (!(THIS_Y & 0x01) || MATRIX_TYPE) // Even rows run forwards + return (THIS_Y * _WIDTH + THIS_X); + else + return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); // Odd rows run backwards +} + +// оставлено для совместимости со эффектами из старых прошивок +uint16_t getPixelNumber(uint8_t x, uint8_t y) +{ + return XY(x, y); +} diff --git a/README.md b/README.md index 00fb2df..4573326 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -# GyverLamp for Arduino +# ArduinoLamp Это облегченная версия прошивки AlexGyver под ардуино. (Оригинал здесь: ![Исходная версия](https://github.com/AlexGyver/GyverLamp/)) +Обновление будут выходить там: https://github.com/80Stepko08/ArduinoLamp ## Краткое описание: @@ -12,23 +13,13 @@ - работа с Wi-Fi (у ардуинки его нет); - эффект "Светляки" - под него не хватило места в ОЗУ; -Что добавлено (как ни странно, но да, было что добавить): -- эффект "Светляки" заменен на "Белая лампа"; -- сохранение настроек всех эффектов, в т.ч. текущего режима в энергонезависимой - памяти. Производится пятикратным нажатием кнопки, подтверждением будет - выключение и включение лампы; -- регулирование скорости (speed) эффектов путем двойного нажатия и удержания - кнопки на втором нажатии; -- регулирование масштаба (scale) эффектов путем тройного нажатия и удержания - кнопки на третьем нажатии; -- индикация уровня яркости/скорости/масштаба вертикальной полосой красного/ - зеленого/синего цветов соответственно; +Что добавлено: демо, куча эффектов; Регулировка уровня яркости/скорости/масштаба реверсивная, т.е. при повторном регулировании изменения будут производиться в обратную сторону (сначала в бОльшую, затем в мЕньшую). -Для работы всех режимов кнопки ОБЯЗАТЕЛЬНО нужно заменить у себя папку GyverButton -на аналогичную с этого сайта. Совместимость с оригиналом сохранилась. -Подключение ардуино производить к тем же пинам, что и esp8266. \ No newline at end of file +Для работы всех режимов кнопки +ОБЯЗАТЕЛЬНО нужно заменить у себя папку GyverButtonOld(переименовал ради удобства) на аналогичную с этого сайта. +Совместимость с оригиналом сохранилась. diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/GyverLamp_v1.4_Arduino_v1.2.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/GyverLamp_v1.4_Arduino_v1.2.ino new file mode 100644 index 0000000..cd51a1c --- /dev/null +++ b/firmware/GyverLamp_v1.4_Arduino_v1.2/GyverLamp_v1.4_Arduino_v1.2.ino @@ -0,0 +1,127 @@ +/* + Скетч к проекту "Многофункциональный RGB светильник" + Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ + Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/ + Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ + Автор: AlexGyver, AlexGyver Technologies, 2019 + https://AlexGyver.ru/ +*/ + +/* + Версия 1.4: + - Исправлен баг при смене режимов + - Исправлены тормоза в режиме точки доступа +*/ + +//// Ссылка для менеджера плат: +//// http://arduino.esp8266.com/stable/package_esp8266com_index.json + +// ============= НАСТРОЙКИ ============= + +//// -------- РАССВЕТ ------- +//#define DAWN_BRIGHT 200 // макс. яркость рассвета +//#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут + +// ---------- МАТРИЦА --------- +#define BRIGHTNESS 40 // стандартная маскимальная яркость (0-255) +#define CURRENT_LIMIT 2000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит + +#define WIDTH 16 // ширина матрицы +#define HEIGHT 16 // высота матрицы + +#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB + +#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная +#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний +#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз +// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" +// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ + +#define numHold_Time 1500 // время отображения индикатора уровня яркости/скорости/масштаба + +// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= +#define LED_PIN 2 // пин ленты +#define BTN_PIN 4 +#define MODE_AMOUNT 18 +#define NUM_LEDS WIDTH * HEIGHT +#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) + +// ---------------- БИБЛИОТЕКИ ----------------- +//#include "timerMinim.h" +#include +#include +#include + +// ------------------- ТИПЫ -------------------- +CRGB leds[NUM_LEDS]; +//timerMinim timeTimer(3000); +GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); //сенсорная кнопка +//GButton touch(BTN_PIN, HIGH_PULL, NORM_OPEN); //механическая кнопка + +// ----------------- ПЕРЕМЕННЫЕ ------------------ + +//String inputBuffer; +static const byte maxDim = max(WIDTH, HEIGHT); +struct { + byte brightness = 50; + byte speed = 30; + byte scale = 10; +} modes[MODE_AMOUNT]; + +//struct { +// boolean state = false; +// int time = 0; +//} alarm[7]; + +//byte dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60}; +//byte dawnMode; +//boolean dawnFlag = false; +//long thisTime; +//boolean manualOff = false; + +int8_t currentMode = 17; +boolean loadingFlag = true; +boolean ONflag = true; +byte numHold; +unsigned long numHold_Timer = 0; +//uint32_t eepromTimer; +//boolean settChanged = false; +// Конфетти, Огонь, Радуга верт., Радуга гориз., Смена цвета, +// Безумие 3D, Облака 3D, Лава 3D, Плазма 3D, Радуга 3D, +// Павлин 3D, Зебра 3D, Лес 3D, Океан 3D, +// colorRoutine, snowRoutine, полосы "Матрица" + +unsigned char matrixValue[8][16]; + +void setup() { + + // ЛЕНТА + FastLED.addLeds(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/; + FastLED.setBrightness(BRIGHTNESS); + if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); + FastLED.clear(); + FastLED.show(); + + touch.setStepTimeout(100); + touch.setClickTimeout(500); + + Serial.begin(9600); + Serial.println(); + + if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР + currentMode = EEPROM.read(1); + for (byte x = 0; x < MODE_AMOUNT; x++) { + modes[x].brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) + modes[x].speed = EEPROM.read(x * 3 + 12); + modes[x].scale = EEPROM.read(x * 3 + 13); + } + + } +} + +void loop() { + effectsTick(); + //timeTick(); + buttonTick(); + //yield(); +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/button.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/button.ino new file mode 100644 index 0000000..d74f069 --- /dev/null +++ b/firmware/GyverLamp_v1.4_Arduino_v1.2/button.ino @@ -0,0 +1,110 @@ +boolean brightDirection, speedDirection, scaleDirection; +//byte numHold; + +void buttonTick() { + touch.tick(); + + + + if (ONflag) { // если включено + + + if ((touch.hasClicks()) && (touch.getClicks() == 5)) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров // && (touch.hasClicks()) + if (EEPROM.read(0) != 102) EEPROM.write(0, 102); + if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект + for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов + if (EEPROM.read(x * 3 + 11) != modes[x].brightness) EEPROM.write(x * 3 + 11, modes[x].brightness); + if (EEPROM.read(x * 3 + 12) != modes[x].speed) EEPROM.write(x * 3 + 12, modes[x].speed); + if (EEPROM.read(x * 3 + 13) != modes[x].scale) EEPROM.write(x * 3 + 13, modes[x].scale); + } + // индикация сохранения + ONflag = false; + changePower(); + delay(200); + ONflag = true; + changePower(); + } + // + // if (touch.isStep()) { // изменение яркости при удержании кнопки + // if (numHold != 1) brightDirection = !brightDirection; + // numHold = 1; + // } + // + // if (touch.isStep(1)) { // изменение скорости "speed" при двойном нажатии и удержании кнопки + // if (numHold != 2) speedDirection = !speedDirection; + // numHold = 2; + // } + // + // if (touch.isStep(2)) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки + // if (numHold != 3) scaleDirection = !scaleDirection; + // numHold = 3; + // } + + if (touch.isHold() && touch.isStep()) { + //numHold = touch.getHoldClicks(); + // if (numHold != 0) { + Serial.print(numHold); + Serial.print(brightDirection); + Serial.print(speedDirection); + Serial.println(scaleDirection); + // Serial.print(" brightness:"); + // Serial.print(modes[currentMode].brightness); + // Serial.print(" speed:"); + // Serial.print(modes[currentMode].speed); + // Serial.print(" scale:"); + // Serial.println(modes[currentMode].scale); + // switch (numHold) { + switch (touch.getHoldClicks() + 1) { + case 1: + if (numHold != 1) brightDirection = !brightDirection; + modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , 255); + numHold = 1; + break; + + case 2: + if (numHold != 2) speedDirection = !speedDirection; + modes[currentMode].speed = constrain(modes[currentMode].speed + (modes[currentMode].speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); + numHold = 2; + break; + + case 3: + if (numHold != 3) scaleDirection = !scaleDirection; + modes[currentMode].scale = constrain(modes[currentMode].scale + (modes[currentMode].scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); + numHold = 3; + break; + } + if (numHold != 0) numHold_Timer = millis(); loadingFlag = true; + } + if ((millis() - numHold_Timer) > numHold_Time) { + numHold = 0; + numHold_Timer = millis(); + } + FastLED.setBrightness(modes[currentMode].brightness); + //settChanged = true; + if (touch.isDouble()) { + if (++currentMode >= MODE_AMOUNT) currentMode = 0; + FastLED.setBrightness(modes[currentMode].brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + if (touch.isTriple()) { + if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; + FastLED.setBrightness(modes[currentMode].brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + } + if (touch.isSingle()) { + if (ONflag) { + ONflag = false; + changePower(); + } else { + ONflag = true; + changePower(); + } + } +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/effectTicker.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/effectTicker.ino new file mode 100644 index 0000000..aab079d --- /dev/null +++ b/firmware/GyverLamp_v1.4_Arduino_v1.2/effectTicker.ino @@ -0,0 +1,99 @@ +uint32_t effTimer; +byte ind; + +void effectsTick() { + // if (!dawnFlag) + { + if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { + effTimer = millis(); + switch (currentMode) { + case 0: sparklesRoutine(); + break; + case 1: fireRoutine(); + break; + case 2: rainbowVertical(); + break; + case 3: rainbowHorizontal(); + break; + case 4: colorsRoutine(); + break; + case 5: madnessNoise(); + break; + case 6: cloudNoise(); + break; + case 7: lavaNoise(); + break; + case 8: plasmaNoise(); + break; + case 9: rainbowNoise(); + break; + case 10: rainbowStripeNoise(); + break; + case 11: zebraNoise(); + break; + case 12: forestNoise(); + break; + case 13: oceanNoise(); + break; + case 14: colorRoutine(); + break; + case 15: snowRoutine(); + break; + case 16: matrixRoutine(); + break; + case 17: whiteLamp(); + // case 17: lightersRoutine(); + break; + } + switch (numHold) { // индикатор уровня яркости/скорости/масштаба + case 1: + ind = sqrt(modes[currentMode].brightness + 1); + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) drawPixelXY(0, y, CHSV(10, 255, 255)); + else drawPixelXY(0, y, 0); + } + break; + case 2: + ind = sqrt(modes[currentMode].speed - 1); + for (byte y = 0; y <= HEIGHT ; y++) { + if (ind <= y) drawPixelXY(0, 15 - y, CHSV(100, 255, 255)); + else drawPixelXY(0, 15 - y, 0); + } + break; + case 3: + ind = sqrt(modes[currentMode].scale + 1); + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) drawPixelXY(0, y, CHSV(150, 255, 255)); + else drawPixelXY(0, y, 0); + } + break; + + } + FastLED.show(); + } + } +} + +void changePower() { // плавное включение/выключение + if (ONflag) { + effectsTick(); + for (int i = 0; i < modes[currentMode].brightness; i += 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.setBrightness(modes[currentMode].brightness); + delay(2); + FastLED.show(); + } else { + effectsTick(); + for (int i = modes[currentMode].brightness; i > 8; i -= 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.clear(); + delay(2); + FastLED.show(); + } +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/effects.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/effects.ino new file mode 100644 index 0000000..7e3e5ac --- /dev/null +++ b/firmware/GyverLamp_v1.4_Arduino_v1.2/effects.ino @@ -0,0 +1,292 @@ +// ================================= ЭФФЕКТЫ ==================================== + +// --------------------------------- конфетти ------------------------------------ +void sparklesRoutine() { + for (byte i = 0; i < modes[0].scale; 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(70); +} + +// функция плавного угасания цвета для всех пикселей +void fader(byte step) { + for (byte i = 0; i < WIDTH; i++) { + for (byte j = 0; j < HEIGHT; j++) { + fadePixel(i, j, step); + } + } +} +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; + } +} + +// -------------------------------------- огонь --------------------------------------------- +// эффект "огонь" +#define SPARKLES 1 // вылетающие угольки вкл выкл +unsigned char line[WIDTH]; +int pcnt = 0; + +//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 } +}; + +void fireRoutine() { + if (loadingFlag) { + loadingFlag = false; + //FastLED.clear(); + generateLine(); + } + if (pcnt >= 100) { + shiftUp(); + generateLine(); + pcnt = 0; + } + drawFrame(pcnt); + pcnt += 30; +} + +// Случайным образом генерирует следующую линию (matrix row) + +void generateLine() { + for (uint8_t x = 0; x < WIDTH; x++) { + line[x] = random(128, 255); + } +} + +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 - 15; + 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 - 15; + matrixValue[0][newX] = line[newX]; + } +} + +// рисует кадр, интерполируя между 2 "ключевых кадров" +// параметр pcnt - процент интерполяции + +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 - 15; + 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( + modes[1].scale * 2.5 + 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); + + } + } + } + + //Перавя стрка интерполируется со следующей "next" линией + for (unsigned char x = 0; x < WIDTH; x++) { + uint8_t newX = x; + if (x > 15) newX = x - 15; + CRGB color = CHSV( + modes[1].scale * 2.5 + 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; + } +} + +byte hue; +// ---------------------------------------- радуга ------------------------------------------ +void rainbowVertical() { + hue += 2; + for (byte j = 0; j < HEIGHT; j++) { + CHSV thisColor = CHSV((byte)(hue + j * modes[2].scale), 255, 255); + for (byte i = 0; i < WIDTH; i++) + drawPixelXY(i, j, thisColor); + } +} +void rainbowHorizontal() { + hue += 2; + for (byte i = 0; i < WIDTH; i++) { + CHSV thisColor = CHSV((byte)(hue + i * modes[3].scale), 255, 255); + for (byte j = 0; j < HEIGHT; j++) + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; + } +} + +// ---------------------------------------- ЦВЕТА ------------------------------------------ +void colorsRoutine() { + hue += modes[4].scale; + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = CHSV(hue, 255, 255); + } +} + +// --------------------------------- ЦВЕТ ------------------------------------ +void colorRoutine() { + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); + } +} + +// ------------------------------ снегопад 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, modes[15].scale) == 0)) + drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); + else + drawPixelXY(x, HEIGHT - 1, 0x000000); + } +} + +// ------------------------------ МАТРИЦА ------------------------------ +void matrixRoutine() { + for (byte x = 0; x < WIDTH; x++) { + // заполняем случайно верхнюю строку + uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); + if (thisColor == 0) + drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, modes[16].scale) == 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 whiteLamp() { + for (byte y = 0; y < (HEIGHT / 2); y++) { + CHSV color = CHSV(100, 1, constrain(modes[17].brightness - (long)modes[17].speed * modes[17].brightness / 255 * y / 2, 1, 255)); + for (byte x = 0; x < WIDTH; x++) { + drawPixelXY(x, y + 8, color); + drawPixelXY(x, 7 - y, color); + } + } +} + + +//// ----------------------------- СВЕТЛЯКИ ------------------------------ в ардуине под него не хватет пямяти +//#define LIGHTERS_AM 100 +//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 < modes[17].scale; 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]); +// } +//} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/noiseEffects.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/noiseEffects.ino new file mode 100644 index 0000000..fefccb6 --- /dev/null +++ b/firmware/GyverLamp_v1.4_Arduino_v1.2/noiseEffects.ino @@ -0,0 +1,205 @@ +// ******************* НАСТРОЙКИ ***************** +// "масштаб" эффектов. Чем меньше, тем крупнее! +#define MADNESS_SCALE 100 +#define CLOUD_SCALE 30 +#define LAVA_SCALE 50 +#define PLASMA_SCALE 30 +#define RAINBOW_SCALE 30 +#define RAINBOW_S_SCALE 20 +#define ZEBRA_SCALE 30 +#define FOREST_SCALE 120 +#define OCEAN_SCALE 90 + +// ***************** ДЛЯ РАЗРАБОТЧИКОВ ****************** + +// The 16 bit version of our coordinates +static uint16_t x; +static uint16_t y; +static uint16_t z; + +uint16_t speed = 20; // speed is set dynamically once we've started up +uint16_t scale = 30; // scale is set dynamically once we've started up + +// This is the array that we keep our computed noise values in (это массив, в котором храним вычисленные значения шума) +#define MAX_DIMENSION (max(WIDTH, HEIGHT)) +#if (WIDTH > HEIGHT) +uint8_t noise[WIDTH][WIDTH]; +#else +uint8_t noise[HEIGHT][HEIGHT]; +#endif + +CRGBPalette16 currentPalette( PartyColors_p ); +uint8_t colorLoop = 1; +uint8_t ihue = 0; + +void madnessNoise() { + if (loadingFlag) { + loadingFlag = false; + scale = modes[5].scale; + speed = modes[5].speed; + } + fillnoise8(); + for (int i = 0; i < WIDTH; i++) { + for (int j = 0; j < HEIGHT; j++) { + CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); + } + } + ihue += 1; +} +void rainbowNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = RainbowColors_p; + scale = modes[9].scale; + speed = modes[9].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void rainbowStripeNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = RainbowStripeColors_p; + scale = modes[10].scale; + speed = modes[10].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void zebraNoise() { + if (loadingFlag) { + loadingFlag = false; + // 'black out' all 16 palette entries... + fill_solid( currentPalette, 16, CRGB::Black); + // and set every fourth one to white. + currentPalette[0] = CRGB::White; + currentPalette[4] = CRGB::White; + currentPalette[8] = CRGB::White; + currentPalette[12] = CRGB::White; + scale = modes[11].scale; + speed = modes[11].speed; + colorLoop = 1; + +// Serial.print(" speed:"); +// Serial.print(modes[currentMode].speed); +// Serial.print(" scale:"); +// Serial.println(modes[currentMode].scale); + } + fillNoiseLED(); +} +void forestNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = ForestColors_p; + scale = modes[12].scale; + speed = modes[12].speed; + colorLoop = 0; + } + fillNoiseLED(); +} +void oceanNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = OceanColors_p; + scale = modes[13].scale; + speed = modes[13].speed; + colorLoop = 0; + } + + fillNoiseLED(); +} +void plasmaNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = PartyColors_p; + scale = modes[8].scale; + speed = modes[8].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void cloudNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = CloudColors_p; + scale = modes[6].scale; + speed = modes[6].speed; + colorLoop = 0; + } + fillNoiseLED(); +} +void lavaNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = LavaColors_p; + scale = modes[7].scale; + speed = modes[7].speed; + colorLoop = 0; + } + fillNoiseLED(); +} + +// ******************* СЛУЖЕБНЫЕ ******************* +void fillNoiseLED() { + uint8_t dataSmoothing = 0; + if ( speed < 50) { + dataSmoothing = 200 - (speed * 4); + } + for (int i = 0; i < MAX_DIMENSION; i++) { + int ioffset = scale * i; + for (int j = 0; j < MAX_DIMENSION; j++) { + int joffset = scale * j; + + uint8_t data = inoise8(x + ioffset, y + joffset, z); + + data = qsub8(data, 16); + data = qadd8(data, scale8(data, 39)); + + if ( dataSmoothing ) { + uint8_t olddata = noise[i][j]; + uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); + data = newdata; + } + + noise[i][j] = data; + } + } + z += speed; + + // apply slow drift to X and Y, just for visual variation. + x += speed / 8; + y -= speed / 16; + + for (int i = 0; i < WIDTH; i++) { + for (int j = 0; j < HEIGHT; j++) { + uint8_t index = noise[j][i]; + uint8_t bri = noise[i][j]; + // if this palette is a 'loop', add a slowly-changing base value + if ( colorLoop) { + index += ihue; + } + // brighten up, as the color palette itself often contains the + // light/dark dynamic range desired + if ( bri > 127 ) { + bri = 255; + } else { + bri = dim8_raw( bri * 2); + } + CRGB color = ColorFromPalette( currentPalette, index, bri); + drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color; + } + } + ihue += 1; +} + +void fillnoise8() { + for (int i = 0; i < MAX_DIMENSION; i++) { + int ioffset = scale * i; + for (int j = 0; j < MAX_DIMENSION; j++) { + int joffset = scale * j; + noise[i][j] = inoise8(x + ioffset, y + joffset, z); + } + } + z += speed; +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/utility.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/utility.ino new file mode 100644 index 0000000..6110de5 --- /dev/null +++ b/firmware/GyverLamp_v1.4_Arduino_v1.2/utility.ino @@ -0,0 +1,87 @@ +// служебные функции + +// залить все +void fillAll(CRGB color) { + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = color; + } +} + +// функция отрисовки точки по координатам 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; + } +} + +// функция получения цвета пикселя по его номеру +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)); +} + +// **************** НАСТРОЙКА МАТРИЦЫ **************** +#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); + } +} From 17be484b475e83a5220393438b1545929c1e47b8 Mon Sep 17 00:00:00 2001 From: Dmytro Korniienko Date: Sun, 18 Oct 2020 00:15:50 +0300 Subject: [PATCH 3/4] =?UTF-8?q?Revert=20"=D0=A1=D0=BF=D0=B5=D1=86=D0=B8?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D0=BD=D0=B0=D1=8F=20=D0=B2=D0=B5=D1=80=D1=81?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20kDn=20(#1)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 5af1d6a68f4070474e012e8dbd3fe07ec3513481. --- ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino | 54 - ArduinoLamp_v1.4/Constants.h | 31 - ArduinoLamp_v1.4/button.ino | 92 - ArduinoLamp_v1.4/effectTicker.ino | 94 - ArduinoLamp_v1.4/effects.ino | 507 ---- ArduinoLamp_v1.4/noiseEffects.ino | 269 --- ArduinoLamp_v1.4/utility.ino | 192 -- ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino | 54 - ArduinoLamp_v1.5/Constants.h | 36 - ArduinoLamp_v1.5/bitmap2.h | 61 - ArduinoLamp_v1.5/button.ino | 93 - ArduinoLamp_v1.5/effectTicker.ino | 108 - ArduinoLamp_v1.5/effects.ino | 2063 ----------------- ArduinoLamp_v1.5/noiseEffects.ino | 283 --- ArduinoLamp_v1.5/utility.ino | 195 -- GyverButtonOld/GyverButton.rar | Bin 3454 -> 0 bytes GyverButtonOld/GyverButtonOld.cpp | 199 -- GyverButtonOld/GyverButtonOld.h | 107 - .../Gbutton_example/Gbutton_example.ino | 50 - .../Gbutton_example_auto.ino | 53 - .../Gbutton_interrupt/Gbutton_interrupt.ino | 48 - .../Gbutton_timer_interrupt.ino | 51 - .../examples/_1-2-3-click/_1-2-3-click.ino | 20 - .../examples/_5_buttons/_5_buttons.ino | 34 - .../_5_buttons_auto/_5_buttons_auto.ino | 34 - .../analogKeyboard/analogKeyboard.ino | 32 - .../examples/increment/increment.ino | 41 - .../examples/many_clicks/many_clicks.ino | 19 - GyverButtonOld/keywords.txt | 48 - GyverButtonOld/old_version.rar | Bin 8826 -> 0 bytes GyverButtonOld/old_version/GyverButton.cpp | 119 - GyverButtonOld/old_version/GyverButton.h | 57 - .../Gbutton_example/Gbutton_example.ino | 46 - .../Gbutton_timer_interrupt.ino | 56 - .../examples/_1-2-3-click/_1-2-3-click.ino | 20 - .../examples/_5_buttons/_5_buttons.ino | 34 - .../examples/increment/increment.ino | 46 - .../examples/many_clicks/many_clicks.ino | 20 - GyverButtonOld/old_version/keywords.txt | 31 - GyverButtonOld/old_version/readme.txt | 13 - .../GyverLamp_v1.4_Arduino_v1.0.ino | 152 -- GyverLamp_v1.4_Arduino_v1.0kDn/button.ino | 223 -- .../effectTicker.ino | 115 - GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino | 158 -- .../noiseEffects.ino | 194 -- GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino | 128 - README.md | 21 +- .../GyverLamp_v1.4_Arduino_v1.2.ino | 127 - .../GyverLamp_v1.4_Arduino_v1.2/button.ino | 110 - .../effectTicker.ino | 99 - .../GyverLamp_v1.4_Arduino_v1.2/effects.ino | 292 --- .../noiseEffects.ino | 205 -- .../GyverLamp_v1.4_Arduino_v1.2/utility.ino | 87 - 53 files changed, 15 insertions(+), 7206 deletions(-) delete mode 100644 ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino delete mode 100644 ArduinoLamp_v1.4/Constants.h delete mode 100644 ArduinoLamp_v1.4/button.ino delete mode 100644 ArduinoLamp_v1.4/effectTicker.ino delete mode 100644 ArduinoLamp_v1.4/effects.ino delete mode 100644 ArduinoLamp_v1.4/noiseEffects.ino delete mode 100644 ArduinoLamp_v1.4/utility.ino delete mode 100644 ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino delete mode 100644 ArduinoLamp_v1.5/Constants.h delete mode 100644 ArduinoLamp_v1.5/bitmap2.h delete mode 100644 ArduinoLamp_v1.5/button.ino delete mode 100644 ArduinoLamp_v1.5/effectTicker.ino delete mode 100644 ArduinoLamp_v1.5/effects.ino delete mode 100644 ArduinoLamp_v1.5/noiseEffects.ino delete mode 100644 ArduinoLamp_v1.5/utility.ino delete mode 100644 GyverButtonOld/GyverButton.rar delete mode 100644 GyverButtonOld/GyverButtonOld.cpp delete mode 100644 GyverButtonOld/GyverButtonOld.h delete mode 100644 GyverButtonOld/examples/Gbutton_example/Gbutton_example.ino delete mode 100644 GyverButtonOld/examples/Gbutton_example_auto/Gbutton_example_auto.ino delete mode 100644 GyverButtonOld/examples/Gbutton_interrupt/Gbutton_interrupt.ino delete mode 100644 GyverButtonOld/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino delete mode 100644 GyverButtonOld/examples/_1-2-3-click/_1-2-3-click.ino delete mode 100644 GyverButtonOld/examples/_5_buttons/_5_buttons.ino delete mode 100644 GyverButtonOld/examples/_5_buttons_auto/_5_buttons_auto.ino delete mode 100644 GyverButtonOld/examples/analogKeyboard/analogKeyboard.ino delete mode 100644 GyverButtonOld/examples/increment/increment.ino delete mode 100644 GyverButtonOld/examples/many_clicks/many_clicks.ino delete mode 100644 GyverButtonOld/keywords.txt delete mode 100644 GyverButtonOld/old_version.rar delete mode 100644 GyverButtonOld/old_version/GyverButton.cpp delete mode 100644 GyverButtonOld/old_version/GyverButton.h delete mode 100644 GyverButtonOld/old_version/examples/Gbutton_example/Gbutton_example.ino delete mode 100644 GyverButtonOld/old_version/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino delete mode 100644 GyverButtonOld/old_version/examples/_1-2-3-click/_1-2-3-click.ino delete mode 100644 GyverButtonOld/old_version/examples/_5_buttons/_5_buttons.ino delete mode 100644 GyverButtonOld/old_version/examples/increment/increment.ino delete mode 100644 GyverButtonOld/old_version/examples/many_clicks/many_clicks.ino delete mode 100644 GyverButtonOld/old_version/keywords.txt delete mode 100644 GyverButtonOld/old_version/readme.txt delete mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/GyverLamp_v1.4_Arduino_v1.0.ino delete mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/button.ino delete mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/effectTicker.ino delete mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino delete mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/noiseEffects.ino delete mode 100644 GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino delete mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/GyverLamp_v1.4_Arduino_v1.2.ino delete mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/button.ino delete mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/effectTicker.ino delete mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/effects.ino delete mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/noiseEffects.ino delete mode 100644 firmware/GyverLamp_v1.4_Arduino_v1.2/utility.ino diff --git a/ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino b/ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino deleted file mode 100644 index 9000450..0000000 --- a/ArduinoLamp_v1.4/ArduinoLamp_v1.4.ino +++ /dev/null @@ -1,54 +0,0 @@ -/* - Скетч к проекту "Многофункциональный RGB светильник" - Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ - Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ - Автор: AlexGyver, AlexGyver Technologies, 2019(Портировал на Ардуино Norovl(+ эффекты, демо от stepko365) - https://AlexGyver.ru/ -*/ -// ---------------- БИБЛИОТЕКИ ----------------- -#include -#include -#include -//----------------- ----------------- -#include "Constants.h" -// ----------------- ПЕРЕМЕННЫЕ ------------------ -static const byte maxDim = max(WIDTH, HEIGHT); -struct { byte Brightness = 10; byte Speed = 30; byte Scale = 10; } modes[MODE_AMOUNT]; //настройки эффекта по умолчанию -int8_t currentMode = 10; -boolean loadingFlag = true; -boolean ONflag = true; -byte numHold; -unsigned long numHold_Timer = 0; -unsigned char matrixValue[8][16]; - - -void setup() { - // ЛЕНТА - FastLED.addLeds(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/; - FastLED.setBrightness(BRIGHTNESS); - if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); - FastLED.clear(); - FastLED.show(); - - touch.setStepTimeout(100); - touch.setClickTimeout(500); - - //Serial.begin(9600); - //Serial.println(); - - if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР - currentMode = EEPROM.read(1); - for (byte x = 0; x < MODE_AMOUNT; x++) { - modes[x].Brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) - modes[x].Speed = EEPROM.read(x * 3 + 12); - modes[x].Scale = EEPROM.read(x * 3 + 13); - } - - } -} - -void loop() { - effectsTick(); - buttonTick(); - demo(); -} diff --git a/ArduinoLamp_v1.4/Constants.h b/ArduinoLamp_v1.4/Constants.h deleted file mode 100644 index 6bec6d7..0000000 --- a/ArduinoLamp_v1.4/Constants.h +++ /dev/null @@ -1,31 +0,0 @@ -// ============= НАСТРОЙКИ ============= -// ---------- МАТРИЦА --------- -#define BRIGHTNESS 10 // стандартная маскимальная яркость (0-255) -#define CURRENT_LIMIT 1000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит - -#define WIDTH 16 // ширина матрицы -#define HEIGHT 16 // высота матрицы - -#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB - -#define MATRIX_TYPE 1 // тип матрицы: 0 - зигзаг, 1 - параллельная -#define CONNECTION_ANGLE 1 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний -#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз -// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" -// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ - -#define numHold_Time (1*1000) // время отображения индикатора уровня яркости/скорости/масштаба - -// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= -#define LED_PIN 6 // пин ленты -#define BTN_PIN 2 -#define MODE_AMOUNT 28 //кол-во эффектов -#define NUM_LEDS WIDTH * HEIGHT -#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) -// ------------------- ТИПЫ -------------------- -CRGB leds[NUM_LEDS]; -GButton touch(BTN_PIN, HIGH_PULL, NORM_OPEN); //если сенсорна кнопка LOW_PULL -#define RANDOM_DEMO 1 // 0,1 - включить рандомный выбор режима -#define DEMOTIMELIMIT ( 1 * 20UL * 1000UL) // минуты/секунды/милисекунды время задержка между эффектами -uint32_t DemTimer = 0UL; // тут будет храниться время следующего переключения эффекта -bool isDemo = false; diff --git a/ArduinoLamp_v1.4/button.ino b/ArduinoLamp_v1.4/button.ino deleted file mode 100644 index 7681dec..0000000 --- a/ArduinoLamp_v1.4/button.ino +++ /dev/null @@ -1,92 +0,0 @@ -boolean brightDirection, speedDirection, scaleDirection; - -void buttonTick() { - touch.tick(); - - if (touch.isSingle()) { - { - if (ONflag) { - ONflag = false; - changePower(); - } else { - ONflag = true; - changePower(); - } - } - } - -if (ONflag) { // если включено - if (touch.isDouble()) { - if (++currentMode >= MODE_AMOUNT) currentMode = 0; - FastLED.setBrightness(modes[currentMode].Brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - if (touch.isTriple()) { - if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; - FastLED.setBrightness(modes[currentMode].Brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - if (touch.hasClicks()) - if (touch.getClicks() == 5) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров - if (EEPROM.read(0) != 102) EEPROM.write(0, 102); - if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект - for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов - if (EEPROM.read(x * 3 + 11) != modes[x].Brightness) EEPROM.write(x * 3 + 11, modes[x].Brightness); - if (EEPROM.read(x * 3 + 12) != modes[x].Speed) EEPROM.write(x * 3 + 12, modes[x].Speed); - if (EEPROM.read(x * 3 + 13) != modes[x].Scale) EEPROM.write(x * 3 + 13, modes[x].Scale); - } - // индикация сохранения - ONflag = false; - changePower(); - delay(200); - ONflag = true; - changePower(); - } - else if (touch.getClicks() == 4){ // если было четырёхкратное нажатие на кнопку, то переключаем демо - isDemo = !isDemo; - DemTimer = 0UL;} - - - if (touch.isHolded()) { // изменение яркости при удержании кнопки - brightDirection = !brightDirection; - numHold = 1; - } - - if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки - speedDirection = !speedDirection; - numHold = 2; - } - - if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки - scaleDirection = !scaleDirection; - numHold = 3; - } - - if (touch.isStep()) { - if (numHold != 0) numHold_Timer = millis(); loadingFlag = true; - switch (numHold) { - case 1: - modes[currentMode].Brightness = constrain(modes[currentMode].Brightness + (modes[currentMode].Brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , 255); - break; - case 2: - modes[currentMode].Speed = constrain(modes[currentMode].Speed + (modes[currentMode].Speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); - break; - - case 3: - modes[currentMode].Scale = constrain(modes[currentMode].Scale + (modes[currentMode].Scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); - break; - } - } - if ((millis() - numHold_Timer) > numHold_Time) { - numHold = 0; - numHold_Timer = millis(); - } - FastLED.setBrightness(modes[currentMode].Brightness); - } -} diff --git a/ArduinoLamp_v1.4/effectTicker.ino b/ArduinoLamp_v1.4/effectTicker.ino deleted file mode 100644 index f1326b6..0000000 --- a/ArduinoLamp_v1.4/effectTicker.ino +++ /dev/null @@ -1,94 +0,0 @@ -uint32_t effTimer; -byte ind; -void effectsTick() { { if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 17) ? modes[currentMode].Speed : 50) ) {effTimer = millis(); switch (currentMode) { -//|номер |название функции эффекта |тоже надо| - case 0 : sparklesRoutine(); break; - case 1 : fireRoutine(); break; - case 3 : rainbowVertical(); break; - case 4 : rainbowHorizontal(); break; - case 5 : rainbowDiagonalRoutine(); break; - case 6 : madnessNoise(); break; - case 7 : cloudNoise(); break; - case 8 : lavaNoise(); break; - case 9 : plasmaNoise(); break; - case 10: rainbowNoise(); break; - case 11: rainbowStripeNoise(); break; - case 12: zebraNoise(); break; - case 13: forestNoise(); break; - case 14: oceanNoise(); break; - case 15: heatNoise(); break; - case 16: smokeNoise(); break; - case 18: colorRoutine(); break; - case 19: colorsRoutine(); break; - case 20: whiteLamp(); break; - case 21: matrixRoutine(); break; - case 22: snowRoutine(); break; - case 23: stormRoutine2(true); break; - case 24: stormRoutine2(false); break; - case 25: ballRoutine(); break; - case 26: ballsRoutine(); break; - case 27: MunchRoutine(); break; -} - switch (numHold) { // индикатор уровня яркости/скорости/масштаба - case 1: - ind = sqrt(modes[currentMode].Brightness + 1); - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) drawPixelXY(0, y, CHSV(10, 255, 255)); - else drawPixelXY(0, y, 0); - } - break; - case 2: - ind = sqrt(modes[currentMode].Speed - 1); - for (byte y = 0; y <= HEIGHT ; y++) { - if (ind <= y) drawPixelXY(0, 15 - y, CHSV(100, 255, 255)); - else drawPixelXY(0, 15 - y, 0); - } - break; - case 3: - ind = sqrt(modes[currentMode].Scale + 1); - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) drawPixelXY(0, y, CHSV(150, 255, 255)); - else drawPixelXY(0, y, 0); - } - break; - - } - FastLED.show(); - } - } -} - -void changePower() { // плавное включение/выключение - if (ONflag) { - effectsTick(); - for (int i = 0; i < modes[currentMode].Brightness; i += 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.setBrightness(modes[currentMode].Brightness); - delay(2); - FastLED.show(); - } else { - effectsTick(); - for (int i = modes[currentMode].Brightness; i > 8; i -= 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.clear(); - delay(2); - FastLED.show(); - } -} - - void demo(){ - if (isDemo && ONflag && millis() >= DemTimer){ - if(RANDOM_DEMO) - currentMode = random8(MODE_AMOUNT); // если нужен следующий случайный эффект - else - currentMode = currentMode + 1U < MODE_AMOUNT ? currentMode + 1U : 0U; // если нужен следующий по списку эффект - FastLED.clear(); - DemTimer = millis() + DEMOTIMELIMIT; - loadingFlag = true;} -} diff --git a/ArduinoLamp_v1.4/effects.ino b/ArduinoLamp_v1.4/effects.ino deleted file mode 100644 index aab879b..0000000 --- a/ArduinoLamp_v1.4/effects.ino +++ /dev/null @@ -1,507 +0,0 @@ -// ================================= ЭФФЕКТЫ ==================================== -uint8_t wrapX(int8_t x){ - return (x + WIDTH)%WIDTH; -} -uint8_t wrapY(int8_t y){ - return (y + HEIGHT)%HEIGHT; -} -uint8_t step; // какой-нибудь счётчик кадров или постедовательностей операций -uint8_t pcnt; -uint8_t line[WIDTH]; -uint8_t deltaValue; // просто повторно используемая переменная -uint8_t shiftHue[HEIGHT]; -uint8_t shiftValue[HEIGHT]; -// палитра для типа реалистичного водопада (если ползунок Масштаб выставить на 100) -extern const TProgmemRGBPalette16 WaterfallColors_p FL_PROGMEM = {0x000000, 0x060707, 0x101110, 0x151717, 0x1C1D22, 0x242A28, 0x363B3A, 0x313634, 0x505552, 0x6B6C70, 0x98A4A1, 0xC1C2C1, 0xCACECF, 0xCDDEDD, 0xDEDFE0, 0xB2BAB9}; -CRGB _pulse_color; -void blurScreen(fract8 blur_amount, CRGB *LEDarray = leds) -{ - blur2d(LEDarray, WIDTH, HEIGHT, blur_amount); -} -const TProgmemRGBPalette16 *palette_arr[] = { - &PartyColors_p, - &OceanColors_p, - &LavaColors_p, - &HeatColors_p, - &WaterfallColors_p, - &CloudColors_p, - &ForestColors_p, - &RainbowColors_p, - &RainbowStripeColors_p -}; -const TProgmemRGBPalette16 *curPalette = palette_arr[0]; -void setCurrentPalette() { - if (modes[currentMode].Scale > 100U) modes[currentMode].Scale = 100U; // чтобы не было проблем при прошивке без очистки памяти - curPalette = palette_arr[(uint8_t)(modes[currentMode].Scale / 100.0F * ((sizeof(palette_arr) / sizeof(TProgmemRGBPalette16 *)) - 0.01F))]; -} -// --------------------------------- конфетти ------------------------------------ -#define FADE_OUT_SPEED (70U) // скорость затухания -void sparklesRoutine() -{ - for (uint8_t i = 0; i < modes[currentMode].Scale; i++) - { - uint8_t x = random(0U, WIDTH); - uint8_t y = random(0U, HEIGHT); - if (getPixColorXY(x, y) == 0U) - { - leds[XY(x, y)] = CHSV(random(0U, 255U), 255U, 255U); - } - } - fader(FADE_OUT_SPEED); -} -// функция плавного угасания цвета для всех пикселей -void fader(uint8_t step) -{ - for (uint8_t i = 0U; i < WIDTH; i++) - { - for (uint8_t j = 0U; j < HEIGHT; j++) - { - fadePixel(i, j, step); - } - } -} -void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер -{ - int32_t pixelNum = XY(i, j); - if (getPixColor(pixelNum) == 0U) return; - - if (leds[pixelNum].r >= 30U || - leds[pixelNum].g >= 30U || - leds[pixelNum].b >= 30U) - { - leds[pixelNum].fadeToBlackBy(step); - } - else - { - leds[pixelNum] = 0U; - } -} -// -------------------------------------- огонь --------------------------------------------- -#define SPARKLES 1 // вылетающие угольки вкл выкл -//these values are substracetd from the generated values to give a shape to the animation -const unsigned char valueMask[8][16] PROGMEM = { - {0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 }, - {0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 }, - {0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 }, - {0 , 32 , 64 , 128, 128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 128, 64 , 32 , 0 }, - {32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 }, - {64 , 96 , 128, 192, 192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128, 96 , 64 }, - {96 , 128, 160, 255, 255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160, 128, 96 }, - {128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128} -}; - -//these are the hues for the fire, -//should be between 0 (red) to about 25 (yellow) -const unsigned char hueMask[8][16] PROGMEM = { - {25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25 }, - {25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19 }, - {19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16 }, - {13, 13, 5 , 1 , 1 , 5 , 11, 13, 13, 13, 5 , 1 , 1 , 5 , 11, 13 }, - {11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11 }, - {8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 }, - {5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 }, - {1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } -}; - -void fireRoutine() { - if (loadingFlag) { - loadingFlag = false; - //FastLED.clear(); - generateLine(); - } - if (pcnt >= 100) { - shiftUp(); - generateLine(); - pcnt = 0; - } - drawFrame(pcnt); - pcnt += 25; -} - -// Случайным образом генерирует следующую линию (matrix row) - -void generateLine() { - for (uint8_t x = 0; x < WIDTH; x++) { - line[x] = random(127, 255); - } -} - -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 - 15; - 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 - 15; - matrixValue[0][newX] = line[newX]; - } -} - -// рисует кадр, интерполируя между 2 "ключевых кадров" -// параметр pcnt - процент интерполяции - -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 - 15; - 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( - modes[currentMode].Scale * 2.5 + 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); - - } - } - } - - //Перавя стрка интерполируется со следующей "next" линией - for (unsigned char x = 0; x < WIDTH; x++) { - uint8_t newX = x; - if (x > 15) newX = x - 15; - CRGB color = CHSV( - modes[currentMode].Scale * 2.5 + 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; - } -} -// ---------------------------------------- радуга ------------------------------------------ -byte hue; -void rainbowVertical() { - hue += 2; - for (byte j = 0; j < HEIGHT; j++) { - CHSV thisColor = CHSV((byte)(hue + j * modes[currentMode].Scale), 255, 255); - for (byte i = 0; i < WIDTH; i++) - drawPixelXY(i, j, thisColor); - } -} -void rainbowHorizontal() { - hue += 2; - for (byte i = 0; i < WIDTH; i++) { - CHSV thisColor = CHSV((byte)(hue + i * modes[currentMode].Scale), 255, 255); - for (byte j = 0; j < HEIGHT; j++) - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; - } -} -void rainbowDiagonalRoutine() -{ - if (loadingFlag) - { - loadingFlag = false; - FastLED.clear(); - } - - hue += 8; - for (uint8_t i = 0U; i < WIDTH; i++) - { - for (uint8_t j = 0U; j < HEIGHT; j++) - { - float twirlFactor = 3.0F * (modes[currentMode].Scale / 100.0F); // на сколько оборотов будет закручена матрица, [0..3] - CRGB thisColor = CHSV((uint8_t)(hue + ((float)WIDTH / HEIGHT * i + j * twirlFactor) * ((float)255 / maxDim)), 255, 255); - drawPixelXY(i, j, thisColor); - } - } -} -// ---------------------------------------- ЦВЕТА ----------------------------- -void colorsRoutine() { - hue += modes[currentMode].Scale; - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(hue, 255, 255); - } -} - -// --------------------------------- ЦВЕТ ------------------------------------ -void colorRoutine() { - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(modes[currentMode].Scale * 2.5, modes[currentMode].Speed * 2.5, 255); - } -} - -// ------------------------------ снегопад 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, modes[currentMode].Scale) == 0)) - drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); - else - drawPixelXY(x, HEIGHT - 1, 0x000000); - } -} - -// ------------------------------ МАТРИЦА ------------------------------ -void matrixRoutine() { - for (byte x = 0; x < WIDTH; x++) { - // заполняем случайно верхнюю строку - uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); - if (thisColor == 0) - drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, modes[currentMode].Scale) == 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 whiteLamp() { - for (byte y = 0; y < (HEIGHT / 2); y++) { - CHSV color = CHSV(100, 1, constrain(modes[currentMode].Brightness - (long)modes[currentMode].Speed * modes[currentMode].Brightness / 255 * y / 2, 1, 255)); - for (byte x = 0; x < WIDTH; x++) { - drawPixelXY(x, y + 8, color); - drawPixelXY(x, 7 - y, color); - } - } -} -//--------------------------Шторм,Метель------------------------- -#define e_sns_DENSE (32U) // плотность снега - меньше = плотнее -void stormRoutine2(bool isColored) -{ - // заполняем головами комет - uint8_t Saturation = 0U; // цвет хвостов - uint8_t e_TAIL_STEP = 127U; // длина хвоста - if (isColored) - Saturation = modes[currentMode].Scale * 2.55; - else - { - e_TAIL_STEP = 255U - modes[currentMode].Scale * 2.55; - } - for (int8_t x = 0U; x < WIDTH - 1U; x++) // fix error i != 0U - { - if (!random8(e_sns_DENSE) && - !getPixColorXY(wrapX(x), HEIGHT - 1U) && - !getPixColorXY(wrapX(x + 1U), HEIGHT - 1U) && - !getPixColorXY(wrapX(x - 1U), HEIGHT - 1U)) - { - drawPixelXY(x, HEIGHT - 1U, CHSV(random8(), Saturation, random8(64U, 255U))); - } - } - - // сдвигаем по диагонали - for (int8_t y = 0U; y < HEIGHT - 1U; y++) - { - for (int8_t x = 0; x < WIDTH; x++) - { - drawPixelXY(wrapX(x + 1U), y, getPixColorXY(x, y + 1U)); - } - } - - // уменьшаем яркость верхней линии, формируем "хвосты" - for (int8_t i = 0U; i < WIDTH; i++) - { - fadePixel(i, HEIGHT - 1U, e_TAIL_STEP); - } -} -//-------------------------Блуждающий кубик----------------------- -#define RANDOM_COLOR (1U) // случайный цвет при отскоке -int16_t coordB[2U]; -int8_t vectorB[2U]; -CRGB ballColor; -//int8_t deltaValue; //ballSize; - -void ballRoutine() -{ - if (loadingFlag) - { - loadingFlag = false; - //FastLED.clear(); - - for (uint8_t i = 0U; i < 2U; i++) - { - coordB[i] = WIDTH / 2 * 10; - vectorB[i] = random(8, 20); - } - deltaValue = map(modes[currentMode].Scale * 2.55, 0U, 255U, 2U, max((uint8_t)min(WIDTH, HEIGHT) / 3, 2)); - ballColor = CHSV(random(0, 9) * 28, 255U, 255U); -// _pulse_color = CHSV(random(0, 9) * 28, 255U, 255U); - } - -// if (!(modes[currentMode].Scale & 0x01)) -// { -// hue += (modes[currentMode].Scale - 1U) % 11U * 8U + 1U; - -// ballColor = CHSV(hue, 255U, 255U); -// } - - if ((modes[currentMode].Scale & 0x01)) - for (uint8_t i = 0U; i < deltaValue; i++) - for (uint8_t j = 0U; j < deltaValue; j++) - leds[XY(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = _pulse_color; - - for (uint8_t i = 0U; i < 2U; 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, 255U, 255U); // if (RANDOM_COLOR && (modes[currentMode].Scale & 0x01)) - //vectorB[i] += random(0, 6) - 3; - } - } - if (coordB[0U] > (int16_t)((WIDTH - deltaValue) * 10)) - { - coordB[0U] = (WIDTH - deltaValue) * 10; - vectorB[0U] = -vectorB[0U]; - if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U); - //vectorB[0] += random(0, 6) - 3; - } - if (coordB[1U] > (int16_t)((HEIGHT - deltaValue) * 10)) - { - coordB[1U] = (HEIGHT - deltaValue) * 10; - vectorB[1U] = -vectorB[1U]; - if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U); - //vectorB[1] += random(0, 6) - 3; - } - -// if (modes[currentMode].Scale & 0x01) -// dimAll(135U); -// dimAll(255U - (modes[currentMode].Scale - 1U) % 11U * 24U); -// else - FastLED.clear(); - - for (uint8_t i = 0U; i < deltaValue; i++) - for (uint8_t j = 0U; j < deltaValue; j++) - leds[XY(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = ballColor; -} - -//-------------------Светлячки со шлейфом---------------------------- -#define BALLS_AMOUNT (3U) // количество "шариков" -#define CLEAR_PATH (1U) // очищать путь -#define BALL_TRACK (1U) // (0 / 1) - вкл/выкл следы шариков -#define TRACK_STEP (70U) // длина хвоста шарика (чем больше цифра, тем хвост короче) -int16_t coord[BALLS_AMOUNT][2U]; -int8_t vector[BALLS_AMOUNT][2U]; -CRGB ballColors[BALLS_AMOUNT]; -void ballsRoutine() -{ - if (loadingFlag) - { - loadingFlag = false; - - for (uint8_t j = 0U; j < BALLS_AMOUNT; j++) - { - int8_t sign; - // забиваем случайными данными - coord[j][0U] = WIDTH / 2 * 10; - random(0, 2) ? sign = 1 : sign = -1; - vector[j][0U] = random(4, 15) * sign; - coord[j][1U] = HEIGHT / 2 * 10; - random(0, 2) ? sign = 1 : sign = -1; - vector[j][1U] = random(4, 15) * sign; - //ballColors[j] = CHSV(random(0, 9) * 28, 255U, 255U); - // цвет зависит от масштаба - ballColors[j] = CHSV((modes[currentMode].Scale * (j + 1)) % 256U, 255U, 255U); - } - } - - if (!BALL_TRACK) // режим без следов шариков - { - FastLED.clear(); - } - else // режим со следами - { - fader(TRACK_STEP); - } - - // движение шариков - for (uint8_t j = 0U; j < BALLS_AMOUNT; j++) - { - // движение шариков - for (uint8_t i = 0U; i < 2U; i++) - { - coord[j][i] += vector[j][i]; - if (coord[j][i] < 0) - { - coord[j][i] = 0; - vector[j][i] = -vector[j][i]; - } - } - - if (coord[j][0U] > (int16_t)((WIDTH - 1) * 10)) - { - coord[j][0U] = (WIDTH - 1) * 10; - vector[j][0U] = -vector[j][0U]; - } - if (coord[j][1U] > (int16_t)((HEIGHT - 1) * 10)) - { - coord[j][1U] = (HEIGHT - 1) * 10; - vector[j][1U] = -vector[j][1U]; - } - leds[XY(coord[j][0U] / 10, coord[j][1U] / 10)] = ballColors[j]; - } -} - -//-----------------Эффект Вышиванка------------- -byte count = 0; -byte dir = 1; -byte flip = 0; -byte generation = 0; -void MunchRoutine() { if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - for (byte x = 0; x < WIDTH; x++) { - for (byte y = 0; y < HEIGHT; y++) { - leds[XY(x, y)] = (x ^ y ^ flip) < count ? ColorFromPalette(*curPalette, ((x ^ y) << 4) + generation) : CRGB::Black; - } - } - - count += dir; - - if (count <= 0 || count >= WIDTH) { - dir = -dir; - } - - if (count <= 0) { - if (flip == 0) - flip = 7; - else - flip = 0; - } - - generation++; -} diff --git a/ArduinoLamp_v1.4/noiseEffects.ino b/ArduinoLamp_v1.4/noiseEffects.ino deleted file mode 100644 index de459ef..0000000 --- a/ArduinoLamp_v1.4/noiseEffects.ino +++ /dev/null @@ -1,269 +0,0 @@ -// ************* НАСТРОЙКИ ************* -// The 16 bit version of our coordinates -static uint16_t x; -static uint16_t y; -static uint16_t z; - -uint16_t speed = 20; // speed is set dynamically once we've started up -uint16_t scale = 30; // scale is set dynamically once we've started up - -// This is the array that we keep our computed noise values in -#define MAX_DIMENSION (max(WIDTH, HEIGHT)) -#if (WIDTH > HEIGHT) -uint8_t noise[WIDTH][WIDTH]; -#else -uint8_t noise[HEIGHT][HEIGHT]; -#endif - -CRGBPalette16 pPalette; - -// This function sets up a palette of black and blue stripes, -// using code. Since the palette is effectively an array of -// sixteen CRGB colors, the various fill_* functions can be used -// to set them up. -void SetupPalette() -{ - // 'black out' all 16 palette entries... - fill_solid( pPalette, 16, CHSV(modes[currentMode].Scale * 2.5,255, 75)); - - for(uint8_t i = 0; i < 6; i++) { - pPalette[i] = CHSV(modes[currentMode].Scale * 2.5, 255, 255); - } -} - - -CRGBPalette16 currentPalette(PartyColors_p); -uint8_t colorLoop = 1; -uint8_t ihue = 0; - -void madnessNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - } - fillnoise8(); - for (uint8_t i = 0; i < WIDTH; i++) - { - for (uint8_t j = 0; j < HEIGHT; j++) - { - CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); - leds[XY(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); - } - } - ihue += 1; -} - -void rainbowNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = RainbowColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 1; - } - fillNoiseLED(0.125,0.0625,1); -} - -void rainbowStripeNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = RainbowStripeColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 1; - } - fillNoiseLED(0.125,0.0625,1); -} - -void zebraNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - // 'black out' all 16 palette entries... - fill_solid(currentPalette, 16, CRGB::Black); - // and set every fourth one to white. - currentPalette[0] = CRGB::White; - currentPalette[4] = CRGB::White; - currentPalette[8] = CRGB::White; - currentPalette[12] = CRGB::White; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 1; - } - fillNoiseLED(0.125,0.0625,1); -} - -void forestNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = ForestColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(0.125,0.0625,1); -} - -void oceanNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = OceanColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - - fillNoiseLED(0.125,0.0625,1); -} - -void plasmaNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = PartyColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 1; - } - fillNoiseLED(0.125,0.0625,1); -} - -void cloudNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = CloudColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(0.125,0.0625,1); -} - -void lavaNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = LavaColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(0.125,0.0625,1); -} - -void heatNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = HeatColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(1,0,0.125); -} - -void smokeNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = WaterfallColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(1,0,0.125); -} -// ************* СЛУЖЕБНЫЕ ************* -void fillNoiseLED(byte x_dir, byte y_dir, byte z_dir) -{ - uint8_t dataSmoothing = 0; - if (speed < 50) - { - dataSmoothing = 200 - (speed * 4); - } - for (uint8_t i = 0; i < MAX_DIMENSION; i++) - { - int32_t ioffset = scale * i; - for (uint8_t j = 0; j < MAX_DIMENSION; j++) - { - int32_t joffset = scale * j; - - uint8_t data = inoise8(x + ioffset, y + joffset, z); - - data = qsub8(data, 16); - data = qadd8(data, scale8(data, 39)); - - if (dataSmoothing) - { - uint8_t olddata = noise[i][j]; - uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); - data = newdata; - } - - noise[i][j] = data; - } - } - z += speed*z_dir; - x -= speed*x_dir; - y += speed*y_dir; - - for (uint8_t i = 0; i < WIDTH; i++) - { - for (uint8_t j = 0; j < HEIGHT; j++) - { - uint8_t index = noise[j][i]; - uint8_t bri = noise[i][j]; - // if this palette is a 'loop', add a slowly-changing base value - if ( colorLoop) - { - index += ihue; - } - // brighten up, as the color palette itself often contains the - // light/dark dynamic range desired - if ( bri > 127 ) - { - bri = 255; - } - else - { - bri = dim8_raw( bri * 2); - } - CRGB color = ColorFromPalette( currentPalette, index, bri); - leds[XY(i, j)] = color; - } - } - ihue += 1; -} - -void fillnoise8() -{ - for (uint8_t i = 0; i < MAX_DIMENSION; i++) - { - int32_t ioffset = scale * i; - for (uint8_t j = 0; j < MAX_DIMENSION; j++) - { - int32_t joffset = scale * j; - noise[i][j] = inoise8(x + ioffset, y + joffset, z); - } - } - z -= speed; -} diff --git a/ArduinoLamp_v1.4/utility.ino b/ArduinoLamp_v1.4/utility.ino deleted file mode 100644 index be238e9..0000000 --- a/ArduinoLamp_v1.4/utility.ino +++ /dev/null @@ -1,192 +0,0 @@ -// служебные функции - -// залить все -void fillAll(CRGB color) { - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = color; - } -} - -// функция отрисовки точки по координатам 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; - } -} - -// функция получения цвета пикселя по его номеру -uint32_t getPixColor(uint32_t thisSegm) -{ - uint32_t thisPixel = thisSegm * SEGMENTS; - if (thisPixel > NUM_LEDS - 1) return 0; - return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b); -} - -// функция получения цвета пикселя в матрице по его координатам -uint32_t getPixColorXY(uint8_t x, uint8_t y) -{ - return getPixColor(XY(x, y)); -} - -// **************** НАСТРОЙКА МАТРИЦЫ **************** -#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 XY(uint8_t x, uint8_t y) -{ - if (!(THIS_Y & 0x01) || MATRIX_TYPE) // Even rows run forwards - return (THIS_Y * _WIDTH + THIS_X); - else - return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); // Odd rows run backwards -} - -// оставлено для совместимости со эффектами из старых прошивок -uint16_t getPixelNumber(uint8_t x, uint8_t y) -{ - return XY(x, y); -} - -// Gamma коррекция (Defalt Gamma = 2.8) -const uint8_t PROGMEM gammaR[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, - 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, - 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, - 33, 34, 35, 36, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 46, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 80, - 81, 83, 84, 85, 87, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, - 104, 105, 107, 109, 110, 112, 113, 115, 116, 118, 120, 121, 123, 125, 127, 128, - 130, 132, 134, 135, 137, 139, 141, 143, 145, 146, 148, 150, 152, 154, 156, 158, - 160, 162, 164, 166, 168, 170, 172, 174, 177, 179, 181, 183, 185, 187, 190, 192, - 194, 196, 199, 201, 203, 206, 208, 210, 213, 215, 218, 220, 223, 225, 227, 230 -}; - -const uint8_t PROGMEM gammaG[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, - 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, - 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, - 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, - 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, - 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, - 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, - 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, - 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114, - 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142, - 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175, - 177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, - 215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255 -}; - -const uint8_t PROGMEM gammaB[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, - 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 8, - 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 12, 13, - 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, - 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, - 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40, - 40, 41, 42, 43, 44, 44, 45, 46, 47, 48, 49, 50, 51, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 70, - 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, - 90, 92, 93, 94, 96, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 112, - 113, 115, 116, 118, 119, 121, 122, 124, 126, 127, 129, 131, 132, 134, 136, 137, - 139, 141, 143, 144, 146, 148, 150, 152, 153, 155, 157, 159, 161, 163, 165, 167, - 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 196, 198, 200 -}; - -// гамма-коррекция (более натуральные цвета) -uint32_t gammaCorrection(uint32_t color) { - byte r = (color >> 16) & 0xFF; // Extract the RR byte - byte g = (color >> 8) & 0xFF; // Extract the GG byte - byte b = color & 0xFF; // Extract the BB byte - - r = pgm_read_byte(&gammaR[r]); - g = pgm_read_byte(&gammaG[g]); - b = pgm_read_byte(&gammaB[b]); - - uint32_t newColor = ((long)(r & 0xff) << 16) + ((long)(g & 0xff) << 8) + ((long)b & 0xff); - return newColor; -} - -// gamma correction для expandColor -static const uint8_t PROGMEM -gamma5[] = { - 0x00, 0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, - 0x0e, 0x11, 0x14, 0x18, 0x1d, 0x22, 0x28, 0x2e, - 0x36, 0x3d, 0x46, 0x4f, 0x59, 0x64, 0x6f, 0x7c, - 0x89, 0x97, 0xa6, 0xb6, 0xc7, 0xd9, 0xeb, 0xff -}, -gamma6[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, - 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x12, 0x13, - 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x20, 0x22, 0x25, - 0x27, 0x2a, 0x2d, 0x30, 0x33, 0x37, 0x3a, 0x3e, - 0x41, 0x45, 0x49, 0x4d, 0x52, 0x56, 0x5b, 0x5f, - 0x64, 0x69, 0x6e, 0x74, 0x79, 0x7f, 0x85, 0x8b, - 0x91, 0x97, 0x9d, 0xa4, 0xab, 0xb2, 0xb9, 0xc0, - 0xc7, 0xcf, 0xd6, 0xde, 0xe6, 0xee, 0xf7, 0xff -}; - -// преобразовать цвет из 16 битного в 24 битный -static uint32_t expandColor(uint16_t color) { - return ((uint32_t)pgm_read_byte(&gamma5[ color >> 11 ]) << 16) | - ((uint32_t)pgm_read_byte(&gamma6[(color >> 5) & 0x3F]) << 8) | - pgm_read_byte(&gamma5[ color & 0x1F]); -} diff --git a/ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino b/ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino deleted file mode 100644 index 23e07c1..0000000 --- a/ArduinoLamp_v1.5/ArduinoLamp_v1.5.ino +++ /dev/null @@ -1,54 +0,0 @@ -/* - Скетч к проекту "Многофункциональный RGB светильник" - Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ - Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ - Автор: AlexGyver, AlexGyver Technologies, 2019(Портировал на Ардуино Norovl(+ эффекты,демо stepko365) - https://AlexGyver.ru/ -*/ -// ---------------- БИБЛИОТЕКИ ----------------- -#include -#include -#include -//----------------- ----------------- -#include "bitmap2.h" -#include "Constants.h" -// ----------------- ПЕРЕМЕННЫЕ ------------------ -static const byte maxDim = max(WIDTH, HEIGHT); -int8_t currentMode = 10; -boolean loadingFlag = true; -boolean ONflag = true; -byte numHold; -unsigned long numHold_Timer = 0; -unsigned char matrixValue[8][16]; - - -void setup() { - // ЛЕНТА - FastLED.addLeds(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/; - FastLED.setBrightness(BRIGHTNESS); - if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); - FastLED.clear(); - FastLED.show(); - - touch.setStepTimeout(100); - touch.setClickTimeout(500); - - //Serial.begin(9600); - //Serial.println(); - - if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР - currentMode = EEPROM.read(1); - for (byte x = 0; x < MODE_AMOUNT; x++) { - modes[x].Brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) - modes[x].Speed = EEPROM.read(x * 3 + 12); - modes[x].Scale = EEPROM.read(x * 3 + 13); - } - - } -} - -void loop() { - effectsTick(); - buttonTick(); - demo(); -} diff --git a/ArduinoLamp_v1.5/Constants.h b/ArduinoLamp_v1.5/Constants.h deleted file mode 100644 index 427640f..0000000 --- a/ArduinoLamp_v1.5/Constants.h +++ /dev/null @@ -1,36 +0,0 @@ -// ============= НАСТРОЙКИ ============= -// ---------- МАТРИЦА --------- -#define BRIGHTNESS 10 // стандартная маскимальная яркость (0-255) -#define CURRENT_LIMIT 1000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит - -#define WIDTH 8 // ширина матрицы -#define HEIGHT 8 // высота матрицы - -#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB - -#define MATRIX_TYPE 1 // тип матрицы: 0 - зигзаг, 1 - параллельная -#define CONNECTION_ANGLE 1 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний -#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз -// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" -// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ - -#define numHold_Time (1*1000) // время отображения индикатора уровня яркости/скорости/масштаба - -// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= -#define LED_PIN 6 // пин ленты -#define BTN_PIN 2 -#define MODE_AMOUNT 36 //кол-во эффектов -#define NUM_LEDS WIDTH * HEIGHT -#define SEGMENTS 1// диодов в одном "пикселе" (для создания матрицы из кусков ленты) -// ------------------- ТИПЫ -------------------- -CRGB leds[NUM_LEDS]; -GButton touch(BTN_PIN, HIGH_PULL, NORM_OPEN); //если сенсорна кнопка LOW_PULL -struct { - byte Brightness = 10; - byte Speed = 30; - byte Scale = 10; -} modes[MODE_AMOUNT]; //настройки эффекта по умолчанию -#define DEMOTIMELIMIT ( 1 * 20UL * 1000UL) // минуты/секунды/милисекунды время задержка между эффектами -#define RANDOM_DEMO 0 // 0,1 - включить рандомный выбор режима -uint32_t DemTimer = 0UL; // тут будет храниться время следующего переключения эффекта -bool isDemo = false; diff --git a/ArduinoLamp_v1.5/bitmap2.h b/ArduinoLamp_v1.5/bitmap2.h deleted file mode 100644 index 6de330d..0000000 --- a/ArduinoLamp_v1.5/bitmap2.h +++ /dev/null @@ -1,61 +0,0 @@ -static const uint16_t framesArray[6][8][8] PROGMEM = {{ - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xFFDE, 0xF813, 0x0000}, - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, - {0x0000, 0x0000, 0xFF3B, 0xDC90, 0x0000, 0xFF3B, 0x0000, 0x0000}, - {0x0000, 0x0000, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90, 0xFF3B, 0xDC90}, - {0x0000, 0x0000, 0x0000, 0xFF3B, 0xFF3B, 0xFF3B, 0xFF3B, 0x0000}, - {0x0000, 0xF813, 0xF813, 0xFFEE, 0x7EBF, 0x7EBF, 0xFE60, 0x0000}, - {0xFFDE, 0x0000, 0x7EBF, 0x7EBF, 0x7EBF, 0x7EBF, 0x6354, 0xC59A}, - {0x0000, 0x0000, 0xC2F4, 0x0000, 0x0000, 0xDC90, 0x0000, 0x0000} - }, - { - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xFFDE, 0xF813, 0x0000}, - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, - {0x0000, 0x0000, 0xFF3B, 0xDC90, 0x0000, 0xFF3B, 0x0000, 0x0000}, - {0x0000, 0x0000, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90, 0xFF3B, 0xDC90}, - {0x0000, 0xF813, 0xF813, 0xFF3B, 0xFF3B, 0xFF3B, 0xFF3B, 0x0000}, - {0xFFDE, 0x0000, 0xF813, 0xFFEE, 0x7EBF, 0x7EBF, 0xFE60, 0xFFDE}, - {0x0000, 0xC2F4, 0x7EBF, 0x7EBF, 0x7EBF, 0x7EBF, 0x6354, 0x0000}, - {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDC90, 0x0000} - }, - { - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xFFDE, 0x0000}, - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, - {0x0000, 0x0000, 0xDC90, 0xFF3B, 0xDC90, 0x0000, 0xFF3B, 0x0000}, - {0x0000, 0x0000, 0xDC90, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90, 0xFF3B}, - {0x0000, 0x0000, 0x0000, 0xDC90, 0xFF3B, 0xFF3B, 0xFF3B, 0x0000}, - {0x0000, 0x0000, 0xF813, 0xF813, 0xFFEE, 0x7EBF, 0x6354, 0x0000}, - {0x0000, 0x0000, 0xF813, 0xFFDE, 0x7EBF, 0x7EBF, 0x6354, 0x0000}, - {0x0000, 0x0000, 0x0000, 0xDC90, 0xDC90, 0xC2F4, 0x0000, 0x0000} - }, - { - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0x0000}, - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, - {0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xDC90, 0x0000, 0x0000}, - {0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90}, - {0x0000, 0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xFF3B, 0x0000}, - {0x0000, 0x0000, 0x7EBF, 0xF813, 0xF813, 0xFFEE, 0x6354, 0x0000}, - {0x0000, 0x0000, 0x7EBF, 0x7EBF, 0xF813, 0xF813, 0xFFDE, 0x0000}, - {0x0000, 0x0000, 0xDC90, 0x0000, 0x0000, 0xC2F4, 0x0000, 0x0000} - }, - { - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0x0000}, - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, - {0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xDC90, 0x0000, 0x0000}, - {0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90}, - {0x0000, 0x0000, 0x0000, 0xDC90, 0xDC90, 0xFF3B, 0xFF3B, 0x0000}, - {0x0000, 0x0000, 0x7EBF, 0xF813, 0xF813, 0xFFEE, 0x6354, 0xFFDE}, - {0x0000, 0xDC90, 0x7EBF, 0x7EBF, 0x7EBF, 0xF813, 0xF813, 0x0000}, - {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xC2F4, 0x0000} - }, - { - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xFFDE, 0x0000}, - {0x0000, 0x0000, 0x0000, 0xF813, 0xF813, 0xF813, 0xF813, 0xF813}, - {0x0000, 0x0000, 0xDC90, 0xFF3B, 0xDC90, 0x0000, 0xFF3B, 0x0000}, - {0x0000, 0x0000, 0xDC90, 0xFF3B, 0xFF3B, 0xDC90, 0xDC90, 0xFF3B}, - {0x0000, 0x0000, 0x0000, 0xDC90, 0xFF3B, 0xFF3B, 0xFF3B, 0x0000}, - {0x0000, 0x0000, 0xF813, 0xF813, 0xFFEE, 0x7EBF, 0x6354, 0x0000}, - {0x0000, 0x0000, 0xF813, 0xFFDE, 0x7EBF, 0x7EBF, 0x6354, 0x0000}, - {0x0000, 0x0000, 0x0000, 0xDC90, 0xDC90, 0xC2F4, 0x0000, 0x0000} - } -}; diff --git a/ArduinoLamp_v1.5/button.ino b/ArduinoLamp_v1.5/button.ino deleted file mode 100644 index 52aa994..0000000 --- a/ArduinoLamp_v1.5/button.ino +++ /dev/null @@ -1,93 +0,0 @@ -boolean brightDirection, speedDirection, scaleDirection; - -void buttonTick() { - touch.tick(); - - if (touch.isSingle()) { - { - if (ONflag) { - ONflag = false; - changePower(); - } else { - ONflag = true; - changePower(); - } - } - } - - if (ONflag) { // если включено - if (touch.isDouble()) { - if (++currentMode >= MODE_AMOUNT) currentMode = 0; - FastLED.setBrightness(modes[currentMode].Brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - if (touch.isTriple()) { - if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; - FastLED.setBrightness(modes[currentMode].Brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - if (touch.hasClicks()) - if (touch.getClicks() == 5) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров - if (EEPROM.read(0) != 102) EEPROM.write(0, 102); - if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект - for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов - if (EEPROM.read(x * 3 + 11) != modes[x].Brightness) EEPROM.write(x * 3 + 11, modes[x].Brightness); - if (EEPROM.read(x * 3 + 12) != modes[x].Speed) EEPROM.write(x * 3 + 12, modes[x].Speed); - if (EEPROM.read(x * 3 + 13) != modes[x].Scale) EEPROM.write(x * 3 + 13, modes[x].Scale); - } - // индикация сохранения - ONflag = false; - changePower(); - delay(200); - ONflag = true; - changePower(); - } - else if (touch.getClicks() == 4) { // если было четырёхкратное нажатие на кнопку, то переключаем демо - isDemo = !isDemo; - DemTimer = 0UL; - } - - - if (touch.isHolded()) { // изменение яркости при удержании кнопки - brightDirection = !brightDirection; - numHold = 1; - } - - if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки - speedDirection = !speedDirection; - numHold = 2; - } - - if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки - scaleDirection = !scaleDirection; - numHold = 3; - } - - if (touch.isStep()) { - if (numHold != 0) numHold_Timer = millis(); loadingFlag = true; - switch (numHold) { - case 1: - modes[currentMode].Brightness = constrain(modes[currentMode].Brightness + (modes[currentMode].Brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , 255); - break; - case 2: - modes[currentMode].Speed = constrain(modes[currentMode].Speed + (modes[currentMode].Speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); - break; - - case 3: - modes[currentMode].Scale = constrain(modes[currentMode].Scale + (modes[currentMode].Scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); - break; - } - } - if ((millis() - numHold_Timer) > numHold_Time) { - numHold = 0; - numHold_Timer = millis(); - } - FastLED.setBrightness(modes[currentMode].Brightness); - } -} diff --git a/ArduinoLamp_v1.5/effectTicker.ino b/ArduinoLamp_v1.5/effectTicker.ino deleted file mode 100644 index efb4d27..0000000 --- a/ArduinoLamp_v1.5/effectTicker.ino +++ /dev/null @@ -1,108 +0,0 @@ -uint32_t effTimer; -byte ind; -void effectsTick() { - { - if (ONflag && millis() - effTimer >= ((currentMode < 6 || currentMode > 21) ? modes[currentMode].Speed : 50) ) { - effTimer = millis(); switch (currentMode) { - //|номер |название функции эффекта |тоже надо| - case 0 : sparklesRoutine(); break; - case 1 : fireRoutine(); break; - case 2 : rainbowVertical(); break; - case 3 : rainbowHorizontal(); break; - case 4 : rainbowDiagonalRoutine(); break; - case 5 : WaveRoutine(); break; - case 6 : BBallsRoutine(); break; - case 7 : SinusoidRoutine(); break; - case 8 : MetaBallsRoutine(); break; - case 9 : PrismataRoutine(); break; - case 10: madnessNoise(); break; - case 11: cloudNoise(); break; - case 12: lavaNoise(); break; - case 13: plasmaNoise(); break; - case 14: rainbowNoise(); break; - case 15: rainbowStripeNoise(); break; - case 16: zebraNoise(); break; - case 17: forestNoise(); break; - case 18: oceanNoise(); break; - case 19: heatNoise(); break; - case 20: smokeNoise(); break; - case 21: lavLampNoise(); break; - case 22: colorRoutine(); break; - case 23: colorsRoutine(); break; - case 24: RainRoutine(); break; - case 25: stormRoutine2(true); break; - case 26: stormRoutine2(false); break; - case 27: ballRoutine(); break; - case 28: ballsRoutine(); break; - case 29: fire2012WithPalette(); break; - case 30: lightersRoutine(); break; - case 31: pulseRoutine(1); break; - case 32: ringsRoutine(); break; - case 33: starRoutine(); break; - case 34: MunchRoutine(); break; - - } - switch (numHold) { // индикатор уровня яркости/скорости/масштаба - case 1: - ind = sqrt(modes[currentMode].Brightness + 1); - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) drawPixelXY(y, 0, CHSV(10, 255, 255)); - else drawPixelXY(y, 0, 0); - } - break; - case 2: - ind = sqrt(modes[currentMode].Speed + 1); - for (byte y = 0; y <= HEIGHT ; y++) { - if (ind <= y) drawPixelXY(y, 0, CHSV(100, 255, 255)); - else drawPixelXY(y, 0, 0); - } - break; - case 3: - ind = sqrt(modes[currentMode].Scale + 1); - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) drawPixelXY(y, 0, CHSV(150, 255, 255)); - else drawPixelXY(y, 0, 0); - } - break; - - } - FastLED.show(); - } - } -} - -void changePower() { // плавное включение/выключение - if (ONflag) { - effectsTick(); - for (int i = 0; i < modes[currentMode].Brightness; i += 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.setBrightness(modes[currentMode].Brightness); - delay(2); - FastLED.show(); - } else { - effectsTick(); - for (int i = modes[currentMode].Brightness; i > 8; i -= 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.clear(); - delay(2); - FastLED.show(); - } -} - -void demo() { - if (isDemo && ONflag && millis() >= DemTimer) { - if (RANDOM_DEMO) - currentMode = random8(MODE_AMOUNT); // если нужен следующий случайный эффект - else - currentMode = currentMode + 1U < MODE_AMOUNT ? currentMode + 1U : 0U; // если нужен следующий по списку эффект - FastLED.clear(); - DemTimer = millis() + DEMOTIMELIMIT; - loadingFlag = true; - } -} diff --git a/ArduinoLamp_v1.5/effects.ino b/ArduinoLamp_v1.5/effects.ino deleted file mode 100644 index 02b7a21..0000000 --- a/ArduinoLamp_v1.5/effects.ino +++ /dev/null @@ -1,2063 +0,0 @@ -// ================================= ЭФФЕКТЫ ==================================== -uint8_t wrapX(int8_t x) { - return (x + WIDTH) % WIDTH; -} -uint8_t wrapY(int8_t y) { - return (y + HEIGHT) % HEIGHT; -} -uint8_t deltaHue, deltaHue2; // ещё пара таких же, когда нужно много -uint8_t step; // какой-нибудь счётчик кадров или постедовательностей операций -uint8_t pcnt; -uint8_t line[WIDTH]; -uint8_t deltaValue; // просто повторно используемая переменная -#define NUM_LAYERSMAX 2 -uint8_t noise3d[NUM_LAYERSMAX][WIDTH][HEIGHT]; -uint8_t shiftHue[HEIGHT]; -uint8_t shiftValue[HEIGHT]; - -// палитра для типа реалистичного водопада (если ползунок Масштаб выставить на 100) -extern const TProgmemRGBPalette16 WaterfallColors_p FL_PROGMEM = {0x000000, 0x060707, 0x101110, 0x151717, 0x1C1D22, 0x242A28, 0x363B3A, 0x313634, 0x505552, 0x6B6C70, 0x98A4A1, 0xC1C2C1, 0xCACECF, 0xCDDEDD, 0xDEDFE0, 0xB2BAB9}; -// добавлено изменение текущей палитры (используется во многих эффектах ниже для бегунка Масштаб) -const TProgmemRGBPalette16 *palette_arr[] = { - &PartyColors_p, - &OceanColors_p, - &LavaColors_p, - &HeatColors_p, - &WaterfallColors_p, - &CloudColors_p, - &ForestColors_p, - &RainbowColors_p, - &RainbowStripeColors_p -}; -const TProgmemRGBPalette16 *curPalette = palette_arr[0]; -void setCurrentPalette() { - if (modes[currentMode].Scale > 100U) modes[currentMode].Scale = 100U; // чтобы не было проблем при прошивке без очистки памяти - curPalette = palette_arr[(uint8_t)(modes[currentMode].Scale / 100.0F * ((sizeof(palette_arr) / sizeof(TProgmemRGBPalette16 *)) - 0.01F))]; -} -CRGB _pulse_color; -void blurScreen(fract8 blur_amount, CRGB *LEDarray = leds) -{ - blur2d(LEDarray, WIDTH, HEIGHT, blur_amount); -} -void dimAll(uint8_t value) { - for (uint16_t i = 0; i < NUM_LEDS; i++) { - leds[i].nscale8(value); //fadeToBlackBy - } -} -void drawPixelXYF(float x, float y, CRGB color) -{ - // extract the fractional parts and derive their inverses - uint8_t xx = (x - (int)x) * 255, yy = (y - (int)y) * 255, ix = 255 - xx, iy = 255 - yy; - // calculate the intensities for each affected pixel - #define WU_WEIGHT(a,b) ((uint8_t) (((a)*(b)+(a)+(b))>>8)) - uint8_t wu[4] = {WU_WEIGHT(ix, iy), WU_WEIGHT(xx, iy), - WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)}; - // multiply the intensities by the colour, and saturating-add them to the pixels - for (uint8_t i = 0; i < 4; i++) { - int16_t xn = x + (i & 1), yn = y + ((i >> 1) & 1); - CRGB clr = getPixColorXY(xn, yn); - clr.r = qadd8(clr.r, (color.r * wu[i]) >> 8); - clr.g = qadd8(clr.g, (color.g * wu[i]) >> 8); - clr.b = qadd8(clr.b, (color.b * wu[i]) >> 8); - drawPixelXY(xn, yn, clr); - } -} - -void drawCircleF(float x0, float y0, float radius, CRGB color){ - float x = 0, y = radius, error = 0; - float delta = 1 - 2 * radius; - - while (y >= 0) { - drawPixelXYF(x0 + x, y0 + y, color); - drawPixelXYF(x0 + x, y0 - y, color); - drawPixelXYF(x0 - x, y0 + y, color); - drawPixelXYF(x0 - x, y0 - y, color); - error = 2 * (delta + y) - 1; - if (delta < 0 && error <= 0) { - ++x; - delta += 2 * x + 1; - continue; - } - error = 2 * (delta - x) - 1; - if (delta > 0 && error > 0) { - --y; - delta += 1 - 2 * y; - continue; - } - ++x; - delta += 2 * (x - y); - --y; - } -} - -// --------------------------------- конфетти ------------------------------------ -#define FADE_OUT_SPEED (70U) // скорость затухания -void sparklesRoutine() -{ - for (uint8_t i = 0; i < modes[currentMode].Scale; i++) - { - uint8_t x = random(0U, WIDTH); - uint8_t y = random(0U, HEIGHT); - if (getPixColorXY(x, y) == 0U) - { - leds[XY(x, y)] = CHSV(random(0U, 255U), 255U, 255U); - } - } - fader(FADE_OUT_SPEED); -} -// функция плавного угасания цвета для всех пикселей -void fader(uint8_t step) -{ - for (uint8_t i = 0U; i < WIDTH; i++) - { - for (uint8_t j = 0U; j < HEIGHT; j++) - { - fadePixel(i, j, step); - } - } -} -void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер -{ - int32_t pixelNum = XY(i, j); - if (getPixColor(pixelNum) == 0U) return; - - if (leds[pixelNum].r >= 30U || - leds[pixelNum].g >= 30U || - leds[pixelNum].b >= 30U) - { - leds[pixelNum].fadeToBlackBy(step); - } - else - { - leds[pixelNum] = 0U; - } -} -// -------------------------------------- огонь --------------------------------------------- -#define SPARKLES 0 // вылетающие угольки вкл выкл -//these values are substracetd from the generated values to give a shape to the animation -const unsigned char valueMask[8][16] PROGMEM = { - {0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 }, - {0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 }, - {0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 }, - {0 , 32 , 64 , 128, 128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 128, 64 , 32 , 0 }, - {32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 }, - {64 , 96 , 128, 192, 192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128, 96 , 64 }, - {96 , 128, 160, 255, 255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160, 128, 96 }, - {128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128} -}; - -//these are the hues for the fire, -//should be between 0 (red) to about 25 (yellow) -const unsigned char hueMask[8][16] PROGMEM = { - {25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25 }, - {25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19 }, - {19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16 }, - {13, 13, 5 , 1 , 1 , 5 , 11, 13, 13, 13, 5 , 1 , 1 , 5 , 11, 13 }, - {11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11 }, - {8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 }, - {5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 }, - {1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } -}; -void fireRoutine() { - if (loadingFlag) { - loadingFlag = false; - //FastLED.clear(); - generateLine(); - } - if (pcnt >= 100) { - shiftUp(); - generateLine(); - pcnt = 0; - } - drawFrame(pcnt); - pcnt += 25; -} - -// Случайным образом генерирует следующую линию (matrix row) - -void generateLine() { - for (uint8_t x = 0; x < WIDTH; x++) { - line[x] = random(127, 255); - } -} - -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 - 15; - 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 - 15; - matrixValue[0][newX] = line[newX]; - } -} - -// рисует кадр, интерполируя между 2 "ключевых кадров" -// параметр pcnt - процент интерполяции - -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 - 15; - 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( - modes[currentMode].Scale * 2.5 + 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); - - } - } - } - - //Перавя стрка интерполируется со следующей "next" линией - for (unsigned char x = 0; x < WIDTH; x++) { - uint8_t newX = x; - if (x > 15) newX = x - 15; - CRGB color = CHSV( - modes[currentMode].Scale * 2.5 + 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; - } -} -// ---------------------------------------- радуга ------------------------------------------ -byte hue; byte hue2; -void rainbowVertical() { - hue += 2; - for (byte j = 0; j < HEIGHT; j++) { - CHSV thisColor = CHSV((byte)(hue + j * modes[currentMode].Scale), 255, 255); - for (byte i = 0; i < WIDTH; i++) - drawPixelXY(i, j, thisColor); - } -} -void rainbowHorizontal() { - hue += 2; - for (byte i = 0; i < WIDTH; i++) { - CHSV thisColor = CHSV((byte)(hue + i * modes[currentMode].Scale), 255, 255); - for (byte j = 0; j < HEIGHT; j++) - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; - } -} -void rainbowDiagonalRoutine() -{ - if (loadingFlag) - { - loadingFlag = false; - FastLED.clear(); - } - - hue += 8; - for (uint8_t i = 0U; i < WIDTH; i++) - { - for (uint8_t j = 0U; j < HEIGHT; j++) - { - float twirlFactor = 3.0F * (modes[currentMode].Scale / 100.0F); // на сколько оборотов будет закручена матрица, [0..3] - CRGB thisColor = CHSV((uint8_t)(hue + ((float)WIDTH / HEIGHT * i + j * twirlFactor) * ((float)255 / maxDim)), 255, 255); - drawPixelXY(i, j, thisColor); - } - } -} -// ---------------------------------------- ЦВЕТА ----------------------------- -void colorsRoutine() { - hue += modes[currentMode].Scale; - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(hue, 255, 255); - } -} - -// --------------------------------- ЦВЕТ ------------------------------------ -void colorRoutine() { - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(modes[currentMode].Scale * 2.5, modes[currentMode].Speed * 2.5, 255); - } -} - -// ------------------------------ снегопад 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, modes[currentMode].Scale) == 0)) - drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); - else - drawPixelXY(x, HEIGHT - 1, 0x000000); - } - } -*/ -// ------------------------------ МАТРИЦА ------------------------------ -/*void matrixRoutine() { - for (byte x = 0; x < WIDTH; x++) { - // заполняем случайно верхнюю строку - uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); - if (thisColor == 0) - drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, modes[currentMode].Scale) == 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 whiteLamp() { - for (byte y = 0; y < (HEIGHT / 2); y++) { - CHSV color = CHSV(100, 1, constrain(modes[currentMode].Brightness - (long)modes[currentMode].Speed * modes[currentMode].Brightness / 255 * y / 2, 1, 255)); - for (byte x = 0; x < WIDTH; x++) { - drawPixelXY(x, y + 8, color); - drawPixelXY(x, 7 - y, color); - } - } - }*/ -//--------------------------Шторм,Метель------------------------- -#define e_sns_DENSE (32U) // плотность снега - меньше = плотнее -void stormRoutine2(bool isColored) -{ - // заполняем головами комет - uint8_t Saturation = 0U; // цвет хвостов - uint8_t e_TAIL_STEP = 127U; // длина хвоста - if (isColored) - Saturation = modes[currentMode].Scale * 2.55; - else - { - e_TAIL_STEP = 255U - modes[currentMode].Scale * 2.55; - } - for (int8_t x = 0U; x < WIDTH - 1U; x++) // fix error i != 0U - { - if (!random8(e_sns_DENSE) && - !getPixColorXY(wrapX(x), HEIGHT - 1U) && - !getPixColorXY(wrapX(x + 1U), HEIGHT - 1U) && - !getPixColorXY(wrapX(x - 1U), HEIGHT - 1U)) - { - drawPixelXY(x, HEIGHT - 1U, CHSV(random8(), Saturation, random8(64U, 255U))); - } - } - - // сдвигаем по диагонали - for (int8_t y = 0U; y < HEIGHT - 1U; y++) - { - for (int8_t x = 0; x < WIDTH; x++) - { - drawPixelXY(wrapX(x + 1U), y, getPixColorXY(x, y + 1U)); - } - } - - // уменьшаем яркость верхней линии, формируем "хвосты" - for (int8_t i = 0U; i < WIDTH; i++) - { - fadePixel(i, HEIGHT - 1U, e_TAIL_STEP); - } -} -//------------------Синусоид3----------------------- -//Stefan Petrick -void SinusoidRoutine() -{ - const uint8_t semiHeightMajor = HEIGHT / 2 + (HEIGHT % 2); - const uint8_t semiWidthMajor = WIDTH / 2 + (WIDTH % 2) ; - float e_s3_Speed = 0.004 * modes[currentMode].Speed + 0.015; // Speed of the movement along the Lissajous curves - float e_s3_size = 3 * (float)modes[currentMode].Scale / 100.0 + 2; // amplitude of the curves - - float time_shift = float(millis() % (uint32_t)(30000 * (1.0 / ((float)modes[currentMode].Speed / 255)))); - - for (uint8_t y = 0; y < HEIGHT; y++) { - for (uint8_t x = 0; x < WIDTH; x++) { - CRGB color; - - float cx = y + float(e_s3_size * (sinf (float(e_s3_Speed * 0.003 * time_shift)))) - semiHeightMajor; // the 8 centers the middle on a 16x16 - float cy = x + float(e_s3_size * (cosf (float(e_s3_Speed * 0.0022 * time_shift)))) - semiWidthMajor; - float v = 127 * (1 + sinf ( sqrtf ( ((cx * cx) + (cy * cy)) ) )); - color.r = v; - - cx = x + float(e_s3_size * (sinf (e_s3_Speed * float(0.0021 * time_shift)))) - semiWidthMajor; - cy = y + float(e_s3_size * (cosf (e_s3_Speed * float(0.002 * time_shift)))) - semiHeightMajor; - v = 127 * (1 + sinf ( sqrtf ( ((cx * cx) + (cy * cy)) ) )); - color.b = v; - - cx = x + float(e_s3_size * (sinf (e_s3_Speed * float(0.0041 * time_shift)))) - semiWidthMajor; - cy = y + float(e_s3_size * (cosf (e_s3_Speed * float(0.0052 * time_shift)))) - semiHeightMajor; - v = 127 * (1 + sinf ( sqrtf ( ((cx * cx) + (cy * cy)) ) )); - color.g = v; - drawPixelXY(x, y, color); - } - } -} -//-------------------------Метаболз------------------- -//Stefan Petrick -void MetaBallsRoutine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - - float Speed = modes[currentMode].Speed / 127.0; - - // get some 2 random moving points - uint8_t x2 = inoise8(millis() * Speed, 25355, 685 ) / WIDTH; - uint8_t y2 = inoise8(millis() * Speed, 355, 11685 ) / HEIGHT; - - uint8_t x3 = inoise8(millis() * Speed, 55355, 6685 ) / WIDTH; - uint8_t y3 = inoise8(millis() * Speed, 25355, 22685 ) / HEIGHT; - - // and one Lissajou function - uint8_t x1 = beatsin8(23 * Speed, 0, 15); - uint8_t y1 = beatsin8(28 * Speed, 0, 15); - - for (uint8_t y = 0; y < HEIGHT; y++) { - for (uint8_t x = 0; x < WIDTH; x++) { - - // calculate distances of the 3 points from actual pixel - // and add them together with weightening - uint8_t dx = abs(x - x1); - uint8_t dy = abs(y - y1); - uint8_t dist = 2 * sqrt((dx * dx) + (dy * dy)); - - dx = abs(x - x2); - dy = abs(y - y2); - dist += sqrt((dx * dx) + (dy * dy)); - - dx = abs(x - x3); - dy = abs(y - y3); - dist += sqrt((dx * dx) + (dy * dy)); - - // inverse result - //byte color = modes[currentMode].Speed * 10 / dist; - byte color = 1000U / dist; - - // map color between thresholds - if (color > 0 and color < 60) { - if (modes[currentMode].Scale == 100U) - drawPixelXY(x, y, CHSV(color * 9, 255, 255));// это оригинальный цвет эффекта - else - drawPixelXY(x, y, ColorFromPalette(*curPalette, color * 9)); - } else { - if (modes[currentMode].Scale == 100U) - drawPixelXY(x, y, CHSV(0, 255, 255)); // в оригинале центральный глаз почему-то крвсный - else - drawPixelXY(x, y, ColorFromPalette(*curPalette, 0U)); - } - // show the 3 points, too - drawPixelXY(x1, y1, CRGB(255, 255, 255)); - drawPixelXY(x2, y2, CRGB(255, 255, 255)); - drawPixelXY(x3, y3, CRGB(255, 255, 255)); - } - } -} - -// ============= ЭФФЕКТ ВОЛНЫ =============== -// https://github.com/pixelmatix/aurora/blob/master/PatternWave.h -// Адаптация от (c) SottNick - -byte waveThetaUpdate = 0; -byte waveThetaUpdateFrequency = 0; -byte waveTheta = 0; - -byte hueUpdate = 0; -byte hueUpdateFrequency = 0; -// byte hue = 0; будем использовать сдвиг от эффектов Радуга - -byte waveRotation = 0; -uint8_t waveScale = 256 / WIDTH; -uint8_t waveCount = 1; - -void WaveRoutine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - - //waveRotation = random(0, 4);// теперь вместо этого регулятор Масштаб - waveRotation = (modes[currentMode].Scale - 1) / 25U; - //waveCount = random(1, 3);// теперь вместо этого чётное/нечётное у регулятора Скорость - waveCount = modes[currentMode].Speed % 2; - //waveThetaUpdateFrequency = random(1, 2); - //hueUpdateFrequency = random(1, 6); - } - - dimAll(254); - - int n = 0; - - switch (waveRotation) { - case 0: - for (uint8_t x = 0; x < WIDTH; x++) { - n = quadwave8(x * 2 + waveTheta) / waveScale; - drawPixelXY(x, n, ColorFromPalette(*curPalette, hue + x)); - if (waveCount != 1) - drawPixelXY(x, HEIGHT - 1 - n, ColorFromPalette(*curPalette, hue + x)); - } - break; - - case 1: - for (uint8_t y = 0; y < HEIGHT; y++) { - n = quadwave8(y * 2 + waveTheta) / waveScale; - drawPixelXY(n, y, ColorFromPalette(*curPalette, hue + y)); - if (waveCount != 1) - drawPixelXY(WIDTH - 1 - n, y, ColorFromPalette(*curPalette, hue + y)); - } - break; - - case 2: - for (uint8_t x = 0; x < WIDTH; x++) { - n = quadwave8(x * 2 - waveTheta) / waveScale; - drawPixelXY(x, n, ColorFromPalette(*curPalette, hue + x)); - if (waveCount != 1) - drawPixelXY(x, HEIGHT - 1 - n, ColorFromPalette(*curPalette, hue + x)); - } - break; - - case 3: - for (uint8_t y = 0; y < HEIGHT; y++) { - n = quadwave8(y * 2 - waveTheta) / waveScale; - drawPixelXY(n, y, ColorFromPalette(*curPalette, hue + y)); - if (waveCount != 1) - drawPixelXY(WIDTH - 1 - n, y, ColorFromPalette(*curPalette, hue + y)); - } - break; - } - - - if (waveThetaUpdate >= waveThetaUpdateFrequency) { - waveThetaUpdate = 0; - waveTheta++; - } - else { - waveThetaUpdate++; - } - - if (hueUpdate >= hueUpdateFrequency) { - hueUpdate = 0; - hue++; - } - else { - hueUpdate++; - } - - blurScreen(10); // @Palpalych советует делать размытие. вот в этом эффекте его явно не хватает... -} - -//-------------------------Блуждающий кубик----------------------- -#define RANDOM_COLOR (1U) // случайный цвет при отскоке -int16_t coordB[2U]; -int8_t vectorB[2U]; -CRGB ballColor; -//int8_t deltaValue; //ballSize; - -void ballRoutine() -{ - if (loadingFlag) - { - loadingFlag = false; - //FastLED.clear(); - - for (uint8_t i = 0U; i < 2U; i++) - { - coordB[i] = WIDTH / 2 * 10; - vectorB[i] = random(8, 20); - } - deltaValue = map(modes[currentMode].Scale * 2.55, 0U, 255U, 2U, max((uint8_t)min(WIDTH, HEIGHT) / 3, 2)); - ballColor = CHSV(random(0, 9) * 28, 255U, 255U); - // _pulse_color = CHSV(random(0, 9) * 28, 255U, 255U); - } - - // if (!(modes[currentMode].Scale & 0x01)) - // { - // hue += (modes[currentMode].Scale - 1U) % 11U * 8U + 1U; - - // ballColor = CHSV(hue, 255U, 255U); - // } - - if ((modes[currentMode].Scale & 0x01)) - for (uint8_t i = 0U; i < deltaValue; i++) - for (uint8_t j = 0U; j < deltaValue; j++) - leds[XY(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = _pulse_color; - - for (uint8_t i = 0U; i < 2U; 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, 255U, 255U); // if (RANDOM_COLOR && (modes[currentMode].Scale & 0x01)) - //vectorB[i] += random(0, 6) - 3; - } - } - if (coordB[0U] > (int16_t)((WIDTH - deltaValue) * 10)) - { - coordB[0U] = (WIDTH - deltaValue) * 10; - vectorB[0U] = -vectorB[0U]; - if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U); - //vectorB[0] += random(0, 6) - 3; - } - if (coordB[1U] > (int16_t)((HEIGHT - deltaValue) * 10)) - { - coordB[1U] = (HEIGHT - deltaValue) * 10; - vectorB[1U] = -vectorB[1U]; - if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U); - //vectorB[1] += random(0, 6) - 3; - } - - // if (modes[currentMode].Scale & 0x01) - // dimAll(135U); - // dimAll(255U - (modes[currentMode].Scale - 1U) % 11U * 24U); - //else - FastLED.clear(); - - for (uint8_t i = 0U; i < deltaValue; i++) - for (uint8_t j = 0U; j < deltaValue; j++) - leds[XY(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = ballColor; -} - -//-------------------Светлячки со шлейфом---------------------------- -#define BALLS_AMOUNT (3U) // количество "шариков" -#define CLEAR_PATH (1U) // очищать путь -#define TRACK_STEP (130U) // длина хвоста шарика (чем больше цифра, тем хвост короче) -int16_t coord[BALLS_AMOUNT][2U]; -int8_t vector[BALLS_AMOUNT][2U]; -CRGB ballColors[BALLS_AMOUNT]; -void ballsRoutine() -{ - if (loadingFlag) - { - loadingFlag = false; - - for (uint8_t j = 0U; j < BALLS_AMOUNT; j++) - { - int8_t sign; - // забиваем случайными данными - coord[j][0U] = WIDTH / 2 * 10; - random(0, 2) ? sign = 1 : sign = -1; - vector[j][0U] = random(4, 15) * sign; - coord[j][1U] = HEIGHT / 2 * 10; - random(0, 2) ? sign = 1 : sign = -1; - vector[j][1U] = random(4, 15) * sign; - //ballColors[j] = CHSV(random(0, 9) * 28, 255U, 255U); - // цвет зависит от масштаба - ballColors[j] = CHSV((modes[currentMode].Scale * (j + 1)) % 256U, 255U, 255U); - } - } - - fader(TRACK_STEP); - - - // движение шариков - for (uint8_t j = 0U; j < BALLS_AMOUNT; j++) - { - // движение шариков - for (uint8_t i = 0U; i < 2U; i++) - { - coord[j][i] += vector[j][i]; - if (coord[j][i] < 0) - { - coord[j][i] = 0; - vector[j][i] = -vector[j][i]; - } - } - - if (coord[j][0U] > (int16_t)((WIDTH - 1) * 10)) - { - coord[j][0U] = (WIDTH - 1) * 10; - vector[j][0U] = -vector[j][0U]; - } - if (coord[j][1U] > (int16_t)((HEIGHT - 1) * 10)) - { - coord[j][1U] = (HEIGHT - 1) * 10; - vector[j][1U] = -vector[j][1U]; - } - leds[XY(coord[j][0U] / 10, coord[j][1U] / 10)] = ballColors[j]; - } -} - -//-------------------Водопад------------------------------ -#define COOLINGNEW 32 -#define SPARKINGNEW 80 -/*extern const TProgmemRGBPalette16 WaterfallColors4in1_p FL_PROGMEM = {CRGB::Black, CRGB::DarkSlateGray, CRGB::DimGray, CRGB::LightSlateGray, CRGB::DimGray, CRGB::DarkSlateGray, CRGB::Silver, CRGB::Lavender, CRGB::Silver, CRGB::Azure, CRGB::LightGrey, CRGB::GhostWhite, CRGB::Silver, CRGB::White, CRGB::RoyalBlue}; - void fire2012WithPalette4in1() { - uint8_t rCOOLINGNEW = constrain((uint16_t)(modes[currentMode].Scale % 16) * 32 / HEIGHT + 16, 1, 255) ; - // Array of temperature readings at each simulation cell - //static byte heat[WIDTH][HEIGHT]; будет noise3d[0][WIDTH][HEIGHT] - - for (uint8_t x = 0; x < WIDTH; x++) { - // Step 1. Cool down every cell a little - for (unsigned int i = 0; i < HEIGHT; i++) { - //noise3d[0][x][i] = qsub8(noise3d[0][x][i], random8(0, ((rCOOLINGNEW * 10) / HEIGHT) + 2)); - noise3d[0][x][i] = qsub8(noise3d[0][x][i], random8(0, rCOOLINGNEW)); - } - - // Step 2. Heat from each cell drifts 'up' and diffuses a little - for (int k = HEIGHT - 1; k >= 2; k--) { - noise3d[0][x][k] = (noise3d[0][x][k - 1] + noise3d[0][x][k - 2] + noise3d[0][x][k - 2]) / 3; - } - - // Step 3. Randomly ignite new 'sparks' of heat near the bottom - if (random8() < SPARKINGNEW) { - int y = random8(2); - noise3d[0][x][y] = qadd8(noise3d[0][x][y], random8(160, 255)); - } - - // Step 4. Map from heat cells to LED colors - for (unsigned int j = 0; j < HEIGHT; j++) { - // Scale the heat value from 0-255 down to 0-240 - // for best results with color palettes. - byte colorindex = scale8(noise3d[0][x][j], 240); - if (modes[currentMode].Scale < 16) { // Lavafall - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(LavaColors_p, colorindex); - } else if (modes[currentMode].Scale < 32) { // Firefall - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(HeatColors_p, colorindex); - } else if (modes[currentMode].Scale < 48) { // Waterfall - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(WaterfallColors4in1_p, colorindex); - } else if (modes[currentMode].Scale < 64) { // Skyfall - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(CloudColors_p, colorindex); - } else if (modes[currentMode].Scale < 80) { // Forestfall - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(ForestColors_p, colorindex); - } else if (modes[currentMode].Scale < 96) { // Rainbowfall - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(RainbowColors_p, colorindex); - } else { // Aurora - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(RainbowStripeColors_p, colorindex); - } - } - } - }*/ -void fire2012WithPalette() { - // bool fire_water = modes[currentMode].Scale <= 50; - // uint8_t COOLINGNEW = fire_water ? modes[currentMode].Scale * 2 + 20 : (100 - modes[currentMode].Scale ) * 2 + 20 ; - // uint8_t COOLINGNEW = modes[currentMode].Scale * 2 + 20 ; - // Array of temperature readings at each simulation cell - //static byte heat[WIDTH][HEIGHT]; будет noise3d[0][WIDTH][HEIGHT] - - for (uint8_t x = 0; x < WIDTH; x++) { - // Step 1. Cool down every cell a little - for (int i = 0; i < HEIGHT; i++) { - noise3d[0][x][i] = qsub8(noise3d[0][x][i], random8(0, ((COOLINGNEW * 10) / HEIGHT) + 2)); - } - - // Step 2. Heat from each cell drifts 'up' and diffuses a little - for (int k = HEIGHT - 1; k >= 2; k--) { - noise3d[0][x][k] = (noise3d[0][x][k - 1] + noise3d[0][x][k - 2] + noise3d[0][x][k - 2]) / 3; - } - - // Step 3. Randomly ignite new 'sparks' of heat near the bottom - if (random8() < SPARKINGNEW) { - int y = random8(2); - noise3d[0][x][y] = qadd8(noise3d[0][x][y], random8(160, 255)); - } - - // Step 4. Map from heat cells to LED colors - for (int j = 0; j < HEIGHT; j++) { - // Scale the heat value from 0-255 down to 0-240 - // for best results with color palettes. - byte colorindex = scale8(noise3d[0][x][j], 240); - if (modes[currentMode].Scale == 100) - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(WaterfallColors_p, colorindex); - else - leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(CRGBPalette16( CRGB::Black, CHSV(modes[currentMode].Scale * 2.57, 255U, 255U) , CHSV(modes[currentMode].Scale * 2.57, 128U, 255U) , CRGB::White), colorindex);// 2.57 вместо 2.55, потому что 100 для белого цвета - //leds[XY(x, (HEIGHT - 1) - j)] = ColorFromPalette(fire_water ? HeatColors_p : OceanColors_p, colorindex); - } - } -} -//-----------------------Недо огонь--------------------------------------- -//stepko -#define FOR_i(from, to) for(int i = (from); i < (to); i++) -#define FOR_j(from, to) for(int j = (from); j < (to); j++) -unsigned int counter; -int STEP = modes[currentMode].Scale; //нужно виставить номер эффекта с пометкой false или любое число если не хотите Белого огня -void noiseWave(bool isColored) { -if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - FastLED.clear(); - - FOR_i(0, WIDTH) { - byte thisVal = sin8(STEP*counter*i); - byte thisMax = map(thisVal, 0, 255, 0, HEIGHT); - if (isColored) { - FOR_j(0, thisMax) { - CRGB color = (CRGB)ColorFromPalette(*curPalette, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND); - drawPixelXY(i, j, color);}} - else { - STEP = modes[currentMode].Scale; - FOR_j(0, thisMax) { - drawPixelXY(i, j, ColorFromPalette(WaterfallColors_p, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND)); - } - } - } - counter += 1; -} - -//----------------Gifка---------------------- -byte frameNum; - void animation1() { - frameNum++; - if (frameNum >= (framesArray)) frameNum = 0; - for (byte i = 0; i < 8; i++) - for (byte j = 0; j < 8; j++) - drawPixelXY(i, j, gammaCorrection(expandColor(pgm_read_word(&framesArray[frameNum][HEIGHT - j - 1][i])))); - } - - - -// -------------- эффект пульс ------------ -// Stefan Petrick's PULSE Effect mod by PalPalych for GyverLamp - -void drawCircle(int16_t x0, int16_t y0, uint16_t radius, const CRGB & color) { - int a = radius, b = 0; - int radiusError = 1 - a; - - if (radius == 0) { - drawPixelXY(x0, y0, color); - return; - } - - while (a >= b) { - drawPixelXY(a + x0, b + y0, color); - drawPixelXY(b + x0, a + y0, color); - drawPixelXY(-a + x0, b + y0, color); - drawPixelXY(-b + x0, a + y0, color); - drawPixelXY(-a + x0, -b + y0, color); - drawPixelXY(-b + x0, -a + y0, color); - drawPixelXY(a + x0, -b + y0, color); - drawPixelXY(b + x0, -a + y0, color); - b++; - if (radiusError < 0) - radiusError += 2 * b + 1; - else - { - a--; - radiusError += 2 * (b - a + 1); - } - } -} - -CRGBPalette16 palette; -uint8_t currentRadius = 4; -uint8_t pulse_centerX = random8(WIDTH - 5U) + 3U; -uint8_t pulse_centerY = random8(HEIGHT - 5U) + 3U; -//uint16_t _rc; вроде, не используется -//uint8_t _pulse_hue; заменено на deltaHue из общих переменных -//uint8_t _pulse_hueall; заменено на hue2 из общих переменных -//uint8_t _pulse_delta; заменено на deltaHue2 из общих переменных -//uint8_t pulse_hue; заменено на hue из общих переменных - -void pulseRoutine(uint8_t PMode) { - palette = RainbowColors_p; - const uint8_t limitSteps = 6U; - static const float fadeRate = 0.8; - - dimAll(248U); - uint8_t _sat; - if (step <= currentRadius) { - for (uint8_t i = 0; i < step; i++ ) { - uint8_t _dark = qmul8( 2U, cos8 (128U / (step + 1U) * (i + 1U))) ; - switch (PMode) { - case 1U: // 1 - случайные диски - deltaHue = hue; - _pulse_color = CHSV(deltaHue, 255U, _dark); - break; - case 2U: // 2...17 - перелив цвета дисков - deltaHue2 = modes[currentMode].Scale; - _pulse_color = CHSV(hue2, 255U, _dark); - break; - case 3U: // 18...33 - выбор цвета дисков - deltaHue = modes[currentMode].Scale * 2.55; - _pulse_color = CHSV(deltaHue, 255U, _dark); - break; - case 4U: // 34...50 - дискоцветы - deltaHue += modes[currentMode].Scale; - _pulse_color = CHSV(deltaHue, 255U, _dark); - break; - case 5U: // 51...67 - пузыри цветы - _sat = qsub8( 255U, cos8 (128U / (step + 1U) * (i + 1U))) ; - deltaHue += modes[currentMode].Scale; - _pulse_color = CHSV(deltaHue, _sat, _dark); - break; - case 6U: // 68...83 - выбор цвета пузырей - _sat = qsub8( 255U, cos8 (128U / (step + 1U) * (i + 1U))) ; - deltaHue = modes[currentMode].Scale * 2.55; - _pulse_color = CHSV(deltaHue, _sat, _dark); - break; - case 7U: // 84...99 - перелив цвета пузырей - _sat = qsub8( 255U, cos8 (128U / (step + 1U) * (i + 1U))) ; - deltaHue2 = modes[currentMode].Scale; - _pulse_color = CHSV(hue2, _sat, _dark); - break; - case 8U: // 100 - случайные пузыри - _sat = qsub8( 255U, cos8 (128U / (step + 1U) * (i + 1U))) ; - deltaHue = hue; - _pulse_color = CHSV(deltaHue, _sat, _dark); - break; - } - drawCircle(pulse_centerX, pulse_centerY, i, _pulse_color ); - } - } else { - pulse_centerX = random8(WIDTH - 5U) + 3U; - pulse_centerY = random8(HEIGHT - 5U) + 3U; - hue2 += deltaHue2; - hue = random8(0U, 255U); - currentRadius = random8(3U, 9U); - step = 0; - } - step++; -} -// ============= ЭФФЕКТ CНЕГ/МАТРИЦА/ДОЖДЬ =============== -// от @Shaitan -void RainRoutine() -{ - for (uint8_t x = 0U; x < WIDTH; x++) - { - // заполняем случайно верхнюю строку - CRGB thisColor = getPixColorXY(x, HEIGHT - 1U); - if ((uint32_t)thisColor == 0U) - { - if (random8(0, 50) == 0U) - { - if (modes[currentMode].Scale == 1) drawPixelXY(x, HEIGHT - 1U, CHSV(random(0, 9) * 28, 255U, 255U)); // Радужный дождь - else if (modes[currentMode].Scale >= 100) drawPixelXY(x, HEIGHT - 1U, 0xE0FFFF - 0x101010 * random(0, 4)); // Снег - else - drawPixelXY(x, HEIGHT - 1U, CHSV(modes[currentMode].Scale * 2.4 + random(0, 16), 255, 255)); // Цветной дождь - } - } - else - leds[XY(x, HEIGHT - 1U)] -= CHSV(0, 0, random(96, 128)); - } - // сдвигаем всё вниз - for (uint8_t x = 0U; x < WIDTH; x++) - { - for (uint8_t y = 0U; y < HEIGHT - 1U; y++) - { - drawPixelXY(x, y, getPixColorXY(x, y + 1U)); - } - } -} -// --------------------------- эффект спирали ---------------------- -/* - Aurora: https://github.com/pixelmatix/aurora - https://github.com/pixelmatix/aurora/blob/sm3.0-64x64/PatternSpiro.h - Copyright (c) 2014 Jason Coon - Неполная адаптация SottNick -*/ -byte spirotheta1 = 0; -byte spirotheta2 = 0; -// byte spirohueoffset = 0; // будем использовать переменную сдвига оттенка hue из эффектов Радуга - - -const uint8_t spiroradiusx = WIDTH / 4; -const uint8_t spiroradiusy = HEIGHT / 4; - -const uint8_t spirocenterX = WIDTH / 2-1; -const uint8_t spirocenterY = HEIGHT / 2-1; - -const uint8_t spirominx = spirocenterX - spiroradiusx; -const uint8_t spiromaxx = spirocenterX + spiroradiusx + 1; -const uint8_t spirominy = spirocenterY - spiroradiusy; -const uint8_t spiromaxy = spirocenterY + spiroradiusy + 1; - -uint8_t spirocount = 1; -uint8_t spirooffset = 256 / spirocount; -boolean spiroincrement = false; - -boolean spirohandledChange = false; - -uint8_t mapsin8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) { - uint8_t beatsin = sin8(theta); - uint8_t rangewidth = highest - lowest; - uint8_t Scaledbeat = scale8(beatsin, rangewidth); - uint8_t result = lowest + Scaledbeat; - return result; -} - -uint8_t mapcos8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) { - uint8_t beatcos = cos8(theta); - uint8_t rangewidth = highest - lowest; - uint8_t Scaledbeat = scale8(beatcos, rangewidth); - uint8_t result = lowest + Scaledbeat; - return result; -} - -uint8_t beatcos8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0) -{ - uint8_t beat = beat8(beats_per_minute, timebase); - uint8_t beatcos = cos8(beat + phase_offset); - uint8_t rangewidth = highest - lowest; - uint8_t scaledbeat = scale8(beatcos, rangewidth); - uint8_t result = lowest + scaledbeat; - return result; -} - -void spiroRoutine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - - blurScreen(5); - dimAll(255U - modes[currentMode].Speed / 10); - - boolean change = false; - - for (uint8_t i = 0; i < spirocount; i++) { - uint8_t x = mapsin8(spirotheta1 + i * spirooffset, spirominx, spiromaxx); - uint8_t y = mapcos8(spirotheta1 + i * spirooffset, spirominy, spiromaxy); - - uint8_t x2 = mapsin8(spirotheta2 + i * spirooffset, x - spiroradiusx, x + spiroradiusx); - uint8_t y2 = mapcos8(spirotheta2 + i * spirooffset, y - spiroradiusy, y + spiroradiusy); - - - //CRGB color = ColorFromPalette( PartyColors_p, (hue + i * spirooffset), 128U); // вообще-то палитра должна постоянно меняться, но до адаптации этого руки уже не дошли - //CRGB color = ColorFromPalette(*curPalette, hue + i * spirooffset, 128U); // вот так уже прикручена к бегунку Масштаба. за - //leds[XY(x2, y2)] += color; - if (x2 < WIDTH && y2 < HEIGHT) // добавил проверки. не знаю, почему эффект подвисает без них - leds[XY(x2, y2)] += (CRGB)ColorFromPalette(*curPalette, hue + i * spirooffset); - - if ((x2 == spirocenterX && y2 == spirocenterY) || - (x2 == spirocenterX && y2 == spirocenterY)) change = true; - } - - spirotheta2 += 2; - - EVERY_N_MILLIS(12) { - spirotheta1 += 1; - } - - EVERY_N_MILLIS(75) { - if (change && !spirohandledChange) { - spirohandledChange = true; - - if (spirocount >= WIDTH || spirocount == 1) spiroincrement = !spiroincrement; - - if (spiroincrement) { - if (spirocount >= 10) - spirocount *= 2; - else - spirocount += 1; - } - else { - if (spirocount > 4) - spirocount /= 2; - else - spirocount -= 1; - } - - spirooffset = 256 / spirocount; - } - - if (!change) spirohandledChange = false; - } - - EVERY_N_MILLIS(33) { - hue += 1; - } -} - - - void driftRoutine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - uint8_t dim = beatsin8(2, 230, 250); - dimAll(dim); - - for (int i = 2; i <= WIDTH / 2; i++) - { - CRGB color = (CRGB)ColorFromPalette(*curPalette,(i - 2) * (240 / (WIDTH / 2))); - - uint8_t x = beatcos8((spirocenterX + 1 - i) * 2, spirocenterX - i, spirocenterX + i); - uint8_t y = beatsin8((spirocenterY + 1 - i) * 2, spirocenterY - i, spirocenterY + i); - - drawPixelXY(x, y, color); - } - } - -void drift2Routine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - uint8_t dim = beatsin8(2, 170, 250); - dimAll(dim); - //FastLED.clear(); - - for (uint8_t i = 0; i < WIDTH; i++) - { - CRGB color; - - uint8_t x = 0; - uint8_t y = 0; - - if (i < spirocenterX) { - x = beatcos8((i + 1) * 20, i, WIDTH - i); - y = beatsin8((i + 1) * 20, i, HEIGHT - i); - color = (CRGB)ColorFromPalette(*curPalette, i * 14); - } - else - { - x = beatsin8((WIDTH - i) * 20, WIDTH - i, i + 1); - y = beatcos8((HEIGHT - i) * 20, HEIGHT - i, i + 1); - color = (CRGB)ColorFromPalette(*curPalette, (7 - i) * 14); - } - - drawPixelXY(x, y,color); - } -} - -/*void infinityRoutine() { //не очень - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - dimAll(255U - modes[currentMode].Speed / 10); - //FastLED.clear(); - - // the horizontal position of the head of the infinity sign - // oscillates from 0 to the maximum horizontal and back - int x = beatsin8(15, 1, WIDTH - 1); - - // the vertical position of the head oscillates - int y = (HEIGHT - 1) - beatsin8(30, HEIGHT / 4, ((HEIGHT / 4) * 3) - 1); - - // the hue oscillates from 0 to 255, overflowing back to 0 - hue++; - - CRGB color = (CRGB)ColorFromPalette(*curPalette, hue); - - drawPixelXY(x, y, color); - drawPixelXY(x - 1, y, color); -} -*/ - -byte theta = 0; -void radarRoutine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - dimAll(254); - - for (int offset = 0; offset < spirocenterX; offset++) { - byte hue = 255 - (offset * (256 / spirocenterX) + hue); - CRGB color = ColorFromPalette(*curPalette, hue); - uint8_t x = mapcos8(theta, offset, (WIDTH - 1) - offset); - uint8_t y = mapsin8(theta, offset, (HEIGHT - 1) - offset); - leds[XY(x, y)] = color; - - EVERY_N_MILLIS(25) { - theta += 2; - hue += 1; - } - } -} - -//-----------------Эффект Вышиванка------------- -byte count = 0; -byte dir = 1; -byte flip = 0; -byte generation = 0; -void MunchRoutine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - for (byte x = 0; x < WIDTH; x++) { - for (byte y = 0; y < HEIGHT; y++) { - leds[XY(x, y)] = (x ^ y ^ flip) < count ? ColorFromPalette(*curPalette, ((x ^ y) << 4) + generation) : CRGB::Black; - } - } - - count += dir; - - if (count <= 0 || count >= WIDTH) { - dir = -dir; - } - - if (count <= 0) { - if (flip == 0) - flip = 7; - else - flip = 0; - } - - generation++; -} - - - int time = 0; - - void PlasmaRoutine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - for (int x = 0; x < WIDTH; x++) { - for (int y = 0; y < HEIGHT; y++) { - int16_t v = 0; - uint8_t wibble = sin8(time); - v += sin16(x * wibble * 2 + time); - v += cos16(y * (128 - wibble) * 2 + time); - v += sin16(y * x * cos8(-time) / 2); - CRGB color = ColorFromPalette(*curPalette,(v >> 8) + 127); - drawPixelXY(x, y, color); - } - } - - time += 1; - - } -// ------------------------------ ЭФФЕКТ КОЛЬЦА / КОДОВЫЙ ЗАМОК ---------------------- -// (c) SottNick -// из-за повторного использоваия переменных от других эффектов теперь в этом коде невозможно что-то понять. -// поэтому для понимания придётся сперва заменить названия переменных на человеческие. но всё равно это песец, конечно. -//uint8_t deltaHue2; // максимальне количество пикселей в кольце (толщина кольца) от 1 до HEIGHT / 2 + 1 -//uint8_t deltaHue; // количество колец от 2 до HEIGHT -//uint8_t noise3d[1][1][HEIGHT]; // начальный оттенок каждого кольца (оттенка из палитры) 0-255 -//uint8_t shiftValue[HEIGHT]; // местоположение начального оттенка кольца 0-WIDTH-1 -//uint8_t shiftHue[HEIGHT]; // 4 бита на ringHueShift, 4 на ringHueShift2 -////ringHueShift[ringsCount]; // шаг градиета оттенка внутри кольца -8 - +8 случайное число -////ringHueShift2[ringsCount]; // обычная скорость переливания оттенка всего кольца -8 - +8 случайное число -//uint8_t deltaValue; // кольцо, которое в настоящий момент нужно провернуть -//uint8_t step; // оставшееся количество шагов, на которое нужно провернуть активное кольцо - случайное от WIDTH/5 до WIDTH-3 -//uint8_t hue, hue2; // количество пикселей в нижнем (hue) и верхнем (hue2) кольцах - -void ringsRoutine() { - uint8_t h, x, y; - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - - //deltaHue2 = (modes[currentMode].Scale - 1U) / 99.0 * (HEIGHT / 2 - 1U) + 1U; // толщина кольца в пикселях. если на весь бегунок масштаба (от 1 до HEIGHT / 2 + 1) - deltaHue2 = (modes[currentMode].Scale - 1U) % 11U + 1U; // толщина кольца от 1 до 11 для каждой из палитр - deltaHue = HEIGHT / deltaHue2 + ((HEIGHT % deltaHue2 == 0U) ? 0U : 1U); // количество колец - hue2 = deltaHue2 - (deltaHue2 * deltaHue - HEIGHT) / 2U; // толщина верхнего кольца. может быть меньше нижнего - hue = HEIGHT - hue2 - (deltaHue - 2U) * deltaHue2; // толщина нижнего кольца = всё оставшееся - for (uint8_t i = 0; i < deltaHue; i++) - { - noise3d[0][0][i] = random8(257U - WIDTH / 2U); // начальный оттенок кольца из палитры 0-255 за минусом длины кольца, делённой пополам - shiftHue[i] = random8(); - shiftValue[i] = 0U; //random8(WIDTH); само прокрутится постепенно - step = 0U; - //do { // песец конструкцию придумал бредовую - // step = WIDTH - 3U - random8((WIDTH - 3U) * 2U); само присвоится при первом цикле - //} while (step < WIDTH / 5U || step > 255U - WIDTH / 5U); - deltaValue = random8(deltaHue); - } - - } - for (uint8_t i = 0; i < deltaHue; i++) - { - if (i != deltaValue) // если это не активное кольцо - { - h = shiftHue[i] & 0x0F; // сдвигаем оттенок внутри кольца - if (h > 8U) - //noise3d[0][0][i] += (uint8_t)(7U - h); // с такой скоростью сдвиг оттенка от вращения кольца не отличается - noise3d[0][0][i]--; - else - //noise3d[0][0][i] += h; - noise3d[0][0][i]++; - } - else - { - if (step == 0) // если сдвиг активного кольца завершён, выбираем следующее - { - deltaValue = random8(deltaHue); - do { - step = WIDTH - 3U - random8((WIDTH - 3U) * 2U); // проворот кольца от хз до хз - } while (step < WIDTH / 5U || step > 255U - WIDTH / 5U); - } - else - { - if (step > 127U) - { - step++; - shiftValue[i] = (shiftValue[i] + 1U) % WIDTH; - } - else - { - step--; - shiftValue[i] = (shiftValue[i] - 1U + WIDTH) % WIDTH; - } - } - } - // отрисовываем кольца - h = (shiftHue[i] >> 4) & 0x0F; // берём шаг для градиента вутри кольца - if (h > 8U) - h = 7U - h; - for (uint8_t j = 0U; j < ((i == 0U) ? hue : ((i == deltaHue - 1U) ? hue2 : deltaHue2)); j++) // от 0 до (толщина кольца - 1) - { - y = i * deltaHue2 + j - ((i == 0U) ? 0U : deltaHue2 - hue); - // mod для чётных скоростей by @kostyamat - получается какая-то другая фигня. не стоит того - //for (uint8_t k = 0; k < WIDTH / ((modes[currentMode].Speed & 0x01) ? 2U : 4U); k++) // полукольцо для нечётных скоростей и четверть кольца для чётных - for (uint8_t k = 0; k < WIDTH / 2U; k++) // полукольцо - { - x = (shiftValue[i] + k) % WIDTH; // первая половина кольца - drawPixelXY(x, y, ColorFromPalette(*curPalette, noise3d[0][0][i] + k * h)); - x = (WIDTH - 1 + shiftValue[i] - k) % WIDTH; // вторая половина кольца (зеркальная первой) - - drawPixelXY(x, y, ColorFromPalette(*curPalette, noise3d[0][0][i] + k * h)); - } - if (WIDTH & 0x01) //(WIDTH % 2U > 0U) // если число пикселей по ширине матрицы нечётное, тогда не забываем и про среднее значение - { - x = (shiftValue[i] + WIDTH / 2U) % WIDTH; - drawPixelXY(x, y, ColorFromPalette(*curPalette, noise3d[0][0][i] + WIDTH / 2U * h)); - } - } - } -} - - -// ------------------------------ ЭФФЕКТ ЗВЁЗДЫ ---------------------- -// (c) SottNick -// производная от эффекта White Warp -// https://github.com/marcmerlin/NeoMatrix-FastLED-IR/blob/master/Table_Mark_Estes_Impl.h -// https://github.com/marcmerlin/FastLED_NeoMatrix_SmartMatrix_LEDMatrix_GFX_Demos/blob/master/LEDMatrix/Table_Mark_Estes/Table_Mark_Estes.ino -//int16_t pointy, blender = 128;//, laps, hue, steper, xblender, hhowmany, radius3, xpoffset[MATRIX_WIDTH * 3]; -#define STAR_BLENDER 128U // хз что это -#define CENTER_DRIFT_SPEED 6U // скорость перемещения плавающего центра возникновения звёзд -#define bballsMaxNUM (WIDTH * 2) -//, ringdelay;//, bringdelay, sumthum; -//int16_t shifty = 6;//, pattern = 0, poffset; -int16_t radius2;//, fpeed[WIDTH * 3], fcount[WIDTH * 3], fcountr[WIDTH * 3];//, xxx, yyy, dot = 3, rr, gg, bb, adjunct = 3; -//uint8_t fcolor[WIDTH * 3]; -uint16_t ccoolloorr; //, why1, why2, why3, eeks1, eeks2, eeks3, oldpattern, xhowmany, kk; -float driftx, drifty;//, locusx, locusy, xcen, ycen, yangle, xangle; -float cangle, sangle;//xfire[WIDTH * 3], yfire[WIDTH * 3], radius, xslope[MATRIX_WIDTH * 3], yslope[MATRIX_WIDTH * 3]; - -//Дополнительная функция построения линий -void DrawLine(int x1, int y1, int x2, int y2, CRGB color) -{ - int tmp; - int x, y; - int dx, dy; - int err; - int ystep; - - uint8_t swapxy = 0; - - if ( x1 > x2 ) dx = x1 - x2; else dx = x2 - x1; - if ( y1 > y2 ) dy = y1 - y2; else dy = y2 - y1; - - if ( dy > dx ) - { - swapxy = 1; - tmp = dx; dx = dy; dy = tmp; - tmp = x1; x1 = y1; y1 = tmp; - tmp = x2; x2 = y2; y2 = tmp; - } - if ( x1 > x2 ) - { - tmp = x1; x1 = x2; x2 = tmp; - tmp = y1; y1 = y2; y2 = tmp; - } - err = dx >> 1; - if ( y2 > y1 ) ystep = 1; else ystep = -1; - y = y1; - - for ( x = x1; x <= x2; x++ ) - { - if ( swapxy == 0 ) drawPixelXY(x, y, color); - else drawPixelXY(y, x, color); - err -= (uint8_t)dy; - if ( err < 0 ) - { - y += ystep; - err += dx; - } - } -} - -void drawstar(int16_t xlocl, int16_t ylocl, int16_t biggy, int16_t little, int16_t points, int16_t dangle, uint8_t koler)// random multipoint star -{ - // if (counter == 0) { // это, блин, вообще что за хрень была?! - // shifty = 3;//move quick - // } - radius2 = 255 / points; - for (int i = 0; i < points; i++) - { - //DrawLine(xlocl + ((little * (sin8(i * radius2 + radius2 / 2 - dangle) - 128.0)) / 128), ylocl + ((little * (cos8(i * radius2 + radius2 / 2 - dangle) - 128.0)) / 128), xlocl + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), ylocl + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), CHSV(koler , 255, 255)); - //DrawLine(xlocl + ((little * (sin8(i * radius2 - radius2 / 2 - dangle) - 128.0)) / 128), ylocl + ((little * (cos8(i * radius2 - radius2 / 2 - dangle) - 128.0)) / 128), xlocl + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), ylocl + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), CHSV(koler , 255, 255)); - // две строчки выше - рисуют звезду просто по оттенку, а две строчки ниже - берут цвет из текущей палитры - DrawLine(xlocl + ((little * (sin8(i * radius2 + radius2 / 2 - dangle) - 128.0)) / 128), ylocl + ((little * (cos8(i * radius2 + radius2 / 2 - dangle) - 128.0)) / 128), xlocl + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), ylocl + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), ColorFromPalette(*curPalette, koler)); - DrawLine(xlocl + ((little * (sin8(i * radius2 - radius2 / 2 - dangle) - 128.0)) / 128), ylocl + ((little * (cos8(i * radius2 - radius2 / 2 - dangle) - 128.0)) / 128), xlocl + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), ylocl + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), ColorFromPalette(*curPalette, koler)); - } -} - -uint8_t bballsCOLOR[bballsMaxNUM] ; // цвет звезды (используем повторно массив эффекта Мячики) -uint8_t bballsX[bballsMaxNUM] ; // количество углов в звезде (используем повторно массив эффекта Мячики) -int bballsPos[bballsMaxNUM] ; // задержка пуска звезды относительно счётчика (используем повторно массив эффекта Мячики) -uint8_t bballsNUM; // количество звёзд (используем повторно переменную эффекта Мячики) - -void starRoutine() { - //dimAll(255U - modes[currentMode].Scale * 2); - dimAll(89U); - //dimAll(myscale8(modes[currentMode].Scale)); - - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - - driftx = random8(4, WIDTH - 4);//set an initial location for the animation center - drifty = random8(4, HEIGHT - 4);// set an initial location for the animation center - - cangle = (sin8(random(25, 220)) - 128.0) / 128.0;//angle of movement for the center of animation gives a float value between -1 and 1 - sangle = (sin8(random(25, 220)) - 128.0) / 128.0;//angle of movement for the center of animation in the y direction gives a float value between -1 and 1 - //shifty = random (3, 12);//how often the drifter moves будет CENTER_DRIFT_SPEED = 6 - - //pointy = 7; теперь количество углов у каждой звезды своё - bballsNUM = (WIDTH + 6U) / 2U;//(modes[currentMode].Scale - 1U) / 99.0 * (bballsMaxNUM - 1U) + 1U; - if (bballsNUM > bballsMaxNUM) bballsNUM = bballsMaxNUM; - for (uint8_t num = 0; num < bballsNUM; num++) { - bballsX[num] = random8(3, 9);//pointy = random8(3, 9); // количество углов в звезде - bballsPos[num] = counter + (num << 2) + 1U;//random8(50);//modes[currentMode].Scale;//random8(50, 99); // задержка следующего пуска звезды - bballsCOLOR[num] = random8(); - } - - } - - - //hue++;//increment the color basis был общий оттенок на весь эффект. теперь у каждой звезды свой - //h = hue; //set h to the color basis - counter++; - if (driftx > (WIDTH - spirocenterX / 2U))//change directin of drift if you get near the right 1/4 of the screen - cangle = 0 - fabs(cangle); - if (driftx < spirocenterX / 2U)//change directin of drift if you get near the right 1/4 of the screen - cangle = fabs(cangle); - if (counter % CENTER_DRIFT_SPEED == 0) - driftx = driftx + cangle;//move the x center every so often - - if (drifty > ( HEIGHT - spirocenterY / 2U))// if y gets too big, reverse - sangle = 0 - fabs(sangle); - if (drifty < spirocenterY / 2U) // if y gets too small reverse - sangle = fabs(sangle); - if ((counter + CENTER_DRIFT_SPEED / 2U) % CENTER_DRIFT_SPEED == 0) - drifty = drifty + sangle;//move the y center every so often - - //по идее, не нужно равнять диапазоны плавающего центра. за них и так вылет невозможен - //driftx = constrain(driftx, spirocenterX - spirocenterX / 3, spirocenterX + spirocenterX / 3);//constrain the center, probably never gets evoked any more but was useful at one time to keep the graphics on the screen.... - //drifty = constrain(drifty, spirocenterY - spirocenterY / 3, spirocenterY + spirocenterY / 3); - - for (uint8_t num = 0; num < bballsNUM; num++) { - if (counter >= bballsPos[num])//(counter >= ringdelay) - { - if (counter - bballsPos[num] <= WIDTH + 5U) { //(counter - ringdelay <= WIDTH + 5){ - //drawstar(driftx , drifty, 2 * (counter - ringdelay), (counter - ringdelay), pointy, blender + h, h * 2 + 85); - drawstar(driftx , drifty, 2 * (counter - bballsPos[num]), (counter - bballsPos[num]), bballsX[num], STAR_BLENDER + bballsCOLOR[num], bballsCOLOR[num] * 2);//, h * 2 + 85);// что, бл, за 85?! - bballsCOLOR[num]++; - } - else - //bballsX[num] = random8(3, 9);//pointy = random8(3, 9); // количество углов в звезде - bballsPos[num] = counter + (bballsNUM << 1) + 1U;//random8(50, 99);//modes[currentMode].Scale;//random8(50, 99); // задержка следующего пуска звезды - } - } -} - - - - -// ============= ЭФФЕКТ ПРИЗМАТА =============== -// Prismata Loading Animation -// https://github.com/pixelmatix/aurora/blob/master/PatternPendulumWave.h -// Адаптация от (c) SottNick - -void PrismataRoutine() { - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - } - - EVERY_N_MILLIS(33) { - hue++; // используем переменную сдвига оттенка из функций радуги, чтобы не занимать память - } - FastLED.clear(); - - for (uint8_t x = 0; x < WIDTH; x++) - { - //uint8_t y = beatsin8(x + 1, 0, HEIGHT-1); // это я попытался распотрошить данную функцию до исходного кода и вставить в неё регулятор скорости - // вместо 28 в оригинале было 280, умножения на .Speed не было, а вместо >>17 было (<<8)>>24. короче, оригинальная скорость достигается при бегунке .Speed=20 - uint8_t beat = (GET_MILLIS() * (accum88(x + 1)) * 28 * modes[currentMode].Speed) >> 17; - uint8_t y = scale8(sin8(beat), HEIGHT - 1); - //и получилось!!! - - drawPixelXY(x, y, ColorFromPalette(*curPalette, x * 7 + hue)); - } -} -// ------------- светлячки -------------- -#define BALLS_AMOUNT2 (10U) // количество "cветлячков" -#define CLEAR_PATH2 (1U) // очищать путь -int16_t coord2[BALLS_AMOUNT2][2U]; -int8_t vector2[BALLS_AMOUNT2][2U]; -CRGB ballColors2[BALLS_AMOUNT2]; -void lightersRoutine() -{ - if (loadingFlag) - { - loadingFlag = false; - - for (uint8_t j = 0U; j < BALLS_AMOUNT2; j++) - { - int8_t sign2; - // забиваем случайными данными - coord2[j][0U] = WIDTH / 2 * 10; - random(0, 2) ? sign2 = 1 : sign2 = -1; - vector2[j][0U] = random(4, 15) * sign2; - coord2[j][1U] = HEIGHT / 2 * 10; - random(0, 2) ? sign2 = 1 : sign2 = -1; - vector2[j][1U] = random(4, 15) * sign2; - //ballColors[j] = CHSV(random(0, 9) * 28, 255U, 255U); - // цвет зависит от масштаба - ballColors2[j] = CHSV((modes[currentMode].Scale * (j + 1)) % 256U, 255U, 255U); - } - } - - - FastLED.clear(); - - // движение шариков - for (uint8_t j = 0U; j < BALLS_AMOUNT2; j++) - { - // движение шариков - for (uint8_t i = 0U; i < 2U; i++) - { - coord2[j][i] += vector2[j][i]; - if (coord2[j][i] < 0) - { - coord2[j][i] = 0; - vector2[j][i] = -vector2[j][i]; - } - } - - if (coord2[j][0U] > (int16_t)((WIDTH - 1) * 10)) - { - coord2[j][0U] = (WIDTH - 1) * 10; - vector2[j][0U] = -vector2[j][0U]; - } - if (coord2[j][1U] > (int16_t)((HEIGHT - 1) * 10)) - { - coord2[j][1U] = (HEIGHT - 1) * 10; - vector2[j][1U] = -vector2[j][1U]; - } - leds[XY(coord2[j][0U] / 10, coord2[j][1U] / 10)] = ballColors2[j]; - } -} - -// --------------------------- эффект мячики ---------------------- -// BouncingBalls2014 is a program that lets you animate an LED strip -// to look like a group of bouncing balls -// Daniel Wilson, 2014 -// https://github.com/githubcdr/Arduino/blob/master/bouncingballs/bouncingballs.ino -// With BIG thanks to the FastLED community! -// адаптация от SottNick -#define bballsGRAVITY (-9.81) // Downward (negative) acceleration of gravity in m/s^2 -#define bballsH0 (1) // Starting height, in meters, of the ball (strip length) -//#define bballsMaxNUM (WIDTH * 2) // максимальное количество мячиков прикручено при адаптации для бегунка Масштаб -//uint8_t bballsNUM; // Number of bouncing balls you want (recommend < 7, but 20 is fun in its own way) ... количество мячиков теперь задаётся бегунком, а не константой -//uint8_t bballsCOLOR[bballsMaxNUM] ; // прикручено при адаптации для разноцветных мячиков -//uint8_t bballsX[bballsMaxNUM] ; // прикручено при адаптации для распределения мячиков по радиусу лампы -bool bballsShift[bballsMaxNUM] ; // прикручено при адаптации для того, чтобы мячики не стояли на месте -float bballsVImpact0 = sqrt( -2 * bballsGRAVITY * bballsH0 ); // Impact velocity of the ball when it hits the ground if "dropped" from the top of the strip -float bballsVImpact[bballsMaxNUM] ; // As time goes on the impact velocity will change, so make an array to store those values -//uint16_t bballsPos[bballsMaxNUM] ; // The integer position of the dot on the strip (LED index) -long bballsTLast[bballsMaxNUM] ; // The clock time of the last ground strike -float bballsCOR[bballsMaxNUM] ; // Coefficient of Restitution (bounce damping) - -void BBallsRoutine() { - if (loadingFlag) - { - loadingFlag = false; - FastLED.clear(); - bballsNUM = (modes[currentMode].Scale - 1U) / 99.0 * (bballsMaxNUM - 1U) + 1U; - if (bballsNUM > bballsMaxNUM) bballsNUM = bballsMaxNUM; - for (uint8_t i = 0 ; i < bballsNUM ; i++) { // Initialize variables - bballsCOLOR[i] = random8(); - bballsX[i] = random8(0U, WIDTH); - bballsTLast[i] = millis(); - bballsPos[i] = 0U; // Balls start on the ground - bballsVImpact[i] = bballsVImpact0; // And "pop" up at vImpact0 - bballsCOR[i] = 0.90 - float(i) / pow(bballsNUM, 2); // это, видимо, прыгучесть. для каждого мячика уникальная изначально - bballsShift[i] = false; - hue2 = (modes[currentMode].Speed > 127U) ? 255U : 0U; // цветные или белые мячики - hue = (modes[currentMode].Speed == 128U) ? 255U : 254U - modes[currentMode].Speed % 128U * 2U; // скорость угасания хвостов 0 = моментально - } - } - - float bballsHi; - float bballsTCycle; - deltaHue++; // постепенное изменение оттенка мячиков (закомментировать строчку, если не нужно) - dimAll(hue); - for (uint8_t i = 0 ; i < bballsNUM ; i++) { - //leds[XY(bballsX[i], bballsPos[i])] = CRGB::Black; // off for the next loop around // теперь пиксели гасятся в dimAll() - - bballsTCycle = millis() - bballsTLast[i] ; // Calculate the time since the last time the ball was on the ground - - // A little kinematics equation calculates positon as a function of time, acceleration (gravity) and intial velocity - bballsHi = 0.5 * bballsGRAVITY * pow( bballsTCycle / 1000.0 , 2.0 ) + bballsVImpact[i] * bballsTCycle / 1000.0; - - if ( bballsHi < 0 ) { - bballsTLast[i] = millis(); - bballsHi = 0; // If the ball crossed the threshold of the "ground," put it back on the ground - bballsVImpact[i] = bballsCOR[i] * bballsVImpact[i] ; // and recalculate its new upward velocity as it's old velocity * COR - - if ( bballsVImpact[i] < 0.01 ) // If the ball is barely moving, "pop" it back up at vImpact0 - { - bballsCOR[i] = 0.90 - float(random(0U, 9U)) / pow(random(4U, 9U), 2); // сделал, чтобы мячики меняли свою прыгучесть каждый цикл - bballsShift[i] = bballsCOR[i] >= 0.89; // если мячик максимальной прыгучести, то разрешаем ему сдвинуться - bballsVImpact[i] = bballsVImpact0; - } - } - bballsPos[i] = round( bballsHi * (HEIGHT - 1) / bballsH0); // Map "h" to a "pos" integer index position on the LED strip - if (bballsShift[i] && (bballsPos[i] == HEIGHT - 1)) { // если мячик получил право, то пускай сдвинется на максимальной высоте 1 раз - bballsShift[i] = false; - if (bballsCOLOR[i] % 2 == 0) { // чётные налево, нечётные направо - if (bballsX[i] == 0U) bballsX[i] = WIDTH - 1U; - else --bballsX[i]; - } else { - if (bballsX[i] == WIDTH - 1U) bballsX[i] = 0U; - else ++bballsX[i]; - } - } - leds[XY(bballsX[i], bballsPos[i])] = CHSV(bballsCOLOR[i] + deltaHue, hue2, 255U); - } -} - -/*// ------------------------------ ЭФФЕКТ ПРЫГУНЫ ---------------------- - // стырено откуда-то by @obliterator - // https://github.com/DmytroKorniienko/FireLamp_JeeUI/blob/templ/src/effects.cpp - - //Leaper leapers[20]; - //вместо класса Leaper будем повторно использовать переменные из эффекта мячики - //float x, y; будет: - float leaperX[bballsMaxNUM]; - float leaperY[bballsMaxNUM]; - //float xd, yd; будет: - ////float bballsVImpact[bballsMaxNUM]; // As time goes on the impact velocity will change, so make an array to store those values - ////float bballsCOR[bballsMaxNUM]; // Coefficient of Restitution (bounce damping) - //CHSV color; будет: - ////uint8_t bballsCOLOR[bballsMaxNUM]; - - void LeapersRestart_leaper(uint8_t l) { - // leap up and to the side with some random component - bballsVImpact[l] = (1 * (float)random8(1, 100) / 100); - bballsCOR[l] = (2 * (float)random8(1, 100) / 100); - - // for variety, sometimes go 50% faster - if (random8() < 12) { - bballsVImpact[l] += bballsVImpact[l] * 0.5; - bballsCOR[l] += bballsCOR[l] * 0.5; - } - - // leap towards the centre of the screen - if (leaperX[l] > (WIDTH / 2)) { - bballsVImpact[l] = -bballsVImpact[l]; - } - } - - void LeapersMove_leaper(uint8_t l) { - #define GRAVITY 0.06 - #define SETTLED_THRESHOLD 0.1 - #define WALL_FRICTION 0.95 - #define WIND 0.95 // wind resistance - - leaperX[l] += bballsVImpact[l]; - leaperY[l] += bballsCOR[l]; - - // bounce off the floor and ceiling? - if (leaperY[l] < 0 || leaperY[l] > HEIGHT - 1) { - bballsCOR[l] = (-bballsCOR[l] * WALL_FRICTION); - bballsVImpact[l] = ( bballsVImpact[l] * WALL_FRICTION); - leaperY[l] += bballsCOR[l]; - if (leaperY[l] < 0) leaperY[l] = 0; - // settled on the floor? - if (leaperY[l] <= SETTLED_THRESHOLD && fabs(bballsCOR[l]) <= SETTLED_THRESHOLD) { - LeapersRestart_leaper(l); - } - } - - // bounce off the sides of the screen? - if (leaperX[l] <= 0 || leaperX[l] >= WIDTH - 1) { - bballsVImpact[l] = (-bballsVImpact[l] * WALL_FRICTION); - if (leaperX[l] <= 0) { - leaperX[l] = bballsVImpact[l]; - } else { - leaperX[l] = WIDTH - 1 - bballsVImpact[l]; - } - } - - bballsCOR[l] -= GRAVITY; - bballsVImpact[l] *= WIND; - bballsCOR[l] *= WIND; - } - - - void LeapersRoutine(){ - //unsigned num = map(Scale, 0U, 255U, 6U, sizeof(boids) / sizeof(*boids)); - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - //FastLED.clear(); - //bballsNUM = (modes[currentMode].Scale - 1U) / 99.0 * (bballsMaxNUM - 1U) + 1U; - bballsNUM = (modes[currentMode].Scale - 1U) % 11U / 10.0 * (bballsMaxNUM - 1U) + 1U; - if (bballsNUM > bballsMaxNUM) bballsNUM = bballsMaxNUM; - //if (bballsNUM < 2U) bballsNUM = 2U; - - for (uint8_t i = 0 ; i < bballsNUM ; i++) { - leaperX[i] = random8(WIDTH); - leaperY[i] = random8(HEIGHT); - - //curr->color = CHSV(random(1U, 255U), 255U, 255U); - bballsCOLOR[i] = random8(); - } - } - FastLED.clear(); - - for (uint8_t i = 0; i < bballsNUM; i++) { - LeapersMove_leaper(i); - //drawPixelXYF(leaperX[i], leaperY[i], CHSV(bballsCOLOR[i], 255U, 255U)); - drawPixelXYF(leaperX[i], leaperY[i], ColorFromPalette(*curPalette, bballsCOLOR[i])); - }; - - blurScreen(20); - }*/ - - #define PAUSE_MAX 7 // пропустить 7 кадров после завершения анимации сдвига ячеек - -//uint8_t noise3d[1][WIDTH][HEIGHT]; // тут используем только нулевую колонку и нулевую строку. просто для экономии памяти взяли существующий трёхмерный массив -//uint8_t hue2; // осталось шагов паузы -//uint8_t step; // текущий шаг сдвига (от 0 до deltaValue-1) -//uint8_t deltaValue; // всего шагов сдвига (до razmer? до (razmer?+1)*shtuk?) -//uint8_t deltaHue, deltaHue2; // глобальный X и глобальный Y нашего "кубика" -uint8_t razmerX, razmerY; // размеры ячеек по горизонтали / вертикали -uint8_t shtukX, shtukY; // количество ячеек по горизонтали / вертикали -uint8_t poleX, poleY; // размер всего поля по горизонтали / вертикали (в том числе 1 дополнительная пустая дорожка-разделитель с какой-то из сторон) -int8_t globalShiftX, globalShiftY; // нужно ли сдвинуть всё поле по окончаии цикла и в каком из направлений (-1, 0, +1) -bool seamlessX; // получилось ли сделать поле по Х бесшовным -bool krutimVertikalno; // направление вращения в данный момент - -void cube2dRoutine(){ - uint8_t x, y; - uint8_t anim0; // будем считать тут начальный пиксель для анимации сдвига строки/колонки - int8_t shift, kudaVse; // какое-то расчётное направление сдвига (-1, 0, +1) - CRGB color, color2; - - if (loadingFlag) - { - loadingFlag = false; - setCurrentPalette(); - FastLED.clear(); - - razmerX = (modes[currentMode].Scale - 1U) % 11U + 1U; // размер ячейки от 1 до 11 пикселей для каждой из 9 палитр - razmerY = razmerX; - if (modes[currentMode].Speed & 0x01) // по идее, ячейки не обязательно должны быть квадратными, поэтому можно тут поизвращаться - razmerY = (razmerY << 1U) + 1U; - - shtukY = HEIGHT / (razmerY + 1U); - if (shtukY < 2U) - shtukY = 2U; - y = HEIGHT / shtukY - 1U; - if (razmerY > y) - razmerY = y; - poleY = (razmerY + 1U) * shtukY; - shtukX = WIDTH / (razmerX + 1U); - if (shtukX < 2U) - shtukX = 2U; - x = WIDTH / shtukX - 1U; - if (razmerX > x) - razmerX = x; - poleX = (razmerX + 1U) * shtukX; - seamlessX = (poleX == WIDTH); - deltaHue = 0U; - deltaHue2 = 0U; - globalShiftX = 0; - globalShiftY = 0; - - for (uint8_t j = 0U; j < shtukY; j++) - { - y = j * (razmerY + 1U); // + deltaHue2 т.к. оно =0U - for (uint8_t i = 0U; i < shtukX; i++) - { - x = i * (razmerX + 1U); // + deltaHue т.к. оно =0U - if (modes[currentMode].Scale == 100U) - color = CHSV(45U, 0U, 128U + random8(128U)); - else - color = ColorFromPalette(*curPalette, random8()); - for (uint8_t k = 0U; k < razmerY; k++) - for (uint8_t m = 0U; m < razmerX; m++) - leds[XY(x+m, y+k)] = color; - } - } - step = 4U; // текущий шаг сдвига первоначально с перебором (от 0 до deltaValue-1) - deltaValue = 4U; // всего шагов сдвига (от razmer? до (razmer?+1) * shtuk?) - hue2 = 0U; // осталось шагов паузы - - //это лишнее обнуление - //krutimVertikalno = true; - //for (uint8_t i = 0U; i < shtukX; i++) - // noise3d[0][i][0] = 0U; - } - - //двигаем, что получилось... - if (hue2 == 0 && step < deltaValue) // если пауза закончилась, а цикл вращения ещё не завершён - { - step++; - if (krutimVertikalno) - { - for (uint8_t i = 0U; i < shtukX; i++) - { - x = (deltaHue + i * (razmerX + 1U)) % WIDTH; - if (noise3d[0][i][0] > 0) // в нулевой ячейке храним оставшееся количество ходов прокрутки - { - noise3d[0][i][0]--; - shift = noise3d[0][i][1] - 1; // в первой ячейке храним направление прокрутки - - if (globalShiftY == 0) - anim0 = (deltaHue2 == 0U) ? 0U : deltaHue2 - 1U; - else if (globalShiftY > 0) - anim0 = deltaHue2; - else - anim0 = deltaHue2 - 1U; - - if (shift < 0) // если крутим столбец вниз - { - color = leds[XY(x, anim0)]; // берём цвет от нижней строчки - for (uint8_t k = anim0; k < anim0+poleY-1; k++) - { - color2 = leds[XY(x,k+1)]; // берём цвет от строчки над нашей - for (uint8_t m = x; m < x + razmerX; m++) - leds[XY(m % WIDTH,k)] = color2; // копируем его на всю нашу строку - } - for (uint8_t m = x; m < x + razmerX; m++) - leds[XY(m % WIDTH,anim0+poleY-1)] = color; // цвет нижней строчки копируем на всю верхнюю - } - else if (shift > 0) // если крутим столбец вверх - { - color = leds[XY(x,anim0+poleY-1)]; // берём цвет от верхней строчки - for (uint8_t k = anim0+poleY-1; k > anim0 ; k--) - { - color2 = leds[XY(x,k-1)]; // берём цвет от строчки под нашей - for (uint8_t m = x; m < x + razmerX; m++) - leds[XY(m % WIDTH,k)] = color2; // копируем его на всю нашу строку - } - for (uint8_t m = x; m < x + razmerX; m++) - leds[XY(m % WIDTH, anim0)] = color; // цвет верхней строчки копируем на всю нижнюю - } - } - } - } - else - { - for (uint8_t j = 0U; j < shtukY; j++) - { - y = deltaHue2 + j * (razmerY + 1U); - if (noise3d[0][0][j] > 0) // в нулевой ячейке храним оставшееся количество ходов прокрутки - { - noise3d[0][0][j]--; - shift = noise3d[0][1][j] - 1; // в первой ячейке храним направление прокрутки - - if (seamlessX) - anim0 = 0U; - else if (globalShiftX == 0) - anim0 = (deltaHue == 0U) ? 0U : deltaHue - 1U; - else if (globalShiftX > 0) - anim0 = deltaHue; - else - anim0 = deltaHue - 1U; - - if (shift < 0) // если крутим строку влево - { - color = leds[XY(anim0, y)]; // берём цвет от левой колонки (левого пикселя) - for (uint8_t k = anim0; k < anim0+poleX-1; k++) - { - color2 = leds[XY(k+1, y)]; // берём цвет от колонки (пикселя) правее - for (uint8_t m = y; m < y + razmerY; m++) - leds[XY(k, m)] = color2; // копируем его на всю нашу колонку - } - for (uint8_t m = y; m < y + razmerY; m++) - leds[XY(anim0+poleX-1, m)] = color; // цвет левой колонки копируем на всю правую - } - else if (shift > 0) // если крутим столбец вверх - { - color = leds[XY(anim0+poleX-1, y)]; // берём цвет от правой колонки - for (uint8_t k = anim0+poleX-1; k > anim0 ; k--) - { - color2 = leds[XY(k-1, y)]; // берём цвет от колонки левее - for (uint8_t m = y; m < y + razmerY; m++) - leds[XY(k, m)] = color2; // копируем его на всю нашу колонку - } - for (uint8_t m = y; m < y + razmerY; m++) - leds[XY(anim0, m)] = color; // цвет правой колонки копируем на всю левую - } - } - } - } - - } - else if (hue2 != 0U) // пропускаем кадры после прокрутки кубика (делаем паузу) - hue2--; - - if (step >= deltaValue) // если цикл вращения завершён, меняем местами соответствующие ячейки (цвет в них) и точку первой ячейки - { - step = 0U; - hue2 = PAUSE_MAX; - //если часть ячеек двигалась на 1 пиксель, пододвигаем глобальные координаты начала - deltaHue2 = deltaHue2 + globalShiftY; //+= globalShiftY; - globalShiftY = 0; - //deltaHue += globalShiftX; для бесшовной не годится - deltaHue = (WIDTH + deltaHue + globalShiftX) % WIDTH; - globalShiftX = 0; - - //пришла пора выбрать следующие параметры вращения - kudaVse = 0; - krutimVertikalno = random8(2U); - if (krutimVertikalno) // идём по горизонтали, крутим по вертикали (столбцы двигаются) - { - for (uint8_t i = 0U; i < shtukX; i++) - { - noise3d[0][i][1] = random8(3); - shift = noise3d[0][i][1] - 1; // в первой ячейке храним направление прокрутки - if (kudaVse == 0) - kudaVse = shift; - else if (shift != 0 && kudaVse != shift) - kudaVse = 50; - } - deltaValue = razmerY + ((deltaHue2 - kudaVse >= 0 && deltaHue2 - kudaVse + poleY < (int)HEIGHT) ? random8(2U) : 1U); - -/* if (kudaVse == 0) // пытался сделать, чтобы при совпадении "весь кубик стоит" сдвинуть его весь на пиксель, но заколебался - { - deltaValue = razmerY; - kudaVse = (random8(2)) ? 1 : -1; - if (deltaHue2 - kudaVse < 0 || deltaHue2 - kudaVse + poleY >= (int)HEIGHT) - kudaVse = 0 - kudaVse; - } -*/ - if (deltaValue == razmerY) // значит полюбому kudaVse было = (-1, 0, +1) - и для нуля в том числе мы двигаем весь куб на 1 пиксель - { - globalShiftY = 1 - kudaVse; //временно на единичку больше, чем надо - for (uint8_t i = 0U; i < shtukX; i++) - if (noise3d[0][i][1] == 1U) // если ячейка никуда не планировала двигаться - { - noise3d[0][i][1] = globalShiftY; - noise3d[0][i][0] = 1U; // в нулевой ячейке храним количество ходов сдвига - } - else - noise3d[0][i][0] = deltaValue; // в нулевой ячейке храним количество ходов сдвига - globalShiftY--; - } - else - { - x = 0; - for (uint8_t i = 0U; i < shtukX; i++) - if (noise3d[0][i][1] != 1U) - { - y = random8(shtukY); - if (y > x) - x = y; - noise3d[0][i][0] = deltaValue * (x + 1U); // в нулевой ячейке храним количество ходов сдвига - } - deltaValue = deltaValue * (x + 1U); - } - - } - else // идём по вертикали, крутим по горизонтали (строки двигаются) - { - for (uint8_t j = 0U; j < shtukY; j++) - { - noise3d[0][1][j] = random8(3); - shift = noise3d[0][1][j] - 1; // в первой ячейке храним направление прокрутки - if (kudaVse == 0) - kudaVse = shift; - else if (shift != 0 && kudaVse != shift) - kudaVse = 50; - } - if (seamlessX) - deltaValue = razmerX + ((kudaVse < 50) ? random8(2U) : 1U); - else - deltaValue = razmerX + ((deltaHue - kudaVse >= 0 && deltaHue - kudaVse + poleX < (int)WIDTH) ? random8(2U) : 1U); - -/* if (kudaVse == 0) // пытался сделать, чтобы при совпадении "весь кубик стоит" сдвинуть его весь на пиксель, но заколебался - { - deltaValue = razmerX; - kudaVse = (random8(2)) ? 1 : -1; - if (deltaHue - kudaVse < 0 || deltaHue - kudaVse + poleX >= (int)WIDTH) - kudaVse = 0 - kudaVse; - } -*/ - if (deltaValue == razmerX) // значит полюбому kudaVse было = (-1, 0, +1) - и для нуля в том числе мы двигаем весь куб на 1 пиксель - { - globalShiftX = 1 - kudaVse; //временно на единичку больше, чем надо - for (uint8_t j = 0U; j < shtukY; j++) - if (noise3d[0][1][j] == 1U) // если ячейка никуда не планировала двигаться - { - noise3d[0][1][j] = globalShiftX; - noise3d[0][0][j] = 1U; // в нулевой ячейке храним количество ходов сдвига - } - else - noise3d[0][0][j] = deltaValue; // в нулевой ячейке храним количество ходов сдвига - globalShiftX--; - } - else - { - y = 0; - for (uint8_t j = 0U; j < shtukY; j++) - if (noise3d[0][1][j] != 1U) - { - x = random8(shtukX); - if (x > y) - y = x; - noise3d[0][0][j] = deltaValue * (x + 1U); // в нулевой ячейке храним количество ходов сдвига - } - deltaValue = deltaValue * (y + 1U); - } - } - } -} diff --git a/ArduinoLamp_v1.5/noiseEffects.ino b/ArduinoLamp_v1.5/noiseEffects.ino deleted file mode 100644 index e2888a7..0000000 --- a/ArduinoLamp_v1.5/noiseEffects.ino +++ /dev/null @@ -1,283 +0,0 @@ -// ************* НАСТРОЙКИ ************* -// The 16 bit version of our coordinates -static uint16_t x; -static uint16_t y; -static uint16_t z; - -uint16_t speed = 20; // speed is set dynamically once we've started up -uint16_t scale = 30; // scale is set dynamically once we've started up - -// This is the array that we keep our computed noise values in -#define MAX_DIMENSION (max(WIDTH, HEIGHT)) -#if (WIDTH > HEIGHT) -uint8_t noise[WIDTH][WIDTH]; -#else -uint8_t noise[HEIGHT][HEIGHT]; -#endif - -CRGBPalette16 pPalette; - -// This function sets up a palette of black and blue stripes, -// using code. Since the palette is effectively an array of -// sixteen CRGB colors, the various fill_* functions can be used -// to set them up. -void SetupPalette() -{ - fill_solid( pPalette, 16, CHSV(modes[currentMode].Scale * 2.5, 255, 75)); - - for (uint8_t i = 0; i < 6; i++) { - pPalette[i] = CHSV(modes[currentMode].Scale * 2.5, 255, 255); - - } - } - - -CRGBPalette16 currentPalette(PartyColors_p); -uint8_t colorLoop = 1; -uint8_t ihue = 0; - -void madnessNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - } - fillnoise8(); - for (uint8_t i = 0; i < WIDTH; i++) - { - for (uint8_t j = 0; j < HEIGHT; j++) - { - CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); - leds[XY(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); - } - } - ihue += 1; -} - -void rainbowNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = RainbowColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 1; - } - fillNoiseLED(0.125, 0.0625, 1); -} - -void rainbowStripeNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = RainbowStripeColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 1; - } - fillNoiseLED(0.125, 0.0625, 1); -} - -void zebraNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - // 'black out' all 16 palette entries... - fill_solid(currentPalette, 16, CRGB::Black); - // and set every fourth one to white. - currentPalette[0] = CRGB::White; - currentPalette[4] = CRGB::White; - currentPalette[8] = CRGB::White; - currentPalette[12] = CRGB::White; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 1; - } - fillNoiseLED(0.125, 0.0625, 1); -} - -void forestNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = ForestColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(0.125, 0.0625, 1); -} - -void oceanNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = OceanColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - - fillNoiseLED(0.125, 0.0625, 1); -} - -void plasmaNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = PartyColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 1; - } - fillNoiseLED(0.125, 0.0625, 1); -} - -void cloudNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = CloudColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(0.125, 0.0625, 1); -} - -void lavaNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = LavaColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(0.125, 0.0625, 1); -} - -void heatNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = HeatColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(1, 0.625, 0.125); -} - -void smokeNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - currentPalette = WaterfallColors_p; - scale = modes[currentMode].Scale; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(1, 0.625, 0.125); -} - -void lavLampNoise() -{ - if (loadingFlag) - { - loadingFlag = false; - SetupPalette(); - currentPalette = pPalette; - scale = 30; - speed = modes[currentMode].Speed; - colorLoop = 0; - } - fillNoiseLED(1, 0, 0.125); -} -// ************* СЛУЖЕБНЫЕ ************* -void fillNoiseLED(byte x_dir, byte y_dir, byte z_dir) -{ - uint8_t dataSmoothing = 0; - if (speed < 50) - { - dataSmoothing = 200 - (speed * 4); - } - for (uint8_t i = 0; i < MAX_DIMENSION; i++) - { - int32_t ioffset = scale * i; - for (uint8_t j = 0; j < MAX_DIMENSION; j++) - { - int32_t joffset = scale * j; - - uint8_t data = inoise8(x + ioffset, y + joffset, z); - - data = qsub8(data, 16); - data = qadd8(data, scale8(data, 39)); - - if (dataSmoothing) - { - uint8_t olddata = noise[i][j]; - uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); - data = newdata; - } - - noise[i][j] = data; - } - } - z += speed * z_dir; - x -= speed * x_dir; - y += speed * y_dir; - - for (uint8_t i = 0; i < WIDTH; i++) - { - for (uint8_t j = 0; j < HEIGHT; j++) - { - uint8_t index = noise[j][i]; - uint8_t bri = noise[i][j]; - // if this palette is a 'loop', add a slowly-changing base value - if ( colorLoop) - { - index += ihue; - } - // brighten up, as the color palette itself often contains the - // light/dark dynamic range desired - if ( bri > 127 ) - { - bri = 255; - } - else - { - bri = dim8_raw( bri * 2); - } - CRGB color = ColorFromPalette( currentPalette, index, bri); - leds[XY(i, j)] = color; - } - } - ihue += 1; -} - -void fillnoise8() -{ - for (uint8_t i = 0; i < MAX_DIMENSION; i++) - { - int32_t ioffset = scale * i; - for (uint8_t j = 0; j < MAX_DIMENSION; j++) - { - int32_t joffset = scale * j; - noise[i][j] = inoise8(x + ioffset, y + joffset, z); - } - } - z -= speed; -} diff --git a/ArduinoLamp_v1.5/utility.ino b/ArduinoLamp_v1.5/utility.ino deleted file mode 100644 index d9e167c..0000000 --- a/ArduinoLamp_v1.5/utility.ino +++ /dev/null @@ -1,195 +0,0 @@ -// служебные функции - -// залить все -void fillAll(CRGB color) { - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = color; - } -} - -// функция отрисовки точки по координатам X Y -void drawPixelXY(uint8_t x, uint8_t y, CRGB color) -{ - if (x < 0 || x > (WIDTH - 1) || y < 0 || y > (HEIGHT - 1)) return; - uint32_t thisPixel = XY((uint8_t)x, (uint8_t)y) * SEGMENTS; - for (uint8_t i = 0; i < SEGMENTS; i++) - { - leds[thisPixel + i] = color; - } -} - - -// функция получения цвета пикселя по его номеру -uint32_t getPixColor(uint32_t thisSegm) -{ - uint32_t thisPixel = thisSegm * SEGMENTS; - if (thisPixel > NUM_LEDS - 1) return 0; - return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b); -} - -// функция получения цвета пикселя в матрице по его координатам -uint32_t getPixColorXY(uint8_t x, uint8_t y) -{ - return getPixColor(XY(x, y)); -} - -// **************** НАСТРОЙКА МАТРИЦЫ **************** -#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 XY(uint8_t x, uint8_t y) -{ - if (!(THIS_Y & 0x01) || MATRIX_TYPE) // Even rows run forwards - return (THIS_Y * _WIDTH + THIS_X); - else - return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); // Odd rows run backwards -} - -// оставлено для совместимости со эффектами из старых прошивок -uint16_t getPixelNumber(uint8_t x, uint8_t y) -{ - return XY(x, y); -} - - // Gamma коррекция (Defalt Gamma = 2.8) - const uint8_t PROGMEM gammaR[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, - 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, - 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, - 33, 34, 35, 36, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 46, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 80, - 81, 83, 84, 85, 87, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, - 104, 105, 107, 109, 110, 112, 113, 115, 116, 118, 120, 121, 123, 125, 127, 128, - 130, 132, 134, 135, 137, 139, 141, 143, 145, 146, 148, 150, 152, 154, 156, 158, - 160, 162, 164, 166, 168, 170, 172, 174, 177, 179, 181, 183, 185, 187, 190, 192, - 194, 196, 199, 201, 203, 206, 208, 210, 213, 215, 218, 220, 223, 225, 227, 230 - }; - - const uint8_t PROGMEM gammaG[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, - 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, - 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, - 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, - 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, - 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, - 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, - 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, - 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114, - 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142, - 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175, - 177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, - 215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255 - }; - - const uint8_t PROGMEM gammaB[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, - 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 8, - 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 12, 13, - 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, - 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, - 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40, - 40, 41, 42, 43, 44, 44, 45, 46, 47, 48, 49, 50, 51, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 70, - 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, - 90, 92, 93, 94, 96, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 112, - 113, 115, 116, 118, 119, 121, 122, 124, 126, 127, 129, 131, 132, 134, 136, 137, - 139, 141, 143, 144, 146, 148, 150, 152, 153, 155, 157, 159, 161, 163, 165, 167, - 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 196, 198, 200 - }; - - // гамма-коррекция (более натуральные цвета) - uint32_t gammaCorrection(uint32_t color) { - byte r = (color >> 16) & 0xFF; // Extract the RR byte - byte g = (color >> 8) & 0xFF; // Extract the GG byte - byte b = color & 0xFF; // Extract the BB byte - - r = pgm_read_byte(&gammaR[r]); - g = pgm_read_byte(&gammaG[g]); - b = pgm_read_byte(&gammaB[b]); - - uint32_t newColor = ((long)(r & 0xff) << 16) + ((long)(g & 0xff) << 8) + ((long)b & 0xff); - return newColor; - } - - // gamma correction для expandColor - static const uint8_t PROGMEM - gamma5[] = { - 0x00, 0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, - 0x0e, 0x11, 0x14, 0x18, 0x1d, 0x22, 0x28, 0x2e, - 0x36, 0x3d, 0x46, 0x4f, 0x59, 0x64, 0x6f, 0x7c, - 0x89, 0x97, 0xa6, 0xb6, 0xc7, 0xd9, 0xeb, 0xff - }, - gamma6[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, - 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x12, 0x13, - 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x20, 0x22, 0x25, - 0x27, 0x2a, 0x2d, 0x30, 0x33, 0x37, 0x3a, 0x3e, - 0x41, 0x45, 0x49, 0x4d, 0x52, 0x56, 0x5b, 0x5f, - 0x64, 0x69, 0x6e, 0x74, 0x79, 0x7f, 0x85, 0x8b, - 0x91, 0x97, 0x9d, 0xa4, 0xab, 0xb2, 0xb9, 0xc0, - 0xc7, 0xcf, 0xd6, 0xde, 0xe6, 0xee, 0xf7, 0xff - }; - - // преобразовать цвет из 16 битного в 24 битный - static uint32_t expandColor(uint16_t color) { - return ((uint32_t)pgm_read_byte(&gamma5[ color >> 11 ]) << 16) | - ((uint32_t)pgm_read_byte(&gamma6[(color >> 5) & 0x3F]) << 8) | - pgm_read_byte(&gamma5[ color & 0x1F]); - } diff --git a/GyverButtonOld/GyverButton.rar b/GyverButtonOld/GyverButton.rar deleted file mode 100644 index a0913fae148716451f406daea8c426c326a0a608..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3454 zcmV-^4T17fVR9iF2LR8Ia{vGh000000002(RdgVLF900`000UR0006n(cTIrE#gic zGYZ*DGQaBvI(O%TZa6cv4>_^g(sDG*blmWrUDm9(e?j);OD zq)?M&HCRa&&4NM{N`c{hFUppxR3gwm7kB9DQXLW!M)PwwGdH3l!g?MiYi~H)<8L!3 z%)Xp&j~`0o=uPv9bJw1JmFZ2RT5`nnX>jl?$HucP)1{BS=!)u(f5C~>tx9&&LM&Y; z7_)OtqBtpM-7S(-@Z=MUEJ<>8HOZboS=OVima6Q>k!)+W(+tt;P0W#^A5egN5h=-~0Op_W2arS?Ob{=~ zOI!E{roHqxXefuliPFaf9#iE0poPk7r*p*zQj?GPC|dK$9mXKKk)$Jy*v2P+CvH&O za=}fYRhF4;$&m#9(Ore6-GDI7?hC_S>-iMca)}_w5(rAy52&_?eWEb3tedFSs^%FC z>aO}i8buLujSb^&<DsdOS2?1HFy|rWne>Za9DKP*Rd0+ zu#8As@!fGS7>{C;=y0g8j5DWfZh<=mE}Y&yhR&A?!`K`+T<9HA2&?bOzvae1`FxyA ztT$Pt=2F5+`%BWHM+Cb`q0KeM7%a3*OhR~9DVAh}&(9`ObTLM}Aw#roAG_uw7wE^X z#Hma#Qp9Y#5;vwf!QEd!9N}n~{%~3P3o~I1+?ig^i3x!Ll-_eUMu|t?UX9QN`|2R$ z{CnMCnirT;zqt+&XkxeL+(1uIoDf&G`C$i^3!X)Cspo-&o^T)(Ise=v&h^2m{NX`6 z>=s^`h)j%vH}-3xzDBv4=WF^#yDdh#fk2pXkQpG4;fT|hpuML@X7ZDZ;{D=H!=C8y z_ITj_-kf_}j2>UU&<`CJ0iDlWflT8e8@Dtq^pl6E*C~>SkZD5H2D|X?L{1vV>U#)H z-W?}%f`lwj#kp3YRXR%-0TfqUV6grI9T2ey_D(fT256;f6CbP$F2?y=<7=c1E~JdO z&<16e3*A(yXF5Rp!P@b*!ob;Ei;J9)8?2}VLdATPnt6nyFLLDJs(BwE$r&OD-m}lV zhP#(a8C@V>b%p@}l1BMj{WZ?t)Gn8yugKure2ww9_kDFI;eP;jL)xMEV3qNtadAQ# zu1Dckl>`Li`chAnXAuiT2bPxspbkY8K^X9Kv0II6@CC0of?JR#0_O`u_y#{ojQCx7 z(*!w6r{|2NOmydX!7~pu4Tl}$!VM;aC9JmEdY84004Cu0007% zpC6SaE#gicGYtSB0000-d3I%TLUnX>Z*DGV3>{Gr$kWZ8SGax^iB6W{a2qD>sj%JD zjR~?uqyb19I~oS?2DFWdykb#B5`gw>nt=ja-@hfk07ndl0LFMLen+Y|93yz&Dz5S6 z<~(9>o7f~ZnO9d;%K2Shc*TDRx%%xZReZX;N|o1VQeK?NOX;oK@@y|V@1VmIW=PeA z)C8r>UHMxIPPGeEx7m|ARS%4ti>voSg^ksPh@raOWvcq>v_JU=?MmBKS*yoae$sGS z3ftWEI=r@)udrzTb*PU%I^Uri**C$4;p*`$TZ-OrOV(Z?0M&FxKHDgJG)Rs*`Q|M= zUyc2Tp9oG=23)ock~ZwzWCMSz$ZLYyb&pxLsk*PQxNDTjBXJO7ZZ@88=cZi{h zL8VsdPT)ob1=={@>2hcQBY-Ca$2dfw`R<+*dou9DwcGcN>#}izq8dO3a!}%6Kw?Ep z*$GmGfx?uN9OhDd^@@oVktk}?c|#H$@SH-n|J0ool>(KiUE+M3;V3{9n@2?uZc7^h z0e{z`_KvT~*)oGdsbGj9TZB1{49ZQ>Vxpk3tNsH{B7tjqhoWcItNmh)HMWfwOxGd~ z4qB-wpG9H7S!TB3Nry4LuTmWP3IW=XR_o$WlMO-T&;!DwTXkav-r3SA88{?CS|=zQ zCr_|8(t*0;RpLocIio{WThLAMvMrF(5CJTm5~flEw0ld8dBl47HGjfMk6|Wglwj$A zLdxFkt&fWz9Ope~{ft=Md|Y_Z{cx+9Mm(D9ml#vnokB|xyrG2B zn>Sf)CMHOFYMCgtdMgr{v_#p)s;&KP@hQa2_}Hr+8DqzOwo= z*L+txa`WfBCvoNV-=wC@Un^Q&*X%xQ$H?iM7tHUDY^8mP%vjhZJMI|ymFI8p02%oY zp6uOtkfBMnH!`-Q8$$BJTGmj~0p7^*S;Fwf0c>_8F>3kvnHY)w#>Pys2-x?F=&6wd zndE}u=zz!cXu%=*sC1~^BPrXea`Q1xgfcJS+qOZ zz9aI8oB{XV&gj~*OWSnJ&G2{RX6JUZD~IQmZ(bhIq^F<2MCx~}^8&~m1wl?VyLp*$ zQYcB7s%_+8=vx1dR#kKy;YBc$x~pzynt))D4DFj*iP-tI{VBV~>;PTHrwt1l+Q*X{ zSbO!WuG#@@062if;2wN~Oza!ORxffDEIR%U#MyF|p1T=q=?e%+T;`HL)FzfvNTPrO zz-U?jnx*FpxGYsLOtRgG!sJb@5zt0_zZ&iC!=QE$K>%-mSG?ib#rHHgFdtqr z0Ez())%_SJ3-r(nVVO?@c`ydvuU{!ZqV zJXy9Hw$MYO=t3gYgb8_%gUcvBsDnHrtrwaBabDL_+LI+J70Z`7c`Qp8czbo;fH4Dc za+9bUtHysx*eZAHJ7LJG-AfT#fX`1Ej=Xe`c77rE@^dsYO8J>O8TqjVkV4@Z?u^db zDP1apJg*Un%bAQ5-y=Gh4zH?a(i=`AUBe*z&)@<`1U}%}BOGF|Cf!~U{^md`ql0{e zVH+e~KX+axAQc4Ag)_UqLON)bCOQ{kp)cPa~q3?<}z+u zfF%T-B=EYV(mc#uV^fa-xdLL~dcX{*mrfFIdb^|9=R?8p)&A=G&wa9qF1-Ruj)V>5 zM|w@Orm?Q5Ejd8|ZWau_?-KXnrq!Rr;D--$E??=MkhLtP9b6+h>^XA(kc3BawEp0j zrd;Ds=GOZ-F`8z1Pdvs#P_X&B`YCDZ!S5~6?AE>JVr8NDLocKbZ>?{Xt zsnYffx&nBbx?Hvb*zAD+xZ>Jn`i(amNd?&>?OHZM96992AFbABZ);!Yhi3;-Yi003)c zd3SGeWOFWbcytUEP{_~KK^JiTDWqw)WuFF6AVp6Ucqp!@i3X%5i!+II6$knc1Xzyf-wc+Y2iU(CZf`MRf>- zf9)jEz;q2dv6?OVF_jczq*It)$C6^Y4wjpoqx>Znk(;VDgJk^TO}F*_e-kMcA~_jK zsO=WbI0Y?ZtJjX|sdmQW`snBaA^1b1JUyCL<6-WHk{!(Bx+0n9uJZaIdK~yg2L)fz g3{Am=Z0}@^q(|6-Z;fPv#L~i-zoNuFdjLQO0OZ<~j{pDw diff --git a/GyverButtonOld/GyverButtonOld.cpp b/GyverButtonOld/GyverButtonOld.cpp deleted file mode 100644 index aba8a17..0000000 --- a/GyverButtonOld/GyverButtonOld.cpp +++ /dev/null @@ -1,199 +0,0 @@ -#include "GyverButtonOld.h" -#include - -GButton::GButton(uint8_t pin) { - _PIN = pin; - GButton::init(); -} -GButton::GButton(uint8_t pin, boolean type, boolean dir) { - _PIN = pin; - GButton::init(); - GButton::setType(type); - flags.inv_state = dir; -} - -void GButton::init() { - _debounce = 60; - _timeout = 500; - _step_timeout = 400; - _click_timeout = 300; - flags.inv_state = NORM_OPEN; - flags.mode = false; - flags.type = false; - flags.tickMode = false; - GButton::setType(HIGH_PULL); -} - -void GButton::setDebounce(uint16_t debounce) { - _debounce = debounce; -} -void GButton::setTimeout(uint16_t timeout) { - _timeout = timeout; -} -void GButton::setClickTimeout(uint16_t timeout) { - _click_timeout = timeout; -} -void GButton::setStepTimeout(uint16_t step_timeout) { - _step_timeout = step_timeout; -} -void GButton::setType(boolean type) { - flags.type = type; - if (type) pinMode(_PIN, INPUT); - else pinMode(_PIN, INPUT_PULLUP); -} -void GButton::setDirection(boolean dir) { - flags.inv_state = dir; -} -void GButton::setTickMode(boolean tickMode) { - flags.tickMode = tickMode; -} - -boolean GButton::isPress() { - if (flags.tickMode) GButton::tick(); - if (flags.isPress_f) { - flags.isPress_f = false; - return true; - } else return false; -} -boolean GButton::isRelease() { - if (flags.tickMode) GButton::tick(); - if (flags.isRelease_f) { - flags.isRelease_f = false; - return true; - } else return false; -} -boolean GButton::isClick() { - if (flags.tickMode) GButton::tick(); - if (flags.isOne_f) { - flags.isOne_f = false; - return true; - } else return false; -} -boolean GButton::isHolded() { - if (flags.tickMode) GButton::tick(); - if (flags.isHolded_f == 1) { - flags.isHolded_f = 0; - return true; - } else return false; -} - -boolean GButton::isHolded2() { - if (flags.tickMode) GButton::tick(); - if (flags.isHolded_f == 2) { - flags.isHolded_f = 0; - return true; - } else return false; -} -boolean GButton::isHolded3() { - if (flags.tickMode) GButton::tick(); - if (flags.isHolded_f == 3) { - flags.isHolded_f = 0; - return true; - } else return false; -} -boolean GButton::isHold() { - if (flags.tickMode) GButton::tick(); - if (flags.step_flag) return true; - else return false; -} -boolean GButton::state() { - if (flags.tickMode) GButton::tick(); - return flags.btn_state; -} -boolean GButton::isSingle() { - if (flags.tickMode) GButton::tick(); - if (flags.counter_flag && last_counter == 1) { - flags.counter_flag = false; - return true; - } else return false; -} -boolean GButton::isDouble() { - if (flags.tickMode) GButton::tick(); - if (flags.counter_flag && last_counter == 2) { - flags.counter_flag = false; - return true; - } else return false; -} -boolean GButton::isTriple() { - if (flags.tickMode) GButton::tick(); - if (flags.counter_flag && last_counter == 3) { - flags.counter_flag = false; - return true; - } else return false; -} -boolean GButton::hasClicks() { - if (flags.tickMode) GButton::tick(); - if (flags.counter_flag) { - flags.counter_flag = false; - return true; - } else return false; -} -uint8_t GButton::getClicks() { - return last_counter; -} -boolean GButton::isStep() { - if (flags.tickMode) GButton::tick(); - if (flags.step_flag && (millis() - btn_timer >= _step_timeout)) { - btn_timer = millis(); - return true; - } - else return false; -} -void GButton::tick(boolean state) { - flags.mode = true; - flags.btn_state = state ^ flags.inv_state; - GButton::tick(); - flags.mode = false; -} -void GButton::tick() { - // - if (!flags.mode) flags.btn_state = !digitalRead(_PIN) ^ (flags.inv_state ^ flags.type); - - // - if (flags.btn_state && !flags.btn_flag) { - if (!flags.btn_deb) { - flags.btn_deb = true; - btn_timer = millis(); - } else { - if (millis() - btn_timer >= _debounce) { - flags.btn_flag = true; - flags.isPress_f = true; - flags.oneClick_f = true; - } - } - } else { - flags.btn_deb = false; - } - - // - if (!flags.btn_state && flags.btn_flag) { - flags.btn_flag = false; - if (!flags.hold_flag) btn_counter++; - flags.hold_flag = false; - flags.isRelease_f = true; - btn_timer = millis(); - flags.step_flag = false; - if (flags.oneClick_f) { - flags.oneClick_f = false; - flags.isOne_f = true; - } - } - - // - if (flags.btn_flag && flags.btn_state && (millis() - btn_timer >= _timeout) && !flags.hold_flag) { - flags.hold_flag = true; - flags.isHolded_f = btn_counter + 1; - btn_counter = 0; - last_counter = 0; - flags.step_flag = true; - flags.oneClick_f = false; - btn_timer = millis(); - } - - // - if ((millis() - btn_timer >= _click_timeout) && (btn_counter != 0)) { - last_counter = btn_counter; - btn_counter = 0; - flags.counter_flag = true; - } -} diff --git a/GyverButtonOld/GyverButtonOld.h b/GyverButtonOld/GyverButtonOld.h deleted file mode 100644 index 2216164..0000000 --- a/GyverButtonOld/GyverButtonOld.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef GyverButtonOld_h -#define GyverButton_h -#include - -/* - GyverButton - библиотека для многофункциональной отработки нажатия кнопки. Возможности: - - Работа с нормально замкнутыми и нормально разомкнутыми кнопками - - Работа с подключением PULL_UP и PULL_DOWN - - Опрос кнопки с программным антидребезгом контактов - - Настраиваемое время антидребезга - - Отработка нажатия, удерживания, отпускания, клика по кнопке - - Настраиваемый таймаут удержания - - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) - - Отработка любого количества нажатий кнопки (функция возвращает количество нажатий) - - Настраиваемый таймаут повторного нажатия/удержания - - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени - - Возможность опрашивать не кнопку, а напрямую давать величину (все возможности библиотеки для матричных и резистивных клавиатур) - - Текущая версия: 2.12 от 18.03.2019: - - Поправлены баги при совместной работе методов опроса -*/ - -#pragma pack(push,1) -typedef struct -{ - bool btn_state: 1; - bool btn_deb: 1; - bool btn_flag: 1; - bool hold_flag: 1; - bool counter_flag: 1; - uint8_t isHolded_f: 3; - bool isRelease_f: 1; - bool isPress_f: 1; - bool step_flag: 1; - bool oneClick_f: 1; - bool isOne_f: 1; - bool inv_state: 1; - bool mode: 1; - bool type: 1; - bool tickMode: 1; -} GyverButtonFlags; -#pragma pack(pop) - -class GButton -{ - public: - GButton(uint8_t pin); // класс кнопки, принимает пин - - GButton(uint8_t pin, boolean type, boolean dir); // класс кнопки, принимает PIN пин, тип type (HIGH_PULL / LOW_PULL) и направление dir (NORM_OPEN / NORM_CLOSE) - // HIGH_PULL - кнопка подключена к GND, пин подтянут к VCC, pinMode - INPUT_PULLUP (по умолчанию) - // LOW_PULL - кнопка подключена к VCC, пин подтянут к GND, pinMode - INPUT - // NORM_OPEN - кнопка по умолчанию разомкнута (по умолчанию) - // NORM_CLOSE - кнопка по умолчанию замкнута - - void setDebounce(uint16_t debounce); // установка времени антидребезга (по умолчанию 80 мс) - void setTimeout(uint16_t timeout); // установка таймаута удержания (по умолчанию 300 мс) - void setClickTimeout(uint16_t timeout); // установка таймаута между кликами (по умолчанию 500 мс) - void setStepTimeout(uint16_t step_timeout); // установка таймаута между инкрементами (по умолчанию 400 мс) - void setType(boolean type); // установка типа кнопки (HIGH_PULL - подтянута к питанию, LOW_PULL - к gnd) - void setDirection(boolean dir); // установка направления (разомкнута/замкнута по умолчанию - NORM_OPEN, NORM_CLOSE) - - void setTickMode(boolean tickMode); // (MANUAL / AUTO) ручной или автоматический опрос кнопки функцией tick() - // MANUAL - нужно вызывать функцию tick() вручную - // AUTO - tick() входит во все остальные функции и опрашивается сама - - - void tick(); // опрос кнопки - void tick(boolean state); // опрос внешнего значения (0 нажато, 1 не нажато) (для матричных, резистивных клавиатур и джойстиков) - - boolean isPress(); // возвращает true при нажатии на кнопку. Сбрасывается после вызова - boolean isRelease(); // возвращает true при отпускании кнопки. Сбрасывается после вызова - boolean isClick(); // возвращает true при клике. Сбрасывается после вызова - boolean isHolded(); // возвращает true при удержании дольше timeout. Сбрасывается после вызова - boolean isHolded2(); // возвращает true при двойном нажатии и удержании дольше timeout. Сбрасывается после вызова - boolean isHolded3(); // возвращает true при тройном нажатии и удержании дольше timeout. Сбрасывается после вызова - boolean isHold(); // возвращает true при нажатой кнопке, не сбрасывается - boolean state(); // возвращает состояние кнопки - - boolean isSingle(); // возвращает true при одиночном клике. Сбрасывается после вызова - boolean isDouble(); // возвращает true при двойном клике. Сбрасывается после вызова - boolean isTriple(); // возвращает true при тройном клике. Сбрасывается после вызова - - boolean hasClicks(); // проверка на наличие кликов. Сбрасывается после вызова - uint8_t getClicks(); // вернуть количество кликов - - boolean isStep(); // возвращает true по таймеру setStepTimeout, смотри пример - - private: - void init(); - GyverButtonFlags flags; - uint8_t _PIN = 0; - uint16_t _debounce = 0; - uint16_t _timeout = 0; - uint16_t _click_timeout = 0; - uint16_t _step_timeout = 0; - uint8_t btn_counter = 0, last_counter = 0; - uint32_t btn_timer = 0; -}; - -#define HIGH_PULL 0 -#define LOW_PULL 1 -#define NORM_OPEN 0 -#define NORM_CLOSE 1 -#define MANUAL 0 -#define AUTO 1 - -#endif diff --git a/GyverButtonOld/examples/Gbutton_example/Gbutton_example.ino b/GyverButtonOld/examples/Gbutton_example/Gbutton_example.ino deleted file mode 100644 index d1aefa4..0000000 --- a/GyverButtonOld/examples/Gbutton_example/Gbutton_example.ino +++ /dev/null @@ -1,50 +0,0 @@ -/* - Пример использования библиотеки GyverButton, все возможности в одном скетче. -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(PIN); -// GButton butt1(PIN, HIGH_PULL, NORM_OPEN); // можно инициализировать так - -int value = 0; - -void setup() { - Serial.begin(9600); - - butt1.setDebounce(50); // настройка антидребезга (по умолчанию 80 мс) - butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) - butt1.setClickTimeout(600); // настройка таймаута между кликами (по умолчанию 300 мс) - - // HIGH_PULL - кнопка подключена к GND, пин подтянут к VCC (PIN --- КНОПКА --- GND) - // LOW_PULL - кнопка подключена к VCC, пин подтянут к GND - butt1.setType(HIGH_PULL); - - // NORM_OPEN - нормально-разомкнутая кнопка - // NORM_CLOSE - нормально-замкнутая кнопка - butt1.setDirection(NORM_OPEN); -} - -void loop() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - - if (butt1.isClick()) Serial.println("Click"); // проверка на один клик - if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик - if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик - if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик - - if (butt1.hasClicks()) // проверка на наличие нажатий - Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий - - if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) - if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) - if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание - if (butt1.isHold()) Serial.println("Holding"); // проверка на удержание - //if (butt1.state()) Serial.println("Hold"); // возвращает состояние кнопки - - if (butt1.isStep()) { // если кнопка была удержана (это для инкремента) - value++; // увеличивать/уменьшать переменную value с шагом и интервалом - Serial.println(value); // для примера выведем в порт - } -} diff --git a/GyverButtonOld/examples/Gbutton_example_auto/Gbutton_example_auto.ino b/GyverButtonOld/examples/Gbutton_example_auto/Gbutton_example_auto.ino deleted file mode 100644 index 10e46b8..0000000 --- a/GyverButtonOld/examples/Gbutton_example_auto/Gbutton_example_auto.ino +++ /dev/null @@ -1,53 +0,0 @@ -/* - Пример использования библиотеки GyverButton, все возможности в одном скетче. -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(PIN); -// GButton butt1(PIN, HIGH_PULL, NORM_OPEN); // можно инициализировать так - -int value = 0; - -void setup() { - Serial.begin(9600); - - butt1.setDebounce(90); // настройка антидребезга (по умолчанию 80 мс) - butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) - - // HIGH_PULL - кнопка подключена к GND, пин подтянут к VCC (PIN --- КНОПКА --- GND) - // LOW_PULL - кнопка подключена к VCC, пин подтянут к GND - butt1.setType(HIGH_PULL); - - // NORM_OPEN - нормально-разомкнутая кнопка - // NORM_CLOSE - нормально-замкнутая кнопка - butt1.setDirection(NORM_OPEN); - - // MANUAL - нужно вызывать функцию tick() вручную - // AUTO - tick() входит во все остальные функции и опрашивается сама! - butt1.setTickMode(AUTO); -} - -void loop() { - // butt1.tick(); // не нужна, в этом режиме (AUTO) она входит в каждую функцию - - if (butt1.isClick()) Serial.println("Click"); // проверка на один клик - if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик - if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик - if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик - - if (butt1.hasClicks()) // проверка на наличие нажатий - Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий - - if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) - if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) - if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание - if (butt1.isHold()) Serial.println("Holding"); // проверка на удержание - //if (butt1.state()) Serial.println("Hold"); // возвращает состояние кнопки - - if (butt1.isStep()) { // если кнопка была удержана (это для инкремента) - value++; // увеличивать/уменьшать переменную value с шагом и интервалом - Serial.println(value); // для примера выведем в порт - } -} diff --git a/GyverButtonOld/examples/Gbutton_interrupt/Gbutton_interrupt.ino b/GyverButtonOld/examples/Gbutton_interrupt/Gbutton_interrupt.ino deleted file mode 100644 index b529801..0000000 --- a/GyverButtonOld/examples/Gbutton_interrupt/Gbutton_interrupt.ino +++ /dev/null @@ -1,48 +0,0 @@ -/* - Пример использования библиотеки GyverButton, все возможности в одном скетче. - - Опрос кнопки с программным антидребезгом контактов - - Отработка нажатия, удерживания отпускания кнопки - - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) - - Отработка любого количества нажатий кнопки (функция возвращает число нажатий) - - Отработка нажатия и удержания кнопки - - Настраиваемый таймаут повторного нажатия/удержания - - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(PIN); -int value = 0; - -void setup() { - Serial.begin(9600); - attachInterrupt(1, isr, CHANGE); - - butt1.setDebounce(80); // настройка антидребезга (по умолчанию 80 мс) - butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) -} - -void isr() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться -} - -void loop() { - if (butt1.isClick()) Serial.println("Click"); // проверка на один клик - if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик - if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик - if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик - - if (butt1.hasClicks()) // проверка на наличие нажатий - Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий - - if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) - if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) - if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание - //if (butt1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки - - if (butt1.isStep()) { // если кнопка была удержана (это для инкремента) - value++; // увеличивать/уменьшать переменную value с шагом и интервалом - Serial.println(value); // для примера выведем в порт - } -} diff --git a/GyverButtonOld/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino b/GyverButtonOld/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino deleted file mode 100644 index 1db28f8..0000000 --- a/GyverButtonOld/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino +++ /dev/null @@ -1,51 +0,0 @@ -/* - Пример использования библиотеки GyverButton, все возможности в одном скетче. - - Опрос кнопки с программным антидребезгом контактов - - Отработка нажатия, удерживания отпускания кнопки - - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) - - Отработка любого количества нажатий кнопки (функция возвращает число нажатий) - - Отработка нажатия и удержания кнопки - - Настраиваемый таймаут повторного нажатия/удержания - - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени - Данный скетч показывает, как быть в сложном "не сквозном" коде с кучей delay и замкнутых циклов - Здесь кнопка опрашивается каждые 10 миллисекунд независимо от того, что происходит у вас в коде - Используется библиотека TimerOne https://github.com/PaulStoffregen/TimerOne -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -#include "TimerOne.h" -GButton butt1(PIN); -int value = 0; - -void setup() { - Serial.begin(9600); - - Timer1.initialize(10000); // установка таймера на каждые 10000 микросекунд (= 10 мс) - Timer1.attachInterrupt(timerIsr); // запуск таймера -} - -void timerIsr() { // прерывание таймера - butt1.tick(); // отработка теперь находится здесь -} - -void loop() { - if (butt1.isClick()) Serial.println("Click"); // проверка на один клик - if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик - if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик - if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик - - if (butt1.hasClicks()) // проверка на наличие нажатий - Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий - - if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) - if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) - if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание - //if (butt1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки - - if (butt1.isStep()) { // если кнопка была удержана (это для инкремента) - value++; // увеличивать/уменьшать переменную value с шагом и интервалом - Serial.println(value); // для примера выведем в порт - } -} diff --git a/GyverButtonOld/examples/_1-2-3-click/_1-2-3-click.ino b/GyverButtonOld/examples/_1-2-3-click/_1-2-3-click.ino deleted file mode 100644 index a4118f5..0000000 --- a/GyverButtonOld/examples/_1-2-3-click/_1-2-3-click.ino +++ /dev/null @@ -1,20 +0,0 @@ -/* - Пример использования библиотеки GyverButton, 1- 2- 3- нажатие -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(PIN); - -void setup() { - Serial.begin(9600); -} - -void loop() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - - if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик - if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик - if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик -} diff --git a/GyverButtonOld/examples/_5_buttons/_5_buttons.ino b/GyverButtonOld/examples/_5_buttons/_5_buttons.ino deleted file mode 100644 index edeec32..0000000 --- a/GyverButtonOld/examples/_5_buttons/_5_buttons.ino +++ /dev/null @@ -1,34 +0,0 @@ -/* - Пример использования библиотеки GyverButton, 5 кнопок -*/ - -#define BTN1 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN2 4 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN3 5 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN4 6 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN5 7 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(BTN1); -GButton butt2(BTN2); -GButton butt3(BTN3); -GButton butt4(BTN4); -GButton butt5(BTN5); - -void setup() { - Serial.begin(9600); -} - -void loop() { - butt1.tick(); - butt2.tick(); - butt3.tick(); - butt4.tick(); - butt5.tick(); - - if (butt1.isClick()) Serial.println("Button 1"); - if (butt2.isClick()) Serial.println("Button 2"); - if (butt3.isClick()) Serial.println("Button 3"); - if (butt4.isClick()) Serial.println("Button 4"); - if (butt5.isClick()) Serial.println("Button 5"); -} diff --git a/GyverButtonOld/examples/_5_buttons_auto/_5_buttons_auto.ino b/GyverButtonOld/examples/_5_buttons_auto/_5_buttons_auto.ino deleted file mode 100644 index 2fff75e..0000000 --- a/GyverButtonOld/examples/_5_buttons_auto/_5_buttons_auto.ino +++ /dev/null @@ -1,34 +0,0 @@ -/* - Пример использования библиотеки GyverButton, 5 кнопок - Режим опроса - автоматический -*/ - -#define BTN1 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN2 4 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN3 5 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN4 6 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN5 7 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(BTN1); -GButton butt2(BTN2); -GButton butt3(BTN3); -GButton butt4(BTN4); -GButton butt5(BTN5); - -void setup() { - Serial.begin(9600); - butt1.setTickMode(AUTO); - butt2.setTickMode(AUTO); - butt3.setTickMode(AUTO); - butt4.setTickMode(AUTO); - butt5.setTickMode(AUTO); -} - -void loop() { - if (butt1.isClick()) Serial.println("Button 1"); - if (butt2.isClick()) Serial.println("Button 2"); - if (butt3.isClick()) Serial.println("Button 3"); - if (butt4.isClick()) Serial.println("Button 4"); - if (butt5.isClick()) Serial.println("Button 5"); -} diff --git a/GyverButtonOld/examples/analogKeyboard/analogKeyboard.ino b/GyverButtonOld/examples/analogKeyboard/analogKeyboard.ino deleted file mode 100644 index 490a2f7..0000000 --- a/GyverButtonOld/examples/analogKeyboard/analogKeyboard.ino +++ /dev/null @@ -1,32 +0,0 @@ -#include "GyverButton.h" - -// пин подключения не важен, лучше какой-нибудь ненужный -GButton myButt1(3, LOW_PULL, NORM_OPEN); -GButton myButt2(3, LOW_PULL, NORM_OPEN); -GButton myButt3(3, LOW_PULL, NORM_OPEN); - -void setup() { - Serial.begin(9600); -} - -void loop() { - int analog = analogRead(7); - //Serial.println(analog); - - myButt1.tick(analog < 860 && analog > 820); - myButt2.tick(analog < 740 && analog > 700); - myButt3.tick(analog < 650 && analog > 600); - - if (myButt1.isHolded()) { - Serial.println("hold 1"); - } - if (myButt2.isHolded()) { - Serial.println("hold 2"); - } - if (myButt3.isHolded()) { - Serial.println("hold 3"); - } - - delay(10); - -} diff --git a/GyverButtonOld/examples/increment/increment.ino b/GyverButtonOld/examples/increment/increment.ino deleted file mode 100644 index d0ace38..0000000 --- a/GyverButtonOld/examples/increment/increment.ino +++ /dev/null @@ -1,41 +0,0 @@ -/* - Пример использования библиотеки GyverButton, управляем переменной value при помощи двух кнопок - Конструкция с isIncr делает увеличение/уменьшение переменной при нажатой кнопке с шагом по времени -*/ - -#define BTN1 2 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN2 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(BTN1); -GButton butt2(BTN2); -int value = 0; - -void setup() { - Serial.begin(9600); -} - -void loop() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - butt2.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - - if (butt1.isClick()) { // одиночное нажатие - value++; // инкремент - Serial.println(value); // для примера выведем в порт - } - - if (butt2.isClick()) { // одиночное нажатие - value--; // декремент - Serial.println(value); // для примера выведем в порт - } - - if (butt1.isStep()) { // обработчик удержания с шагами - value++; // увеличивать/уменьшать переменную value с шагом и интервалом! - Serial.println(value); // для примера выведем в порт - } - - if (butt2.isStep()) { // обработчик удержания с шагами - value--; // увеличивать/уменьшать переменную value с шагом и интервалом! - Serial.println(value); // для примера выведем в порт - } -} diff --git a/GyverButtonOld/examples/many_clicks/many_clicks.ino b/GyverButtonOld/examples/many_clicks/many_clicks.ino deleted file mode 100644 index 63d42e2..0000000 --- a/GyverButtonOld/examples/many_clicks/many_clicks.ino +++ /dev/null @@ -1,19 +0,0 @@ -/* - Пример использования библиотеки GyverButton, отработка любого количества нажатий -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#include "GyverButton.h" -GButton butt1(PIN); - -void setup() { - Serial.begin(9600); - butt1.setTimeout(400); // настройка таймаута на удержание и второй клик (по умолчанию 500 мс) -} - -void loop() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - - if (butt1.hasClicks()) // проверка на наличие нажатий - Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий -} diff --git a/GyverButtonOld/keywords.txt b/GyverButtonOld/keywords.txt deleted file mode 100644 index e4173ba..0000000 --- a/GyverButtonOld/keywords.txt +++ /dev/null @@ -1,48 +0,0 @@ -####################################### -# Syntax Coloring Map For GyverButton -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -GButton KEYWORD1 -GyverButtonOld KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -setDebounce KEYWORD2 -setTimeout KEYWORD2 -setStepTimeout KEYWORD2 -setClickTimeout KEYWORD2 -setType KEYWORD2 -setDirection KEYWORD2 -setTickMode KEYWORD2 - -tick KEYWORD2 -isPress KEYWORD2 -isRelease KEYWORD2 -isClick KEYWORD2 -isHolded KEYWORD2 -isHold KEYWORD2 -state KEYWORD2 - -hasClicks KEYWORD2 -getClicks KEYWORD2 -isSingle KEYWORD2 -isDouble KEYWORD2 -isTriple KEYWORD2 -isStep KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### - -HIGH_PULL LITERAL1 -LOW_PULL LITERAL1 -NORM_OPEN LITERAL1 -NORM_CLOSE LITERAL1 -MANUAL LITERAL1 -AUTO LITERAL1 \ No newline at end of file diff --git a/GyverButtonOld/old_version.rar b/GyverButtonOld/old_version.rar deleted file mode 100644 index 661aae111ab419539b8aca49e94bdd4f736bc4cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8826 zcma)iWl$Z>y7k6_1b3HYL+}K5ceg-rcXxMpw~f2IyE_DTcY<#uK(KtAn^WhWI`@6= z{pMHCRQ0N{002mUKi3V&ku+8v5CjbXBq0I-kgM(O{0@!= zGDJ-508&x_z{b*0$JxlU_v&plL6rBQzAB%X=wJw&H#EPfCu7Uvmw zBRJT6;TWC%{I0vP+xF!(21=>Fn4c}nW>jT-CeM@lBL6U(OM!2eW%$T3wSl>qvk9%W z;xyA{Gu+MbeC#JHnw~T5Ih_Ept;IfMk6;VmiA@8Qko3I3$2M!;W!9>BLnddyltqb}X zQV9Z^XTJ6OM?QNAp!xo|0p;1<>;wuD@)rbACyOO7Jm7~xxlhNb%<+(YA3TgiJ8h?5 z&+~XnYliA0zB-WHIX^uRwv)OE7;H2wxUpUlHFk#8jpF5tSSHcQ(fh_Dl^UoNTBVgA zi3XfXS(H``s*lUbN7$K;J{D365K_Chn)6AN%EmD^jG}T2pX6z3`Rv|vDpRCs9FjyxE&MpaTW~$U}Lvw+bg`r9bv2{(sw>qnVYFy^fi+qmjM6lda>w zZ02Xr{k#Esv({vfIPdydA7f{;% zF;PsT6Z5?Yj?A#2_77Sj|!SwY5gGJ$I_O+Av*KC^oRx2AM zUWk`1i}ZSwbJv$Na%W|A^CkD1NOn^zBmr@z+%a*BsS^&!LxZQl(Vw$^g3gi;y|21Js2E=+pMVgxC37p5 zgWvDmPo5Fn_g5;UR+>tUdU%SUyt4&Md#H@axRYMttt*9`W@@(zyNW2 zMCC`7#U^E83XEorBoo|sX@^C6iNw2OI49|Dt(m(rlSIKyU(Wr8X_}DOIC~E~Fy$eo zXfs>+sOfErasAC-C{&GLE<+<6oM%n+(LM1c@vE|VdzqwIDvbK1yNAzbosZE}a^*kL zneBuOJWZu6k1AM-UnNU(Hn8(ZAEfesqz)c!A^U3-&=xaR$kF)#kq!nl$s+g6*u@N&UJhgXlYwSUiO69q+E>W;0 zb*+d#Ht?-MT!r{XvOlt|P7PA>B3_9K>A_3zKg^4gzf;vQ#%sO3yD zUJ5AF=)GjjZk>NnuS>c?y4W(SFbl}dsz8guj0w(l(|m(&?cc1@N{ScwL!Xh z<=pRg_JFA?k3)&~@=v>z{9-qi-uW{b`OeExaXk# zs66!HyFoJrQa%_{8qNZz0T)SWZugKa)4WQ#<`A#>63g;>0zf877=>Ges9QNUQl`HM z>R$Vlipxt>&$Z~+E2~`U=N#^lb8n||3PGH(+3nA&79iOm6O%hRRiws6w~xv63h5}0 z&YtUpRaOQv^F%lU41571OWw#-E~ipYq3yjGw3BzbfmiL=#tqs((J~MA?2<8a{Fclu zz&_`h66-RIt*&mwoI&SXD01xI_+Eye-@1e>fCmZySVnm356G#Yt>hjnqGnA}1ga-~Ug$3R z{q?w(Sh_=^omwJQ_Xpz=;~VwfTCV24XyhJOM3bjmp@D?OF$P?!q2UC4HV?HZXQRz> zE;%vUP2}xs>C}pF_%pw`805)7l}9MFdB4KzZ zA<}^q;U00r=c+5@Y@%K@9?U*|rLcx-N|FHzFT;uXyxE*+I8$W1YN2qPIg`bK;a(dw zlttRMLi1}`g@&)0Gm8lB_fv5w{)|}Y68tRSoXFHzen)}OdX}2 z)EshM(=2b-!rTfq*d8|O?Ye<4Sm@Wu@y*g9Q)hCu@6G!q3#5pT%7&rWsz%rX(I9vg zc-a%?0i;Vd0Du(dp_;r_W+#QwnWX**nO==+&IWMAki18Ga$O@xm4IecNZsps?G}hB zsuvYF;-`6kfnU%dM6S8PP78;agNM|ojbo5!8lgsSYROV>l{{Z+L4F#hYc3KzV&kpC z5dMA!iLu8$z7|D9KKQ1`;$qN`rZcsD!(V9EU7tS!Ie=}PYB^OMn?*+5pB&iU8ZUxn zcsZT;1n`d4I;zr-3s0cuZ1ORm2*%D(-k}Y{Ewl1?ql^aF_!nd!X*WJ> zw{}GN&sa#=QCDo}u8}}bA+E2Fx3#sE?=5|EQ*(23atql~5YWczH8ZLSgT5YomWFT2 zioQhjr%T+FnZFb1$SPTrs7ViKd{#CTNH`eN zD{!d?_~iNfQ<@wEJTX8+Kc$XTy_+818pOW9usEbefqQ$*QnaBGcl+z;Bil5KWL$d7 zr_a*BREKDOTYoY*NUU$%R!~f*v5D&vdvX+F!<#U-UnhSt!j9R9jGaW`X+s?lX%`R1m1 zqVYyWBE5ToPABoQsMo)*;m{x^5KG%d!=)vQp!`w2PR|HWBM7rnh>2!kyI+zkD$>~W zWVhTrbN;O^d9`}fdEkyKx_wJGb@9fX&r?8FztqF{Q~#Ojmf)7~rk9M5Zv{1O_l>St z(hdxvSYNZ8%C3lhLPaEK57$#EyQpS1MCROOW|rpizP<&C4X zxWuS^w9sbC3`R_OX&9d7JjIAX>*0Ti=H+ zj-L(Q()I13saRJ9s$C&n+>9VgUTSz(f#?jzM}Ru^0Bq09`4nChx0+8kWUE2x>+SQO17!wk-3l zSsOP`XDK=)t0OQi-0bUA|G#j7Mdwcf=Afzbui-y= zfF&b8zJcR#86M2(K-o+;WfCh@6{;{NOarECrn9we6+Ora6VReh{AQ2vOs624+|>R4 z?2);yu+`zqP0AMwFplQTG0$AqWdZ!nbVBDD@RP3WjWn|P1&D=)(l3=Sy%V;}C*kR6 zGiBqLZ{{ldeP_tSIFFp`Lu|Ek_$|MKtHLCkd$t*vTQG!Wh{I&fZs^Pk!VkV{!j4%N zSST)&R-t0t55X54IZfY3rtA}t-GN4Q7M?TQxY@ut5JZM{{EHYKY%_z@(SHc$3wzG3 z#JCJYz;sDm@KLq>7-eyr=!r9;ci_)XTC&hW3Ejvn-NhUxBqJb$o|b(PT*~#F*GEg6 zhpE0xPuqv9N6-3QzM(()tSHAJ-)T0`*)=UiCLG+7b+JDhinKg#*0hhQvfqqXI-2uI zY(vjzq)Q0-AaW7HAuUlF_>-1}mNH*Kgr0?-vR@&v zO|Icd_HFri03~lSzK4HXzI#UGhCjSyFf3vW6~cxPafV1H`ZuGQKsa)T>WkVU#>*6HX$@1Pc9@s~U)Xenx4&_k+-1qZj_jLiaI$geskies<5w}IlpD7q}wcf^@iaP`z6Y!|E z48w8|+*sn7KS|&gRn0B3&&yriECr}m;gP}CbCn!yrdTx zfNxH(BAYK!EUq1!bFFPtH6f6$M>T_QTKL){=i<*$8F@-qa{ZNRo}9UxJ<*#0hALX} zDSG<0a0xbmxjvrHX{YN+>@Wd0jUVSK13!EneZrM+Q>F$TjTS|eOxt&@Ayk(=_5&I7 z^sGlPpuc=}8na;mV!&J{Riw75lS_?`h3lb`(TZ|D*l3-$z5`UpUauTVADi#aOxPQ% z*^zgXO?M05J^h>|oQ}%wuT;haevC&+E=$Rx@Y3#bZ@&w~Ge`jMFt~P$itb`D?^bJ$ zqOu&LjhEBS7yQ;-W>Vi1G8=zI*h>h$-ZvOe?Vk+I1RUwawXsxx;OI6W;zi#@+i_&d zYP)7T$f<(o_Aq-O8xp9cbt@GYtnop}i;}1cGq@$j+3Uv%15NMl(Cdy5!3`j=7>~xL zr)T!}tY@*N#v5Me>gOe~;o7O-@oaOq8zdTA*EVH-Fp$@qpDQ0b=21sY8kAA^@S*oi zHIeE6e_YlxPor2BHecBRf>g4@EUrM zJZ2Rxim?DLSYN!1AgZ7pglZ}X7HvxTum}m|5`Z=-Z9)){Js--^5|q-;{5$q%{2R%+ z03C1pp;)*#l8bQUGyfqu-v3H+)3*@*ADf>}tR#=32NiNoO$@>vae3dsP~jY>(AW!e z(QC0Xj>@8+18{=Ek#KOB=v+PGV!rHq%j*syz1qKU3zqjidXzUWnydXj_M~mNIi)1I zIJur(qE<9DxghF2(x`H1vOalGj)eDPJT7_proJt5@;S0%1rMa=HYUs_ z=G3`u_i<9-j4MtlpEW5RlIDly(A1avA;Zad08K&KX|hUenbVx6ea&vW zs?I8f%g_+F56)BWzsLQcciJ!9kUrH~1a7bA-!t*aE>)B;BWsLB1w#t~wn7T5IIG z2LtmhBFU5J(F<=Bp>4S*R5z0(rOynT>4e`jx{5~~XVoSzt)BuyXkWzY&`qUr587va5 z?%`r?Q-uMqB}=tq?;{khZFj1ApSw$GiKWp;1{e|cB_$e29q|ZIxw@wr$2hkaYcskN zDxL#S4Xq-1c6;kiT4<}Q97qUzS8jKPN}K<|zm zOy5(nT`RBO6hluw6dP;eSv0FAl@nl0A?5tB`Q^?1CHMke>`hl|u@8wfO+E$^2<%om zae=6*sI4pUDQA6-cC!Xi!)_ak%4xXGgg*|EeET*T-^R?tnFb<8G-7BvqM^f7>pjFU7Z|&xF(bC!7p*TZh%;4}6k(J59Sx%kjXhj}7(?j6yE7 zq7pfeq3gL+1e1tMLzzXpj8L7YOp;|f6UUR*NYLjl-D=-xz{yCyrH8emH+0ki zS_t_3W>ui8w6R9u3}Cx$hvM+YiQ6tVrsgT)hOSesA^tht1{2j6C+?KsDd}k(;XSbG zR#-)vjS(;rjT;*MI9^F1@9Ox7Hq8JDu17J8|25Qvk~b26bSo&6v*C4&(O-~PkE61WKjPrps55`oXyTAa#AZ3 z1))>TlF5THu1XYC#i{BLHrpYm8zB*@jU+?-`_$kI0$2W#&&vx2rnhqpr`O5A5yN7x zw5Hy~M0K%oTQz4`9T7}ec}-FzoE-T*CjGcI@w{8f1POZns>keKi(YVUU#s>eD!9k5 zt7ELqM#yIBm~7%*Cf3xjzub^a;s4^iFh|HLmKEJ|=yB`<<=U*n?p1 z7^M~%G2oDj74#;y4V=SBG*0mLrQF7hqJk#abkWS5*x=3Y_DdXRdiLj_z6kNbIU?|G z`pvm@u0>H$LAkEx_Gi~u@u}JSE1lWe;2KwiZQ^(6qZmv3a}!y3s%o5#_TW3Y|mmwJB=soZ(YLeznd<(=wDOBdp}i9*r0{4G}PcFqT$ z%cQ4K;}jKM!h*muJ7L$k0+RNc*U+XZKmN$_LTclIme61Irsl(!#hfZj>YHP_t2C82 z`@_?@Cys5)2k$B)88}{PV)QcDWF_F{j{{!&92@vM-XU^0kH2-}lZp zOXR?85Wq@l6>p~8xUf5whIHkbRJmW;kVy(S#km&P0->!bVb|WVzK`eEhT`@7ZZ=_c zB9)83e2K`KvOnl#kk1mT#%8eGkfdHAL(>nL7xbL|gUd9B=N|uqECKiiU;1trCXq$Y zYR=%tC7q4MJ!#f$aeYI-P~TLjdcJo7@YsrUZ9B*g>$SrePxg|T^WIejzfEGqQOPAD4Epbc-)QN0%%X zw3~13Co4E^$4dP3w}Lk{{$nKJK_QFz1qeVT{r~%u001@(@&9f12Bh#;K(zli(0`oG z0l;a`{vg#iK%u_^B>sEAe}%dL@Pu6evdkNV$X`K_{yoIMMNt6o%VB`n+8c=IUxASQ zJ;=XD4FE8IKp+YI8;bB>p^*G9DF6CQ1%T}y0^iNQVQ~Bv2Ik*l0KoEPf!Ek?6Tke` V#P|O>5daqB@E_pu0Pw>C{vVaVQ_=tc diff --git a/GyverButtonOld/old_version/GyverButton.cpp b/GyverButtonOld/old_version/GyverButton.cpp deleted file mode 100644 index 35feee7..0000000 --- a/GyverButtonOld/old_version/GyverButton.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "GyverButton.h" -#include - -GButton::GButton(uint8_t BUTT) { - _BUTT = BUTT; - _debounce = 80; - _timeout = 500; - _incr_timeout = 800; - step = 1; - pinMode (_BUTT, INPUT_PULLUP); -} - -void GButton::setDebounce(uint8_t debounce) { - _debounce = debounce; -} -void GButton::setTimeout(uint16_t timeout) { - _timeout = timeout; -} -void GButton::setIncrStep(int16_t incr_step) { - step = incr_step; -} -void GButton::setIncrTimeout(uint16_t incr_timeout) { - _incr_timeout = incr_timeout; -} - -boolean GButton::isPress() { - if (isPress_f) { - isPress_f = false; - return true; - } else return false; -} -boolean GButton::isRelease() { - if (isRelease_f) { - isRelease_f = false; - return true; - } else return false; -} -boolean GButton::isHolded() { - if (isHolded_f) { - isHolded_f = false; - return true; - } else return false; -} -boolean GButton::isHold() { - if (isHold_f) return true; - else return false; -} -boolean GButton::isSingle() { - if (counter_flag && last_counter == 1) { - counter_flag = false; - return true; - } else return false; -} -boolean GButton::isDouble() { - if (counter_flag && last_counter == 2) { - counter_flag = false; - return true; - } else return false; -} -boolean GButton::isTriple() { - if (counter_flag && last_counter == 3) { - counter_flag = false; - return true; - } else return false; -} -boolean GButton::hasClicks() { - if (counter_flag) { - counter_flag = false; - return true; - } else return false; -} -uint8_t GButton::getClicks() { - return last_counter; -} - -boolean GButton::isIncr() { - if (incr_flag) return true; - else return false; -} -int16_t GButton::getIncr(int16_t incr_value) { - if (isHold_f && (millis() - incr_timer > _incr_timeout)) { - incr_timer = millis(); - incr_flag = true; - return (incr_value + step); - } else return incr_value; -} - -void GButton::tick() { - btn_state = !digitalRead(_BUTT); - if (btn_state) isHold_f = true; - else isHold_f = false; - - if (btn_state && !btn_flag && (millis() - btn_timer > _debounce)) { - btn_flag = true; - btn_counter++; - btn_timer = millis(); - isPress_f = true; - } - if (!btn_state && btn_flag) { - btn_flag = false; - hold_flag = false; - isRelease_f = true; - btn_timer = millis(); - incr_flag = false; - } - if (btn_flag && btn_state && (millis() - btn_timer > _timeout) && !hold_flag) { - hold_flag = true; - btn_counter = 0; - isHolded_f = true; - incr_flag = true; - incr_timer = millis(); - } - - if ((millis() - btn_timer > _timeout) && (btn_counter != 0)) { - last_counter = btn_counter; - btn_counter = 0; - counter_flag = true; - } -} \ No newline at end of file diff --git a/GyverButtonOld/old_version/GyverButton.h b/GyverButtonOld/old_version/GyverButton.h deleted file mode 100644 index 913a6b5..0000000 --- a/GyverButtonOld/old_version/GyverButton.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef GyverButton_h -#define GyverButton_h -#include - -/* -Текущая версия: 1.1 от 29.03.2018 -GyverButton - библиотека для полной отработки нажатия кнопки. Возможности: -Опрос кнопки с программным антидребезгом контактов -Отработка нажатия, удерживания отпускания кнопки -Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) -Отработка любого количества нажатий кнопки (функция возвращает число нажатий) -Отработка нажатия и удержания кнопки -Настраиваемый таймаут повторного нажатия/удержания -Функция изменения значения переменной с заданным шагом и заданным интервалом по времени -Пример использования в папке examples, показывает все возможности библиотеки -Отличия от oneBtton и подобных библиотек: методы библиотеки не создают новые функции, что упрощает применение в сотни раз -*/ - -class GButton -{ - public: - GButton(uint8_t BUTT); - void setDebounce(uint8_t debounce); - void setTimeout(uint16_t timeout); - void tick(); - - boolean isPress(); - boolean isRelease(); - boolean isHolded(); - boolean isHold(); - - boolean hasClicks(); - uint8_t getClicks(); - - boolean isSingle(); - boolean isDouble(); - boolean isTriple(); - - boolean isIncr(); - void setIncrStep(int16_t incr_step); - void setIncrTimeout(uint16_t incr_timeout); - int16_t getIncr(int16_t incr_value); - - int16_t step; - - private: - uint8_t _BUTT; - uint8_t _debounce; - uint16_t _timeout; - uint8_t btn_counter, last_counter; - boolean btn_state, btn_flag, hold_flag, counter_flag; - uint32_t btn_timer, incr_timer; - boolean isHold_f, isHolded_f, isRelease_f, isPress_f, incr_flag; - uint16_t _incr_timeout; -}; - -#endif \ No newline at end of file diff --git a/GyverButtonOld/old_version/examples/Gbutton_example/Gbutton_example.ino b/GyverButtonOld/old_version/examples/Gbutton_example/Gbutton_example.ino deleted file mode 100644 index 5d2771a..0000000 --- a/GyverButtonOld/old_version/examples/Gbutton_example/Gbutton_example.ino +++ /dev/null @@ -1,46 +0,0 @@ -/* - Пример использования библиотеки GyverButton, все возможности в одном скетче. - - Опрос кнопки с программным антидребезгом контактов - - Отработка нажатия, удерживания отпускания кнопки - - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) - - Отработка любого количества нажатий кнопки (функция возвращает число нажатий) - - Отработка нажатия и удержания кнопки - - Настраиваемый таймаут повторного нажатия/удержания - - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(PIN); -int value = 0; - -void setup() { - Serial.begin(9600); - - butt1.setDebounce(50); // настройка антидребезга (по умолчанию 80 мс) - butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) - butt1.setIncrStep(2); // настройка инкремента, может быть отрицательным (по умолчанию 1) - butt1.setIncrTimeout(500); // настрйока интервала инкремента (по умолчанию 800 мс) -} - -void loop() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - - if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик - if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик - if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик - - if (butt1.hasClicks()) // проверка на наличие нажатий - Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий - - if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) - if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) - if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание - //if (butt1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки - - if (butt1.isIncr()) { // если кнопка была удержана (это для инкремента) - value = butt1.getIncr(value); // увеличивать/уменьшать переменную value с шагом и интервалом - Serial.println(value); // для примера выведем в порт - } -} diff --git a/GyverButtonOld/old_version/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino b/GyverButtonOld/old_version/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino deleted file mode 100644 index 4e654b0..0000000 --- a/GyverButtonOld/old_version/examples/Gbutton_timer_interrupt/Gbutton_timer_interrupt.ino +++ /dev/null @@ -1,56 +0,0 @@ -/* - Пример использования библиотеки GyverButton, все возможности в одном скетче. - - Опрос кнопки с программным антидребезгом контактов - - Отработка нажатия, удерживания отпускания кнопки - - Отработка одиночного, двойного и тройного нажатия (вынесено отдельно) - - Отработка любого количества нажатий кнопки (функция возвращает число нажатий) - - Отработка нажатия и удержания кнопки - - Настраиваемый таймаут повторного нажатия/удержания - - Функция изменения значения переменной с заданным шагом и заданным интервалом по времени - Данный скетч показывает, как быть в сложном "не сквозном" коде с кучей delay и замкнутых циклов - Здесь кнопка опрашивается каждые 10 миллисекунд независимо от того, что происходит у вас в коде - Используется библиотека TimerOne https://github.com/PaulStoffregen/TimerOne -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -#include "TimerOne.h" -GButton butt1(PIN); -int value = 0; - -void setup() { - Serial.begin(9600); - - Timer1.initialize(10000); // установка таймера на каждые 10000 микросекунд (= 10 мс) - Timer1.attachInterrupt(timerIsr); // запуск таймера - - butt1.setDebounce(50); // настройка антидребезга (по умолчанию 80 мс) - butt1.setTimeout(300); // настройка таймаута на удержание (по умолчанию 500 мс) - butt1.setIncrStep(2); // настройка инкремента, может быть отрицательным (по умолчанию 1) - butt1.setIncrTimeout(500); // настрйока интервала инкремента (по умолчанию 800 мс) -} - -void timerIsr() { // прерывание таймера - butt1.tick(); // отработка теперь находится здесь - // при добавлении кнопок, их .tick() нужно добавить сюда -} - -void loop() { - if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик - if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик - if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик - - if (butt1.hasClicks()) // проверка на наличие нажатий - Serial.println(butt1.getClicks()); // получить (и вывести) число нажатий - - if (butt1.isPress()) Serial.println("Press"); // нажатие на кнопку (+ дебаунс) - if (butt1.isRelease()) Serial.println("Release"); // отпускание кнопки (+ дебаунс) - if (butt1.isHolded()) Serial.println("Holded"); // проверка на удержание - //if (butt1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки - - if (butt1.isIncr()) { // если кнопка была удержана (это для инкремента) - value = butt1.getIncr(value); // увеличивать/уменьшать переменную value с шагом и интервалом - Serial.println(value); // для примера выведем в порт - } -} diff --git a/GyverButtonOld/old_version/examples/_1-2-3-click/_1-2-3-click.ino b/GyverButtonOld/old_version/examples/_1-2-3-click/_1-2-3-click.ino deleted file mode 100644 index 6496dc5..0000000 --- a/GyverButtonOld/old_version/examples/_1-2-3-click/_1-2-3-click.ino +++ /dev/null @@ -1,20 +0,0 @@ -/* - Пример использования библиотеки GyverButton, 1- 2- 3- нажатие -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(PIN); - -void setup() { - Serial.begin(9600); -} - -void loop() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - - if (butt1.isSingle()) Serial.println("Single"); // проверка на один клик - if (butt1.isDouble()) Serial.println("Double"); // проверка на двойной клик - if (butt1.isTriple()) Serial.println("Triple"); // проверка на тройной клик -} diff --git a/GyverButtonOld/old_version/examples/_5_buttons/_5_buttons.ino b/GyverButtonOld/old_version/examples/_5_buttons/_5_buttons.ino deleted file mode 100644 index a03fb24..0000000 --- a/GyverButtonOld/old_version/examples/_5_buttons/_5_buttons.ino +++ /dev/null @@ -1,34 +0,0 @@ -/* - Пример использования библиотеки GyverButton, 5 кнопок -*/ - -#define BTN1 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN2 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN3 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN4 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN5 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(BTN1); -GButton butt2(BTN2); -GButton butt3(BTN3); -GButton butt4(BTN4); -GButton butt5(BTN5); - -void setup() { - Serial.begin(9600); -} - -void loop() { - butt1.tick(); - butt2.tick(); - butt3.tick(); - butt4.tick(); - butt5.tick(); - - if (butt1.isSingle()) Serial.println("Button 1"); - if (butt2.isSingle()) Serial.println("Button 2"); - if (butt3.isSingle()) Serial.println("Button 3"); - if (butt4.isSingle()) Serial.println("Button 4"); - if (butt5.isSingle()) Serial.println("Button 5"); -} diff --git a/GyverButtonOld/old_version/examples/increment/increment.ino b/GyverButtonOld/old_version/examples/increment/increment.ino deleted file mode 100644 index f342d92..0000000 --- a/GyverButtonOld/old_version/examples/increment/increment.ino +++ /dev/null @@ -1,46 +0,0 @@ -/* - Пример использования библиотеки GyverButton, управляем переменной value при помощи двух кнопок - Конструкция с isIncr делает увеличение/уменьшение переменной при нажатой кнопке с шагом по времени -*/ - -#define BTN1 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) -#define BTN2 4 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(BTN1); -GButton butt2(BTN2); -int value = 0; - -void setup() { - Serial.begin(9600); - butt1.setIncrStep(2); // настройка инкремента, может быть отрицательным (по умолчанию 1) - butt1.setIncrTimeout(500); // настрйока интервала инкремента (по умолчанию 800 мс) - - butt2.setIncrStep(-2); // настройка инкремента, может быть отрицательным (по умолчанию 1) - butt2.setIncrTimeout(500); // настрйока интервала инкремента (по умолчанию 800 мс) -} - -void loop() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - butt2.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - - if (butt1.isSingle()) { // одиночное нажатие - value += butt1.step; // изменить на шаг, указанный в setIncrStep - Serial.println(value); // для примера выведем в порт - } - - if (butt2.isSingle()) { // одиночное нажатие - value += butt2.step; // изменить на шаг, указанный в setIncrStep - Serial.println(value); // для примера выведем в порт - } - - if (butt1.isIncr()) { // если кнопка была удержана (это для инкремента) - value = butt1.getIncr(value); // увеличивать/уменьшать переменную value с шагом и интервалом! - Serial.println(value); // для примера выведем в порт - } - - if (butt2.isIncr()) { // если кнопка была удержана (это для инкремента) - value = butt2.getIncr(value); // увеличивать/уменьшать переменную value с шагом и интервалом! - Serial.println(value); // для примера выведем в порт - } -} diff --git a/GyverButtonOld/old_version/examples/many_clicks/many_clicks.ino b/GyverButtonOld/old_version/examples/many_clicks/many_clicks.ino deleted file mode 100644 index 58a92a5..0000000 --- a/GyverButtonOld/old_version/examples/many_clicks/many_clicks.ino +++ /dev/null @@ -1,20 +0,0 @@ -/* - Пример использования библиотеки GyverButton, отработка любого количества нажатий -*/ - -#define PIN 3 // кнопка подключена сюда (PIN --- КНОПКА --- GND) - -#include "GyverButton.h" -GButton butt1(PIN); - -void setup() { - Serial.begin(9600); - butt1.setTimeout(300); // настройка таймаута на удержание и второй клик (по умолчанию 500 мс) -} - -void loop() { - butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться - - if (butt1.hasClicks()) // проверка на наличие нажатий - Serial.println(butt1.getClicks()); // получить (и вывести) количество нажатий -} diff --git a/GyverButtonOld/old_version/keywords.txt b/GyverButtonOld/old_version/keywords.txt deleted file mode 100644 index 525a6d7..0000000 --- a/GyverButtonOld/old_version/keywords.txt +++ /dev/null @@ -1,31 +0,0 @@ -####################################### -# Syntax Coloring Map For GyverButton -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -GButton KEYWORD1 -setDebounce KEYWORD1 -setTimeout KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -tick KEYWORD2 -isPress KEYWORD2 -isRelease KEYWORD2 -isHolded KEYWORD2 -isHold KEYWORD2 -hasClicks KEYWORD2 -getClicks KEYWORD2 -isSingle KEYWORD2 -isDouble KEYWORD2 -isTriple KEYWORD2 -isIncr KEYWORD2 -setIncrStep KEYWORD2 -setIncrTimeout KEYWORD2 -getIncr KEYWORD2 -step KEYWORD2 \ No newline at end of file diff --git a/GyverButtonOld/old_version/readme.txt b/GyverButtonOld/old_version/readme.txt deleted file mode 100644 index faf75c4..0000000 --- a/GyverButtonOld/old_version/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -- **GyverButton (текущая 1.1)** - библиотека для полной отработки нажатия кнопки. Возможности: - + Класс **GButton (pin)** - указать пин, куда подключена кнопка (PIN --- КНОПКА --- GND) - + **setDebounce(time)** - время антидребезга (по умолчанию 80 мс) - + **setTimeout(time)** - таймаут на удержание/повторное нажатие (по умолчанию 500 мс) - + **tick()** - опрос кнопки с программным антидребезгом контактов - + **isPress(), isRelease(), isHolded(), isHold()** - отработка нажатия, удерживания отпускания кнопки - + **isSingle(), isDouble(), isTriple** - отработка одиночного, двойного и тройного нажатия (вынесено отдельно) - + **getClicks()** - отработка любого количества нажатий кнопки (функция возвращает число нажатий) - + **getIncr(value)** - функция изменения значения переменной с заданным шагом и заданным интервалом по времени - + **setIncrStep(step)** - настройка инкремента, может быть отрицательным (по умолчанию 1) - + **setIncrTimeout(time)** - настрйока интервала инкремента (по умолчанию 800 мс) - + Пример использования в папке examples, показывает все возможности библиотеки - + Отличия от oneBtton и подобных библиотек: методы библиотеки не создают новые функции, что упрощает применение в сотни раз \ No newline at end of file diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/GyverLamp_v1.4_Arduino_v1.0.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/GyverLamp_v1.4_Arduino_v1.0.ino deleted file mode 100644 index 0eeceda..0000000 --- a/GyverLamp_v1.4_Arduino_v1.0kDn/GyverLamp_v1.4_Arduino_v1.0.ino +++ /dev/null @@ -1,152 +0,0 @@ -/* - Скетч к проекту "Многофункциональный RGB светильник" - Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ - Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/ - Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ - Автор: AlexGyver, AlexGyver Technologies, 2019 - https://AlexGyver.ru/ -*/ - -/* - Версия 1.4: - - Исправлен баг при смене режимов - - Исправлены тормоза в режиме точки доступа -*/ - -//// Ссылка для менеджера плат: -//// http://arduino.esp8266.com/stable/package_esp8266com_index.json - -// ============= НАСТРОЙКИ ============= - -//#define DEBUG // Дебаг(Нужен, расскоментируйте) -#define VERTGAUGE 0 // вертикальный/горизонтальный индикатор -#define DEMOTIME 5 // в секундах -#define RANDOM_DEMO 1 // 0,1 - включить рандомный выбор режима - -//// -------- РАССВЕТ ------- -//#define DAWN_BRIGHT 200 // макс. яркость рассвета -//#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут - -// ---------- МАТРИЦА --------- -#define BRIGHTNESS 255 // стандартная маскимальная яркость (0-255) -#define MINBRIGHTNESS 25 // минимальная яркость режимов (0-100) для исключения черной лампы -#define CURRENT_LIMIT 2600 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит - -#define WIDTH 16 // ширина матрицы -#define HEIGHT 16 // высота матрицы - -#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB - -#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная -#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний -#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз -// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" -// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ - -#define numHold_Time 1500 // время отображения индикатора уровня яркости/скорости/масштаба - -// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= -#define LED_PIN 2 // пин ленты -#define BTN_PIN 4 -#define MODE_AMOUNT 18 -#define NUM_LEDS WIDTH * HEIGHT -#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) - -// ---------------- БИБЛИОТЕКИ ----------------- -#include -#include -#include - -// ------------------- ТИПЫ -------------------- -CRGB leds[NUM_LEDS]; -GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); - -// ----------------- ПЕРЕМЕННЫЕ ------------------ - -static const byte maxDim = max(WIDTH, HEIGHT); -struct { - byte brightness = 50; - byte speed = 30; - byte scale = 10; -} modes[MODE_AMOUNT]; - - -int8_t currentMode = 17; -boolean loadingFlag = true; -boolean ONflag = true; -byte numHold; -unsigned long numHold_Timer = 0UL; -unsigned long userTimer = 0UL; -unsigned char matrixValue[8][16]; -byte xStep; -byte xCol; -byte yStep; -byte yCol; - -void setup() { - - // ЛЕНТА - FastLED.addLeds(leds, NUM_LEDS).setCorrection(0xFFB0F0); - FastLED.setBrightness(BRIGHTNESS); - if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); - FastLED.clear(); - FastLED.show(); - - touch.setStepTimeout(100); - touch.setClickTimeout(500); - - //Serial.begin(9600); - //Serial.println(); - - xStep = WIDTH / 4; - xCol = 4; - if(xStep<2) { - xStep = WIDTH / 3; - xCol = 3; - } else if(xStep<2) { - xStep = WIDTH / 2; - xCol = 2; - } else if(xStep<2) { - xStep = 1; - xCol = 1; - } - - yStep = HEIGHT / 4; - yCol = 4; - if(yStep<2) { - yStep = HEIGHT / 3; - yCol = 3; - } else if(yStep<2) { - yStep = HEIGHT / 2; - yCol = 2; - } else if(yStep<2) { - yStep = 1; - yCol = 1; - } - - #ifdef DEBUG - Serial.print("xStep: "); - Serial.print(xStep); - Serial.print(" xCol:"); - Serial.println(xCol); - Serial.print("yStep: "); - Serial.print(yStep); - Serial.print(" yCol:"); - Serial.println(yCol); - #endif - - if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР - currentMode = EEPROM.read(1); - for (byte x = 0; x < MODE_AMOUNT; x++) { - modes[x].brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) - modes[x].speed = EEPROM.read(x * 3 + 12); - modes[x].scale = EEPROM.read(x * 3 + 13); - } - - } -} - -void loop() { - effectsTick(); - buttonTick(); //yield(); -} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/button.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/button.ino deleted file mode 100644 index a2e2a28..0000000 --- a/GyverLamp_v1.4_Arduino_v1.0kDn/button.ino +++ /dev/null @@ -1,223 +0,0 @@ -boolean brightDirection, speedDirection, scaleDirection; -//byte numHold; -#ifdef DEBUG -void debugPrint(){ - Serial.print(numHold); - Serial.print(F(" brightness:")); - Serial.print(modes[currentMode].brightness); - Serial.print(F(" speed:")); - Serial.print(modes[currentMode].speed); - Serial.print(F(" scale:")); - Serial.print(modes[currentMode].scale); - Serial.print(F(" numHold_Timer:")); - Serial.println(numHold_Timer); -} -#endif -void changeDirection(byte numHold){ - switch(numHold){ - case 0: case 1: brightDirection = !brightDirection; break; - case 2: speedDirection = !speedDirection; break; - case 3: scaleDirection = !scaleDirection; break; - } - numHold_Timer = millis(); -} - -void buttonTick() { - touch.tick(); - - if (!ONflag) { // Обработка из выключенного состояния - #ifdef DEBUG - if(touch.isPress()) - Serial.println(F("Off state")); - #endif - - if (touch.isDouble()) { // Демо-режим, с переключением каждые 30 секунд для двойного клика в выключенном состоянии - numHold = 254; - currentMode = random(0, 255)%17; // 17 скипаем - //modes[currentMode].brightness = BRIGHTNESS/2; // в половину яркости - FastLED.setBrightness(modes[currentMode].brightness); - ONflag = true; - userTimer = millis(); // момент включения для таймаута в DEMOTIME - numHold_Timer = millis(); - //brightDirection = 0; // на уменьшение - changePower(); - #ifdef DEBUG - Serial.print(F("Demo mode: ")); - Serial.println(currentMode); - #endif - } - - if (touch.isHolded()) { - #ifdef DEBUG - Serial.println(F("Holdeded from offed state")); - #endif - currentMode = 17; - modes[currentMode].brightness = BRIGHTNESS; - FastLED.setBrightness(modes[currentMode].brightness); - numHold = 255; - ONflag = true; - userTimer = millis(); // момент включения для таймаута в переключения в режим регулировки яркости - numHold_Timer = millis(); - brightDirection = 0; // на уменьшение - changePower(); - } - } - - if (touch.isSingle()) { // Включение/выключение одиночным - - { - if (ONflag) { - ONflag = false; - #ifdef DEBUG - Serial.println(F("Off lamp")); - #endif - changePower(); - } else { - ONflag = true; - #ifdef DEBUG - Serial.println(F("On lamp")); - debugPrint(); // отладка - #endif - - } - } - } - -if (ONflag) { // если включено - if (touch.isDouble()) { - #ifdef DEBUG - Serial.println(F("Double click")); - //debugPrint(); // отладка - #endif - if (++currentMode >= MODE_AMOUNT) currentMode = 0; - FastLED.setBrightness(modes[currentMode].brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - if (touch.isTriple()) { - #ifdef DEBUG - Serial.println(F("Triple click")); - //debugPrint(); // отладка - #endif - if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; - FastLED.setBrightness(modes[currentMode].brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - - if ((touch.hasClicks()) && (touch.getClicks() == 5)) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров // && (touch.hasClicks()) - if (EEPROM.read(0) != 102) EEPROM.write(0, 102); - if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект - for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов - if (EEPROM.read(x * 3 + 11) != modes[x].brightness) EEPROM.write(x * 3 + 11, modes[x].brightness); - if (EEPROM.read(x * 3 + 12) != modes[x].speed) EEPROM.write(x * 3 + 12, modes[x].speed); - if (EEPROM.read(x * 3 + 13) != modes[x].scale) EEPROM.write(x * 3 + 13, modes[x].scale); - } - // индикация сохранения - ONflag = false; - changePower(); - delay(200); - ONflag = true; - changePower(); - } - - if (touch.isHolded() && numHold != 255) { // изменение яркости при удержании кнопки - if(modes[currentMode].brightness == BRIGHTNESS && numHold == 1){ - brightDirection = 0; - } else if (modes[currentMode].brightness <= 1 && numHold == 1){ - brightDirection = 1; - } else - changeDirection(numHold); - if(!numHold || numHold==254) - numHold = 1; - } - - if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки - if(modes[currentMode].speed == 255 && numHold == 2){ - speedDirection = 0; - } else if (modes[currentMode].speed <= 1 && numHold == 2){ - speedDirection = 1; - } else - changeDirection(numHold); - if(!numHold) - numHold = 2; - } - - if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки - if(modes[currentMode].scale == 255 && numHold == 3){ - scaleDirection = 0; - } else if (modes[currentMode].scale <= 1 && numHold == 3){ - scaleDirection = 1; - } else - changeDirection(numHold); - if(!numHold) - numHold = 3; - } - - if (touch.isStep()) { - #ifdef DEBUG - debugPrint(); // отладка - #endif - if (numHold != 0 && numHold != 255) { - numHold_Timer = millis(); - loadingFlag = true; - } - - switch (numHold) { - case 1: - - modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), MINBRIGHTNESS , BRIGHTNESS); - break; - - case 2: - - modes[currentMode].speed = constrain(modes[currentMode].speed + (modes[currentMode].speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); - break; - - case 3: - - modes[currentMode].scale = constrain(modes[currentMode].scale + (modes[currentMode].scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); - break; - } - } - - if ((millis() - userTimer) > numHold_Time && numHold>=250) { - if(numHold == 255){ - numHold = 1; - userTimer = millis(); - numHold_Timer = millis(); - } - } - - if ((millis() - numHold_Timer) > numHold_Time && !touch.isHolded() && numHold<250) { - numHold = 0; - numHold_Timer = millis(); - } - - if((millis() - userTimer > DEMOTIME*1000) && (numHold == 254)){ - //FastLED.clear(); - //delay(2); - for(byte i = 250; i>10; i-=10){ - fader(30); - FastLED.delay(33); - //FastLED.show(); - } - - if(RANDOM_DEMO) - currentMode = random(0, 255)%17; // 17 скипаем - else - currentMode=(currentMode+1)%17; // 17 скипаем и идем по наростанию - #ifdef DEBUG - Serial.print(F("Demo mode: ")); - Serial.println(currentMode); - #endif - userTimer = millis(); - } - - FastLED.setBrightness(modes[currentMode].brightness); - } -} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/effectTicker.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/effectTicker.ino deleted file mode 100644 index 2a92161..0000000 --- a/GyverLamp_v1.4_Arduino_v1.0kDn/effectTicker.ino +++ /dev/null @@ -1,115 +0,0 @@ -uint32_t effTimer; -byte ind; - -void effectsTick() { - { - if (millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { - effTimer = millis(); - if(ONflag){ - switch (currentMode) { - case 0: sparklesRoutine(); - break; - case 1: rainbowVertical(); - break; - case 2: rainbowHorizontal(); - break; - case 3: Fire2020(); - break; - case 4: colorsRoutine(); - break; - case 5: madnessNoise(); - break; - case 6: cloudNoise(); - break; - case 7: lavaNoise(); - break; - case 8: plasmaNoise(); - break; - case 9: rainbowNoise(); - break; - case 10: rainbowStripeNoise(); - break; - case 11: zebraNoise(); - break; - case 12: forestNoise(); - break; - case 13: oceanNoise(); - break; - case 14: colorRoutine(); - break; - case 15: snowRoutine(); - break; - case 16: matrixRoutine(); - break; - case 17: whiteLampRoutine(); - break; - } - if(VERTGAUGE) - GaugeShowVertical(); - } - FastLED.show(); - } - } -} - -void GaugeShowVertical() { - switch (numHold) { // индикатор уровня яркости/скорости/масштаба - case 1: - ind = ind = sqrt(modes[currentMode].brightness + 1); - for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) - drawPixelXY(x, y, CHSV(10, 255, 255)); - else - drawPixelXY(x, y, 0); - } - } - break; - case 2: - ind = sqrt(modes[currentMode].speed - 1); - for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { - for (byte y = 0; y <= HEIGHT ; y++) { - if (ind <= y) - drawPixelXY(x, HEIGHT-1-y, CHSV(100, 255, 255)); - else - drawPixelXY(x, HEIGHT-1-y, 0); - } - } - break; - case 3: - ind = sqrt(modes[currentMode].scale + 1); - for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) - drawPixelXY(x, y, CHSV(150, 255, 255)); - else - drawPixelXY(x, y, 0); - } - } - break; - } -} - -void changePower() { // плавное включение/выключение - if (ONflag) { - effectsTick(); - for (int i = 0; i < modes[currentMode].brightness; i += 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.setBrightness(modes[currentMode].brightness); - delay(2); - FastLED.show(); - } else { - //effectsTick(); - for (int i = modes[currentMode].brightness; i > 8; i -= 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.clear(); - delay(2); - FastLED.show(); - } -} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino deleted file mode 100644 index d2259ce..0000000 --- a/GyverLamp_v1.4_Arduino_v1.0kDn/effects.ino +++ /dev/null @@ -1,158 +0,0 @@ -// ================================= ЭФФЕКТЫ ==================================== -// --------------------------------- конфетти ------------------------------------ -#define FADE_OUT_SPEED (70U) // скорость затухания -void sparklesRoutine() -{ - for (uint8_t i = 0; i < modes[currentMode].scale; i++) - { - uint8_t x = random(0U, WIDTH); - uint8_t y = random(0U, HEIGHT); - if (getPixColorXY(x, y) == 0U) - { - drawPixelXY(x, y,CHSV(random(0U, 255U), 255U, 255U)); - } - } - fader(FADE_OUT_SPEED); -} -//----------------------Огонь-------------------- -void Fire2020() { - uint8_t speedy = map(modes[currentMode].speed, 1, 255, 255, 0); - uint8_t _scale = modes[currentMode].scale + 30; - - uint32_t a = millis(); - for (byte i = 0U; i < WIDTH; i++) { - for (float j = 0.; j < HEIGHT; j++) { - - drawPixelXY((WIDTH - 1) - i, (HEIGHT - 1) - j, ColorFromPalette(HeatColors_p/*myPal*/, qsub8(inoise8(i * _scale, j * _scale + a, a / speedy), abs8(j - (HEIGHT - 1)) * 255 / (HEIGHT - 1)), 255)); - } - } -} -byte hue; -// ---------------------------------------- радуга ------------------------------------------ -void rainbowVertical() { - hue += 2; - for (byte j = 0; j < HEIGHT; j++) { - CHSV thisColor = CHSV((byte)(hue + j * modes[currentMode].scale), 255, 255); - for (byte i = 0; i < WIDTH; i++) - drawPixelXY(i, j, thisColor); - } -} -void rainbowHorizontal() { - hue += 2; - for (byte i = 0; i < WIDTH; i++) { - CHSV thisColor = CHSV((byte)(hue + i * modes[currentMode].scale), 255, 255); - for (byte j = 0; j < HEIGHT; j++) - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; - } -} - -// ---------------------------------------- ЦВЕТА ------------------------------------------ -void colorsRoutine() { - hue += modes[currentMode].scale; - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(hue, 255, 255); - } -} - -// --------------------------------- ЦВЕТ ------------------------------------ -void colorRoutine() { - for (int i = 0; i < NUM_LEDS; i++) { - //leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); - leds[i] = CHSV(modes[currentMode].speed*(modes[currentMode].scale/16+1), 255, 255); - } -} - -// ------------------------------ снегопад 2.0 -------------------------------- -void snowRoutine() { - shiftDown(); - - for (byte x = 0; x < WIDTH; x++) { - // заполняем случайно верхнюю строку - // а также не даём двум блокам по вертикали вместе быть - if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, modes[currentMode].scale) == 0)) - drawPixelXY(x, HEIGHT - 1U, 0xE0FFFF - 0x101010 * random(0, 4)); - else - drawPixelXY(x, HEIGHT - 1, 0x000000); - } -} -// ------------------------------ МАТРИЦА ------------------------------ -void matrixRoutine() -{ - for (uint8_t x = 0U; x < WIDTH; x++) - { - // обрабатываем нашу матрицу снизу вверх до второй сверху строчки - for (uint8_t y = 0U; y < HEIGHT - 1U; y++) - { - uint32_t thisColor = getPixColorXY(x, y); // берём цвет нашего пикселя - uint32_t upperColor = getPixColorXY(x, y + 1U); // берём цвет пикселя над нашим - if (upperColor >= 0x900000 && random(7 * HEIGHT) != 0U) // если выше нас максимальная яркость, игнорим этот факт с некой вероятностью или опускаем цепочку ниже - drawPixelXY(x, y, upperColor); - else if (thisColor == 0U && random((100 - modes[currentMode].scale) * HEIGHT) == 0U) // если наш пиксель ещё не горит, иногда зажигаем новые цепочки - //else if (thisColor == 0U && random((100 - modes[currentMode].Scale) * HEIGHT*3) == 0U) // для длинных хвостов - drawPixelXY(x, y, 0x9bf800); - else if (thisColor <= 0x050800) // если наш пиксель почти погас, стараемся сделать затухание медленней - { - if (thisColor >= 0x030000) - drawPixelXY(x, y, 0x020300); - else if (thisColor != 0U) - drawPixelXY(x, y, 0U); - } - else if (thisColor >= 0x900000) // если наш пиксель максимальной яркости, резко снижаем яркость - drawPixelXY(x, y, 0x558800); - else - drawPixelXY(x, y, thisColor - 0x0a1000); // в остальных случаях снижаем яркость на 1 уровень - //drawPixelXY(x, y, thisColor - 0x050800); // для длинных хвостов - } - // аналогично обрабатываем верхний ряд пикселей матрицы - uint32_t thisColor = getPixColorXY(x, HEIGHT - 1U); - if (thisColor == 0U) // если наш верхний пиксель не горит, заполняем его с вероятностью .Scale - { - if (random(100 - modes[currentMode].scale) == 0U) - drawPixelXY(x, HEIGHT - 1U, 0x9bf800); - } - else if (thisColor <= 0x050800) // если наш верхний пиксель почти погас, стараемся сделать затухание медленней - { - if (thisColor >= 0x030000) - drawPixelXY(x, HEIGHT - 1U, 0x020300); - else - drawPixelXY(x, HEIGHT - 1U, 0U); - } - else if (thisColor >= 0x900000) // если наш верхний пиксель максимальной яркости, резко снижаем яркость - drawPixelXY(x, HEIGHT - 1U, 0x558800); - else - drawPixelXY(x, HEIGHT - 1U, thisColor - 0x0a1000); // в остальных случаях снижаем яркость на 1 уровень - //drawPixelXY(x, HEIGHT - 1U, thisColor - 0x050800); // для длинных хвостов - } -} -// ------------------------------ БЕЛАЯ ЛАМПА ------------------------------ -void whiteLampRoutine() -{ - if (loadingFlag) - { - loadingFlag = false; - FastLED.clear(); - //delay(1); - - uint8_t centerY = (uint8_t)round(HEIGHT / 2.0F) - 1U;// max((uint8_t)round(HEIGHT / 2.0F) - 1, 0); нахрена тут максимум было вычислять? для ленты?! - uint8_t bottomOffset = (uint8_t)(!(HEIGHT & 0x01));// && (HEIGHT > 1)); и высота больше единицы. супер! // если высота матрицы чётная, линий с максимальной яркостью две, а линии с минимальной яркостью снизу будут смещены на один ряд - - uint8_t fullRows = centerY / 100.0 * modes[currentMode].scale; - uint8_t iPol = (centerY / 100.0 * modes[currentMode].scale - fullRows) * 255; - - for (int16_t y = centerY; y >= 0; y--) - { - CRGB color = CHSV( - 45U, // определяем тон - map(modes[currentMode].speed, 0U, 255U, 0U, 170U), // определяем насыщенность - y > (centerY - fullRows - 1) // определяем яркость - ? 255U // для центральных горизонтальных полос - : iPol * (y > centerY - fullRows - 2)); // для остальных горизонтальных полос яркость равна либо 255, либо 0 в зависимости от масштаба - - for (uint8_t x = 0U; x < WIDTH; x++) - { - drawPixelXY(x, y, color); // при чётной высоте матрицы максимально яркими отрисуются 2 центральных горизонтальных полосы - drawPixelXY(x, HEIGHT + bottomOffset - y - 2U, color); // при нечётной - одна, но дважды - } - } - } -} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/noiseEffects.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/noiseEffects.ino deleted file mode 100644 index 11f3c90..0000000 --- a/GyverLamp_v1.4_Arduino_v1.0kDn/noiseEffects.ino +++ /dev/null @@ -1,194 +0,0 @@ -// ******************* НАСТРОЙКИ ***************** -// ***************** ДЛЯ РАЗРАБОТЧИКОВ ****************** - -// The 16 bit version of our coordinates -static uint16_t x; -static uint16_t y; -static uint16_t z; - -uint16_t speed = 20; // speed is set dynamically once we've started up -uint16_t scale = 30; // scale is set dynamically once we've started up - -// This is the array that we keep our computed noise values in (это массив, в котором храним вычисленные значения шума) -#define MAX_DIMENSION (max(WIDTH, HEIGHT)) -#if (WIDTH > HEIGHT) -uint8_t noise[WIDTH][WIDTH]; -#else -uint8_t noise[HEIGHT][HEIGHT]; -#endif - -CRGBPalette16 currentPalette( PartyColors_p ); -uint8_t colorLoop = 1; -uint8_t ihue = 0; - -void madnessNoise() { - if (loadingFlag) { - loadingFlag = false; - scale = modes[5].scale; - speed = modes[5].speed; - } - fillnoise8(); - for (int i = 0; i < WIDTH; i++) { - for (int j = 0; j < HEIGHT; j++) { - CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); - } - } - ihue += 1; -} -void rainbowNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = RainbowColors_p; - scale = modes[currentMode].scale; - speed = modes[currentMode].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void rainbowStripeNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = RainbowStripeColors_p; - scale = modes[currentMode].scale; - speed = modes[currentMode].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void zebraNoise() { - if (loadingFlag) { - loadingFlag = false; - // 'black out' all 16 palette entries... - fill_solid( currentPalette, 16, CRGB::Black); - // and set every fourth one to white. - currentPalette[0] = CRGB::White; - currentPalette[4] = CRGB::White; - currentPalette[8] = CRGB::White; - currentPalette[12] = CRGB::White; - scale = modes[11].scale; - speed = modes[11].speed; - colorLoop = 1; - -// Serial.print(" speed:"); -// Serial.print(modes[currentMode].speed); -// Serial.print(" scale:"); -// Serial.println(modes[currentMode].scale); - } - fillNoiseLED(); -} -void forestNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = ForestColors_p; - scale = modes[currentMode].scale; - speed = modes[currentMode].speed; - colorLoop = 0; - } - fillNoiseLED(); -} -void oceanNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = OceanColors_p; - scale = modes[currentMode].scale; - speed = modes[currentMode].speed; - colorLoop = 0; - } - - fillNoiseLED(); -} -void plasmaNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = PartyColors_p; - scale = modes[currentMode].scale; - speed = modes[currentMode].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void cloudNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = CloudColors_p; - scale = modes[currentMode].scale; - speed = modes[currentMode].speed; - colorLoop = 0; - } - fillNoiseLED(); -} -void lavaNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = LavaColors_p; - scale = modes[currentMode].scale; - speed = modes[currentMode].speed; - colorLoop = 0; - } - fillNoiseLED(); -} - -// ******************* СЛУЖЕБНЫЕ ******************* -void fillNoiseLED() { - uint8_t dataSmoothing = 0; - if ( speed < 50) { - dataSmoothing = 200 - (speed * 4); - } - for (int i = 0; i < MAX_DIMENSION; i++) { - int ioffset = scale * i; - for (int j = 0; j < MAX_DIMENSION; j++) { - int joffset = scale * j; - - uint8_t data = inoise8(x + ioffset, y + joffset, z); - - data = qsub8(data, 16); - data = qadd8(data, scale8(data, 39)); - - if ( dataSmoothing ) { - uint8_t olddata = noise[i][j]; - uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); - data = newdata; - } - - noise[i][j] = data; - } - } - z += speed; - - // apply slow drift to X and Y, just for visual variation. - x += speed / 8; - y -= speed / 16; - - for (int i = 0; i < WIDTH; i++) { - for (int j = 0; j < HEIGHT; j++) { - uint8_t index = noise[j][i]; - uint8_t bri = noise[i][j]; - // if this palette is a 'loop', add a slowly-changing base value - if ( colorLoop) { - index += ihue; - } - // brighten up, as the color palette itself often contains the - // light/dark dynamic range desired - if ( bri > 127 ) { - bri = 255; - } else { - bri = dim8_raw( bri * 2); - } - CRGB color = ColorFromPalette( currentPalette, index, bri); - drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color; - } - } - ihue += 1; -} - -void fillnoise8() { - for (int i = 0; i < MAX_DIMENSION; i++) { - int ioffset = scale * i; - for (int j = 0; j < MAX_DIMENSION; j++) { - int joffset = scale * j; - noise[i][j] = inoise8(x + ioffset, y + joffset, z); - } - } - z += speed; -} diff --git a/GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino b/GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino deleted file mode 100644 index c481eb4..0000000 --- a/GyverLamp_v1.4_Arduino_v1.0kDn/utility.ino +++ /dev/null @@ -1,128 +0,0 @@ -// служебные функции -// функция плавного угасания цвета для всех пикселей -void fader(uint8_t step) -{ - for (uint8_t i = 0U; i < WIDTH; i++) - { - for (uint8_t j = 0U; j < HEIGHT; j++) - { - fadePixel(i, j, step); - } - } -} -void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер -{ - int32_t pixelNum = XY(i, j); - if (getPixColor(pixelNum) == 0U) return; - - if (leds[pixelNum].r >= 30U || - leds[pixelNum].g >= 30U || - leds[pixelNum].b >= 30U) - { - leds[pixelNum].fadeToBlackBy(step); - } - else - { - leds[pixelNum] = 0U; - } -} -void shiftDown(){ - for (byte x = 0; x < WIDTH; x++) { - for (byte y = 0; y < HEIGHT - 1; y++) { - drawPixelXY(x, y, getPixColorXY(x, y + 1)); - }}} -// залить все -void fillAll(CRGB color) { - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = color; - } -} - - - -// функция отрисовки точки по координатам X Y -void drawPixelXY(uint8_t x, uint8_t y, CRGB color) -{ - if (x < 0 || x > (WIDTH - 1) || y < 0 || y > (HEIGHT - 1)) return; - uint32_t thisPixel = XY((uint8_t)x, (uint8_t)y) * SEGMENTS; - for (uint8_t i = 0; i < SEGMENTS; i++) - { - leds[thisPixel + i] = color; - } -} - -// функция получения цвета пикселя по его номеру -uint32_t getPixColor(uint32_t thisSegm) -{ - uint32_t thisPixel = thisSegm * SEGMENTS; - if (thisPixel > NUM_LEDS - 1) return 0; - return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b); -} -// функция получения цвета пикселя в матрице по его координатам -uint32_t getPixColorXY(uint8_t x, uint8_t y) -{ - return getPixColor(XY(x, y)); -} - -// **************** НАСТРОЙКА МАТРИЦЫ **************** -#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 XY(uint8_t x, uint8_t y) -{ - if (!(THIS_Y & 0x01) || MATRIX_TYPE) // Even rows run forwards - return (THIS_Y * _WIDTH + THIS_X); - else - return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); // Odd rows run backwards -} - -// оставлено для совместимости со эффектами из старых прошивок -uint16_t getPixelNumber(uint8_t x, uint8_t y) -{ - return XY(x, y); -} diff --git a/README.md b/README.md index 4573326..00fb2df 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ -# ArduinoLamp +# GyverLamp for Arduino Это облегченная версия прошивки AlexGyver под ардуино. (Оригинал здесь: ![Исходная версия](https://github.com/AlexGyver/GyverLamp/)) -Обновление будут выходить там: https://github.com/80Stepko08/ArduinoLamp ## Краткое описание: @@ -13,13 +12,23 @@ - работа с Wi-Fi (у ардуинки его нет); - эффект "Светляки" - под него не хватило места в ОЗУ; -Что добавлено: демо, куча эффектов; +Что добавлено (как ни странно, но да, было что добавить): +- эффект "Светляки" заменен на "Белая лампа"; +- сохранение настроек всех эффектов, в т.ч. текущего режима в энергонезависимой + памяти. Производится пятикратным нажатием кнопки, подтверждением будет + выключение и включение лампы; +- регулирование скорости (speed) эффектов путем двойного нажатия и удержания + кнопки на втором нажатии; +- регулирование масштаба (scale) эффектов путем тройного нажатия и удержания + кнопки на третьем нажатии; +- индикация уровня яркости/скорости/масштаба вертикальной полосой красного/ + зеленого/синего цветов соответственно; Регулировка уровня яркости/скорости/масштаба реверсивная, т.е. при повторном регулировании изменения будут производиться в обратную сторону (сначала в бОльшую, затем в мЕньшую). +Для работы всех режимов кнопки ОБЯЗАТЕЛЬНО нужно заменить у себя папку GyverButton +на аналогичную с этого сайта. Совместимость с оригиналом сохранилась. -Для работы всех режимов кнопки -ОБЯЗАТЕЛЬНО нужно заменить у себя папку GyverButtonOld(переименовал ради удобства) на аналогичную с этого сайта. -Совместимость с оригиналом сохранилась. +Подключение ардуино производить к тем же пинам, что и esp8266. \ No newline at end of file diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/GyverLamp_v1.4_Arduino_v1.2.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/GyverLamp_v1.4_Arduino_v1.2.ino deleted file mode 100644 index cd51a1c..0000000 --- a/firmware/GyverLamp_v1.4_Arduino_v1.2/GyverLamp_v1.4_Arduino_v1.2.ino +++ /dev/null @@ -1,127 +0,0 @@ -/* - Скетч к проекту "Многофункциональный RGB светильник" - Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ - Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/ - Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ - Автор: AlexGyver, AlexGyver Technologies, 2019 - https://AlexGyver.ru/ -*/ - -/* - Версия 1.4: - - Исправлен баг при смене режимов - - Исправлены тормоза в режиме точки доступа -*/ - -//// Ссылка для менеджера плат: -//// http://arduino.esp8266.com/stable/package_esp8266com_index.json - -// ============= НАСТРОЙКИ ============= - -//// -------- РАССВЕТ ------- -//#define DAWN_BRIGHT 200 // макс. яркость рассвета -//#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут - -// ---------- МАТРИЦА --------- -#define BRIGHTNESS 40 // стандартная маскимальная яркость (0-255) -#define CURRENT_LIMIT 2000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит - -#define WIDTH 16 // ширина матрицы -#define HEIGHT 16 // высота матрицы - -#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB - -#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная -#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний -#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз -// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" -// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ - -#define numHold_Time 1500 // время отображения индикатора уровня яркости/скорости/масштаба - -// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= -#define LED_PIN 2 // пин ленты -#define BTN_PIN 4 -#define MODE_AMOUNT 18 -#define NUM_LEDS WIDTH * HEIGHT -#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) - -// ---------------- БИБЛИОТЕКИ ----------------- -//#include "timerMinim.h" -#include -#include -#include - -// ------------------- ТИПЫ -------------------- -CRGB leds[NUM_LEDS]; -//timerMinim timeTimer(3000); -GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); //сенсорная кнопка -//GButton touch(BTN_PIN, HIGH_PULL, NORM_OPEN); //механическая кнопка - -// ----------------- ПЕРЕМЕННЫЕ ------------------ - -//String inputBuffer; -static const byte maxDim = max(WIDTH, HEIGHT); -struct { - byte brightness = 50; - byte speed = 30; - byte scale = 10; -} modes[MODE_AMOUNT]; - -//struct { -// boolean state = false; -// int time = 0; -//} alarm[7]; - -//byte dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60}; -//byte dawnMode; -//boolean dawnFlag = false; -//long thisTime; -//boolean manualOff = false; - -int8_t currentMode = 17; -boolean loadingFlag = true; -boolean ONflag = true; -byte numHold; -unsigned long numHold_Timer = 0; -//uint32_t eepromTimer; -//boolean settChanged = false; -// Конфетти, Огонь, Радуга верт., Радуга гориз., Смена цвета, -// Безумие 3D, Облака 3D, Лава 3D, Плазма 3D, Радуга 3D, -// Павлин 3D, Зебра 3D, Лес 3D, Океан 3D, -// colorRoutine, snowRoutine, полосы "Матрица" - -unsigned char matrixValue[8][16]; - -void setup() { - - // ЛЕНТА - FastLED.addLeds(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/; - FastLED.setBrightness(BRIGHTNESS); - if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); - FastLED.clear(); - FastLED.show(); - - touch.setStepTimeout(100); - touch.setClickTimeout(500); - - Serial.begin(9600); - Serial.println(); - - if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР - currentMode = EEPROM.read(1); - for (byte x = 0; x < MODE_AMOUNT; x++) { - modes[x].brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) - modes[x].speed = EEPROM.read(x * 3 + 12); - modes[x].scale = EEPROM.read(x * 3 + 13); - } - - } -} - -void loop() { - effectsTick(); - //timeTick(); - buttonTick(); - //yield(); -} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/button.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/button.ino deleted file mode 100644 index d74f069..0000000 --- a/firmware/GyverLamp_v1.4_Arduino_v1.2/button.ino +++ /dev/null @@ -1,110 +0,0 @@ -boolean brightDirection, speedDirection, scaleDirection; -//byte numHold; - -void buttonTick() { - touch.tick(); - - - - if (ONflag) { // если включено - - - if ((touch.hasClicks()) && (touch.getClicks() == 5)) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров // && (touch.hasClicks()) - if (EEPROM.read(0) != 102) EEPROM.write(0, 102); - if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект - for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов - if (EEPROM.read(x * 3 + 11) != modes[x].brightness) EEPROM.write(x * 3 + 11, modes[x].brightness); - if (EEPROM.read(x * 3 + 12) != modes[x].speed) EEPROM.write(x * 3 + 12, modes[x].speed); - if (EEPROM.read(x * 3 + 13) != modes[x].scale) EEPROM.write(x * 3 + 13, modes[x].scale); - } - // индикация сохранения - ONflag = false; - changePower(); - delay(200); - ONflag = true; - changePower(); - } - // - // if (touch.isStep()) { // изменение яркости при удержании кнопки - // if (numHold != 1) brightDirection = !brightDirection; - // numHold = 1; - // } - // - // if (touch.isStep(1)) { // изменение скорости "speed" при двойном нажатии и удержании кнопки - // if (numHold != 2) speedDirection = !speedDirection; - // numHold = 2; - // } - // - // if (touch.isStep(2)) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки - // if (numHold != 3) scaleDirection = !scaleDirection; - // numHold = 3; - // } - - if (touch.isHold() && touch.isStep()) { - //numHold = touch.getHoldClicks(); - // if (numHold != 0) { - Serial.print(numHold); - Serial.print(brightDirection); - Serial.print(speedDirection); - Serial.println(scaleDirection); - // Serial.print(" brightness:"); - // Serial.print(modes[currentMode].brightness); - // Serial.print(" speed:"); - // Serial.print(modes[currentMode].speed); - // Serial.print(" scale:"); - // Serial.println(modes[currentMode].scale); - // switch (numHold) { - switch (touch.getHoldClicks() + 1) { - case 1: - if (numHold != 1) brightDirection = !brightDirection; - modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , 255); - numHold = 1; - break; - - case 2: - if (numHold != 2) speedDirection = !speedDirection; - modes[currentMode].speed = constrain(modes[currentMode].speed + (modes[currentMode].speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); - numHold = 2; - break; - - case 3: - if (numHold != 3) scaleDirection = !scaleDirection; - modes[currentMode].scale = constrain(modes[currentMode].scale + (modes[currentMode].scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); - numHold = 3; - break; - } - if (numHold != 0) numHold_Timer = millis(); loadingFlag = true; - } - if ((millis() - numHold_Timer) > numHold_Time) { - numHold = 0; - numHold_Timer = millis(); - } - FastLED.setBrightness(modes[currentMode].brightness); - //settChanged = true; - if (touch.isDouble()) { - if (++currentMode >= MODE_AMOUNT) currentMode = 0; - FastLED.setBrightness(modes[currentMode].brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - if (touch.isTriple()) { - if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; - FastLED.setBrightness(modes[currentMode].brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - } - if (touch.isSingle()) { - if (ONflag) { - ONflag = false; - changePower(); - } else { - ONflag = true; - changePower(); - } - } -} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/effectTicker.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/effectTicker.ino deleted file mode 100644 index aab079d..0000000 --- a/firmware/GyverLamp_v1.4_Arduino_v1.2/effectTicker.ino +++ /dev/null @@ -1,99 +0,0 @@ -uint32_t effTimer; -byte ind; - -void effectsTick() { - // if (!dawnFlag) - { - if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { - effTimer = millis(); - switch (currentMode) { - case 0: sparklesRoutine(); - break; - case 1: fireRoutine(); - break; - case 2: rainbowVertical(); - break; - case 3: rainbowHorizontal(); - break; - case 4: colorsRoutine(); - break; - case 5: madnessNoise(); - break; - case 6: cloudNoise(); - break; - case 7: lavaNoise(); - break; - case 8: plasmaNoise(); - break; - case 9: rainbowNoise(); - break; - case 10: rainbowStripeNoise(); - break; - case 11: zebraNoise(); - break; - case 12: forestNoise(); - break; - case 13: oceanNoise(); - break; - case 14: colorRoutine(); - break; - case 15: snowRoutine(); - break; - case 16: matrixRoutine(); - break; - case 17: whiteLamp(); - // case 17: lightersRoutine(); - break; - } - switch (numHold) { // индикатор уровня яркости/скорости/масштаба - case 1: - ind = sqrt(modes[currentMode].brightness + 1); - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) drawPixelXY(0, y, CHSV(10, 255, 255)); - else drawPixelXY(0, y, 0); - } - break; - case 2: - ind = sqrt(modes[currentMode].speed - 1); - for (byte y = 0; y <= HEIGHT ; y++) { - if (ind <= y) drawPixelXY(0, 15 - y, CHSV(100, 255, 255)); - else drawPixelXY(0, 15 - y, 0); - } - break; - case 3: - ind = sqrt(modes[currentMode].scale + 1); - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) drawPixelXY(0, y, CHSV(150, 255, 255)); - else drawPixelXY(0, y, 0); - } - break; - - } - FastLED.show(); - } - } -} - -void changePower() { // плавное включение/выключение - if (ONflag) { - effectsTick(); - for (int i = 0; i < modes[currentMode].brightness; i += 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.setBrightness(modes[currentMode].brightness); - delay(2); - FastLED.show(); - } else { - effectsTick(); - for (int i = modes[currentMode].brightness; i > 8; i -= 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.clear(); - delay(2); - FastLED.show(); - } -} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/effects.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/effects.ino deleted file mode 100644 index 7e3e5ac..0000000 --- a/firmware/GyverLamp_v1.4_Arduino_v1.2/effects.ino +++ /dev/null @@ -1,292 +0,0 @@ -// ================================= ЭФФЕКТЫ ==================================== - -// --------------------------------- конфетти ------------------------------------ -void sparklesRoutine() { - for (byte i = 0; i < modes[0].scale; 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(70); -} - -// функция плавного угасания цвета для всех пикселей -void fader(byte step) { - for (byte i = 0; i < WIDTH; i++) { - for (byte j = 0; j < HEIGHT; j++) { - fadePixel(i, j, step); - } - } -} -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; - } -} - -// -------------------------------------- огонь --------------------------------------------- -// эффект "огонь" -#define SPARKLES 1 // вылетающие угольки вкл выкл -unsigned char line[WIDTH]; -int pcnt = 0; - -//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 } -}; - -void fireRoutine() { - if (loadingFlag) { - loadingFlag = false; - //FastLED.clear(); - generateLine(); - } - if (pcnt >= 100) { - shiftUp(); - generateLine(); - pcnt = 0; - } - drawFrame(pcnt); - pcnt += 30; -} - -// Случайным образом генерирует следующую линию (matrix row) - -void generateLine() { - for (uint8_t x = 0; x < WIDTH; x++) { - line[x] = random(128, 255); - } -} - -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 - 15; - 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 - 15; - matrixValue[0][newX] = line[newX]; - } -} - -// рисует кадр, интерполируя между 2 "ключевых кадров" -// параметр pcnt - процент интерполяции - -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 - 15; - 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( - modes[1].scale * 2.5 + 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); - - } - } - } - - //Перавя стрка интерполируется со следующей "next" линией - for (unsigned char x = 0; x < WIDTH; x++) { - uint8_t newX = x; - if (x > 15) newX = x - 15; - CRGB color = CHSV( - modes[1].scale * 2.5 + 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; - } -} - -byte hue; -// ---------------------------------------- радуга ------------------------------------------ -void rainbowVertical() { - hue += 2; - for (byte j = 0; j < HEIGHT; j++) { - CHSV thisColor = CHSV((byte)(hue + j * modes[2].scale), 255, 255); - for (byte i = 0; i < WIDTH; i++) - drawPixelXY(i, j, thisColor); - } -} -void rainbowHorizontal() { - hue += 2; - for (byte i = 0; i < WIDTH; i++) { - CHSV thisColor = CHSV((byte)(hue + i * modes[3].scale), 255, 255); - for (byte j = 0; j < HEIGHT; j++) - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; - } -} - -// ---------------------------------------- ЦВЕТА ------------------------------------------ -void colorsRoutine() { - hue += modes[4].scale; - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(hue, 255, 255); - } -} - -// --------------------------------- ЦВЕТ ------------------------------------ -void colorRoutine() { - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); - } -} - -// ------------------------------ снегопад 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, modes[15].scale) == 0)) - drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); - else - drawPixelXY(x, HEIGHT - 1, 0x000000); - } -} - -// ------------------------------ МАТРИЦА ------------------------------ -void matrixRoutine() { - for (byte x = 0; x < WIDTH; x++) { - // заполняем случайно верхнюю строку - uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); - if (thisColor == 0) - drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, modes[16].scale) == 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 whiteLamp() { - for (byte y = 0; y < (HEIGHT / 2); y++) { - CHSV color = CHSV(100, 1, constrain(modes[17].brightness - (long)modes[17].speed * modes[17].brightness / 255 * y / 2, 1, 255)); - for (byte x = 0; x < WIDTH; x++) { - drawPixelXY(x, y + 8, color); - drawPixelXY(x, 7 - y, color); - } - } -} - - -//// ----------------------------- СВЕТЛЯКИ ------------------------------ в ардуине под него не хватет пямяти -//#define LIGHTERS_AM 100 -//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 < modes[17].scale; 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]); -// } -//} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/noiseEffects.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/noiseEffects.ino deleted file mode 100644 index fefccb6..0000000 --- a/firmware/GyverLamp_v1.4_Arduino_v1.2/noiseEffects.ino +++ /dev/null @@ -1,205 +0,0 @@ -// ******************* НАСТРОЙКИ ***************** -// "масштаб" эффектов. Чем меньше, тем крупнее! -#define MADNESS_SCALE 100 -#define CLOUD_SCALE 30 -#define LAVA_SCALE 50 -#define PLASMA_SCALE 30 -#define RAINBOW_SCALE 30 -#define RAINBOW_S_SCALE 20 -#define ZEBRA_SCALE 30 -#define FOREST_SCALE 120 -#define OCEAN_SCALE 90 - -// ***************** ДЛЯ РАЗРАБОТЧИКОВ ****************** - -// The 16 bit version of our coordinates -static uint16_t x; -static uint16_t y; -static uint16_t z; - -uint16_t speed = 20; // speed is set dynamically once we've started up -uint16_t scale = 30; // scale is set dynamically once we've started up - -// This is the array that we keep our computed noise values in (это массив, в котором храним вычисленные значения шума) -#define MAX_DIMENSION (max(WIDTH, HEIGHT)) -#if (WIDTH > HEIGHT) -uint8_t noise[WIDTH][WIDTH]; -#else -uint8_t noise[HEIGHT][HEIGHT]; -#endif - -CRGBPalette16 currentPalette( PartyColors_p ); -uint8_t colorLoop = 1; -uint8_t ihue = 0; - -void madnessNoise() { - if (loadingFlag) { - loadingFlag = false; - scale = modes[5].scale; - speed = modes[5].speed; - } - fillnoise8(); - for (int i = 0; i < WIDTH; i++) { - for (int j = 0; j < HEIGHT; j++) { - CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); - } - } - ihue += 1; -} -void rainbowNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = RainbowColors_p; - scale = modes[9].scale; - speed = modes[9].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void rainbowStripeNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = RainbowStripeColors_p; - scale = modes[10].scale; - speed = modes[10].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void zebraNoise() { - if (loadingFlag) { - loadingFlag = false; - // 'black out' all 16 palette entries... - fill_solid( currentPalette, 16, CRGB::Black); - // and set every fourth one to white. - currentPalette[0] = CRGB::White; - currentPalette[4] = CRGB::White; - currentPalette[8] = CRGB::White; - currentPalette[12] = CRGB::White; - scale = modes[11].scale; - speed = modes[11].speed; - colorLoop = 1; - -// Serial.print(" speed:"); -// Serial.print(modes[currentMode].speed); -// Serial.print(" scale:"); -// Serial.println(modes[currentMode].scale); - } - fillNoiseLED(); -} -void forestNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = ForestColors_p; - scale = modes[12].scale; - speed = modes[12].speed; - colorLoop = 0; - } - fillNoiseLED(); -} -void oceanNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = OceanColors_p; - scale = modes[13].scale; - speed = modes[13].speed; - colorLoop = 0; - } - - fillNoiseLED(); -} -void plasmaNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = PartyColors_p; - scale = modes[8].scale; - speed = modes[8].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void cloudNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = CloudColors_p; - scale = modes[6].scale; - speed = modes[6].speed; - colorLoop = 0; - } - fillNoiseLED(); -} -void lavaNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = LavaColors_p; - scale = modes[7].scale; - speed = modes[7].speed; - colorLoop = 0; - } - fillNoiseLED(); -} - -// ******************* СЛУЖЕБНЫЕ ******************* -void fillNoiseLED() { - uint8_t dataSmoothing = 0; - if ( speed < 50) { - dataSmoothing = 200 - (speed * 4); - } - for (int i = 0; i < MAX_DIMENSION; i++) { - int ioffset = scale * i; - for (int j = 0; j < MAX_DIMENSION; j++) { - int joffset = scale * j; - - uint8_t data = inoise8(x + ioffset, y + joffset, z); - - data = qsub8(data, 16); - data = qadd8(data, scale8(data, 39)); - - if ( dataSmoothing ) { - uint8_t olddata = noise[i][j]; - uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); - data = newdata; - } - - noise[i][j] = data; - } - } - z += speed; - - // apply slow drift to X and Y, just for visual variation. - x += speed / 8; - y -= speed / 16; - - for (int i = 0; i < WIDTH; i++) { - for (int j = 0; j < HEIGHT; j++) { - uint8_t index = noise[j][i]; - uint8_t bri = noise[i][j]; - // if this palette is a 'loop', add a slowly-changing base value - if ( colorLoop) { - index += ihue; - } - // brighten up, as the color palette itself often contains the - // light/dark dynamic range desired - if ( bri > 127 ) { - bri = 255; - } else { - bri = dim8_raw( bri * 2); - } - CRGB color = ColorFromPalette( currentPalette, index, bri); - drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color; - } - } - ihue += 1; -} - -void fillnoise8() { - for (int i = 0; i < MAX_DIMENSION; i++) { - int ioffset = scale * i; - for (int j = 0; j < MAX_DIMENSION; j++) { - int joffset = scale * j; - noise[i][j] = inoise8(x + ioffset, y + joffset, z); - } - } - z += speed; -} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.2/utility.ino b/firmware/GyverLamp_v1.4_Arduino_v1.2/utility.ino deleted file mode 100644 index 6110de5..0000000 --- a/firmware/GyverLamp_v1.4_Arduino_v1.2/utility.ino +++ /dev/null @@ -1,87 +0,0 @@ -// служебные функции - -// залить все -void fillAll(CRGB color) { - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = color; - } -} - -// функция отрисовки точки по координатам 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; - } -} - -// функция получения цвета пикселя по его номеру -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)); -} - -// **************** НАСТРОЙКА МАТРИЦЫ **************** -#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); - } -} From eeb63f6bbad7362e34b2b040480adfff086fc5d7 Mon Sep 17 00:00:00 2001 From: Stepko/ Date: Sun, 18 Oct 2020 23:32:04 +0300 Subject: [PATCH 4/4] kDn branch (#2) * Delete GyverLamp_v1.4_Arduino_v1.0.ino * Delete button.ino * Delete effectTicker.ino * Delete effects.ino * Delete noiseEffects.ino * Delete utility.ino * Delete ArduinoLamp_v1.4.ino * Delete Constants.h * Delete button.ino * Delete effectTicker.ino * Delete effects.ino * Delete noiseEffects.ino * Delete utility.ino * Delete ArduinoLamp_v1.5.ino * Delete Constants.h * Delete bitmap2.h * Delete button.ino * Delete effectTicker.ino * Delete effects.ino * Delete noiseEffects.ino * Delete utility.ino * Add files via upload --- .../GyverLamp_v1.4_Arduino_v1.0.ino | 326 +++++----- .../GyverLamp_v1.4_Arduino_v1.0/button.ino | 488 +++++++-------- .../effectTicker.ino | 278 ++++----- .../GyverLamp_v1.4_Arduino_v1.0/effects.ino | 557 +++++++++--------- .../noiseEffects.ino | 399 ++++++------- .../GyverLamp_v1.4_Arduino_v1.0/utility.ino | 215 ++++--- 6 files changed, 1075 insertions(+), 1188 deletions(-) diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/GyverLamp_v1.4_Arduino_v1.0.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/GyverLamp_v1.4_Arduino_v1.0.ino index 2bb917f..0eeceda 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/GyverLamp_v1.4_Arduino_v1.0.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/GyverLamp_v1.4_Arduino_v1.0.ino @@ -1,174 +1,152 @@ -/* - Скетч к проекту "Многофункциональный RGB светильник" - Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ - Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/ - Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ - Автор: AlexGyver, AlexGyver Technologies, 2019 - https://AlexGyver.ru/ -*/ - -/* - Версия 1.4: - - Исправлен баг при смене режимов - - Исправлены тормоза в режиме точки доступа -*/ - -//// Ссылка для менеджера плат: -//// http://arduino.esp8266.com/stable/package_esp8266com_index.json - -// ============= НАСТРОЙКИ ============= - -#define DEBUG 1 -#define VERTGAUGE 1 // вертикальный/горизонтальный индикатор -#define DEMOTIME 5 // в секундах -#define RANDOM_DEMO 1 // 0,1 - включить рандомный выбор режима - -//// -------- РАССВЕТ ------- -//#define DAWN_BRIGHT 200 // макс. яркость рассвета -//#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут - -// ---------- МАТРИЦА --------- -#define BRIGHTNESS 255 // стандартная маскимальная яркость (0-255) -#define MIN17BRIGHTNESS 50 // минимальная яркость 17 режима, белая лампа (0-100) для исключения нерабочей зоны -#define CURRENT_LIMIT 2600 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит - -#define WIDTH 16 // ширина матрицы -#define HEIGHT 16 // высота матрицы - -#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB - -#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная -#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний -#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз -// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" -// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ - -#define numHold_Time 1500 // время отображения индикатора уровня яркости/скорости/масштаба - -// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= -#define LED_PIN 2 // пин ленты -#define BTN_PIN 4 -#define MODE_AMOUNT 18 -#define NUM_LEDS WIDTH * HEIGHT -#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) - -// ---------------- БИБЛИОТЕКИ ----------------- -//#include "timerMinim.h" -#include -#include -#include - -// ------------------- ТИПЫ -------------------- -CRGB leds[NUM_LEDS]; -//timerMinim timeTimer(3000); -GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); - -// ----------------- ПЕРЕМЕННЫЕ ------------------ - -//String inputBuffer; -static const byte maxDim = max(WIDTH, HEIGHT); -struct { - byte brightness = 50; - byte speed = 30; - byte scale = 10; -} modes[MODE_AMOUNT]; - -//struct { -// boolean state = false; -// int time = 0; -//} alarm[7]; - -//byte dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60}; -//byte dawnMode; -//boolean dawnFlag = false; -//long thisTime; -//boolean manualOff = false; - -int8_t currentMode = 17; -boolean loadingFlag = true; -boolean ONflag = true; -byte numHold; -unsigned long numHold_Timer = 0UL; -unsigned long userTimer = 0UL; -//uint32_t eepromTimer; -//boolean settChanged = false; -// Конфетти, Огонь, Радуга верт., Радуга гориз., Смена цвета, -// Безумие 3D, Облака 3D, Лава 3D, Плазма 3D, Радуга 3D, -// Павлин 3D, Зебра 3D, Лес 3D, Океан 3D, -// colorRoutine, snowRoutine, полосы "Матрица" - -unsigned char matrixValue[8][16]; -byte xStep; -byte xCol; -byte yStep; -byte yCol; - -void setup() { - - // ЛЕНТА - FastLED.addLeds(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/; - FastLED.setBrightness(BRIGHTNESS); - if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); - FastLED.clear(); - FastLED.show(); - - touch.setStepTimeout(100); - touch.setClickTimeout(500); - - Serial.begin(9600); - Serial.println(); - - xStep = WIDTH / 4; - xCol = 4; - if(xStep<2) { - xStep = WIDTH / 3; - xCol = 3; - } else if(xStep<2) { - xStep = WIDTH / 2; - xCol = 2; - } else if(xStep<2) { - xStep = 1; - xCol = 1; - } - - yStep = HEIGHT / 4; - yCol = 4; - if(yStep<2) { - yStep = HEIGHT / 3; - yCol = 3; - } else if(yStep<2) { - yStep = HEIGHT / 2; - yCol = 2; - } else if(yStep<2) { - yStep = 1; - yCol = 1; - } - - #ifdef DEBUG - Serial.print("xStep: "); - Serial.print(xStep); - Serial.print(" xCol:"); - Serial.println(xCol); - Serial.print("yStep: "); - Serial.print(yStep); - Serial.print(" yCol:"); - Serial.println(yCol); - #endif - - if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР - currentMode = EEPROM.read(1); - for (byte x = 0; x < MODE_AMOUNT; x++) { - modes[x].brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) - modes[x].speed = EEPROM.read(x * 3 + 12); - modes[x].scale = EEPROM.read(x * 3 + 13); - } - - } -} - -void loop() { - effectsTick(); - //timeTick(); - buttonTick(); - //yield(); -} +/* + Скетч к проекту "Многофункциональный RGB светильник" + Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ + Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/ + Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ + Автор: AlexGyver, AlexGyver Technologies, 2019 + https://AlexGyver.ru/ +*/ + +/* + Версия 1.4: + - Исправлен баг при смене режимов + - Исправлены тормоза в режиме точки доступа +*/ + +//// Ссылка для менеджера плат: +//// http://arduino.esp8266.com/stable/package_esp8266com_index.json + +// ============= НАСТРОЙКИ ============= + +//#define DEBUG // Дебаг(Нужен, расскоментируйте) +#define VERTGAUGE 0 // вертикальный/горизонтальный индикатор +#define DEMOTIME 5 // в секундах +#define RANDOM_DEMO 1 // 0,1 - включить рандомный выбор режима + +//// -------- РАССВЕТ ------- +//#define DAWN_BRIGHT 200 // макс. яркость рассвета +//#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут + +// ---------- МАТРИЦА --------- +#define BRIGHTNESS 255 // стандартная маскимальная яркость (0-255) +#define MINBRIGHTNESS 25 // минимальная яркость режимов (0-100) для исключения черной лампы +#define CURRENT_LIMIT 2600 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит + +#define WIDTH 16 // ширина матрицы +#define HEIGHT 16 // высота матрицы + +#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB + +#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная +#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний +#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз +// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" +// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ + +#define numHold_Time 1500 // время отображения индикатора уровня яркости/скорости/масштаба + +// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= +#define LED_PIN 2 // пин ленты +#define BTN_PIN 4 +#define MODE_AMOUNT 18 +#define NUM_LEDS WIDTH * HEIGHT +#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) + +// ---------------- БИБЛИОТЕКИ ----------------- +#include +#include +#include + +// ------------------- ТИПЫ -------------------- +CRGB leds[NUM_LEDS]; +GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); + +// ----------------- ПЕРЕМЕННЫЕ ------------------ + +static const byte maxDim = max(WIDTH, HEIGHT); +struct { + byte brightness = 50; + byte speed = 30; + byte scale = 10; +} modes[MODE_AMOUNT]; + + +int8_t currentMode = 17; +boolean loadingFlag = true; +boolean ONflag = true; +byte numHold; +unsigned long numHold_Timer = 0UL; +unsigned long userTimer = 0UL; +unsigned char matrixValue[8][16]; +byte xStep; +byte xCol; +byte yStep; +byte yCol; + +void setup() { + + // ЛЕНТА + FastLED.addLeds(leds, NUM_LEDS).setCorrection(0xFFB0F0); + FastLED.setBrightness(BRIGHTNESS); + if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); + FastLED.clear(); + FastLED.show(); + + touch.setStepTimeout(100); + touch.setClickTimeout(500); + + //Serial.begin(9600); + //Serial.println(); + + xStep = WIDTH / 4; + xCol = 4; + if(xStep<2) { + xStep = WIDTH / 3; + xCol = 3; + } else if(xStep<2) { + xStep = WIDTH / 2; + xCol = 2; + } else if(xStep<2) { + xStep = 1; + xCol = 1; + } + + yStep = HEIGHT / 4; + yCol = 4; + if(yStep<2) { + yStep = HEIGHT / 3; + yCol = 3; + } else if(yStep<2) { + yStep = HEIGHT / 2; + yCol = 2; + } else if(yStep<2) { + yStep = 1; + yCol = 1; + } + + #ifdef DEBUG + Serial.print("xStep: "); + Serial.print(xStep); + Serial.print(" xCol:"); + Serial.println(xCol); + Serial.print("yStep: "); + Serial.print(yStep); + Serial.print(" yCol:"); + Serial.println(yCol); + #endif + + if (EEPROM.read(0) == 102) { // если было сохранение настроек, то восстанавливаем их (с)НР + currentMode = EEPROM.read(1); + for (byte x = 0; x < MODE_AMOUNT; x++) { + modes[x].brightness = EEPROM.read(x * 3 + 11); // (2-10 байт - резерв) + modes[x].speed = EEPROM.read(x * 3 + 12); + modes[x].scale = EEPROM.read(x * 3 + 13); + } + + } +} + +void loop() { + effectsTick(); + buttonTick(); //yield(); +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/button.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/button.ino index f839ee6..a2e2a28 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/button.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/button.ino @@ -1,265 +1,223 @@ -boolean brightDirection, speedDirection, scaleDirection; -//byte numHold; - -void debugPrint(){ - Serial.print(numHold); - Serial.print(" brightness:"); - Serial.print(modes[currentMode].brightness); - Serial.print(" speed:"); - Serial.print(modes[currentMode].speed); - Serial.print(" scale:"); - Serial.print(modes[currentMode].scale); - Serial.print(" numHold_Timer:"); - Serial.println(numHold_Timer); -} - -void changeDirection(byte numHold){ - switch(numHold){ - case 0: case 1: brightDirection = !brightDirection; break; - case 2: speedDirection = !speedDirection; break; - case 3: scaleDirection = !scaleDirection; break; - } - numHold_Timer = millis(); -} - -void buttonTick() { - touch.tick(); - - if (!ONflag) { // Обработка из выключенного состояния - #ifdef DEBUG - if(touch.isPress()) - Serial.println("Off state"); - #endif - - if (touch.isDouble()) { // Демо-режим, с переключением каждые 30 секунд для двойного клика в выключенном состоянии - numHold = 254; - currentMode = random(0, 255)%17; // 17 скипаем - //modes[currentMode].brightness = BRIGHTNESS/2; // в половину яркости - FastLED.setBrightness(modes[currentMode].brightness); - ONflag = true; - userTimer = millis(); // момент включения для таймаута в DEMOTIME - numHold_Timer = millis(); - //brightDirection = 0; // на уменьшение - changePower(); - #ifdef DEBUG - Serial.print("Demo mode: "); - Serial.println(currentMode); - #endif - } - - if (touch.isHolded()) { - #ifdef DEBUG - Serial.println("Holdeded from offed state"); - #endif - currentMode = 17; - modes[currentMode].brightness = BRIGHTNESS; - FastLED.setBrightness(modes[currentMode].brightness); - numHold = 255; - ONflag = true; - userTimer = millis(); // момент включения для таймаута в переключения в режим регулировки яркости - numHold_Timer = millis(); - brightDirection = 0; // на уменьшение - changePower(); - } - } - - if (touch.isSingle()) { // Включение/выключение одиночным - // if (dawnFlag) { - // //manualOff = true; - // dawnFlag = false; - // loadingFlag = true; - // FastLED.setBrightness(modes[currentMode].brightness); - // changePower(); - // } else - // Serial.println("Single click"); - { - if (ONflag) { - ONflag = false; - #ifdef DEBUG - Serial.println("Off lamp"); - #endif - changePower(); - } else { - ONflag = true; - #ifdef DEBUG - Serial.println("On lamp"); - debugPrint(); // отладка - #endif - //FastLED.setBrightness(modes[currentMode].brightness); - //changePower(); - } - } - } - -if (ONflag) { // если включено - if (touch.isDouble()) { - #ifdef DEBUG - Serial.println("Double click"); - //debugPrint(); // отладка - #endif - if (++currentMode >= MODE_AMOUNT) currentMode = 0; - FastLED.setBrightness(modes[currentMode].brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - if (touch.isTriple()) { - #ifdef DEBUG - Serial.println("Triple click"); - //debugPrint(); // отладка - #endif - if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; - FastLED.setBrightness(modes[currentMode].brightness); - loadingFlag = true; - //settChanged = true; - FastLED.clear(); - delay(1); - } - - if ((touch.hasClicks()) && (touch.getClicks() == 5)) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров // && (touch.hasClicks()) - if (EEPROM.read(0) != 102) EEPROM.write(0, 102); - if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект - for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов - if (EEPROM.read(x * 3 + 11) != modes[x].brightness) EEPROM.write(x * 3 + 11, modes[x].brightness); - if (EEPROM.read(x * 3 + 12) != modes[x].speed) EEPROM.write(x * 3 + 12, modes[x].speed); - if (EEPROM.read(x * 3 + 13) != modes[x].scale) EEPROM.write(x * 3 + 13, modes[x].scale); - } - // индикация сохранения - ONflag = false; - changePower(); - delay(200); - ONflag = true; - changePower(); - } - - if (touch.isHolded() && numHold != 255) { // изменение яркости при удержании кнопки - if(modes[currentMode].brightness == BRIGHTNESS && numHold == 1){ - brightDirection = 0; - } else if (modes[currentMode].brightness <= 1 && numHold == 1){ - brightDirection = 1; - } else - changeDirection(numHold); - if(!numHold || numHold==254) - numHold = 1; - } - - if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки - if(modes[currentMode].speed == 255 && numHold == 2){ - speedDirection = 0; - } else if (modes[currentMode].speed <= 1 && numHold == 2){ - speedDirection = 1; - } else - changeDirection(numHold); - if(!numHold) - numHold = 2; - } - - if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки - if(modes[currentMode].scale == 255 && numHold == 3){ - scaleDirection = 0; - } else if (modes[currentMode].scale <= 1 && numHold == 3){ - scaleDirection = 1; - } else - changeDirection(numHold); - if(!numHold) - numHold = 3; - } - - if (touch.isStep()) { - #ifdef DEBUG - debugPrint(); // отладка - #endif - if (numHold != 0 && numHold != 255) { - numHold_Timer = millis(); - loadingFlag = true; - } - - switch (numHold) { - case 1: - case 254: - // if (brightDirection) { - // if (modes[currentMode].brightness < 10) modes[currentMode].brightness += 1; - // else if (modes[currentMode].brightness < 250) modes[currentMode].brightness += 5; - // else modes[currentMode].brightness = 255; - // } else { - // if (modes[currentMode].brightness > 15) modes[currentMode].brightness -= 5; - // else if (modes[currentMode].brightness > 1) modes[currentMode].brightness -= 1; - // else modes[currentMode].brightness = 1; - // } - if(currentMode==17) - modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), MIN17BRIGHTNESS , BRIGHTNESS); - else - modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), 1 , BRIGHTNESS); - // byte x = sqrt(modes[currentMode].brightness); - // for (byte y = 0; y < HEIGHT - 1; y++) { - // if (x < y) drawPixelXY(1, y, CHSV(10,200,200)); - // else drawPixelXY(1, y, CHSV(1,0,0)); - // } - break; - - case 2: - // if (speedDirection) { - // if (modes[currentMode].speed < 10) modes[currentMode].speed += 1; - // else if (modes[currentMode].speed < 250) modes[currentMode].speed += 5; - // else modes[currentMode].speed = 255; - // } else { - // if (modes[currentMode].speed > 15) modes[currentMode].speed -= 5; - // else if (modes[currentMode].speed > 1) modes[currentMode].speed -= 1; - // else modes[currentMode].speed = 1; - // } - modes[currentMode].speed = constrain(modes[currentMode].speed + (modes[currentMode].speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); - break; - - case 3: - // if (scaleDirection) { - // if (modes[currentMode].scale < 10) modes[currentMode].scale += 1; - // else if (modes[currentMode].scale < 250) modes[currentMode].scale += 5; - // else modes[currentMode].scale = 255; - // } else { - // if (modes[currentMode].scale > 15) modes[currentMode].scale -= 5; - // else if (modes[currentMode].scale > 1) modes[currentMode].scale -= 1; - // else modes[currentMode].scale = 1; - // } - modes[currentMode].scale = constrain(modes[currentMode].scale + (modes[currentMode].scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); - break; - } - } - - if ((millis() - userTimer) > numHold_Time && numHold>=250) { - if(numHold == 255){ - numHold = 1; - userTimer = millis(); - numHold_Timer = millis(); - } - } - - if ((millis() - numHold_Timer) > numHold_Time && !touch.isHolded() && numHold<250) { - numHold = 0; - numHold_Timer = millis(); - } - - if((millis() - userTimer > DEMOTIME*1000) && (numHold == 254)){ - //FastLED.clear(); - //delay(2); - for(byte i = 250; i>10; i-=10){ - fader(30); - FastLED.delay(33); - //FastLED.show(); - } - - if(RANDOM_DEMO) - currentMode = random(0, 255)%17; // 17 скипаем - else - currentMode=(currentMode+1)%17; // 17 скипаем и идем по наростанию - #ifdef DEBUG - Serial.print("Demo mode: "); - Serial.println(currentMode); - #endif - userTimer = millis(); - } - - FastLED.setBrightness(modes[currentMode].brightness); - //settChanged = true; - } -} +boolean brightDirection, speedDirection, scaleDirection; +//byte numHold; +#ifdef DEBUG +void debugPrint(){ + Serial.print(numHold); + Serial.print(F(" brightness:")); + Serial.print(modes[currentMode].brightness); + Serial.print(F(" speed:")); + Serial.print(modes[currentMode].speed); + Serial.print(F(" scale:")); + Serial.print(modes[currentMode].scale); + Serial.print(F(" numHold_Timer:")); + Serial.println(numHold_Timer); +} +#endif +void changeDirection(byte numHold){ + switch(numHold){ + case 0: case 1: brightDirection = !brightDirection; break; + case 2: speedDirection = !speedDirection; break; + case 3: scaleDirection = !scaleDirection; break; + } + numHold_Timer = millis(); +} + +void buttonTick() { + touch.tick(); + + if (!ONflag) { // Обработка из выключенного состояния + #ifdef DEBUG + if(touch.isPress()) + Serial.println(F("Off state")); + #endif + + if (touch.isDouble()) { // Демо-режим, с переключением каждые 30 секунд для двойного клика в выключенном состоянии + numHold = 254; + currentMode = random(0, 255)%17; // 17 скипаем + //modes[currentMode].brightness = BRIGHTNESS/2; // в половину яркости + FastLED.setBrightness(modes[currentMode].brightness); + ONflag = true; + userTimer = millis(); // момент включения для таймаута в DEMOTIME + numHold_Timer = millis(); + //brightDirection = 0; // на уменьшение + changePower(); + #ifdef DEBUG + Serial.print(F("Demo mode: ")); + Serial.println(currentMode); + #endif + } + + if (touch.isHolded()) { + #ifdef DEBUG + Serial.println(F("Holdeded from offed state")); + #endif + currentMode = 17; + modes[currentMode].brightness = BRIGHTNESS; + FastLED.setBrightness(modes[currentMode].brightness); + numHold = 255; + ONflag = true; + userTimer = millis(); // момент включения для таймаута в переключения в режим регулировки яркости + numHold_Timer = millis(); + brightDirection = 0; // на уменьшение + changePower(); + } + } + + if (touch.isSingle()) { // Включение/выключение одиночным + + { + if (ONflag) { + ONflag = false; + #ifdef DEBUG + Serial.println(F("Off lamp")); + #endif + changePower(); + } else { + ONflag = true; + #ifdef DEBUG + Serial.println(F("On lamp")); + debugPrint(); // отладка + #endif + + } + } + } + +if (ONflag) { // если включено + if (touch.isDouble()) { + #ifdef DEBUG + Serial.println(F("Double click")); + //debugPrint(); // отладка + #endif + if (++currentMode >= MODE_AMOUNT) currentMode = 0; + FastLED.setBrightness(modes[currentMode].brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + if (touch.isTriple()) { + #ifdef DEBUG + Serial.println(F("Triple click")); + //debugPrint(); // отладка + #endif + if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; + FastLED.setBrightness(modes[currentMode].brightness); + loadingFlag = true; + //settChanged = true; + FastLED.clear(); + delay(1); + } + + if ((touch.hasClicks()) && (touch.getClicks() == 5)) { // если было пятикратное нажатие на кнопку, то производим сохранение параметров // && (touch.hasClicks()) + if (EEPROM.read(0) != 102) EEPROM.write(0, 102); + if (EEPROM.read(1) != currentMode) EEPROM.write(1, currentMode); // запоминаем текущий эфект + for (byte x = 0; x < MODE_AMOUNT; x++) { // сохраняем настройки всех режимов + if (EEPROM.read(x * 3 + 11) != modes[x].brightness) EEPROM.write(x * 3 + 11, modes[x].brightness); + if (EEPROM.read(x * 3 + 12) != modes[x].speed) EEPROM.write(x * 3 + 12, modes[x].speed); + if (EEPROM.read(x * 3 + 13) != modes[x].scale) EEPROM.write(x * 3 + 13, modes[x].scale); + } + // индикация сохранения + ONflag = false; + changePower(); + delay(200); + ONflag = true; + changePower(); + } + + if (touch.isHolded() && numHold != 255) { // изменение яркости при удержании кнопки + if(modes[currentMode].brightness == BRIGHTNESS && numHold == 1){ + brightDirection = 0; + } else if (modes[currentMode].brightness <= 1 && numHold == 1){ + brightDirection = 1; + } else + changeDirection(numHold); + if(!numHold || numHold==254) + numHold = 1; + } + + if (touch.isHolded2()) { // изменение скорости "speed" при двойном нажатии и удержании кнопки + if(modes[currentMode].speed == 255 && numHold == 2){ + speedDirection = 0; + } else if (modes[currentMode].speed <= 1 && numHold == 2){ + speedDirection = 1; + } else + changeDirection(numHold); + if(!numHold) + numHold = 2; + } + + if (touch.isHolded3()) { // изменение масштаба "scale" при тройном нажатии и удержании кнопки + if(modes[currentMode].scale == 255 && numHold == 3){ + scaleDirection = 0; + } else if (modes[currentMode].scale <= 1 && numHold == 3){ + scaleDirection = 1; + } else + changeDirection(numHold); + if(!numHold) + numHold = 3; + } + + if (touch.isStep()) { + #ifdef DEBUG + debugPrint(); // отладка + #endif + if (numHold != 0 && numHold != 255) { + numHold_Timer = millis(); + loadingFlag = true; + } + + switch (numHold) { + case 1: + + modes[currentMode].brightness = constrain(modes[currentMode].brightness + (modes[currentMode].brightness / 25 + 1) * (brightDirection * 2 - 1), MINBRIGHTNESS , BRIGHTNESS); + break; + + case 2: + + modes[currentMode].speed = constrain(modes[currentMode].speed + (modes[currentMode].speed / 25 + 1) * (speedDirection * 2 - 1), 1 , 255); + break; + + case 3: + + modes[currentMode].scale = constrain(modes[currentMode].scale + (modes[currentMode].scale / 25 + 1) * (scaleDirection * 2 - 1), 1 , 255); + break; + } + } + + if ((millis() - userTimer) > numHold_Time && numHold>=250) { + if(numHold == 255){ + numHold = 1; + userTimer = millis(); + numHold_Timer = millis(); + } + } + + if ((millis() - numHold_Timer) > numHold_Time && !touch.isHolded() && numHold<250) { + numHold = 0; + numHold_Timer = millis(); + } + + if((millis() - userTimer > DEMOTIME*1000) && (numHold == 254)){ + //FastLED.clear(); + //delay(2); + for(byte i = 250; i>10; i-=10){ + fader(30); + FastLED.delay(33); + //FastLED.show(); + } + + if(RANDOM_DEMO) + currentMode = random(0, 255)%17; // 17 скипаем + else + currentMode=(currentMode+1)%17; // 17 скипаем и идем по наростанию + #ifdef DEBUG + Serial.print(F("Demo mode: ")); + Serial.println(currentMode); + #endif + userTimer = millis(); + } + + FastLED.setBrightness(modes[currentMode].brightness); + } +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/effectTicker.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/effectTicker.ino index 4d04b64..193199c 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/effectTicker.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/effectTicker.ino @@ -1,163 +1,115 @@ -uint32_t effTimer; -byte ind; - -void effectsTick() { - // if (!dawnFlag) - { - if (millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { - effTimer = millis(); - if(ONflag){ - switch (currentMode) { - case 0: sparklesRoutine(); - break; - case 1: fireRoutine(); - break; - case 2: rainbowVertical(); - break; - case 3: rainbowHorizontal(); - break; - case 4: colorsRoutine(); - break; - case 5: madnessNoise(); - break; - case 6: cloudNoise(); - break; - case 7: lavaNoise(); - break; - case 8: plasmaNoise(); - break; - case 9: rainbowNoise(); - break; - case 10: rainbowStripeNoise(); - break; - case 11: zebraNoise(); - break; - case 12: forestNoise(); - break; - case 13: oceanNoise(); - break; - case 14: colorRoutine(); - break; - case 15: snowRoutine(); - break; - case 16: matrixRoutine(); - break; - case 17: whiteLamp(); - // case 17: lightersRoutine(); - break; - } - if(VERTGAUGE) - GaugeShowVertical(); - else - GaugeShowHorizontal(); - } - FastLED.show(); - } - } -} - -void GaugeShowVertical() { - switch (numHold) { // индикатор уровня яркости/скорости/масштаба - case 1: - if(currentMode==17) - ind = sqrt((255.0/(BRIGHTNESS-MIN17BRIGHTNESS))*(modes[currentMode].brightness-MIN17BRIGHTNESS) + 1); // привести к полной шкале - else - ind = sqrt((255.0/BRIGHTNESS)*modes[currentMode].brightness + 1); // привести к полной шкале - for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) - drawPixelXY(x, y, CHSV(10, 255, 255)); - else - drawPixelXY(x, y, 0); - } - } - break; - case 2: - ind = sqrt(modes[currentMode].speed - 1); - for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { - for (byte y = 0; y <= HEIGHT ; y++) { - if (ind <= y) - drawPixelXY(x, HEIGHT-1-y, CHSV(100, 255, 255)); - else - drawPixelXY(x, HEIGHT-1-y, 0); - } - } - break; - case 3: - ind = sqrt(modes[currentMode].scale + 1); - for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { - for (byte y = 0; y < HEIGHT ; y++) { - if (ind > y) - drawPixelXY(x, y, CHSV(150, 255, 255)); - else - drawPixelXY(x, y, 0); - } - } - break; - } -} - -void GaugeShowHorizontal() { - switch (numHold) { // индикатор уровня яркости/скорости/масштаба - case 1: - if(currentMode==17) - ind = sqrt((255.0/(BRIGHTNESS-MIN17BRIGHTNESS))*(modes[currentMode].brightness-MIN17BRIGHTNESS) + 1); // привести к полной шкале - else - ind = sqrt((255.0/BRIGHTNESS)*modes[currentMode].brightness + 1); // привести к полной шкале - for (byte y = 0; y <= yCol*(yStep-1) ; y+=yStep) { - for (byte x = 0; x < WIDTH ; x++) { - if (ind > x) - drawPixelXY((x+y)%WIDTH, y, CHSV(10, 255, 255)); - else - drawPixelXY((x+y)%WIDTH, y, 0); - } - } - break; - case 2: - ind = sqrt(modes[currentMode].speed - 1); - for (byte y = 0; y <= yCol*(yStep-1) ; y+=yStep) { - for (byte x = 0; x <= WIDTH ; x++) { - if (ind < x) - drawPixelXY((WIDTH-x+y)%WIDTH, y, CHSV(100, 255, 255)); - else - drawPixelXY((WIDTH-x+y)%WIDTH, y, 0); - } - } - break; - case 3: - ind = sqrt(modes[currentMode].scale + 1); - for (byte y = 0; y <= yCol*(yStep-1) ; y+=yStep) { - for (byte x = 0; x < WIDTH ; x++) { - if (ind > x) - drawPixelXY((x+y)%WIDTH, y, CHSV(150, 255, 255)); - else - drawPixelXY((x+y)%WIDTH, y, 0); - } - } - break; - } -} - -void changePower() { // плавное включение/выключение - if (ONflag) { - effectsTick(); - for (int i = 0; i < modes[currentMode].brightness; i += 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.setBrightness(modes[currentMode].brightness); - delay(2); - FastLED.show(); - } else { - //effectsTick(); - for (int i = modes[currentMode].brightness; i > 8; i -= 8) { - FastLED.setBrightness(i); - delay(1); - FastLED.show(); - } - FastLED.clear(); - delay(2); - FastLED.show(); - } -} +uint32_t effTimer; +byte ind; + +void effectsTick() { + { + if (millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { + effTimer = millis(); + if(ONflag){ + switch (currentMode) { + case 0: sparklesRoutine(); + break; + case 1: rainbowVertical(); + break; + case 2: rainbowHorizontal(); + break; + case 3: fireRoutine(); + break; + case 4: colorsRoutine(); + break; + case 5: madnessNoise(); + break; + case 6: cloudNoise(); + break; + case 7: lavaNoise(); + break; + case 8: plasmaNoise(); + break; + case 9: rainbowNoise(); + break; + case 10: rainbowStripeNoise(); + break; + case 11: zebraNoise(); + break; + case 12: forestNoise(); + break; + case 13: oceanNoise(); + break; + case 14: colorRoutine(); + break; + case 15: snowRoutine(); + break; + case 16: matrixRoutine(); + break; + case 17: whiteLampRoutine(); + break; + } + if(VERTGAUGE) + GaugeShowVertical(); + } + FastLED.show(); + } + } +} + +void GaugeShowVertical() { + switch (numHold) { // индикатор уровня яркости/скорости/масштаба + case 1: + ind = ind = sqrt(modes[currentMode].brightness + 1); + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) + drawPixelXY(x, y, CHSV(10, 255, 255)); + else + drawPixelXY(x, y, 0); + } + } + break; + case 2: + ind = sqrt(modes[currentMode].speed - 1); + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y <= HEIGHT ; y++) { + if (ind <= y) + drawPixelXY(x, HEIGHT-1-y, CHSV(100, 255, 255)); + else + drawPixelXY(x, HEIGHT-1-y, 0); + } + } + break; + case 3: + ind = sqrt(modes[currentMode].scale + 1); + for (byte x = 0; x <= xCol*(xStep-1) ; x+=xStep) { + for (byte y = 0; y < HEIGHT ; y++) { + if (ind > y) + drawPixelXY(x, y, CHSV(150, 255, 255)); + else + drawPixelXY(x, y, 0); + } + } + break; + } +} + +void changePower() { // плавное включение/выключение + if (ONflag) { + effectsTick(); + for (int i = 0; i < modes[currentMode].brightness; i += 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.setBrightness(modes[currentMode].brightness); + delay(2); + FastLED.show(); + } else { + //effectsTick(); + for (int i = modes[currentMode].brightness; i > 8; i -= 8) { + FastLED.setBrightness(i); + delay(1); + FastLED.show(); + } + FastLED.clear(); + delay(2); + FastLED.show(); + } +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/effects.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/effects.ino index ed2cccc..3f0ddd2 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/effects.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/effects.ino @@ -1,294 +1,263 @@ -// ================================= ЭФФЕКТЫ ==================================== - -// --------------------------------- конфетти ------------------------------------ -void sparklesRoutine() { - for (byte i = 0; i < modes[0].scale; 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(70); -} - -// функция плавного угасания цвета для всех пикселей -void fader(byte step) { - for (byte i = 0; i < WIDTH; i++) { - for (byte j = 0; j < HEIGHT; j++) { - fadePixel(i, j, step); - } - } -} -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; - } -} - -// -------------------------------------- огонь --------------------------------------------- -// эффект "огонь" -#define SPARKLES 1 // вылетающие угольки вкл выкл -unsigned char line[WIDTH]; -int pcnt = 0; - -//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 } -}; - -void fireRoutine() { - if (loadingFlag) { - loadingFlag = false; - //FastLED.clear(); - generateLine(); - } - if (pcnt >= 100) { - shiftUp(); - generateLine(); - pcnt = 0; - } - drawFrame(pcnt); - pcnt += 30; -} - -// Случайным образом генерирует следующую линию (matrix row) - -void generateLine() { - for (uint8_t x = 0; x < WIDTH; x++) { - line[x] = random(64, 255); - } -} - -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 - 15; - 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 - 15; - matrixValue[0][newX] = line[newX]; - } -} - -// рисует кадр, интерполируя между 2 "ключевых кадров" -// параметр pcnt - процент интерполяции - -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 - 15; - 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( - modes[1].scale * 2.5 + 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); - - } - } - } - - //Перавя стрка интерполируется со следующей "next" линией - for (unsigned char x = 0; x < WIDTH; x++) { - uint8_t newX = x; - if (x > 15) newX = x - 15; - CRGB color = CHSV( - modes[1].scale * 2.5 + 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; - } -} - -byte hue; -// ---------------------------------------- радуга ------------------------------------------ -void rainbowVertical() { - hue += 2; - for (byte j = 0; j < HEIGHT; j++) { - CHSV thisColor = CHSV((byte)(hue + j * modes[2].scale), 255, 255); - for (byte i = 0; i < WIDTH; i++) - drawPixelXY(i, j, thisColor); - } -} -void rainbowHorizontal() { - hue += 2; - for (byte i = 0; i < WIDTH; i++) { - CHSV thisColor = CHSV((byte)(hue + i * modes[3].scale), 255, 255); - for (byte j = 0; j < HEIGHT; j++) - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; - } -} - -// ---------------------------------------- ЦВЕТА ------------------------------------------ -void colorsRoutine() { - hue += modes[4].scale; - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = CHSV(hue, 255, 255); - } -} - -// --------------------------------- ЦВЕТ ------------------------------------ -void colorRoutine() { - for (int i = 0; i < NUM_LEDS; i++) { - //leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); - leds[i] = CHSV(modes[14].speed*(modes[14].scale/16+1), 255, 255); - } -} - -// ------------------------------ снегопад 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, modes[15].scale) == 0)) - drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); - else - drawPixelXY(x, HEIGHT - 1, 0x000000); - } -} - -// ------------------------------ МАТРИЦА ------------------------------ -void matrixRoutine() { - for (byte x = 0; x < WIDTH; x++) { - // заполняем случайно верхнюю строку - uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); - if (thisColor == 0) - drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, modes[16].scale) == 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 whiteLamp() { - for (byte y = 0; y < (HEIGHT / 2); y++) { - CHSV color = CHSV(56, modes[17].scale, constrain(modes[17].brightness - (long)modes[17].speed * modes[17].brightness / BRIGHTNESS * y / 2, 1, 255)); - //CHSV color = CHSV(100, 1, constrain(modes[17].brightness - (long)modes[17].speed * modes[17].brightness / BRIGHTNESS * y / 2, 1, 255)); - for (byte x = 0; x < WIDTH; x++) { - drawPixelXY(x, y + 8, color); - drawPixelXY(x, 7 - y, color); - } - } -} - - -//// ----------------------------- СВЕТЛЯКИ ------------------------------ в ардуине под него не хватет пямяти -//#define LIGHTERS_AM 100 -//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 < modes[17].scale; 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]); -// } -//} +// ================================= ЭФФЕКТЫ ==================================== +uint8_t pcnt; +uint8_t line[WIDTH]; +// --------------------------------- конфетти ------------------------------------ +#define FADE_OUT_SPEED (70U) // скорость затухания +void sparklesRoutine() +{ + for (uint8_t i = 0; i < modes[currentMode].scale; i++) + { + uint8_t x = random(0U, WIDTH); + uint8_t y = random(0U, HEIGHT); + if (getPixColorXY(x, y) == 0U) + { + drawPixelXY(x, y,CHSV(random(0U, 255U), 255U, 255U)); + } + } + fader(FADE_OUT_SPEED); +} +// -------------------------------------- огонь --------------------------------------------- +#define SPARKLES 0 // вылетающие угольки вкл выкл +//these values are substracetd from the generated values to give a shape to the animation +const unsigned char valueMask[8][16] PROGMEM = { + {0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 }, + {0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 }, + {0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 }, + {0 , 32 , 64 , 128, 128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 128, 64 , 32 , 0 }, + {32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 }, + {64 , 96 , 128, 192, 192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128, 96 , 64 }, + {96 , 128, 160, 255, 255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160, 128, 96 }, + {128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128} +}; + +//these are the hues for the fire, +//should be between 0 (red) to about 25 (yellow) +const unsigned char hueMask[8][16] PROGMEM = { + {25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25 }, + {25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19 }, + {19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16 }, + {13, 13, 5 , 1 , 1 , 5 , 11, 13, 13, 13, 5 , 1 , 1 , 5 , 11, 13 }, + {11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11 }, + {8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 }, + {5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 }, + {1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } +}; +void fireRoutine() { + if (loadingFlag) { + loadingFlag = false; + //FastLED.clear(); + generateLine(); + } + if (pcnt >= 100) { + shiftUp(); + generateLine(); + pcnt = 0; + } + drawFrame(pcnt); + pcnt += 25; +} + +// Случайным образом генерирует следующую линию (matrix row) + +void generateLine() { + for (uint8_t x = 0; x < WIDTH; x++) { + line[x] = random(127, 255); + } +} + +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 - 15; + 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 - 15; + matrixValue[0][newX] = line[newX]; + } +} + +// рисует кадр, интерполируя между 2 "ключевых кадров" +// параметр pcnt - процент интерполяции + +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 - 15; + 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( + modes[currentMode].scale * 2.5 + 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); + + } + } + } + + //Перавя стрка интерполируется со следующей "next" линией + for (unsigned char x = 0; x < WIDTH; x++) { + uint8_t newX = x; + if (x > 15) newX = x - 15; + CRGB color = CHSV( + modes[currentMode].scale * 2.5 + 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; + } +} +byte hue; +// ---------------------------------------- радуга ------------------------------------------ +void rainbowVertical() { + hue += 2; + for (byte j = 0; j < HEIGHT; j++) { + CHSV thisColor = CHSV((byte)(hue + j * modes[currentMode].scale), 255, 255); + for (byte i = 0; i < WIDTH; i++) + drawPixelXY(i, j, thisColor); + } +} +void rainbowHorizontal() { + hue += 2; + for (byte i = 0; i < WIDTH; i++) { + CHSV thisColor = CHSV((byte)(hue + i * modes[currentMode].scale), 255, 255); + for (byte j = 0; j < HEIGHT; j++) + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; + } +} + +// ---------------------------------------- ЦВЕТА ------------------------------------------ +void colorsRoutine() { + hue += modes[currentMode].scale; + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = CHSV(hue, 255, 255); + } +} + +// --------------------------------- ЦВЕТ ------------------------------------ +void colorRoutine() { + for (int i = 0; i < NUM_LEDS; i++) { + //leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); + leds[i] = CHSV(modes[currentMode].speed*(modes[currentMode].scale/16+1), 255, 255); + } +} + +// ------------------------------ снегопад 2.0 -------------------------------- +void snowRoutine() { + shiftDown(); + + for (byte x = 0; x < WIDTH; x++) { + // заполняем случайно верхнюю строку + // а также не даём двум блокам по вертикали вместе быть + if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, modes[currentMode].scale) == 0)) + drawPixelXY(x, HEIGHT - 1U, 0xE0FFFF - 0x101010 * random(0, 4)); + else + drawPixelXY(x, HEIGHT - 1, 0x000000); + } +} +// ------------------------------ МАТРИЦА ------------------------------ +void matrixRoutine() +{ + for (uint8_t x = 0U; x < WIDTH; x++) + { + // обрабатываем нашу матрицу снизу вверх до второй сверху строчки + for (uint8_t y = 0U; y < HEIGHT - 1U; y++) + { + uint32_t thisColor = getPixColorXY(x, y); // берём цвет нашего пикселя + uint32_t upperColor = getPixColorXY(x, y + 1U); // берём цвет пикселя над нашим + if (upperColor >= 0x900000 && random(7 * HEIGHT) != 0U) // если выше нас максимальная яркость, игнорим этот факт с некой вероятностью или опускаем цепочку ниже + drawPixelXY(x, y, upperColor); + else if (thisColor == 0U && random((100 - modes[currentMode].scale) * HEIGHT) == 0U) // если наш пиксель ещё не горит, иногда зажигаем новые цепочки + //else if (thisColor == 0U && random((100 - modes[currentMode].Scale) * HEIGHT*3) == 0U) // для длинных хвостов + drawPixelXY(x, y, 0x9bf800); + else if (thisColor <= 0x050800) // если наш пиксель почти погас, стараемся сделать затухание медленней + { + if (thisColor >= 0x030000) + drawPixelXY(x, y, 0x020300); + else if (thisColor != 0U) + drawPixelXY(x, y, 0U); + } + else if (thisColor >= 0x900000) // если наш пиксель максимальной яркости, резко снижаем яркость + drawPixelXY(x, y, 0x558800); + else + drawPixelXY(x, y, thisColor - 0x0a1000); // в остальных случаях снижаем яркость на 1 уровень + //drawPixelXY(x, y, thisColor - 0x050800); // для длинных хвостов + } + // аналогично обрабатываем верхний ряд пикселей матрицы + uint32_t thisColor = getPixColorXY(x, HEIGHT - 1U); + if (thisColor == 0U) // если наш верхний пиксель не горит, заполняем его с вероятностью .Scale + { + if (random(100 - modes[currentMode].scale) == 0U) + drawPixelXY(x, HEIGHT - 1U, 0x9bf800); + } + else if (thisColor <= 0x050800) // если наш верхний пиксель почти погас, стараемся сделать затухание медленней + { + if (thisColor >= 0x030000) + drawPixelXY(x, HEIGHT - 1U, 0x020300); + else + drawPixelXY(x, HEIGHT - 1U, 0U); + } + else if (thisColor >= 0x900000) // если наш верхний пиксель максимальной яркости, резко снижаем яркость + drawPixelXY(x, HEIGHT - 1U, 0x558800); + else + drawPixelXY(x, HEIGHT - 1U, thisColor - 0x0a1000); // в остальных случаях снижаем яркость на 1 уровень + //drawPixelXY(x, HEIGHT - 1U, thisColor - 0x050800); // для длинных хвостов + } +} +// ------------------------------ БЕЛАЯ ЛАМПА ------------------------------ +void whiteLampRoutine() +{ + if (loadingFlag) + { + loadingFlag = false; + FastLED.clear(); + //delay(1); + + uint8_t centerY = (uint8_t)round(HEIGHT / 2.0F) - 1U;// max((uint8_t)round(HEIGHT / 2.0F) - 1, 0); нахрена тут максимум было вычислять? для ленты?! + uint8_t bottomOffset = (uint8_t)(!(HEIGHT & 0x01));// && (HEIGHT > 1)); и высота больше единицы. супер! // если высота матрицы чётная, линий с максимальной яркостью две, а линии с минимальной яркостью снизу будут смещены на один ряд + + uint8_t fullRows = centerY / 100.0 * modes[currentMode].scale; + uint8_t iPol = (centerY / 100.0 * modes[currentMode].scale - fullRows) * 255; + + for (int16_t y = centerY; y >= 0; y--) + { + CRGB color = CHSV( + 45U, // определяем тон + map(modes[currentMode].speed, 0U, 255U, 0U, 170U), // определяем насыщенность + y > (centerY - fullRows - 1) // определяем яркость + ? 255U // для центральных горизонтальных полос + : iPol * (y > centerY - fullRows - 2)); // для остальных горизонтальных полос яркость равна либо 255, либо 0 в зависимости от масштаба + + for (uint8_t x = 0U; x < WIDTH; x++) + { + drawPixelXY(x, y, color); // при чётной высоте матрицы максимально яркими отрисуются 2 центральных горизонтальных полосы + drawPixelXY(x, HEIGHT + bottomOffset - y - 2U, color); // при нечётной - одна, но дважды + } + } + } +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/noiseEffects.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/noiseEffects.ino index fefccb6..11f3c90 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/noiseEffects.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/noiseEffects.ino @@ -1,205 +1,194 @@ -// ******************* НАСТРОЙКИ ***************** -// "масштаб" эффектов. Чем меньше, тем крупнее! -#define MADNESS_SCALE 100 -#define CLOUD_SCALE 30 -#define LAVA_SCALE 50 -#define PLASMA_SCALE 30 -#define RAINBOW_SCALE 30 -#define RAINBOW_S_SCALE 20 -#define ZEBRA_SCALE 30 -#define FOREST_SCALE 120 -#define OCEAN_SCALE 90 - -// ***************** ДЛЯ РАЗРАБОТЧИКОВ ****************** - -// The 16 bit version of our coordinates -static uint16_t x; -static uint16_t y; -static uint16_t z; - -uint16_t speed = 20; // speed is set dynamically once we've started up -uint16_t scale = 30; // scale is set dynamically once we've started up - -// This is the array that we keep our computed noise values in (это массив, в котором храним вычисленные значения шума) -#define MAX_DIMENSION (max(WIDTH, HEIGHT)) -#if (WIDTH > HEIGHT) -uint8_t noise[WIDTH][WIDTH]; -#else -uint8_t noise[HEIGHT][HEIGHT]; -#endif - -CRGBPalette16 currentPalette( PartyColors_p ); -uint8_t colorLoop = 1; -uint8_t ihue = 0; - -void madnessNoise() { - if (loadingFlag) { - loadingFlag = false; - scale = modes[5].scale; - speed = modes[5].speed; - } - fillnoise8(); - for (int i = 0; i < WIDTH; i++) { - for (int j = 0; j < HEIGHT; j++) { - CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); - } - } - ihue += 1; -} -void rainbowNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = RainbowColors_p; - scale = modes[9].scale; - speed = modes[9].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void rainbowStripeNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = RainbowStripeColors_p; - scale = modes[10].scale; - speed = modes[10].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void zebraNoise() { - if (loadingFlag) { - loadingFlag = false; - // 'black out' all 16 palette entries... - fill_solid( currentPalette, 16, CRGB::Black); - // and set every fourth one to white. - currentPalette[0] = CRGB::White; - currentPalette[4] = CRGB::White; - currentPalette[8] = CRGB::White; - currentPalette[12] = CRGB::White; - scale = modes[11].scale; - speed = modes[11].speed; - colorLoop = 1; - -// Serial.print(" speed:"); -// Serial.print(modes[currentMode].speed); -// Serial.print(" scale:"); -// Serial.println(modes[currentMode].scale); - } - fillNoiseLED(); -} -void forestNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = ForestColors_p; - scale = modes[12].scale; - speed = modes[12].speed; - colorLoop = 0; - } - fillNoiseLED(); -} -void oceanNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = OceanColors_p; - scale = modes[13].scale; - speed = modes[13].speed; - colorLoop = 0; - } - - fillNoiseLED(); -} -void plasmaNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = PartyColors_p; - scale = modes[8].scale; - speed = modes[8].speed; - colorLoop = 1; - } - fillNoiseLED(); -} -void cloudNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = CloudColors_p; - scale = modes[6].scale; - speed = modes[6].speed; - colorLoop = 0; - } - fillNoiseLED(); -} -void lavaNoise() { - if (loadingFlag) { - loadingFlag = false; - currentPalette = LavaColors_p; - scale = modes[7].scale; - speed = modes[7].speed; - colorLoop = 0; - } - fillNoiseLED(); -} - -// ******************* СЛУЖЕБНЫЕ ******************* -void fillNoiseLED() { - uint8_t dataSmoothing = 0; - if ( speed < 50) { - dataSmoothing = 200 - (speed * 4); - } - for (int i = 0; i < MAX_DIMENSION; i++) { - int ioffset = scale * i; - for (int j = 0; j < MAX_DIMENSION; j++) { - int joffset = scale * j; - - uint8_t data = inoise8(x + ioffset, y + joffset, z); - - data = qsub8(data, 16); - data = qadd8(data, scale8(data, 39)); - - if ( dataSmoothing ) { - uint8_t olddata = noise[i][j]; - uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); - data = newdata; - } - - noise[i][j] = data; - } - } - z += speed; - - // apply slow drift to X and Y, just for visual variation. - x += speed / 8; - y -= speed / 16; - - for (int i = 0; i < WIDTH; i++) { - for (int j = 0; j < HEIGHT; j++) { - uint8_t index = noise[j][i]; - uint8_t bri = noise[i][j]; - // if this palette is a 'loop', add a slowly-changing base value - if ( colorLoop) { - index += ihue; - } - // brighten up, as the color palette itself often contains the - // light/dark dynamic range desired - if ( bri > 127 ) { - bri = 255; - } else { - bri = dim8_raw( bri * 2); - } - CRGB color = ColorFromPalette( currentPalette, index, bri); - drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color; - } - } - ihue += 1; -} - -void fillnoise8() { - for (int i = 0; i < MAX_DIMENSION; i++) { - int ioffset = scale * i; - for (int j = 0; j < MAX_DIMENSION; j++) { - int joffset = scale * j; - noise[i][j] = inoise8(x + ioffset, y + joffset, z); - } - } - z += speed; -} +// ******************* НАСТРОЙКИ ***************** +// ***************** ДЛЯ РАЗРАБОТЧИКОВ ****************** + +// The 16 bit version of our coordinates +static uint16_t x; +static uint16_t y; +static uint16_t z; + +uint16_t speed = 20; // speed is set dynamically once we've started up +uint16_t scale = 30; // scale is set dynamically once we've started up + +// This is the array that we keep our computed noise values in (это массив, в котором храним вычисленные значения шума) +#define MAX_DIMENSION (max(WIDTH, HEIGHT)) +#if (WIDTH > HEIGHT) +uint8_t noise[WIDTH][WIDTH]; +#else +uint8_t noise[HEIGHT][HEIGHT]; +#endif + +CRGBPalette16 currentPalette( PartyColors_p ); +uint8_t colorLoop = 1; +uint8_t ihue = 0; + +void madnessNoise() { + if (loadingFlag) { + loadingFlag = false; + scale = modes[5].scale; + speed = modes[5].speed; + } + fillnoise8(); + for (int i = 0; i < WIDTH; i++) { + for (int j = 0; j < HEIGHT; j++) { + CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); + } + } + ihue += 1; +} +void rainbowNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = RainbowColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void rainbowStripeNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = RainbowStripeColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void zebraNoise() { + if (loadingFlag) { + loadingFlag = false; + // 'black out' all 16 palette entries... + fill_solid( currentPalette, 16, CRGB::Black); + // and set every fourth one to white. + currentPalette[0] = CRGB::White; + currentPalette[4] = CRGB::White; + currentPalette[8] = CRGB::White; + currentPalette[12] = CRGB::White; + scale = modes[11].scale; + speed = modes[11].speed; + colorLoop = 1; + +// Serial.print(" speed:"); +// Serial.print(modes[currentMode].speed); +// Serial.print(" scale:"); +// Serial.println(modes[currentMode].scale); + } + fillNoiseLED(); +} +void forestNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = ForestColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 0; + } + fillNoiseLED(); +} +void oceanNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = OceanColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 0; + } + + fillNoiseLED(); +} +void plasmaNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = PartyColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 1; + } + fillNoiseLED(); +} +void cloudNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = CloudColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 0; + } + fillNoiseLED(); +} +void lavaNoise() { + if (loadingFlag) { + loadingFlag = false; + currentPalette = LavaColors_p; + scale = modes[currentMode].scale; + speed = modes[currentMode].speed; + colorLoop = 0; + } + fillNoiseLED(); +} + +// ******************* СЛУЖЕБНЫЕ ******************* +void fillNoiseLED() { + uint8_t dataSmoothing = 0; + if ( speed < 50) { + dataSmoothing = 200 - (speed * 4); + } + for (int i = 0; i < MAX_DIMENSION; i++) { + int ioffset = scale * i; + for (int j = 0; j < MAX_DIMENSION; j++) { + int joffset = scale * j; + + uint8_t data = inoise8(x + ioffset, y + joffset, z); + + data = qsub8(data, 16); + data = qadd8(data, scale8(data, 39)); + + if ( dataSmoothing ) { + uint8_t olddata = noise[i][j]; + uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); + data = newdata; + } + + noise[i][j] = data; + } + } + z += speed; + + // apply slow drift to X and Y, just for visual variation. + x += speed / 8; + y -= speed / 16; + + for (int i = 0; i < WIDTH; i++) { + for (int j = 0; j < HEIGHT; j++) { + uint8_t index = noise[j][i]; + uint8_t bri = noise[i][j]; + // if this palette is a 'loop', add a slowly-changing base value + if ( colorLoop) { + index += ihue; + } + // brighten up, as the color palette itself often contains the + // light/dark dynamic range desired + if ( bri > 127 ) { + bri = 255; + } else { + bri = dim8_raw( bri * 2); + } + CRGB color = ColorFromPalette( currentPalette, index, bri); + drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color; + } + } + ihue += 1; +} + +void fillnoise8() { + for (int i = 0; i < MAX_DIMENSION; i++) { + int ioffset = scale * i; + for (int j = 0; j < MAX_DIMENSION; j++) { + int joffset = scale * j; + noise[i][j] = inoise8(x + ioffset, y + joffset, z); + } + } + z += speed; +} diff --git a/firmware/GyverLamp_v1.4_Arduino_v1.0/utility.ino b/firmware/GyverLamp_v1.4_Arduino_v1.0/utility.ino index 6110de5..c481eb4 100644 --- a/firmware/GyverLamp_v1.4_Arduino_v1.0/utility.ino +++ b/firmware/GyverLamp_v1.4_Arduino_v1.0/utility.ino @@ -1,87 +1,128 @@ -// служебные функции - -// залить все -void fillAll(CRGB color) { - for (int i = 0; i < NUM_LEDS; i++) { - leds[i] = color; - } -} - -// функция отрисовки точки по координатам 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; - } -} - -// функция получения цвета пикселя по его номеру -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)); -} - -// **************** НАСТРОЙКА МАТРИЦЫ **************** -#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); - } -} +// служебные функции +// функция плавного угасания цвета для всех пикселей +void fader(uint8_t step) +{ + for (uint8_t i = 0U; i < WIDTH; i++) + { + for (uint8_t j = 0U; j < HEIGHT; j++) + { + fadePixel(i, j, step); + } + } +} +void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер +{ + int32_t pixelNum = XY(i, j); + if (getPixColor(pixelNum) == 0U) return; + + if (leds[pixelNum].r >= 30U || + leds[pixelNum].g >= 30U || + leds[pixelNum].b >= 30U) + { + leds[pixelNum].fadeToBlackBy(step); + } + else + { + leds[pixelNum] = 0U; + } +} +void shiftDown(){ + for (byte x = 0; x < WIDTH; x++) { + for (byte y = 0; y < HEIGHT - 1; y++) { + drawPixelXY(x, y, getPixColorXY(x, y + 1)); + }}} +// залить все +void fillAll(CRGB color) { + for (int i = 0; i < NUM_LEDS; i++) { + leds[i] = color; + } +} + + + +// функция отрисовки точки по координатам X Y +void drawPixelXY(uint8_t x, uint8_t y, CRGB color) +{ + if (x < 0 || x > (WIDTH - 1) || y < 0 || y > (HEIGHT - 1)) return; + uint32_t thisPixel = XY((uint8_t)x, (uint8_t)y) * SEGMENTS; + for (uint8_t i = 0; i < SEGMENTS; i++) + { + leds[thisPixel + i] = color; + } +} + +// функция получения цвета пикселя по его номеру +uint32_t getPixColor(uint32_t thisSegm) +{ + uint32_t thisPixel = thisSegm * SEGMENTS; + if (thisPixel > NUM_LEDS - 1) return 0; + return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b); +} +// функция получения цвета пикселя в матрице по его координатам +uint32_t getPixColorXY(uint8_t x, uint8_t y) +{ + return getPixColor(XY(x, y)); +} + +// **************** НАСТРОЙКА МАТРИЦЫ **************** +#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 XY(uint8_t x, uint8_t y) +{ + if (!(THIS_Y & 0x01) || MATRIX_TYPE) // Even rows run forwards + return (THIS_Y * _WIDTH + THIS_X); + else + return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); // Odd rows run backwards +} + +// оставлено для совместимости со эффектами из старых прошивок +uint16_t getPixelNumber(uint8_t x, uint8_t y) +{ + return XY(x, y); +}