diff --git a/CHANGELOG.md b/CHANGELOG.md index 1277b32e..27f8564d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ ### Development versions after 0.9.1 release +#### Build 2004220 + +- Added Candle Multi effect +- Added Palette capability to Pacifica effect + +#### Build 2004190 + +- Added TM1814 type LED defines + #### Build 2004120 - Added Art-Net support diff --git a/platformio.ini b/platformio.ini index ee05b2b7..fe96477a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,13 +15,13 @@ extra_configs = # Please uncomment one of the lines below to select your board(s) # ------------------------------------------------------------------------------ -# Travis CI binaries +# Travis CI binaries (comment this out when building for single board) default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev -# Release binaries follow +# Release binaries ; default_envs = nodemcuv2, esp01, esp01_1m_ota, esp01_1m_full, esp32dev, custom_WS2801, custom_APA102, custom_LEDPIN_16, custom_LEDPIN_4, custom32_LEDPIN_16 -# Single binaries +# Single binaries (uncomment your board) ; default_envs = nodemcuv2 ; default_envs = esp01 ; default_envs = esp01_1m_ota diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 7230a9b3..c03db766 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2719,50 +2719,92 @@ uint16_t WS2812FX::mode_popcorn(void) { //Inspired by https://github.com/avanhanegem/ArduinoCandleEffectNeoPixel //and https://cpldcpu.wordpress.com/2016/01/05/reverse-engineering-a-real-candle/ -uint16_t WS2812FX::mode_candle() +uint16_t WS2812FX::candle(bool multi) { - if (SEGENV.call == 0) { - SEGENV.aux0 = 128; SEGENV.aux1 = 132; SEGENV.step = 1; - } - bool newTarget = false; - - uint8_t s = SEGENV.aux0, target = SEGENV.aux1, fadeStep = SEGENV.step; - - if (target > s) { //fade up - s = qadd8(s, fadeStep); - if (s >= target) newTarget = true; - } else { - s = qsub8(s, fadeStep); - if (s <= target) newTarget = true; - } - SEGENV.aux0 = s; - - for (uint16_t i = 0; i < SEGLEN; i++) { - setPixelColor(i, color_blend(color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), SEGCOLOR(1), 255-s)); - } - - if (newTarget) + if (multi) { - uint8_t valrange = SEGMENT.intensity; - uint8_t rndval = valrange >> 1; - target = random8(rndval) + random8(rndval); - if (target < (rndval >> 1)) target = (rndval >> 1) + random8(rndval); - uint8_t offset = (255 - valrange) >> 1; - target += offset; + //allocate segment data + uint16_t dataSize = (SEGLEN -1) *3; + if (!SEGENV.allocateData(dataSize)) return candle(false); //allocation failed + } - uint8_t dif = (target > s) ? target - s : s - target; - - //how much to move closer to target per frame - fadeStep = dif >> 2; //mode called every ~25 ms, so 4 frames to have a new target every 100ms - if (fadeStep == 0) fadeStep = 1; + //max. flicker range controlled by intensity + uint8_t valrange = SEGMENT.intensity; + uint8_t rndval = valrange >> 1; + + //step (how much to move closer to target per frame) coarsely set by speed + uint8_t speedFactor = 4; + if (SEGMENT.speed > 252) { //epilepsy + speedFactor = 1; + } else if (SEGMENT.speed > 99) { //regular candle (mode called every ~25 ms, so 4 frames to have a new target every 100ms) + speedFactor = 2; + } else if (SEGMENT.speed > 49) { //slower fade + speedFactor = 3; + } //else 4 (slowest) + + uint16_t numCandles = (multi) ? SEGLEN : 1; + + for (uint16_t i = 0; i < numCandles; i++) + { + uint16_t d = 0; //data location + + uint8_t s = SEGENV.aux0, s_target = SEGENV.aux1, fadeStep = SEGENV.step; + if (i > 0) { + d = (i-1) *3; + s = SEGENV.data[d]; s_target = SEGENV.data[d+1]; fadeStep = SEGENV.data[d+2]; + } + if (fadeStep == 0) { //init vals + s = 128; s_target = 130 + random8(4); fadeStep = 1; + } + + bool newTarget = false; + if (s_target > s) { //fade up + s = qadd8(s, fadeStep); + if (s >= s_target) newTarget = true; + } else { + s = qsub8(s, fadeStep); + if (s <= s_target) newTarget = true; + } + + if (newTarget) { + s_target = random8(rndval) + random8(rndval); + if (s_target < (rndval >> 1)) s_target = (rndval >> 1) + random8(rndval); + uint8_t offset = (255 - valrange) >> 1; + s_target += offset; + + uint8_t dif = (s_target > s) ? s_target - s : s - s_target; - SEGENV.step = fadeStep; - SEGENV.aux1 = target; + fadeStep = dif >> speedFactor; + if (fadeStep == 0) fadeStep = 1; + } + + if (i > 0) { + setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), s)); + + SEGENV.data[d] = s; SEGENV.data[d+1] = s_target; SEGENV.data[d+2] = fadeStep; + } else { + for (uint16_t j = 0; j < SEGLEN; j++) { + setPixelColor(j, color_blend(SEGCOLOR(1), color_from_palette(j, true, PALETTE_SOLID_WRAP, 0), s)); + } + + SEGENV.aux0 = s; SEGENV.aux1 = s_target; SEGENV.step = fadeStep; + } } return FRAMETIME; } +uint16_t WS2812FX::mode_candle() +{ + return candle(false); +} + + +uint16_t WS2812FX::mode_candle_multi() +{ + return candle(true); +} + /* / Fireworks in starburst effect @@ -3205,6 +3247,13 @@ uint16_t WS2812FX::mode_pacifica() CRGBPalette16 pacifica_palette_3 = { 0x000208, 0x00030E, 0x000514, 0x00061A, 0x000820, 0x000927, 0x000B2D, 0x000C33, 0x000E39, 0x001040, 0x001450, 0x001860, 0x001C70, 0x002080, 0x1040BF, 0x2060FF }; + + if (SEGMENT.palette) { + pacifica_palette_1 = currentPalette; + pacifica_palette_2 = currentPalette; + pacifica_palette_3 = currentPalette; + } + // Increment the four "color index start" counters, one for each wave layer. // Each is incremented at a different speed, and the speeds vary over time. uint16_t sCIStart1 = SEGENV.aux0, sCIStart2 = SEGENV.aux1, sCIStart3 = SEGENV.step, sCIStart4 = SEGENV.step >> 16; diff --git a/wled00/FX.h b/wled00/FX.h index a38a1f54..41f7793c 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -95,7 +95,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 102 +#define MODE_COUNT 103 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -199,6 +199,7 @@ #define FX_MODE_RIPPLE_RAINBOW 99 #define FX_MODE_HEARTBEAT 100 #define FX_MODE_PACIFICA 101 +#define FX_MODE_CANDLE_MULTI 102 class WS2812FX { typedef uint16_t (WS2812FX::*mode_ptr)(void); @@ -389,6 +390,7 @@ class WS2812FX { _mode[FX_MODE_RIPPLE_RAINBOW] = &WS2812FX::mode_ripple_rainbow; _mode[FX_MODE_HEARTBEAT] = &WS2812FX::mode_heartbeat; _mode[FX_MODE_PACIFICA] = &WS2812FX::mode_pacifica; + _mode[FX_MODE_CANDLE_MULTI] = &WS2812FX::mode_candle_multi; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -574,7 +576,8 @@ class WS2812FX { mode_percent(void), mode_ripple_rainbow(void), mode_heartbeat(void), - mode_pacifica(void); + mode_pacifica(void), + mode_candle_multi(void); private: @@ -607,6 +610,7 @@ class WS2812FX { // mode helper functions uint16_t blink(uint32_t, uint32_t, bool strobe, bool), + candle(bool), color_wipe(bool, bool), scan(bool), theater_chase(uint32_t, uint32_t, bool), @@ -660,7 +664,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "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","Plasma","Percent","Ripple Rainbow", -"Heartbeat","Pacifica" +"Heartbeat","Pacifica","Candle Multi" ])====="; diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index f3bcfd85..5503d8c0 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -9,7 +9,7 @@ //#define USE_APA102 // Uncomment for using APA102 LEDs. //#define USE_WS2801 // Uncomment for using WS2801 LEDs (make sure you have NeoPixelBus v2.5.6 or newer) //#define USE_LPD8806 // Uncomment for using LPD8806 -//#define USE_TM1814 // Uncomment for using TM1814 LEDs (make sure you have NeoPixelBus v2.5.7 or newer) +//#define USE_TM1814 // Uncomment for using TM1814 LEDs (make sure you have NeoPixelBus v2.5.7 or newer) //#define USE_P9813 // Uncomment for using P9813 LEDs (make sure you have NeoPixelBus v2.5.8 or newer) //#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 diff --git a/wled00/wled.h b/wled00/wled.h index 10343cc0..0e64930a 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2004190 +#define VERSION 2004220 // ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).