diff --git a/platformio.ini b/platformio.ini index e584623d5..c382f9243 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,15 +7,15 @@ data_dir = ./wled00/data ;lib_extra_dirs = ./wled00/src lib_dir = ./wled00/src ; Please uncomment one of the 5 lines below to select your board -env_default = nodemcuv2 -; env_default = esp01 -; env_default = esp01_1m -; env_default = esp07 -; env_default = d1_mini -; env_default = esp32dev -; env_default = esp8285_4CH_MagicHome -; env_default = esp8285_4CH_H801 -; env_default = esp8285_5CH_H801 +default_envs = nodemcuv2 +; default_envs = esp01 +; default_envs = esp01_1m +; default_envs = esp07 +; default_envs = d1_mini +; default_envs = esp32dev +; default_envs = esp8285_4CH_MagicHome +; default_envs = esp8285_4CH_H801 +; default_envs = esp8285_5CH_H801 [common] framework = arduino @@ -30,15 +30,11 @@ build_flags = #build_flags for the IRremoteESP8266 library (enabled decoders have to appear here) -D _IR_ENABLE_DEFAULT_=false -D DECODE_HASH=true - -D DECODE_NEC=true + -D DECODE_NEC=true -D DECODE_SONY=true - -D DECODE_PANASONIC=true - -D DECODE_JVC=true -D DECODE_SAMSUNG=true -D DECODE_LG=true - -D DECODE_SANYO=true - -D DECODE_SHARP=true - -D DECODE_DENON=true + # TODO replace libs in /lib with managed libs in here if possible. # If they are not changed it's just a matter of setting the correct version and change the import statement lib_deps_external = @@ -52,8 +48,7 @@ lib_deps_external = Esp Async WebServer@1.2.0 #ArduinoJson@5.13.5 #IRremoteESP8266@2.7.2 - #For saving 20k program space the brnach "compile_flags" will be used: - https://github.com/crankyoldgit/IRremoteESP8266.git#compile_flags + https://github.com/crankyoldgit/IRremoteESP8266.git #Time@1.5 #Timezone@1.2.1 #For use SSD1306 0.91" OLED display uncomment following diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg b/usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg new file mode 100644 index 000000000..d518ca3e3 Binary files /dev/null and b/usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg differ diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png b/usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png new file mode 100644 index 000000000..cf146918a Binary files /dev/null and b/usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png differ diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/assets/readme.md b/usermods/Enclosure_with_OLED_temp_ESP07/assets/readme.md new file mode 100644 index 000000000..4d1005d9c --- /dev/null +++ b/usermods/Enclosure_with_OLED_temp_ESP07/assets/readme.md @@ -0,0 +1,7 @@ +# Enclosure and PCB + +## IP67 rated enclosure +![Enclosure](controller.jpg) + +## PCB +![PCB](pcb.png) diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/readme.md b/usermods/Enclosure_with_OLED_temp_ESP07/readme.md new file mode 100644 index 000000000..817fb7e4a --- /dev/null +++ b/usermods/Enclosure_with_OLED_temp_ESP07/readme.md @@ -0,0 +1,38 @@ +# Almost universal controller board for outdoor applications +This usermod is using ideas from @mrVanboy and @400killer +## Project repository +- [Original repository](https://github.com/srg74/Controller-for-WLED-firmware) - Main controller repository +## Features +* SSD1306 128x32 and 128x64 I2C OLED display +* On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect) +* Auto display shutoff for saving display lifetime +* Dallas temperature sensor +* Reporting temperature to MQTT broker + +## Hardware +![Hardware connection](assets/controller.jpg) + +## Functionality checked with +* ESP-07S +* PlatformIO +* SSD1306 128x32 I2C OLED display +* DS18B20 (temperature sensor) +* KY-022 (infrared receiver) +* Push button (N.O. momentary switch) + +### Platformio requirements +Uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`: +```ini +# platformio.ini +... +[common] +... +lib_deps_external = + ... + #For use SSD1306 OLED display uncomment following + U8g2@~2.27.3 + #For Dallas sensor uncomment following 2 lines + DallasTemperature@~3.8.0 + OneWire@~2.3.5 +... +``` diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/wled06_usermod.ino b/usermods/Enclosure_with_OLED_temp_ESP07/wled06_usermod.ino new file mode 100644 index 000000000..31bba9e67 --- /dev/null +++ b/usermods/Enclosure_with_OLED_temp_ESP07/wled06_usermod.ino @@ -0,0 +1,206 @@ +#include // from https://github.com/olikraus/u8g2/ +#include //Dallastemperature sensor +//The SCL and SDA pins are defined here. +//Lolin32 boards use SCL=5 SDA=4 +#define U8X8_PIN_SCL 5 +#define U8X8_PIN_SDA 4 +// Dallas sensor +OneWire oneWire(12); +DallasTemperature sensor(&oneWire); +long temptimer = millis(); +long lastMeasure = 0; +#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit + +// If display does not work or looks corrupted check the +// constructor reference: +// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp +// or check the gallery: +// https://github.com/olikraus/u8g2/wiki/gallery +// --> First choise of cheap I2C OLED 128X32 +U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA +// --> Second choise of cheap I2C OLED 128X64 +//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA +// gets called once at boot. Do all initialization that doesn't depend on +// network here +void userSetup() { + sensor.begin(); //Start Dallas temperature sensor + u8x8.begin(); + u8x8.setPowerSave(0); + u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255 + u8x8.setFont(u8x8_font_chroma48medium8_r); + u8x8.drawString(0, 0, "Loading..."); +} + +// gets called every time WiFi is (re-)connected. Initialize own network +// interfaces here +void userConnected() {} + +// needRedraw marks if redraw is required to prevent often redrawing. +bool needRedraw = true; + +// Next variables hold the previous known values to determine if redraw is +// required. +String knownSsid = ""; +IPAddress knownIp; +uint8_t knownBrightness = 0; +uint8_t knownMode = 0; +uint8_t knownPalette = 0; + +long lastUpdate = 0; +long lastRedraw = 0; +bool displayTurnedOff = false; +// How often we are redrawing screen +#define USER_LOOP_REFRESH_RATE_MS 5000 + +void userLoop() { + +//----> Dallas temperature sensor MQTT publishing + temptimer = millis(); +// Timer to publishe new temperature every 60 seconds + if (temptimer - lastMeasure > 60000) + { + lastMeasure = temptimer; +//Check if MQTT Connected, otherwise it will crash the 8266 + if (mqtt != nullptr) + { + sensor.requestTemperatures(); +//Gets prefered temperature scale based on selection in definitions section + #ifdef Celsius + float board_temperature = sensor.getTempCByIndex(0); + #else + float board_temperature = sensor.getTempFByIndex(0); + #endif +//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server. + char subuf[38]; + strcpy(subuf, mqttDeviceTopic); + strcat(subuf, "/temperature"); + mqtt->publish(subuf, 0, true, String(board_temperature).c_str()); + } + } + + // Check if we time interval for redrawing passes. + if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) { + return; + } + lastUpdate = millis(); + + // Turn off display after 3 minutes with no change. + if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) { + u8x8.setPowerSave(1); + displayTurnedOff = true; + } + + // Check if values which are shown on display changed from the last time. + if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) { + needRedraw = true; + } else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) { + needRedraw = true; + } else if (knownBrightness != bri) { + needRedraw = true; + } else if (knownMode != strip.getMode()) { + needRedraw = true; + } else if (knownPalette != strip.getSegment(0).palette) { + needRedraw = true; + } + + if (!needRedraw) { + return; + } + needRedraw = false; + + if (displayTurnedOff) + { + u8x8.setPowerSave(0); + displayTurnedOff = false; + } + lastRedraw = millis(); + + // Update last known values. + #if defined(ESP8266) + knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID(); + #else + knownSsid = WiFi.SSID(); + #endif + knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP(); + knownBrightness = bri; + knownMode = strip.getMode(); + knownPalette = strip.getSegment(0).palette; + u8x8.clear(); + u8x8.setFont(u8x8_font_chroma48medium8_r); + + // First row with Wifi name + u8x8.setCursor(1, 0); + u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0)); + // Print `~` char to indicate that SSID is longer, than owr dicplay + if (knownSsid.length() > u8x8.getCols()) + u8x8.print("~"); + + // Second row with IP or Psssword + u8x8.setCursor(1, 1); + // Print password in AP mode and if led is OFF. + if (apActive && bri == 0) + u8x8.print(apPass); + else + u8x8.print(knownIp); + + // Third row with mode name + u8x8.setCursor(2, 2); + uint8_t qComma = 0; + bool insideQuotes = false; + uint8_t printedChars = 0; + char singleJsonSymbol; + + // Find the mode name in JSON + for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) { + singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i); + switch (singleJsonSymbol) { + case '"': + insideQuotes = !insideQuotes; + break; + case '[': + case ']': + break; + case ',': + qComma++; + default: + if (!insideQuotes || (qComma != knownMode)) + break; + u8x8.print(singleJsonSymbol); + printedChars++; + } + if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2)) + break; + } + // Fourth row with palette name + u8x8.setCursor(2, 3); + qComma = 0; + insideQuotes = false; + printedChars = 0; + // Looking for palette name in JSON. + for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) { + singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i); + switch (singleJsonSymbol) { + case '"': + insideQuotes = !insideQuotes; + break; + case '[': + case ']': + break; + case ',': + qComma++; + default: + if (!insideQuotes || (qComma != knownPalette)) + break; + u8x8.print(singleJsonSymbol); + printedChars++; + } + if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2)) + break; + } + + u8x8.setFont(u8x8_font_open_iconic_embedded_1x1); + u8x8.drawGlyph(0, 0, 80); // wifi icon + u8x8.drawGlyph(0, 1, 68); // home icon + u8x8.setFont(u8x8_font_open_iconic_weather_2x2); + u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon +} \ No newline at end of file diff --git a/usermods/blynk_relay_control/README.md b/usermods/blynk_relay_control/README.md new file mode 100644 index 000000000..b6494b46e --- /dev/null +++ b/usermods/blynk_relay_control/README.md @@ -0,0 +1,28 @@ +# Blynk controllable relay +This usermod allows controlling a relay state from the user variables. It also allows the user variables to be set over Blynk. + +Optionally, the servo can have a reset timer to go back to it's default state after an interval. This interval is set through userVar1. + +## Instalation + +Replace the WLED06_usermod.ino file in Aircoookies WLED folder with the one here. + +## Customizations + +Update the following parameters in WLED06_usermod.ino to configure the mod's behavior: + +```cpp +//Which pin is the relay connected to +#define RELAY_PIN 5 +//Which pin state should the relay default to +#define RELAY_PIN_DEFAULT LOW +//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds +#define RELAY_PIN_TIMER_DEFAULT 3000 + +//Blynk virtual pin for controlling relay +#define BLYNK_USER_VAR0_PIN V9 +//Blynk virtual pin for controlling relay timer +#define BLYNK_USER_VAR1_PIN V10 +//Number of milliseconds between updating blynk +#define BLYNK_RELAY_UPDATE_INTERVAL 5000 +``` diff --git a/usermods/blynk_relay_control/wled06_usermod.ino b/usermods/blynk_relay_control/wled06_usermod.ino new file mode 100644 index 000000000..1004b1ed3 --- /dev/null +++ b/usermods/blynk_relay_control/wled06_usermod.ino @@ -0,0 +1,96 @@ +/* + * This file allows you to add own functionality to WLED more easily + * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality + * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h) + * bytes 2400+ are currently ununsed, but might be used for future wled features + */ + +//Use userVar0 (API calls &U0=, uint16_t) to set relay state +#define relayPinState userVar0 +//Use userVar1 (API calls &U1=, uint16_t) to set relay timer duration +//Ignored if 0, otherwise number of milliseconds to allow relay to stay in +//non default state. +#define relayTimerInterval userVar1 + +//Which pin is the relay connected to +#define RELAY_PIN 5 +//Which pin state should the relay default to +#define RELAY_PIN_DEFAULT LOW +//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds +#define RELAY_PIN_TIMER_DEFAULT 3000 + +//Blynk virtual pin for controlling relay +#define BLYNK_USER_VAR0_PIN V9 +//Blynk virtual pin for controlling relay timer +#define BLYNK_USER_VAR1_PIN V10 +//Number of milliseconds between updating blynk +#define BLYNK_RELAY_UPDATE_INTERVAL 5000 + +//Is the timer for resetting the relay active +bool relayTimerStarted = false; +//millis() time after which relay will be reset +unsigned long relayTimeToDefault = 0; +//millis() time after which relay vars in Blynk will be sent +unsigned long relayBlynkUpdateTime = 0; + +//gets called once at boot. Do all initialization that doesn't depend on network here +void userSetup() +{ + relayPinState = RELAY_PIN_DEFAULT; + relayTimerInterval = RELAY_PIN_TIMER_DEFAULT; + pinMode(RELAY_PIN, OUTPUT); + digitalWrite(RELAY_PIN, relayPinState); +} + +//gets called every time WiFi is (re-)connected. Initialize own network interfaces here +void userConnected() +{ +} + +//loop. You can use "if (WLED_CONNECTED)" to check for successful connection +void userLoop() +{ + //Normalize relayPinState to an accepted value + if (relayPinState != HIGH && relayPinState != LOW) { + relayPinState = RELAY_PIN_DEFAULT; + } + //If relay changes and relayTimerInterval is set, start a timer to change back + if (relayTimerInterval != 0 && + relayPinState != RELAY_PIN_DEFAULT && + !relayTimerStarted ) { + relayTimerStarted = true; + relayTimeToDefault = millis() + relayTimerInterval; + } + //If manually changed back to default, cancel timer + if (relayTimerStarted && relayPinState == RELAY_PIN_DEFAULT ) { + relayTimerStarted = false; + } + //If timer completes, set relay back to default + if (relayTimerStarted && millis() > relayTimeToDefault) { + relayPinState = RELAY_PIN_DEFAULT; + relayTimerStarted = false; + } + digitalWrite(RELAY_PIN, relayPinState); + updateRelayBlynk(); +} + +//Update Blynk with state of userVars at BLYNK_RELAY_UPDATE_INTERVAL +void updateRelayBlynk() +{ + if (!WLED_CONNECTED) return; + if (relayBlynkUpdateTime > millis()) return; + Blynk.virtualWrite(BLYNK_USER_VAR0_PIN, userVar0); + Blynk.virtualWrite(BLYNK_USER_VAR1_PIN, userVar1); + relayBlynkUpdateTime = millis() + BLYNK_RELAY_UPDATE_INTERVAL; +} + +//Add Blynk callback for setting userVar0 +BLYNK_WRITE(BLYNK_USER_VAR0_PIN) +{ + userVar0 = param.asInt(); +} +//Add Blynk callback for setting userVar1 +BLYNK_WRITE(BLYNK_USER_VAR1_PIN) +{ + userVar1 = param.asInt(); +} diff --git a/usermods/stairway_wipe_basic/wled06_usermod.ino b/usermods/stairway_wipe_basic/wled06_usermod.ino index 9fafb6792..ab61c5afe 100644 --- a/usermods/stairway_wipe_basic/wled06_usermod.ino +++ b/usermods/stairway_wipe_basic/wled06_usermod.ino @@ -11,6 +11,9 @@ byte wipeState = 0; //0: inactive 1: wiping 2: solid unsigned long timeStaticStart = 0; uint16_t previousUserVar0 = 0; +//comment this out if you want the turn off effect to be just fading out instead of reverse wipe +#define STAIRCASE_WIPE_OFF + //gets called once at boot. Do all initialization that doesn't depend on network here void userSetup() { @@ -52,14 +55,28 @@ void userLoop() { if (millis() - timeStaticStart > userVar1*1000) wipeState = 3; } - } else { //wipeState == 3, turn off slowly + } else if (wipeState == 3) { //switch to wipe off + #ifdef STAIRCASE_WIPE_OFF + effectCurrent = FX_MODE_COLOR_WIPE; + strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit + colorUpdated(3); + wipeState = 4; + #else turnOff(); - userVar0 = 0; - wipeState = 0; + #endif + } else { //wiping off + if (millis() + strip.timebase > (725 + (255 - effectSpeed)*150)) turnOff(); //wipe complete } } else { - if (previousUserVar0) turnOff(); wipeState = 0; //reset for next time + if (previousUserVar0) { + #ifdef STAIRCASE_WIPE_OFF + userVar0 = previousUserVar0; + wipeState = 3; + #else + turnOff(); + #endif + } previousUserVar0 = 0; } } @@ -81,7 +98,14 @@ void startWipe() void turnOff() { - transitionDelayTemp = 4000; + #ifdef STAIRCASE_WIPE_OFF + transitionDelayTemp = 0; //turn off immediately after wipe completed + #else + transitionDelayTemp = 4000; //fade out slowly + #endif bri = 0; colorUpdated(3); + wipeState = 0; + userVar0 = 0; + previousUserVar0 = 0; } diff --git a/wled00/FX.cpp b/wled00/FX.cpp index b775c787a..bc488b987 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1025,15 +1025,26 @@ uint16_t WS2812FX::larson_scanner(bool dual) { /* - * Firing comets from one end. + * Firing comets from one end. "Lighthouse" */ uint16_t WS2812FX::mode_comet(void) { - uint16_t counter = now * (SEGMENT.speed >>3) +1; + uint16_t counter = now * ((SEGMENT.speed >>2) +1); uint16_t index = counter * SEGLEN >> 16; + if (SEGENV.call == 0) SEGENV.aux0 = index; fade_out(SEGMENT.intensity); setPixelColor( index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); + if (index > SEGENV.aux0) { + for (uint16_t i = SEGENV.aux0; i < index ; i++) { + setPixelColor( i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); + } + } else if (index < SEGENV.aux0 && index < 10) { + for (uint16_t i = 0; i < index ; i++) { + setPixelColor( i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); + } + } + SEGENV.aux0 = index++; return FRAMETIME; } @@ -1172,19 +1183,26 @@ uint16_t WS2812FX::mode_loading(void) { //American Police Light with all LEDs Red and Blue uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2) { - uint16_t counter = now * ((SEGMENT.speed >> 3) +1); + uint16_t counter = now * ((SEGMENT.speed >> 2) +1); uint16_t idexR = (counter * SEGLEN) >> 16; if (idexR >= SEGLEN) idexR = 0; uint16_t topindex = SEGLEN >> 1; uint16_t idexB = idexR + topindex; - + if (SEGENV.call == 0) SEGENV.aux0 = idexR; + if (idexR > topindex) idexB -= SEGLEN; if (idexB >= SEGLEN) idexB = 0; //otherwise overflow on odd number of LEDs - setPixelColor(idexR, color1); - setPixelColor(idexB, color2); - + uint8_t gap = (SEGENV.aux0 < idexR)? idexR - SEGENV.aux0:SEGLEN - SEGENV.aux0 + idexR; + for (uint8_t i = 0; i < gap ; i++) { + if ((idexR - i) < 0) idexR = SEGLEN-1 + i; + if ((idexB - i) < 0) idexB = SEGLEN-1 + i; + setPixelColor(idexR-i, color1); + setPixelColor(idexB-i, color2); + } + SEGENV.aux0 = idexR; + return FRAMETIME; } @@ -1720,7 +1738,8 @@ uint16_t WS2812FX::mode_colorwaves() uint8_t msmultiplier = beatsin88(147, 23, 60); uint16_t hue16 = sHue16;//gHue * 256; - uint16_t hueinc16 = beatsin88(113, 300, 1500); + // uint16_t hueinc16 = beatsin88(113, 300, 1500); + uint16_t hueinc16 = beatsin88(113, 60, 300)*SEGMENT.intensity*10/255; // Use the Intensity Slider for the hues sPseudotime += duration * msmultiplier; sHue16 += duration * beatsin88(400, 5, 9); @@ -2485,22 +2504,33 @@ uint16_t WS2812FX::mode_bouncing_balls(void) { */ uint16_t WS2812FX::sinelon_base(bool dual, bool rainbow=false) { fade_out(SEGMENT.intensity); - int pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); - + uint16_t pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); + if (SEGENV.call == 0) SEGENV.aux0 = pos; uint32_t color1 = color_from_palette(pos, true, false, 0); + uint32_t color2 = SEGCOLOR(2); if (rainbow) { color1 = color_wheel((pos & 0x07) * 32); } setPixelColor(pos, color1); - if (dual) { - uint32_t color2 = SEGCOLOR(2); - if (!color2) color2 = color_from_palette(pos, true, false, 0); if (rainbow) color2 = color1; //rainbow - setPixelColor(SEGLEN-1-pos, color2); } + if (SEGENV.aux0 != pos) { + if (SEGENV.aux0 < pos) { + for (uint16_t i = SEGENV.aux0; i < pos ; i++) { + setPixelColor(i, color1); + if (dual) setPixelColor(SEGLEN-1-i, color2); + } + } else { + for (uint16_t i = SEGENV.aux0; i > pos ; i--) { + setPixelColor(i, color1); + if (dual) setPixelColor(SEGLEN-1-i, color2); + } + } + SEGENV.aux0 = pos; + } return FRAMETIME; } @@ -2890,7 +2920,7 @@ uint16_t WS2812FX::mode_exploding_fireworks(void) uint16_t WS2812FX::mode_drip(void) { //allocate segment data - uint16_t numDrops = 2; + uint16_t numDrops = 4; uint16_t dataSize = sizeof(spark) * numDrops; if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed @@ -2898,6 +2928,8 @@ uint16_t WS2812FX::mode_drip(void) Spark* drops = reinterpret_cast(SEGENV.data); + numDrops = 1 + (SEGMENT.intensity >> 6); + float gravity = -0.001 - (SEGMENT.speed/50000.0); gravity *= SEGLEN; int sourcedrop = 12; @@ -2915,7 +2947,7 @@ uint16_t WS2812FX::mode_drip(void) if (drops[j].col>255) drops[j].col=255; setPixelColor(int(drops[j].pos),color_blend(BLACK,SEGCOLOR(0),drops[j].col)); - drops[j].col += map(SEGMENT.intensity, 0, 255, 1, 6); // swelling + drops[j].col += map(SEGMENT.speed, 0, 255, 1, 6); // swelling if (random8() < drops[j].col/10) { // random drop drops[j].colIndex=2; //fall @@ -2954,3 +2986,54 @@ uint16_t WS2812FX::mode_drip(void) } return FRAMETIME; } + + +/* +/ Plasma Effect +/ adapted from https://github.com/atuline/FastLED-Demos/blob/master/plasma/plasma.ino +*/ +uint16_t WS2812FX::mode_plasma(void) { + uint8_t thisPhase = beatsin8(6,-64,64); // Setting phase change for a couple of waves. + uint8_t thatPhase = beatsin8(7,-64,64); + + for (int i = 0; i < SEGLEN; i++) { // For each of the LED's in the strand, set color & brightness based on a wave as follows: + uint8_t colorIndex = cubicwave8((i*(1+ 3*(SEGMENT.speed >> 5)))+(thisPhase) & 0xFF)/2 // factor=23 // Create a wave and add a phase change and add another wave with its own phase change. + + cos8((i*(1+ 2*(SEGMENT.speed >> 5)))+(thatPhase) & 0xFF)/2; // factor=15 // Hey, you can even change the frequencies if you wish. + uint8_t thisBright = qsub8(colorIndex, beatsin8(6,0, (255 - SEGMENT.intensity)|0x01 )); + CRGB color = ColorFromPalette(currentPalette, colorIndex, thisBright, LINEARBLEND); + setPixelColor(i, color.red, color.green, color.blue); + } + + return FRAMETIME; +} + +/* + * Percentage display + * Intesity values from 0-100 turn on the leds. + */ +uint16_t WS2812FX::mode_percent(void) { + + uint8_t percent = max(0, min(100, SEGMENT.intensity)); + uint16_t active_leds = SEGLEN * percent / 100.0; + + if (SEGENV.call == 0) SEGENV.step = 0; + uint8_t size = (1 + ((SEGMENT.speed * SEGLEN) >> 11)) & 0xFF ; + + for (uint16_t i = 0; i < SEGLEN; i++) { + if (i < SEGENV.step) { + setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); + } + else { + setPixelColor(i, SEGCOLOR(1)); + } + } + if(active_leds > SEGENV.step) { + SEGENV.step += size; + if (SEGENV.step > active_leds) SEGENV.step = active_leds; + } else if (active_leds < SEGENV.step) { + if (SEGENV.step > size) SEGENV.step -= size; else SEGENV.step = 0; + if (SEGENV.step < active_leds) SEGENV.step = active_leds; + } + + return FRAMETIME; +} \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 623f874bb..d4bf4ff5d 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -91,7 +91,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 97 +#define MODE_COUNT 99 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -190,7 +190,8 @@ #define FX_MODE_SINELON_RAINBOW 94 #define FX_MODE_POPCORN 95 #define FX_MODE_DRIP 96 - +#define FX_MODE_PLASMA 97 +#define FX_MODE_PERCENT 98 class WS2812FX { typedef uint16_t (WS2812FX::*mode_ptr)(void); @@ -376,6 +377,8 @@ class WS2812FX { _mode[FX_MODE_SINELON_RAINBOW] = &WS2812FX::mode_sinelon_rainbow; _mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn; _mode[FX_MODE_DRIP] = &WS2812FX::mode_drip; + _mode[FX_MODE_PLASMA] = &WS2812FX::mode_plasma; + _mode[FX_MODE_PERCENT] = &WS2812FX::mode_percent; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -557,7 +560,9 @@ class WS2812FX { mode_sinelon_dual(void), mode_sinelon_rainbow(void), mode_popcorn(void), - mode_drip(void); + mode_drip(void), + mode_plasma(void), + mode_percent(void); private: @@ -637,7 +642,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", "Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst", -"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip" +"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent" ])====="; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 22625c29a..7c87a2920 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -469,7 +469,19 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, if (seg.stop) setRange(seg.start, seg.stop -1, 0); //turn old segment range off if (i2 <= i1) //disable segment { - seg.stop = 0; return; + seg.stop = 0; + if (n == mainSegment) //if main segment is deleted, set first active as main segment + { + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) + { + if (_segments[i].isActive()) { + mainSegment = i; + return; + } + } + mainSegment = 0; //should not happen (always at least one active segment) + } + return; } if (i1 < _length) seg.start = i1; seg.stop = i2; @@ -482,6 +494,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, } void WS2812FX::resetSegments() { + mainSegment = 0; memset(_segments, 0, sizeof(_segments)); //memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); _segment_index = 0; diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index 7648350cb..9f3915568 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -9,7 +9,7 @@ //#define USE_LPD8806 // Uncomment for using LPD8806 //#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13) //#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well -//#define WLED_USE_5CH //5 Channel H801 for cold and warm white +//#define WLED_USE_5CH_LEDS //5 Channel H801 for cold and warm white #define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) #define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0 @@ -34,7 +34,7 @@ #define RPIN 15 //R pin for analog LED strip #define GPIN 13 //G pin for analog LED strip #define BPIN 12 //B pin for analog LED strip - #define WPIN 14 //W pin for analog LED strip (W1: 14, W2: 04) + #define WPIN 14 //W pin for analog LED strip #define W2PIN 04 //W2 pin for analog LED strip #undef BTNPIN #undef IR_PIN @@ -44,7 +44,7 @@ #define RPIN 5 //R pin for analog LED strip #define GPIN 12 //G pin for analog LED strip #define BPIN 15 //B pin for analog LED strip - #define WPIN 13 //W pin for analog LED strip (W1: 14, W2: 04) + #define WPIN 13 //W pin for analog LED strip #endif #undef RLYPIN #define RLYPIN -1 //disable as pin 12 is used by analog LEDs @@ -248,7 +248,7 @@ public: if (color.R == 255 & color.G == 255 && color.B == 255 && color.W == 255) { SetRgbwPwm(0, 0, 0, 0, color.W * b / 255); } else if (color.R == 127 & color.G == 127 && color.B == 127 && color.W == 255) { - SetRgbwPwm(0, 0, 0, color.W * b / 512, colorW.W * b / 255); + SetRgbwPwm(0, 0, 0, color.W * b / 512, color.W * b / 255); } else if (color.R == 0 & color.G == 0 && color.B == 0 && color.W == 255) { SetRgbwPwm(0, 0, 0, color.W * b / 255, 0); } else if (color.R == 130 & color.G == 90 && color.B == 0 && color.W == 255) { @@ -256,7 +256,7 @@ public: } else if (color.R == 255 & color.G == 153 && color.B == 0 && color.W == 255) { SetRgbwPwm(0, 0, 0, color.W * b / 255, 0); } else { // not only white colors - SetRgbwPwm(color.R * b / 255, colorW.G * b / 255, colorW.B * b / 255, color.W * b / 255); + SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255); } #else SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255); diff --git a/wled00/html_settings.h b/wled00/html_settings.h index e99c03c58..44f9842b8 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -189,7 +189,7 @@ const char PAGE_settings_sync[] PROGMEM = R"=====(

Sync setup

Button setup

On/Off button enabled:
-Infrared receiver type (0 = disabled):
+Infrared receiver type (0 = disabled):
IR info

WLED Broadcast

UDP Port:
@@ -234,13 +234,13 @@ Group Topic:
Reboot required to apply changes. MQTT info

Philips Hue

You can find the bridge IP and the light number in the 'About' section of the hue app.
-Poll Hue light every ms:
+Poll Hue light every ms:
Then, receive On/Off, Brightness, and Color
Hue Bridge IP:
- . - . - . -
+ . + . + . +
Press the pushlink button on the bridge, after that save this page!
(when first connecting)
Hue status: Internal ESP Error!
diff --git a/wled00/ir_codes.h b/wled00/ir_codes.h index dda33e7b7..a3988e6d6 100644 --- a/wled00/ir_codes.h +++ b/wled00/ir_codes.h @@ -4,6 +4,16 @@ #define IRCUSTOM_ONOFF 0xA55AEA15 //Pioneer RC-975R "+FAV" button (example) #define IRCUSTOM_MACRO1 0xFFFFFFFF //placeholder, will never be checked for +// Default IR codes for 6-key learning remote https://www.aliexpress.com/item/4000307837886.html +// This cheap remote has the advantage of being more powerful (longer range) than cheap credit-card remotes +#define IR6_POWER 0xFF0FF0 +#define IR6_CHANNEL_UP 0xFF8F70 +#define IR6_CHANNEL_DOWN 0xFF4FB0 +#define IR6_VOLUME_UP 0xFFCF30 +#define IR6_VOLUME_DOWN 0xFF2FD0 +#define IR6_MUTE 0xFFAF50 + + //Infrared codes for 24-key remote from http://woodsgood.ca/projects/2015/02/13/rgb-led-strip-controllers-ir-codes/ #define IR24_BRIGHTER 0xF700FF #define IR24_DARKER 0xF7807F @@ -170,6 +180,29 @@ #define IR44_FADE3 0xFF609F // #define IR44_FADE7 0xFFE01F // +//Infrared codes for 21-key remote https://images-na.ssl-images-amazon.com/images/I/51NMA0XucnL.jpg +#define IR21_BRIGHTER 0xFFE01F +#define IR21_DARKER 0xFFA857 +#define IR21_OFF 0xFF629D +#define IR21_ON 0xFFA25D +#define IR21_RED 0xFF6897 +#define IR21_REDDISH 0xFF30CF +#define IR21_ORANGE 0xFF10EF +#define IR21_YELLOWISH 0xFF42BD +#define IR21_GREEN 0xFF9867 +#define IR21_GREENISH 0xFF18E7 +#define IR21_TURQUOISE 0xFF38C7 +#define IR21_CYAN 0xFF4AB5 +#define IR21_BLUE 0xFFB04F +#define IR21_DEEPBLUE 0xFF7A85 +#define IR21_PURPLE 0xFF5AA5 +#define IR21_PINK 0xFF52AD +#define IR21_WHITE 0xFF906F +#define IR21_FLASH 0xFFE21D +#define IR21_STROBE 0xFF22DD +#define IR21_FADE 0xFF02FD +#define IR21_SMOOTH 0xFFC23D + #define COLOR_RED 0xFF0000 #define COLOR_REDDISH 0xFF7800 #define COLOR_ORANGE 0xFFA000 diff --git a/wled00/wled00.ino b/wled00/wled00.ino index bc4837a72..f2f941451 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -90,7 +90,7 @@ #endif //version code in format yymmddb (b = daily build) -#define VERSION 2001151 +#define VERSION 2001281 char versionString[] = "0.9.0-b2"; @@ -535,6 +535,9 @@ void loop() { if (!offMode) strip.service(); } yield(); + #ifdef ESP8266 + MDNS.update(); + #endif if (millis() - lastMqttReconnectAttempt > 30000) initMqtt(); //DEBUG serial logging diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino index 441712e00..9940c1a53 100644 --- a/wled00/wled02_xml.ino +++ b/wled00/wled02_xml.ino @@ -53,7 +53,9 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr) } oappend(""); oappendi(colSec[3]); - oappend(""); + oappend(""); + oappendi((currentPreset < 1) ? 0:currentPreset); + oappend(""); oappendi(presetCyclingEnabled); oappend(""); if (realtimeActive) diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 3ebec49b1..a1ad3c6df 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -377,11 +377,14 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) if (t < strip.getMaxSegments()) main = t; } + WS2812FX::Segment& mainseg = strip.getSegment(main); pos = req.indexOf("SV="); //segment selected - if (pos > 0) strip.getSegment(main).setOption(0, (req.charAt(pos+3) != '0')); + if (pos > 0) mainseg.setOption(0, (req.charAt(pos+3) != '0')); - uint16_t startI = strip.getSegment(main).start; - uint16_t stopI = strip.getSegment(main).stop; + uint16_t startI = mainseg.start; + uint16_t stopI = mainseg.stop; + uint8_t grpI = mainseg.grouping; + uint16_t spcI = mainseg.spacing; pos = req.indexOf("&S="); //segment start if (pos > 0) { startI = getNumVal(&req, pos); @@ -390,7 +393,16 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) if (pos > 0) { stopI = getNumVal(&req, pos); } - strip.setSegment(main, startI, stopI); + pos = req.indexOf("GP="); //segment grouping + if (pos > 0) { + grpI = getNumVal(&req, pos); + if (grpI == 0) grpI = 1; + } + pos = req.indexOf("SP="); //segment spacing + if (pos > 0) { + spcI = getNumVal(&req, pos); + } + strip.setSegment(main, startI, stopI, grpI, spcI); main = strip.getMainSegmentId(); diff --git a/wled00/wled20_ir.ino b/wled00/wled20_ir.ino index d602e4e12..113b19b53 100644 --- a/wled00/wled20_ir.ino +++ b/wled00/wled20_ir.ino @@ -14,6 +14,7 @@ decode_results results; unsigned long irCheckedTime = 0; uint32_t lastValidCode = 0; uint16_t irTimesRepeated = 0; +uint8_t lastIR6ColourIdx = 0; //Add what your custom IR codes should trigger here. Guide: https://github.com/Aircoookie/WLED/wiki/Infrared-Control @@ -83,6 +84,10 @@ void decodeIR(uint32_t code) case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys + case 5: decodeIR21(code); break; // white 21-key remote + case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness, + // "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE" + // sets bright plain white default: return; } } @@ -146,10 +151,10 @@ void decodeIR24OLD(uint32_t code) case IR24_OLD_MAGENTA : colorFromUint32(COLOR_MAGENTA); break; case IR24_OLD_PINK : colorFromUint32(COLOR_PINK); break; case IR24_OLD_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break; - case IR24_OLD_FLASH : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; break; - case IR24_OLD_STROBE : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; break; - case IR24_OLD_FADE : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; - case IR24_OLD_SMOOTH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; + case IR24_OLD_FLASH : if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break; + case IR24_OLD_STROBE : if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break; + case IR24_OLD_FADE : if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break; + case IR24_OLD_SMOOTH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break; default: return; } lastValidCode = code; @@ -179,13 +184,13 @@ void decodeIR24CT(uint32_t code) case IR24_CT_PURPLE : colorFromUint32(COLOR_PURPLE); break; case IR24_CT_MAGENTA : colorFromUint32(COLOR_MAGENTA); break; case IR24_CT_PINK : colorFromUint32(COLOR_PINK); break; - case IR24_CT_COLDWHITE : colorFromUint32(COLOR_COLDWHITE); effectCurrent = 0; break; - case IR24_CT_WARMWHITE : colorFromUint32(COLOR_WARMWHITE); effectCurrent = 0; break; - case IR24_CT_CTPLUS : colorFromUint32(COLOR_COLDWHITE2); effectCurrent = 0; break; - case IR24_CT_CTMINUS : colorFromUint32(COLOR_WARMWHITE2); effectCurrent = 0; break; + case IR24_CT_COLDWHITE : colorFromUint32(COLOR2_COLDWHITE); effectCurrent = 0; break; + case IR24_CT_WARMWHITE : colorFromUint32(COLOR2_WARMWHITE); effectCurrent = 0; break; + case IR24_CT_CTPLUS : colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; break; + case IR24_CT_CTMINUS : colorFromUint32(COLOR2_WARMWHITE2); effectCurrent = 0; break; case IR24_CT_MEMORY : { if (col[3] > 0) col[3] = 0; - else colorFromUint32(COLOR_NEUTRALWHITE); effectCurrent = 0; } break; + else colorFromUint32(COLOR2_NEUTRALWHITE); effectCurrent = 0; } break; default: return; } lastValidCode = code; @@ -242,10 +247,10 @@ void decodeIR40(uint32_t code) case IR40_SLOW : relativeChange(&effectSpeed, -10, 5); break; case IR40_JUMP7 : relativeChange(&effectIntensity, 10); break; case IR40_AUTO : relativeChange(&effectIntensity, -10, 5); break; - case IR40_JUMP3 : if (!applyPreset(1)) effectCurrent = FX_MODE_STATIC; effectPalette = 0; break; - case IR40_FADE3 : if (!applyPreset(2)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; - case IR40_FADE7 : if (!applyPreset(3)) effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; break; - case IR40_FLASH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; + case IR40_JUMP3 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break; + case IR40_FADE3 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break; + case IR40_FADE7 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break; + case IR40_FLASH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break; } lastValidCode = code; colorUpdated(2); //for notifier, IR is considered a button input @@ -298,12 +303,12 @@ void decodeIR44(uint32_t code) case IR44_BLUEMINUS : relativeChange(&effectIntensity, -10, 5); break; case IR44_QUICK : relativeChange(&effectSpeed, 10); break; case IR44_SLOW : relativeChange(&effectSpeed, -10, 5); break; - case IR44_DIY1 : if (!applyPreset(1)) effectCurrent = FX_MODE_STATIC; effectPalette = 0; break; - case IR44_DIY2 : if (!applyPreset(2)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; - case IR44_DIY3 : if (!applyPreset(3)) effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; break; - case IR44_DIY4 : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; - case IR44_DIY5 : if (!applyPreset(5)) effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; break; - case IR44_DIY6 : if (!applyPreset(6)) effectCurrent = FX_MODE_RAIN; effectPalette = 0; break; + case IR44_DIY1 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break; + case IR44_DIY2 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break; + case IR44_DIY3 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break; + case IR44_DIY4 : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break; + case IR44_DIY5 : if (!applyPreset(5)) { effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; } break; + case IR44_DIY6 : if (!applyPreset(6)) { effectCurrent = FX_MODE_RAIN; effectPalette = 0; } break; case IR44_AUTO : effectCurrent = FX_MODE_STATIC; break; case IR44_FLASH : effectCurrent = FX_MODE_PALETTE; break; case IR44_JUMP3 : bri = 63; break; @@ -315,6 +320,78 @@ void decodeIR44(uint32_t code) colorUpdated(2); //for notifier, IR is considered a button input } +void decodeIR21(uint32_t code) +{ + switch (code) { + case IR21_BRIGHTER: relativeChange(&bri, 10); break; + case IR21_DARKER: relativeChange(&bri, -10, 5); break; + case IR21_OFF: briLast = bri; bri = 0; break; + case IR21_ON: bri = briLast; break; + case IR21_RED: colorFromUint32(COLOR_RED); break; + case IR21_REDDISH: colorFromUint32(COLOR_REDDISH); break; + case IR21_ORANGE: colorFromUint32(COLOR_ORANGE); break; + case IR21_YELLOWISH: colorFromUint32(COLOR_YELLOWISH); break; + case IR21_GREEN: colorFromUint32(COLOR_GREEN); break; + case IR21_GREENISH: colorFromUint32(COLOR_GREENISH); break; + case IR21_TURQUOISE: colorFromUint32(COLOR_TURQUOISE); break; + case IR21_CYAN: colorFromUint32(COLOR_CYAN); break; + case IR21_BLUE: colorFromUint32(COLOR_BLUE); break; + case IR21_DEEPBLUE: colorFromUint32(COLOR_DEEPBLUE); break; + case IR21_PURPLE: colorFromUint32(COLOR_PURPLE); break; + case IR21_PINK: colorFromUint32(COLOR_PINK); break; + case IR21_WHITE: colorFromUint32(COLOR_WHITE); effectCurrent = 0; break; + case IR21_FLASH: if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break; + case IR21_STROBE: if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break; + case IR21_FADE: if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break; + case IR21_SMOOTH: if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break; + default: return; + } + lastValidCode = code; + colorUpdated(2); //for notifier, IR is considered a button input +} + +void decodeIR6(uint32_t code) +{ + + switch (code) { + case IR6_POWER: toggleOnOff(); break; + case IR6_CHANNEL_UP: relativeChange(&bri, 10); break; + case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break; + case IR6_VOLUME_UP: /* next effect */ relativeChange(&effectCurrent, 1); break; + case IR6_VOLUME_DOWN: + /* next palette */ + + relativeChange(&effectPalette, 1); + + switch(lastIR6ColourIdx) + { + case 0: colorFromUint32(COLOR_RED); break; + case 1: colorFromUint32(COLOR_REDDISH); break; + case 2:colorFromUint32(COLOR_ORANGE); break; + case 3:colorFromUint32(COLOR_YELLOWISH); break; + case 4:colorFromUint32(COLOR_GREEN); break; + case 5:colorFromUint32(COLOR_GREENISH); break; + case 6:colorFromUint32(COLOR_TURQUOISE); break; + case 7: colorFromUint32(COLOR_CYAN); break; + case 8:colorFromUint32(COLOR_BLUE); break; + case 9:colorFromUint32(COLOR_DEEPBLUE); break; + case 10:colorFromUint32(COLOR_PURPLE); break; + case 11:colorFromUint32(COLOR_PINK); break; + case 12:colorFromUint32(COLOR_WHITE); break; + default:break; + + } + + lastIR6ColourIdx++; + if(lastIR6ColourIdx > 12) lastIR6ColourIdx = 0; + + break; + case IR6_MUTE: effectCurrent = 0; effectPalette = 0; colorFromUint32(COLOR_WHITE); bri=255; break; + } + lastValidCode = code; + colorUpdated(2); //for notifier, IR is considered a button input +} + void initIR() {