diff --git a/firmware/GyverLamp_v1.5.5/GyverLamp_v1.5.5.ino b/firmware/GyverLamp_v1.5.5/GyverLamp_v1.5.5.ino new file mode 100644 index 0000000..3befd25 --- /dev/null +++ b/firmware/GyverLamp_v1.5.5/GyverLamp_v1.5.5.ino @@ -0,0 +1,293 @@ +/* + Скетч к проекту "Многофункциональный RGB светильник" + Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/ + Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/ + Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/ + Автор: AlexGyver, AlexGyver Technologies, 2019 + https://AlexGyver.ru/ +*/ + +/* + Версия 1.5.1 + - Оптимизировано обращение к серверу времени (нет подвисаний при отсутствии интернета) + - Оптимизация под пины NodeMCU + + Версия 1.5.2 + - Исправлен незначительный баг с таймером + - Исправлено падение по WDT при выводе IP + - Исправлен баг с переназначением времени будильника + - Исправлено переключение с первого на последний режимы + - Приложение автоматически получает настройки с кнопки + - Бегущая строка с текущим временем во время рассвета + + Версия 1.5.3 + - Увеличена плавность рассвета + - Поправлен баг с отображением времени рассвета + + Версия 1.5.4 + - Поправлены глюки во время рассвета + + Версия 1.5.5 + - Поправлено невыключение света во время рассвета + +*/ + +// Ссылка для менеджера плат: +// http://arduino.esp8266.com/stable/package_esp8266com_index.json + +// Для WEMOS выбираем плату LOLIN(WEMOS) D1 R2 & mini +// Для NodeMCU выбираем NodeMCU 1.0 (ESP-12E Module) + +// ============= НАСТРОЙКИ ============= +// -------- КНОПКА ------- +#define USE_BUTTON 1 // 1 - использовать кнопку, 0 - нет + +// -------- ВРЕМЯ ------- +#define GMT 3 // смещение (москва 3) +#define NTP_ADDRESS "europe.pool.ntp.org" // сервер времени + +// -------- РАССВЕТ ------- +#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/ + +// --------- ESP -------- +#define ESP_MODE 1 +// 0 - точка доступа +// 1 - локальный +byte IP_AP[] = {192, 168, 4, 66}; // статический IP точки доступа (менять только последнюю цифру) + +// ----- AP (точка доступа) ------- +#define AP_SSID "GyverLamp" +#define AP_PASS "12345678" +#define AP_PORT 8888 + +// -------- Менеджер WiFi --------- +#define AC_SSID "AutoConnectAP" +#define AC_PASS "12345678" + +// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= +#define LED_PIN D4 // пин ленты +#define BTN_PIN D2 +#define MODE_AMOUNT 18 + +#define NUM_LEDS WIDTH * HEIGHT +#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) +// ---------------- БИБЛИОТЕКИ ----------------- +#define FASTLED_INTERRUPT_RETRY_COUNT 0 +#define FASTLED_ALLOW_INTERRUPTS 0 +#define FASTLED_ESP8266_RAW_PIN_ORDER +#define NTP_INTERVAL 60 * 1000 // обновление (1 минута) + +#include "timer2Minim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fonts.h" + +// ------------------- ТИПЫ -------------------- +CRGB leds[NUM_LEDS]; +WiFiServer server(80); +WiFiUDP Udp; +WiFiUDP ntpUDP; +NTPClient timeClient(ntpUDP, NTP_ADDRESS, GMT * 3600, NTP_INTERVAL); +timerMinim timeTimer(1000); +timerMinim timeStrTimer(120); +GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); + +// ----------------- ПЕРЕМЕННЫЕ ------------------ +const char* autoConnectSSID = AC_SSID; +const char* autoConnectPass = AC_PASS; +const char AP_NameChar[] = AP_SSID; +const char WiFiPassword[] = AP_PASS; +unsigned int localPort = AP_PORT; +char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; //buffer to hold incoming packet +String inputBuffer; +static const byte maxDim = max(WIDTH, HEIGHT); +struct { + byte brightness = 50; + byte speed = 30; + byte scale = 40; +} modes[MODE_AMOUNT]; + +struct { + boolean state = false; + int time = 0; +} alarm[7]; + +const byte dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60}; +byte dawnMode; +boolean dawnFlag = false; +float thisTime; +boolean manualOff = false; +boolean sendSettings_flag = false; + +int8_t currentMode = 0; +boolean loadingFlag = true; +boolean ONflag = true; +uint32_t eepromTimer; +boolean settChanged = false; +// Конфетти, Огонь, Радуга верт., Радуга гориз., Смена цвета, +// Безумие 3D, Облака 3D, Лава 3D, Плазма 3D, Радуга 3D, +// Павлин 3D, Зебра 3D, Лес 3D, Океан 3D, + +unsigned char matrixValue[8][16]; +String lampIP = ""; +byte hrs, mins, secs; +byte days; +String timeStr = "00:00"; + +void setup() { + ESP.wdtDisable(); + //ESP.wdtEnable(WDTO_8S); + + // ЛЕНТА + FastLED.addLeds(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/; + FastLED.setBrightness(BRIGHTNESS); + if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT); + FastLED.show(); + + touch.setStepTimeout(100); + touch.setClickTimeout(500); + + Serial.begin(115200); + Serial.println(); + delay(1000); + + // WI-FI + if (ESP_MODE == 0) { // режим точки доступа + WiFi.softAPConfig(IPAddress(IP_AP[0], IP_AP[1], IP_AP[2], IP_AP[3]), + IPAddress(192, 168, 4, 1), + IPAddress(255, 255, 255, 0)); + + WiFi.softAP(AP_NameChar, WiFiPassword); + IPAddress myIP = WiFi.softAPIP(); + Serial.print("Access point Mode"); + Serial.print("AP IP address: "); + Serial.println(myIP); + + server.begin(); + } else { // подключаемся к роутеру + Serial.print("WiFi manager"); + WiFiManager wifiManager; + wifiManager.setDebugOutput(false); + +#if (USE_BUTTON == 1) + if (digitalRead(BTN_PIN)) wifiManager.resetSettings(); +#endif + + wifiManager.autoConnect(autoConnectSSID, autoConnectPass); + /*WiFi.config(IPAddress(IP_STA[0], IP_STA[1], IP_STA[2], IP_STA[3]), + IPAddress(192, 168, 1, 1), + IPAddress(255, 255, 255, 0));*/ + Serial.print("Connected! IP address: "); + Serial.println(WiFi.localIP()); + lampIP = WiFi.localIP().toString(); + } + Serial.printf("UDP server on port %d\n", localPort); + Udp.begin(localPort); + + // EEPROM + EEPROM.begin(202); + delay(50); + if (EEPROM.read(198) != 20) { // первый запуск + EEPROM.write(198, 20); + EEPROM.commit(); + + for (byte i = 0; i < MODE_AMOUNT; i++) { + EEPROM.put(3 * i + 40, modes[i]); + EEPROM.commit(); + } + for (byte i = 0; i < 7; i++) { + EEPROM.write(5 * i, alarm[i].state); // рассвет + eeWriteInt(5 * i + 1, alarm[i].time); + EEPROM.commit(); + } + EEPROM.write(199, 0); // рассвет + EEPROM.write(200, 0); // режим + EEPROM.commit(); + } + for (byte i = 0; i < MODE_AMOUNT; i++) { + EEPROM.get(3 * i + 40, modes[i]); + } + for (byte i = 0; i < 7; i++) { + alarm[i].state = EEPROM.read(5 * i); + alarm[i].time = eeGetInt(5 * i + 1); + } + dawnMode = EEPROM.read(199); + currentMode = (int8_t)EEPROM.read(200); + + // отправляем настройки + sendSettings(); + + timeClient.begin(); + memset(matrixValue, 0, sizeof(matrixValue)); + + randomSeed(micros()); + + // получаем время + byte count = 0; + while (count < 5) { + if (timeClient.update()) { + hrs = timeClient.getHours(); + mins = timeClient.getMinutes(); + secs = timeClient.getSeconds(); + days = timeClient.getDay(); + break; + } + count++; + delay(500); + } + updTime(); +} + +void loop() { + parseUDP(); + effectsTick(); + eepromTick(); + timeTick(); +#if (USE_BUTTON == 1) + buttonTick(); +#endif + ESP.wdtFeed(); // пнуть собаку + yield(); // ещё раз пнуть собаку +} + +void eeWriteInt(int pos, int val) { + byte* p = (byte*) &val; + EEPROM.write(pos, *p); + EEPROM.write(pos + 1, *(p + 1)); + EEPROM.write(pos + 2, *(p + 2)); + EEPROM.write(pos + 3, *(p + 3)); + EEPROM.commit(); +} + +int eeGetInt(int pos) { + int val; + byte* p = (byte*) &val; + *p = EEPROM.read(pos); + *(p + 1) = EEPROM.read(pos + 1); + *(p + 2) = EEPROM.read(pos + 2); + *(p + 3) = EEPROM.read(pos + 3); + return val; +} diff --git a/firmware/GyverLamp_v1.5.4/button.ino b/firmware/GyverLamp_v1.5.5/button.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/button.ino rename to firmware/GyverLamp_v1.5.5/button.ino diff --git a/firmware/GyverLamp_v1.5.4/eeprom.ino b/firmware/GyverLamp_v1.5.5/eeprom.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/eeprom.ino rename to firmware/GyverLamp_v1.5.5/eeprom.ino diff --git a/firmware/GyverLamp_v1.5.4/effectTicker.ino b/firmware/GyverLamp_v1.5.5/effectTicker.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/effectTicker.ino rename to firmware/GyverLamp_v1.5.5/effectTicker.ino diff --git a/firmware/GyverLamp_v1.5.4/effects.ino b/firmware/GyverLamp_v1.5.5/effects.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/effects.ino rename to firmware/GyverLamp_v1.5.5/effects.ino diff --git a/firmware/GyverLamp_v1.5.4/fonts.h b/firmware/GyverLamp_v1.5.5/fonts.h similarity index 100% rename from firmware/GyverLamp_v1.5.4/fonts.h rename to firmware/GyverLamp_v1.5.5/fonts.h diff --git a/firmware/GyverLamp_v1.5.4/noiseEffects.ino b/firmware/GyverLamp_v1.5.5/noiseEffects.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/noiseEffects.ino rename to firmware/GyverLamp_v1.5.5/noiseEffects.ino diff --git a/firmware/GyverLamp_v1.5.4/parsing.ino b/firmware/GyverLamp_v1.5.5/parsing.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/parsing.ino rename to firmware/GyverLamp_v1.5.5/parsing.ino diff --git a/firmware/GyverLamp_v1.5.4/runningText.ino b/firmware/GyverLamp_v1.5.5/runningText.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/runningText.ino rename to firmware/GyverLamp_v1.5.5/runningText.ino diff --git a/firmware/GyverLamp_v1.5.5/time.ino b/firmware/GyverLamp_v1.5.5/time.ino new file mode 100644 index 0000000..e4672c9 --- /dev/null +++ b/firmware/GyverLamp_v1.5.5/time.ino @@ -0,0 +1,84 @@ +byte minuteCounter = 0; +CHSV dawnColor; + +void timeTick() { + if (ESP_MODE == 1) { + if (timeTimer.isReady()) { // каждую секунду + secs++; + if (secs == 60) { + secs = 0; + mins++; + minuteCounter++; + updTime(); + } + if (mins == 60) { + mins = 0; + hrs++; + if (hrs == 24) { + hrs = 0; + days++; + if (days > 6) days = 0; + } + updTime(); + } + + if (minuteCounter > 30 && WiFi.status() == WL_CONNECTED) { // синхронизация каждые 30 минут + minuteCounter = 0; + if (timeClient.update()) { + hrs = timeClient.getHours(); + mins = timeClient.getMinutes(); + secs = timeClient.getSeconds(); + days = timeClient.getDay(); + } + } + + if (secs % 3 == 0) checkDawn(); // каждые 3 секунды проверяем рассвет + } + } + if (dawnFlag && timeStrTimer.isReady()) { + fill_solid(leds, NUM_LEDS, dawnColor); + fillString(timeStr, CRGB::Black, false); + delay(1); + ESP.wdtFeed(); // пнуть собаку + yield(); // ещё раз пнуть собаку + FastLED.show(); + } +} + +void updTime() { + timeStr = String(hrs); + timeStr += ":"; + timeStr += (mins < 10) ? "0" : ""; + timeStr += String(mins); +} + +void checkDawn() { + byte thisDay = days; + if (thisDay == 0) thisDay = 7; // воскресенье это 0 + thisDay--; + thisTime = hrs * 60 + mins + (float)secs / 60; + + // проверка рассвета + if (alarm[thisDay].state && // день будильника + thisTime >= (alarm[thisDay].time - dawnOffsets[dawnMode]) && // позже начала + thisTime < (alarm[thisDay].time + DAWN_TIMEOUT) ) { // раньше конца + минута + if (!manualOff) { + // величина рассвета 0-255 + int dawnPosition = (float)255 * ((float)((float)thisTime - (alarm[thisDay].time - dawnOffsets[dawnMode])) / dawnOffsets[dawnMode]); + dawnPosition = constrain(dawnPosition, 0, 255); + dawnColor = CHSV(map(dawnPosition, 0, 255, 10, 35), + map(dawnPosition, 0, 255, 255, 170), + map(dawnPosition, 0, 255, 10, DAWN_BRIGHT)); + FastLED.setBrightness(255); + dawnFlag = true; + } + } else { + if (dawnFlag) { + dawnFlag = false; + manualOff = false; + FastLED.setBrightness(modes[currentMode].brightness); + FastLED.clear(); + FastLED.show(); + } + } +} diff --git a/firmware/GyverLamp_v1.5.4/timer2Minim.h b/firmware/GyverLamp_v1.5.5/timer2Minim.h similarity index 100% rename from firmware/GyverLamp_v1.5.4/timer2Minim.h rename to firmware/GyverLamp_v1.5.5/timer2Minim.h diff --git a/firmware/GyverLamp_v1.5.4/utility.ino b/firmware/GyverLamp_v1.5.5/utility.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/utility.ino rename to firmware/GyverLamp_v1.5.5/utility.ino diff --git a/firmware/GyverLamp_v1.5.4/GyverLamp_v1.5.4.ino b/firmware/old/GyverLamp_v1.5.4/GyverLamp_v1.5.4.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/GyverLamp_v1.5.4.ino rename to firmware/old/GyverLamp_v1.5.4/GyverLamp_v1.5.4.ino diff --git a/firmware/old/GyverLamp_v1.5.4/button.ino b/firmware/old/GyverLamp_v1.5.4/button.ino new file mode 100644 index 0000000..66b0d69 --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/button.ino @@ -0,0 +1,75 @@ +boolean brightDirection; + +void buttonTick() { + touch.tick(); + if (touch.isSingle()) { + if (dawnFlag) { + manualOff = true; + dawnFlag = false; + loadingFlag = true; + FastLED.setBrightness(modes[currentMode].brightness); + changePower(); + } else { + if (ONflag) { + ONflag = false; + changePower(); + } else { + ONflag = true; + changePower(); + } + sendSettings_flag = true; + } + } + + if (ONflag && touch.isDouble()) { + if (++currentMode >= MODE_AMOUNT) currentMode = 0; + FastLED.setBrightness(modes[currentMode].brightness); + loadingFlag = true; + settChanged = true; + eepromTimer = millis(); + FastLED.clear(); + delay(1); + sendSettings_flag = true; + } + if (ONflag && touch.isTriple()) { + if (--currentMode < 0) currentMode = MODE_AMOUNT - 1; + FastLED.setBrightness(modes[currentMode].brightness); + loadingFlag = true; + settChanged = true; + eepromTimer = millis(); + FastLED.clear(); + delay(1); + sendSettings_flag = true; + } + + // вывод IP на лампу + if (ONflag && touch.hasClicks()) { + if (touch.getClicks() == 5) { + resetString(); + while (!fillString(lampIP, CRGB::Green, true)) { + delay(1); + ESP.wdtFeed(); // пнуть собаку + yield(); // ещё раз пнуть собаку + } + } + } + + if (ONflag && touch.isHolded()) { + brightDirection = !brightDirection; + } + if (ONflag && touch.isStep()) { + 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; + } + FastLED.setBrightness(modes[currentMode].brightness); + settChanged = true; + eepromTimer = millis(); + sendSettings_flag = true; + } +} diff --git a/firmware/old/GyverLamp_v1.5.4/eeprom.ino b/firmware/old/GyverLamp_v1.5.4/eeprom.ino new file mode 100644 index 0000000..3c25dc1 --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/eeprom.ino @@ -0,0 +1,25 @@ +void saveEEPROM() { + EEPROM.put(3 * currentMode + 40, modes[currentMode]); + EEPROM.commit(); +} + +void eepromTick() { + if (settChanged && millis() - eepromTimer > 30000) { + settChanged = false; + eepromTimer = millis(); + saveEEPROM(); + if (EEPROM.read(200) != currentMode) EEPROM.write(200, currentMode); + EEPROM.commit(); + } +} + +void saveAlarm(byte almNumber) { + EEPROM.write(5 * almNumber, alarm[almNumber].state); // рассвет + eeWriteInt(5 * almNumber + 1, alarm[almNumber].time); + EEPROM.commit(); +} + +void saveDawnMmode() { + EEPROM.write(199, dawnMode); // рассвет + EEPROM.commit(); +} diff --git a/firmware/old/GyverLamp_v1.5.4/effectTicker.ino b/firmware/old/GyverLamp_v1.5.4/effectTicker.ino new file mode 100644 index 0000000..583616b --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/effectTicker.ino @@ -0,0 +1,72 @@ +uint32_t effTimer; + +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: lightersRoutine(); + 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/old/GyverLamp_v1.5.4/effects.ino b/firmware/old/GyverLamp_v1.5.4/effects.ino new file mode 100644 index 0000000..a536e6f --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/effects.ino @@ -0,0 +1,333 @@ +// ================================= ЭФФЕКТЫ ==================================== + +// --------------------------------- конфетти ------------------------------------ +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; +} + +// Randomly generate the next line (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]; + } +} + +// draw a frame, interpolating between 2 "key frames" +// @param pcnt percentage of interpolation + +void drawFrame(int pcnt) { + int nextv; + + //each row interpolates with the one before it + for (unsigned char y = HEIGHT - 1; y > 0; y--) { + for (unsigned char x = 0; x < WIDTH; x++) { + uint8_t newX = x; + if (x > 15) newX = x - 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); + + } + } + } + + //first row interpolates with the "next" line + 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)); + } + } +} + +// ----------------------------- СВЕТЛЯКИ ------------------------------ +#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]); + } +} + +/* + 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); + + lightersColor[i] = CHSV(random(0, 255), 255, 255); + + speedV[i] = random(5, 10); + angle[i] = random(0, 360); + angleSpeed[i] = random(-10, 10); + } + } + FastLED.clear(); + if (++loopCounter > 20) loopCounter = 0; + + for (byte i = 0; i < modes[17].scale; i++) { + if (loopCounter == 0) { // меняем скорость каждые 255 отрисовок + angleSpeed[i] += random(-3, 4); + angleSpeed[i] = constrain(angleSpeed[i], -15, 15); + } + + lightersPos[0][i] += speedV[i] * cos(radians(angle[i])); + lightersPos[1][i] += speedV[i] * sin(radians(angle[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; + angle[i] = 360 - angle[i]; + } else { + angle[i] += angleSpeed[i]; + } + + if (lightersPos[1][i] >= (HEIGHT - 1) * 10) { + lightersPos[1][i] = (HEIGHT - 1) * 10; + angle[i] = 360 - angle[i]; + } else { + angle[i] += angleSpeed[i]; + } + + if (angle[i] > 360) angle[i] = 360 - angle[i]; + if (angle[i] < 0) angle[i] = 360 + angle[i]; + + drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]); + } + } +*/ diff --git a/firmware/old/GyverLamp_v1.5.4/fonts.h b/firmware/old/GyverLamp_v1.5.4/fonts.h new file mode 100644 index 0000000..7786344 --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/fonts.h @@ -0,0 +1,231 @@ +// шрифты для вывода текста +const uint8_t fontHEX[][5] PROGMEM = { + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 32 + {0x00, 0x00, 0x6f, 0x00, 0x00}, // ! 0x21 33 + {0x00, 0x07, 0x00, 0x07, 0x00}, // " 0x22 34 + {0x14, 0x7f, 0x14, 0x7f, 0x14}, // # 0x23 35 + {0x00, 0x07, 0x04, 0x1e, 0x00}, // $ 0x24 36 + {0x23, 0x13, 0x08, 0x64, 0x62}, // % 0x25 37 + {0x36, 0x49, 0x56, 0x20, 0x50}, // & 0x26 38 + {0x00, 0x00, 0x07, 0x00, 0x00}, // ' 0x27 39 + {0x00, 0x1c, 0x22, 0x41, 0x00}, // ( 0x28 40 + {0x00, 0x41, 0x22, 0x1c, 0x00}, // ) 0x29 41 + {0x14, 0x08, 0x3e, 0x08, 0x14}, // * 0x2a 42 + {0x08, 0x08, 0x3e, 0x08, 0x08}, // + 0x2b 43 + {0x00, 0x50, 0x30, 0x00, 0x00}, // , 0x2c 44 + {0x08, 0x08, 0x08, 0x08, 0x08}, // - 0x2d 45 + {0x00, 0x60, 0x60, 0x00, 0x00}, // . 0x2e 46 + {0x20, 0x10, 0x08, 0x04, 0x02}, // / 0x2f 47 + {0x3e, 0x51, 0x49, 0x45, 0x3e}, // 0 0x30 48 + {0x00, 0x42, 0x7f, 0x40, 0x00}, // 1 0x31 49 + {0x42, 0x61, 0x51, 0x49, 0x46}, // 2 0x32 50 + {0x21, 0x41, 0x45, 0x4b, 0x31}, // 3 0x33 51 + {0x18, 0x14, 0x12, 0x7f, 0x10}, // 4 0x34 52 + {0x27, 0x45, 0x45, 0x45, 0x39}, // 5 0x35 53 + {0x3c, 0x4a, 0x49, 0x49, 0x30}, // 6 0x36 54 + {0x01, 0x71, 0x09, 0x05, 0x03}, // 7 0x37 55 + {0x36, 0x49, 0x49, 0x49, 0x36}, // 8 0x38 56 + {0x06, 0x49, 0x49, 0x29, 0x1e}, // 9 0x39 57 + {0x00, 0x36, 0x36, 0x00, 0x00}, // : 0x3a 58 + {0x00, 0x56, 0x36, 0x00, 0x00}, // ; 0x3b 59 + {0x08, 0x14, 0x22, 0x41, 0x00}, // < 0x3c 60 + {0x14, 0x14, 0x14, 0x14, 0x14}, // = 0x3d 61 + {0x00, 0x41, 0x22, 0x14, 0x08}, // > 0x3e 62 + {0x02, 0x01, 0x51, 0x09, 0x06}, // ? 0x3f 63 + {0x3e, 0x41, 0x5d, 0x49, 0x4e}, // @ 0x40 64 + {0x7e, 0x09, 0x09, 0x09, 0x7e}, // A 0x41 65 + {0x7f, 0x49, 0x49, 0x49, 0x36}, // B 0x42 66 + {0x3e, 0x41, 0x41, 0x41, 0x22}, // C 0x43 67 + {0x7f, 0x41, 0x41, 0x41, 0x3e}, // D 0x44 68 + {0x7f, 0x49, 0x49, 0x49, 0x41}, // E 0x45 69 + {0x7f, 0x09, 0x09, 0x09, 0x01}, // F 0x46 70 + {0x3e, 0x41, 0x49, 0x49, 0x7a}, // G 0x47 71 + {0x7f, 0x08, 0x08, 0x08, 0x7f}, // H 0x48 72 + {0x00, 0x41, 0x7f, 0x41, 0x00}, // I 0x49 73 + {0x20, 0x40, 0x41, 0x3f, 0x01}, // J 0x4a 74 + {0x7f, 0x08, 0x14, 0x22, 0x41}, // K 0x4b 75 + {0x7f, 0x40, 0x40, 0x40, 0x40}, // L 0x4c 76 + {0x7f, 0x02, 0x0c, 0x02, 0x7f}, // M 0x4d 77 + {0x7f, 0x04, 0x08, 0x10, 0x7f}, // N 0x4e 78 + {0x3e, 0x41, 0x41, 0x41, 0x3e}, // O 0x4f 79 + {0x7f, 0x09, 0x09, 0x09, 0x06}, // P 0x50 80 + {0x3e, 0x41, 0x51, 0x21, 0x5e}, // Q 0x51 81 + {0x7f, 0x09, 0x19, 0x29, 0x46}, // R 0x52 82 + {0x46, 0x49, 0x49, 0x49, 0x31}, // S 0x53 83 + {0x01, 0x01, 0x7f, 0x01, 0x01}, // T 0x54 84 + {0x3f, 0x40, 0x40, 0x40, 0x3f}, // U 0x55 85 + {0x0f, 0x30, 0x40, 0x30, 0x0f}, // V 0x56 86 + {0x3f, 0x40, 0x30, 0x40, 0x3f}, // W 0x57 87 + {0x63, 0x14, 0x08, 0x14, 0x63}, // X 0x58 88 + {0x07, 0x08, 0x70, 0x08, 0x07}, // Y 0x59 89 + {0x61, 0x51, 0x49, 0x45, 0x43}, // Z 0x5a 90 + {0x3c, 0x4a, 0x49, 0x29, 0x1e}, // [ 0x5b 91 + {0x02, 0x04, 0x08, 0x10, 0x20}, // \ 0x5c 92 + {0x00, 0x41, 0x7f, 0x00, 0x00}, // ] 0x5d 93 + {0x04, 0x02, 0x01, 0x02, 0x04}, // ^ 0x5e 94 + {0x40, 0x40, 0x40, 0x40, 0x40}, // _ 0x5f 95 + {0x00, 0x00, 0x03, 0x04, 0x00}, // ` 0x60 96 + {0x20, 0x54, 0x54, 0x54, 0x78}, // a 0x61 97 + {0x7f, 0x48, 0x44, 0x44, 0x38}, // b 0x62 98 + {0x38, 0x44, 0x44, 0x44, 0x20}, // c 0x63 99 + {0x38, 0x44, 0x44, 0x48, 0x7f}, // d 0x64 100 + {0x38, 0x54, 0x54, 0x54, 0x18}, // e 0x65 101 + {0x08, 0x7e, 0x09, 0x01, 0x02}, // f 0x66 102 + {0x0c, 0x52, 0x52, 0x52, 0x3e}, // g 0x67 103 + {0x7f, 0x08, 0x04, 0x04, 0x78}, // h 0x68 104 + {0x00, 0x44, 0x7d, 0x40, 0x00}, // i 0x69 105 + {0x20, 0x40, 0x44, 0x3d, 0x00}, // j 0x6a 106 + {0x00, 0x7f, 0x10, 0x28, 0x44}, // k 0x6b 107 + {0x00, 0x41, 0x7f, 0x40, 0x00}, // l 0x6c 108 + {0x7c, 0x04, 0x18, 0x04, 0x78}, // m 0x6d 109 + {0x7c, 0x08, 0x04, 0x04, 0x78}, // n 0x6e 110 + {0x38, 0x44, 0x44, 0x44, 0x38}, // o 0x6f 111 + {0x7c, 0x14, 0x14, 0x14, 0x08}, // p 0x70 112 + {0x08, 0x14, 0x14, 0x18, 0x7c}, // q 0x71 113 + {0x7c, 0x08, 0x04, 0x04, 0x08}, // r 0x72 114 + {0x48, 0x54, 0x54, 0x54, 0x20}, // s 0x73 115 + {0x04, 0x3f, 0x44, 0x40, 0x20}, // t 0x74 116 + {0x3c, 0x40, 0x40, 0x20, 0x7c}, // u 0x75 117 + {0x1c, 0x20, 0x40, 0x20, 0x1c}, // v 0x76 118 + {0x3c, 0x40, 0x30, 0x40, 0x3c}, // w 0x77 119 + {0x44, 0x28, 0x10, 0x28, 0x44}, // x 0x78 120 + {0x0c, 0x50, 0x50, 0x50, 0x3c}, // y 0x79 121 + {0x44, 0x64, 0x54, 0x4c, 0x44}, // z 0x7a 122 + {0x00, 0x08, 0x36, 0x41, 0x41}, // { 0x7b 123 + {0x00, 0x00, 0x7f, 0x00, 0x00}, // | 0x7c 124 + {0x41, 0x41, 0x36, 0x08, 0x00}, // } 0x7d 125 + {0x04, 0x02, 0x04, 0x08, 0x04}, // ~ 0x7e 126 + + {0x7E, 0x11, 0x11, 0x11, 0x7E}, //__А (0xC0). + {0x7F, 0x49, 0x49, 0x49, 0x33}, //__Б (0xC1). + {0x7F, 0x49, 0x49, 0x49, 0x36}, //__В (0xC2). + {0x7F, 0x01, 0x01, 0x01, 0x03}, //__Г (0xC3). + {0xE0, 0x51, 0x4F, 0x41, 0xFF}, //__Д (0xC4). + {0x7F, 0x49, 0x49, 0x49, 0x41}, //__Е (0xC5). + {0x77, 0x08, 0x7F, 0x08, 0x77}, //__Ж (0xC6). + {0x41, 0x49, 0x49, 0x49, 0x36}, //__З (0xC7). + {0x7F, 0x10, 0x08, 0x04, 0x7F}, //__И (0xC8). + {0x7C, 0x21, 0x12, 0x09, 0x7C}, //__Й (0xC9). + {0x7F, 0x08, 0x14, 0x22, 0x41}, //__К (0xCA). + {0x20, 0x41, 0x3F, 0x01, 0x7F}, //__Л (0xCB). + {0x7F, 0x02, 0x0C, 0x02, 0x7F}, //__М (0xCC). + {0x7F, 0x08, 0x08, 0x08, 0x7F}, //__Н (0xCD). + {0x3E, 0x41, 0x41, 0x41, 0x3E}, //__О (0xCE). + {0x7F, 0x01, 0x01, 0x01, 0x7F}, //__П (0xCF). + {0x7F, 0x09, 0x09, 0x09, 0x06}, //__Р (0xD0). + {0x3E, 0x41, 0x41, 0x41, 0x22}, //__С (0xD1). + {0x01, 0x01, 0x7F, 0x01, 0x01}, //__Т (0xD2). + {0x47, 0x28, 0x10, 0x08, 0x07}, //__У (0xD3). + {0x1C, 0x22, 0x7F, 0x22, 0x1C}, //__Ф (0xD4). + {0x63, 0x14, 0x08, 0x14, 0x63}, //__Х (0xD5). + {0x7F, 0x40, 0x40, 0x40, 0xFF}, //__Ц (0xD6). + {0x07, 0x08, 0x08, 0x08, 0x7F}, //__Ч (0xD7). + {0x7F, 0x40, 0x7F, 0x40, 0x7F}, //__Ш (0xD8). + {0x7F, 0x40, 0x7F, 0x40, 0xFF}, //__Щ (0xD9). + {0x01, 0x7F, 0x48, 0x48, 0x30}, //__Ъ (0xDA). + {0x7F, 0x48, 0x30, 0x00, 0x7F}, //__Ы (0xDB). + {0x00, 0x7F, 0x48, 0x48, 0x30}, //__Ь (0xDC). + {0x22, 0x41, 0x49, 0x49, 0x3E}, //__Э (0xDD). + {0x7F, 0x08, 0x3E, 0x41, 0x3E}, //__Ю (0xDE). + {0x46, 0x29, 0x19, 0x09, 0x7F}, //__Я (0xDF). + + {0x20, 0x54, 0x54, 0x54, 0x78}, //__а (0xE0). + {0x3C, 0x4A, 0x4A, 0x49, 0x31}, //__б (0xE1). + {0x7C, 0x54, 0x54, 0x28, 0x00}, //__в (0xE2). + {0x7C, 0x04, 0x04, 0x0C, 0x00}, //__г (0xE3). + {0xE0, 0x54, 0x4C, 0x44, 0xFC}, //__д (0xE4). + {0x38, 0x54, 0x54, 0x54, 0x18}, //__е (0xE5). + {0x6C, 0x10, 0x7C, 0x10, 0x6C}, //__ж (0xE6). + {0x44, 0x54, 0x54, 0x28, 0x00}, //__з (0xE7). + {0x7C, 0x20, 0x10, 0x08, 0x7C}, //__и (0xE8). + {0x78, 0x42, 0x24, 0x12, 0x78}, //__й (0xE9). + {0x7C, 0x10, 0x28, 0x44, 0x00}, //__к (0xEA). + {0x20, 0x44, 0x3C, 0x04, 0x7C}, //__л (0xEB). + {0x7C, 0x08, 0x10, 0x08, 0x7C}, //__м (0xEC). + {0x7C, 0x10, 0x10, 0x10, 0x7C}, //__н (0xED). + {0x38, 0x44, 0x44, 0x44, 0x38}, //__о (0xEE). + {0x7C, 0x04, 0x04, 0x04, 0x7C}, //__п (0xEF). + {0x7C, 0x14, 0x14, 0x14, 0x08}, //__р (0xF0). + {0x38, 0x44, 0x44, 0x44, 0x00}, //__с (0xF1). + {0x04, 0x04, 0x7C, 0x04, 0x04}, //__т (0xF2). + {0x0C, 0x50, 0x50, 0x50, 0x3C}, //__у (0xF3). + {0x30, 0x48, 0xFE, 0x48, 0x30}, //__ф (0xF4). + {0x44, 0x28, 0x10, 0x28, 0x44}, //__х (0xF5). + {0x7C, 0x40, 0x40, 0x7C, 0xC0}, //__ц (0xF6). + {0x0C, 0x10, 0x10, 0x10, 0x7C}, //__ч (0xF7). + {0x7C, 0x40, 0x7C, 0x40, 0x7C}, //__ш (0xF8). + {0x7C, 0x40, 0x7C, 0x40, 0xFC}, //__щ (0xF9). + {0x04, 0x7C, 0x50, 0x50, 0x20}, //__ъ (0xFA). + {0x7C, 0x50, 0x50, 0x20, 0x7C}, //__ы (0xFB). + {0x7C, 0x50, 0x50, 0x20, 0x00}, //__ь (0xFC). + {0x28, 0x44, 0x54, 0x54, 0x38}, //__э (0xFD). + {0x7C, 0x10, 0x38, 0x44, 0x38}, //__ю (0xFE). + {0x08, 0x54, 0x34, 0x14, 0x7C}, //__я (0xFF). + /* + {0x7e, 0x09, 0x09, 0x09, 0x7e}, // А 192 + {0x7F, 0x49, 0x49, 0x49, 0x71}, // Б + {0x7f, 0x49, 0x49, 0x49, 0x36}, // В + {0x7F, 0x01, 0x01, 0x01, 0x01}, // Г + {0x60, 0x3E, 0x21, 0x3F, 0x60}, // Д + {0x7f, 0x49, 0x49, 0x49, 0x41}, // Е + {0x76, 0x08, 0x7F, 0x08, 0x76}, // Ж + {0x21, 0x41, 0x45, 0x4b, 0x31}, // З + {0x7F, 0x20, 0x10, 0x08, 0x7F}, // И + {0x7E, 0x20, 0x11, 0x08, 0x7E}, // Й + {0x7f, 0x08, 0x14, 0x22, 0x41}, // К + {0x70, 0x0E, 0x01, 0x01, 0x7F}, // Л + {0x7f, 0x02, 0x0c, 0x02, 0x7f}, // М + {0x7f, 0x08, 0x08, 0x08, 0x7f}, // Н + {0x3e, 0x41, 0x41, 0x41, 0x3e}, // О + {0x7F, 0x01, 0x01, 0x01, 0x7F}, // П + {0x7f, 0x09, 0x09, 0x09, 0x06}, // Р + {0x3e, 0x41, 0x41, 0x41, 0x22}, // С + {0x01, 0x01, 0x7f, 0x01, 0x01}, // Т + {0x07, 0x48, 0x48, 0x48, 0x7F}, // У + {0x1C, 0x22, 0x7F, 0x22, 0x1C}, // Ф + {0x63, 0x14, 0x08, 0x14, 0x63}, // Х + {0x7F, 0x40, 0x40, 0x7F, 0xC0}, // Ц + {0x07, 0x08, 0x08, 0x08, 0x7F}, // Ч + {0x7F, 0x40, 0x7F, 0x40, 0x7F}, // Ш + {0x7F, 0x40, 0x7F, 0x40, 0xFF}, // Щ + {0x01, 0x7F, 0x48, 0x48, 0x70}, // Ъ + {0x7F, 0x48, 0x70, 0x00, 0x7F}, // Ы + {0x00, 0x7F, 0x48, 0x48, 0x70}, // Ь + {0x22, 0x41, 0x49, 0x49, 0x3E}, // Э + {0x7F, 0x08, 0x3E, 0x41, 0x3E}, // Ю + {0x46, 0x29, 0x19, 0x09, 0x7F}, // Я 223 + + {0x20, 0x54, 0x54, 0x54, 0x78}, //a 224 + {0x3c, 0x4a, 0x4a, 0x49, 0x31}, //б + {0x7c, 0x54, 0x54, 0x28, 0x00}, //в + {0x7c, 0x04, 0x04, 0x04, 0x0c}, //г + {0xe0, 0x54, 0x4c, 0x44, 0xfc}, //д + {0x38, 0x54, 0x54, 0x54, 0x18}, //e + {0x6c, 0x10, 0x7c, 0x10, 0x6c}, //ж + {0x44, 0x44, 0x54, 0x54, 0x28}, //з + {0x7c, 0x20, 0x10, 0x08, 0x7c}, //и + {0x7c, 0x41, 0x22, 0x11, 0x7c}, //й + {0x7c, 0x10, 0x28, 0x44, 0x00}, //к + {0x20, 0x44, 0x3c, 0x04, 0x7c}, //л + {0x7c, 0x08, 0x10, 0x08, 0x7c}, //м + {0x7c, 0x10, 0x10, 0x10, 0x7c}, //н + {0x38, 0x44, 0x44, 0x44, 0x38}, //o + {0x7c, 0x04, 0x04, 0x04, 0x7c}, //п + {0x7C, 0x14, 0x14, 0x14, 0x08}, //p + {0x38, 0x44, 0x44, 0x44, 0x20}, //c + {0x04, 0x04, 0x7c, 0x04, 0x04}, //т + {0x0C, 0x50, 0x50, 0x50, 0x3C}, //у + {0x30, 0x48, 0xfc, 0x48, 0x30}, //ф + {0x44, 0x28, 0x10, 0x28, 0x44}, //x + {0x7c, 0x40, 0x40, 0x40, 0xfc}, //ц + {0x0c, 0x10, 0x10, 0x10, 0x7c}, //ч + {0x7c, 0x40, 0x7c, 0x40, 0x7c}, //ш + {0x7c, 0x40, 0x7c, 0x40, 0xfc}, //щ + {0x04, 0x7c, 0x50, 0x50, 0x20}, //ъ + {0x7c, 0x50, 0x50, 0x20, 0x7c}, //ы + {0x7c, 0x50, 0x50, 0x20, 0x00}, //ь + {0x28, 0x44, 0x54, 0x54, 0x38}, //э + {0x7c, 0x10, 0x38, 0x44, 0x38}, //ю + {0x08, 0x54, 0x34, 0x14, 0x7c}, //я 255 +*/ +}; diff --git a/firmware/old/GyverLamp_v1.5.4/noiseEffects.ino b/firmware/old/GyverLamp_v1.5.4/noiseEffects.ino new file mode 100644 index 0000000..06c14cb --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/noiseEffects.ino @@ -0,0 +1,200 @@ +// ******************* НАСТРОЙКИ ***************** +// "масштаб" эффектов. Чем меньше, тем крупнее! +#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; + } + 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/old/GyverLamp_v1.5.4/parsing.ino b/firmware/old/GyverLamp_v1.5.4/parsing.ino new file mode 100644 index 0000000..c87add8 --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/parsing.ino @@ -0,0 +1,114 @@ +void parseUDP() { + int packetSize = Udp.parsePacket(); + if (packetSize) { + int n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); + packetBuffer[n] = 0; + inputBuffer = packetBuffer; + + if (inputBuffer.startsWith("DEB")) { + if (sendSettings_flag) sendCurrent(); + else inputBuffer = "OK " + timeClient.getFormattedTime(); + sendSettings_flag = false; + } else if (inputBuffer.startsWith("GET")) { + sendCurrent(); + } else if (inputBuffer.startsWith("EFF")) { + saveEEPROM(); + currentMode = (byte)inputBuffer.substring(3).toInt(); + loadingFlag = true; + FastLED.clear(); + delay(1); + sendCurrent(); + FastLED.setBrightness(modes[currentMode].brightness); + } else if (inputBuffer.startsWith("BRI")) { + modes[currentMode].brightness = inputBuffer.substring(3).toInt(); + FastLED.setBrightness(modes[currentMode].brightness); + settChanged = true; + eepromTimer = millis(); + } else if (inputBuffer.startsWith("SPD")) { + modes[currentMode].speed = inputBuffer.substring(3).toInt(); + loadingFlag = true; + settChanged = true; + eepromTimer = millis(); + } else if (inputBuffer.startsWith("SCA")) { + modes[currentMode].scale = inputBuffer.substring(3).toInt(); + loadingFlag = true; + settChanged = true; + eepromTimer = millis(); + } else if (inputBuffer.startsWith("P_ON")) { + ONflag = true; + changePower(); + sendCurrent(); + } else if (inputBuffer.startsWith("P_OFF")) { + ONflag = false; + changePower(); + sendCurrent(); + } else if (inputBuffer.startsWith("ALM_SET")) { + byte alarmNum = (char)inputBuffer[7] - '0'; + alarmNum -= 1; + if (inputBuffer.indexOf("ON") != -1) { + alarm[alarmNum].state = true; + inputBuffer = "alm #" + String(alarmNum + 1) + " ON"; + } else if (inputBuffer.indexOf("OFF") != -1) { + alarm[alarmNum].state = false; + inputBuffer = "alm #" + String(alarmNum + 1) + " OFF"; + } else { + int almTime = inputBuffer.substring(8).toInt(); + alarm[alarmNum].time = almTime; + byte hour = floor(almTime / 60); + byte minute = almTime - hour * 60; + inputBuffer = "alm #" + String(alarmNum + 1) + + " " + String(hour) + + ":" + String(minute); + } + saveAlarm(alarmNum); + manualOff = false; + } else if (inputBuffer.startsWith("ALM_GET")) { + sendAlarms(); + } else if (inputBuffer.startsWith("DAWN")) { + dawnMode = inputBuffer.substring(4).toInt() - 1; + saveDawnMmode(); + } + + char reply[inputBuffer.length() + 1]; + inputBuffer.toCharArray(reply, inputBuffer.length() + 1); + Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); + Udp.write(reply); + Udp.endPacket(); + } +} + +void sendCurrent() { + inputBuffer = "CURR"; + inputBuffer += " "; + inputBuffer += String(currentMode); + inputBuffer += " "; + inputBuffer += String(modes[currentMode].brightness); + inputBuffer += " "; + inputBuffer += String(modes[currentMode].speed); + inputBuffer += " "; + inputBuffer += String(modes[currentMode].scale); + inputBuffer += " "; + inputBuffer += String(ONflag); +} + +void sendSettings() { + sendCurrent(); + char reply[inputBuffer.length() + 1]; + inputBuffer.toCharArray(reply, inputBuffer.length() + 1); + Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); + Udp.write(reply); + Udp.endPacket(); +} + +void sendAlarms() { + inputBuffer = "ALMS "; + for (byte i = 0; i < 7; i++) { + inputBuffer += String(alarm[i].state); + inputBuffer += " "; + } + for (byte i = 0; i < 7; i++) { + inputBuffer += String(alarm[i].time); + inputBuffer += " "; + } + inputBuffer += (dawnMode + 1); +} diff --git a/firmware/old/GyverLamp_v1.5.4/runningText.ino b/firmware/old/GyverLamp_v1.5.4/runningText.ino new file mode 100644 index 0000000..9e478d2 --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/runningText.ino @@ -0,0 +1,93 @@ +// работа с бегущим текстом + +// **************** НАСТРОЙКИ **************** +#define TEXT_DIRECTION 1 // 1 - по горизонтали, 0 - по вертикали +#define MIRR_V 0 // отразить текст по вертикали (0 / 1) +#define MIRR_H 0 // отразить текст по горизонтали (0 / 1) + +#define TEXT_HEIGHT 3 // высота, на которой бежит текст (от низа матрицы) +#define LET_WIDTH 5 // ширина буквы шрифта +#define LET_HEIGHT 8 // высота буквы шрифта +#define SPACE 1 // пробел + +// --------------------- ДЛЯ РАЗРАБОТЧИКОВ ---------------------- + +int offset = WIDTH; +uint32_t scrollTimer; + +void resetString() { + offset = WIDTH; +} + +boolean fillString(String text, CRGB textColor, boolean clear) { + if (loadingFlag) { + offset = WIDTH; // перемотка в правый край + loadingFlag = false; + } + + if (millis() - scrollTimer >= 100) { + scrollTimer = millis(); + if (clear) FastLED.clear(); + byte i = 0, j = 0; + while (text[i] != '\0') { + if ((byte)text[i] > 191) { // работаем с русскими буквами! + i++; + } else { + drawLetter(j, text[i], offset + j * (LET_WIDTH + SPACE), textColor); + i++; + j++; + } + } + + offset--; + if (offset < -j * (LET_WIDTH + SPACE)) { // строка убежала + offset = WIDTH + 3; + return true; + } + FastLED.show(); + } + return false; +} + +void drawLetter(uint8_t index, uint8_t letter, int16_t offset, CRGB textColor) { + int8_t start_pos = 0, finish_pos = LET_WIDTH; + + if (offset < -LET_WIDTH || offset > WIDTH) return; + if (offset < 0) start_pos = -offset; + if (offset > (WIDTH - LET_WIDTH)) finish_pos = WIDTH - offset; + + for (byte i = start_pos; i < finish_pos; i++) { + int thisByte; + if (MIRR_V) thisByte = getFont((byte)letter, LET_WIDTH - 1 - i); + else thisByte = getFont((byte)letter, i); + + for (byte j = 0; j < LET_HEIGHT; j++) { + boolean thisBit; + + if (MIRR_H) thisBit = thisByte & (1 << j); + else thisBit = thisByte & (1 << (LET_HEIGHT - 1 - j)); + + // рисуем столбец (i - горизонтальная позиция, j - вертикальная) + if (TEXT_DIRECTION) { + if (thisBit) leds[getPixelNumber(offset + i, TEXT_HEIGHT + j)] = textColor; + //else drawPixelXY(offset + i, TEXT_HEIGHT + j, 0x000000); + } else { + if (thisBit) leds[getPixelNumber(i, offset + TEXT_HEIGHT + j)] = textColor; + //else drawPixelXY(i, offset + TEXT_HEIGHT + j, 0x000000); + } + } + } +} + +// ------------- СЛУЖЕБНЫЕ ФУНКЦИИ -------------- + +// интерпретатор кода символа в массиве fontHEX (для Arduino IDE 1.8.* и выше) +uint8_t getFont(uint8_t font, uint8_t row) { + font = font - '0' + 16; // перевод код символа из таблицы ASCII в номер согласно нумерации массива + if (font <= 90) return pgm_read_byte(&(fontHEX[font][row])); // для английских букв и символов + else if (font >= 112 && font <= 159) { // и пизд*ц ждя русских + return pgm_read_byte(&(fontHEX[font - 17][row])); + } else if (font >= 96 && font <= 111) { + return pgm_read_byte(&(fontHEX[font + 47][row])); + } +} diff --git a/firmware/GyverLamp_v1.5.4/time.ino b/firmware/old/GyverLamp_v1.5.4/time.ino similarity index 100% rename from firmware/GyverLamp_v1.5.4/time.ino rename to firmware/old/GyverLamp_v1.5.4/time.ino diff --git a/firmware/old/GyverLamp_v1.5.4/timer2Minim.h b/firmware/old/GyverLamp_v1.5.4/timer2Minim.h new file mode 100644 index 0000000..37ffe03 --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/timer2Minim.h @@ -0,0 +1,42 @@ +// мини-класс таймера, версия 2.0 +// использован улучшенный алгоритм таймера на millis +// алгоритм чуть медленнее, но обеспечивает кратные интервалы и защиту от пропусков и переполнений + +class timerMinim +{ + public: + timerMinim(uint32_t interval); // объявление таймера с указанием интервала + void setInterval(uint32_t interval); // установка интервала работы таймера + boolean isReady(); // возвращает true, когда пришло время. Сбрасывается в false сам (AUTO) или вручную (MANUAL) + void reset(); // ручной сброс таймера на установленный интервал + + private: + uint32_t _timer = 0; + uint32_t _interval = 0; +}; + +timerMinim::timerMinim(uint32_t interval) { + _interval = interval; + _timer = millis(); +} + +void timerMinim::setInterval(uint32_t interval) { + _interval = (interval == 0) ? 1 : interval; // защита от ввода 0 +} + +boolean timerMinim::isReady() { + uint32_t thisMls = millis(); + if (thisMls - _timer >= _interval) { + do { + _timer += _interval; + if (_timer < _interval) break; // переполнение uint32_t + } while (_timer < thisMls - _interval); // защита от пропуска шага + return true; + } else { + return false; + } +} + +void timerMinim::reset() { + _timer = millis(); +} diff --git a/firmware/old/GyverLamp_v1.5.4/utility.ino b/firmware/old/GyverLamp_v1.5.4/utility.ino new file mode 100644 index 0000000..6110de5 --- /dev/null +++ b/firmware/old/GyverLamp_v1.5.4/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); + } +}