From 9551519a35323eb598fdce5014b64b3a341201f9 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Sat, 9 Jan 2021 00:35:48 +0100 Subject: [PATCH] First working multisegment transitions --- wled00/FX.h | 155 ++++++++++++++++++++++++++++++++++++++----- wled00/FX_fcn.cpp | 95 ++++++++++++++------------ wled00/fcn_declare.h | 2 +- wled00/json.cpp | 18 ++--- wled00/led.cpp | 36 ++++------ wled00/lx_parser.cpp | 2 +- wled00/ntp.cpp | 2 +- wled00/presets.cpp | 1 + wled00/set.cpp | 6 +- wled00/wled.h | 6 +- 10 files changed, 220 insertions(+), 103 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index b50902bb..12f61772 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -62,16 +62,15 @@ /* each segment uses 52 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ #ifdef ESP8266 - #define MAX_NUM_SEGMENTS 12 + #define MAX_NUM_SEGMENTS 12 + /* How many color transitions can run at once */ + #define MAX_NUM_TRANSITIONS 8 + /* How much data bytes all segments combined may allocate */ + #define MAX_SEGMENT_DATA 2048 #else - #define MAX_NUM_SEGMENTS 16 -#endif - -/* How much data bytes all segments combined may allocate */ -#ifdef ESP8266 -#define MAX_SEGMENT_DATA 2048 -#else -#define MAX_SEGMENT_DATA 8192 + #define MAX_NUM_SEGMENTS 16 + #define MAX_NUM_TRANSITIONS 16 + #define MAX_SEGMENT_DATA 8192 #endif #define LED_SKIP_AMOUNT 1 @@ -79,7 +78,7 @@ #define NUM_COLORS 3 /* number of colors per segment */ #define SEGMENT _segments[_segment_index] -#define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x]) +#define SEGCOLOR(x) _colors_t[x] #define SEGENV _segment_runtimes[_segment_index] #define SEGLEN _virtualSegmentLength #define SEGACT SEGMENT.stop @@ -240,11 +239,14 @@ #define FX_MODE_TV_SIMULATOR 116 #define FX_MODE_DYNAMIC_SMOOTH 117 + class WS2812FX { typedef uint16_t (WS2812FX::*mode_ptr)(void); // pre show callback typedef void (*show_callback) (void); + + static WS2812FX* instance; // segment parameters public: @@ -259,14 +261,39 @@ class WS2812FX { uint8_t grouping, spacing; uint8_t opacity; uint32_t colors[NUM_COLORS]; - void setOption(uint8_t n, bool val) + bool setColor(uint8_t slot, uint32_t c, uint8_t segn) { //returns true if changed + if (slot >= NUM_COLORS || segn >= MAX_NUM_SEGMENTS) return false; + if (c == colors[slot]) return false; + ColorTransition::startTransition(opacity, colors[slot], instance->_transitionDur, segn, slot); + colors[slot] = c; return true; + } + void setOpacity(uint8_t o, uint8_t segn) { + if (segn >= MAX_NUM_SEGMENTS) return; + if (opacity == o) return; + ColorTransition::startTransition(o, colors[0], instance->_transitionDur, segn, 0); + opacity = o; + } + uint8_t actualOpacity() { //respects On/Off state + if (!getOption(SEG_OPTION_ON)) return 0; + return opacity; + } + void setOption(uint8_t n, bool val, uint8_t segn = 255) { + bool prevOn = false; + if (n == SEG_OPTION_ON) prevOn = getOption(SEG_OPTION_ON); if (val) { options |= 0x01 << n; } else { options &= ~(0x01 << n); } + if (n == SEG_OPTION_ON && segn < MAX_NUM_SEGMENTS && getOption(SEG_OPTION_ON) != prevOn) { + if (getOption(SEG_OPTION_ON)) { + ColorTransition::startTransition(0, colors[0], instance->_transitionDur, segn, 0); + } else { + ColorTransition::startTransition(opacity, colors[0], instance->_transitionDur, segn, 0); + } + } } bool getOption(uint8_t n) { @@ -309,10 +336,10 @@ class WS2812FX { bool allocateData(uint16_t len){ if (data && _dataLen == len) return true; //already allocated deallocateData(); - if (WS2812FX::_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory + if (WS2812FX::instance->_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory data = new (std::nothrow) byte[len]; if (!data) return false; //allocation failed - WS2812FX::_usedSegmentData += len; + WS2812FX::instance->_usedSegmentData += len; _dataLen = len; memset(data, 0, len); return true; @@ -320,7 +347,7 @@ class WS2812FX { void deallocateData(){ delete[] data; data = nullptr; - WS2812FX::_usedSegmentData -= _dataLen; + WS2812FX::instance->_usedSegmentData -= _dataLen; _dataLen = 0; } @@ -350,7 +377,86 @@ class WS2812FX { bool _requiresReset = false; } segment_runtime; + typedef struct ColorTransition { // 12 bytes + uint32_t colorOld = 0; + uint32_t transitionStart; + uint16_t transitionDur; + uint8_t segment = 0xFF; //lower 6 bits: the segment this transition is for (255 indicates transition not in use/available) upper 2 bits: color channel + uint8_t briOld = 0; + static void startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot) { + Serial.printf("Starting t: Bri %u Col %u Dur %u Seg %u Slot %u\n", oldBri, oldCol, dur, segn, slot); + if (segn >= MAX_NUM_SEGMENTS || slot >= NUM_COLORS || dur == 0) return; + uint8_t tIndex = 0xFF; //none found + uint16_t tProgression = 0; + uint8_t s = segn + (slot << 6); //merge slot and segment into one byte + + for (uint8_t i = 0; i < MAX_NUM_TRANSITIONS; i++) { + uint8_t tSeg = instance->transitions[i].segment; + //see if this segment + color already has a running transition + if (tSeg == s) { + tIndex = i; break; + } + if (tSeg == 0xFF) { //free transition + tIndex = i; tProgression = 0xFFFF; + } + } + + if (tIndex == 0xFF) { //no slot found yet + for (uint8_t i = 0; i < MAX_NUM_TRANSITIONS; i++) { + //find most progressed transition to overwrite + uint16_t prog = instance->transitions[i].progress(); + if (prog > tProgression) { + tIndex = i; tProgression = prog; + } + } + } + + ColorTransition& t = instance->transitions[tIndex]; + if (t.segment == s) //this is an active transition on the same segment+color + { + t.briOld = t.currentBri(); + t.colorOld = t.currentColor(oldCol); + } else { + t.briOld = oldBri; + t.colorOld = oldCol; + uint8_t prevSeg = t.segment & 0x3F; + if (prevSeg < MAX_NUM_SEGMENTS) instance->_segments[prevSeg].setOption(SEG_OPTION_TRANSITIONAL, false); + } + t.transitionDur = dur; + t.transitionStart = millis(); + t.segment = s; + instance->_segments[segn].setOption(SEG_OPTION_TRANSITIONAL, true); + //Serial.printf("S: %u, TNr: %u, St: %u\n", s, tIndex, t.transitionStart); + //instance->transitions[tIndex] = t; + } + uint16_t progress(bool allowEnd = false) { //transition progression between 0-65535 + uint32_t timeNow = millis(); + //Serial.printf("ProgressR %u, St: %u, S: %u\n",timeNow - transitionStart, transitionStart, segment); + if (timeNow - transitionStart > transitionDur) return 0xFFFF; + uint32_t elapsed = timeNow - transitionStart; + uint32_t prog = elapsed * 0xFFFF / transitionDur; + //Serial.printf("Progress %u\n",prog); + if (prog > 0xFFFF && allowEnd) { + uint8_t segn = segment & 0x3F; + if (segn < MAX_NUM_SEGMENTS) instance->_segments[segn].setOption(SEG_OPTION_TRANSITIONAL, false); + segment = 0xFF; + } + return (prog > 0xFFFF) ? 0xFFFF : prog; + } + uint32_t currentColor(uint32_t colorNew) { + return instance->color_blend(colorOld, colorNew, progress(true), true); + } + uint8_t currentBri() { + uint8_t segn = segment & 0x3F; + if (segn >= MAX_NUM_SEGMENTS) return 0; + uint8_t briNew = instance->_segments[segn].actualOpacity(); + uint32_t prog = progress(); + return ((briNew * prog) + (briOld * (0xFFFF - prog))) >> 16; + } + } color_transition; + WS2812FX() { + WS2812FX::instance = this; //assign each member of the _mode[] array to its respective function reference _mode[FX_MODE_STATIC] = &WS2812FX::mode_static; _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; @@ -493,6 +599,7 @@ class WS2812FX { setBrightness(uint8_t b), setRange(uint16_t i, uint16_t i2, uint32_t col), setShowCallback(show_callback cb), + setTransition(uint16_t t), setTransitionMode(bool t), calcGammaTable(float), trigger(void), @@ -547,7 +654,8 @@ class WS2812FX { timebase, color_wheel(uint8_t), color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255), - color_blend(uint32_t,uint32_t,uint8_t), + color_blend(uint32_t,uint32_t,uint16_t,bool b16=false), + currentColor(uint32_t colorNew, uint8_t tNr), gamma32(uint32_t), getLastShow(void), getPixelColor(uint16_t), @@ -695,7 +803,8 @@ class WS2812FX { uint16_t _length, _lengthRaw, _virtualSegmentLength; uint16_t _rand16seed; uint8_t _brightness; - static uint16_t _usedSegmentData; + uint16_t _usedSegmentData = 0; + uint16_t _transitionDur = 750; void load_gradient_palette(uint8_t); void handle_palette(void); @@ -735,10 +844,15 @@ class WS2812FX { CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat); CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff); - void blendPixelColor(uint16_t n, uint32_t color, uint8_t blend); + void + blendPixelColor(uint16_t n, uint32_t color, uint8_t blend), + startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot); uint32_t _lastPaletteChange = 0; uint32_t _lastShow = 0; + + uint32_t _colors_t[3]; + uint8_t _bri_t; #ifdef WLED_USE_ANALOG_LEDS uint32_t _analogLastShow = 0; @@ -755,7 +869,12 @@ class WS2812FX { segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element friend class Segment_runtime; - uint16_t realPixelIndex(uint16_t i); + ColorTransition transitions[MAX_NUM_TRANSITIONS]; //12 bytes per element + friend class ColorTransition; + + uint16_t + realPixelIndex(uint16_t i), + transitionProgress(uint8_t tNr); }; //10 names per line diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 96044512..8c1681a3 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -85,23 +85,31 @@ void WS2812FX::service() { // segment's buffers are cleared SEGENV.resetIfRequired(); - if (SEGMENT.isActive()) + if (!SEGMENT.isActive()) continue; + + if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary { - if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary - { - if (SEGMENT.grouping == 0) SEGMENT.grouping = 1; //sanity check - doShow = true; - uint16_t delay = FRAMETIME; + if (SEGMENT.grouping == 0) SEGMENT.grouping = 1; //sanity check + doShow = true; + uint16_t delay = FRAMETIME; - if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen - _virtualSegmentLength = SEGMENT.virtualLength(); - handle_palette(); - delay = (this->*_mode[SEGMENT.mode])(); //effect function - if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++; + if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen + _virtualSegmentLength = SEGMENT.virtualLength(); + _bri_t = SEGMENT.opacity; _colors_t[0] = SEGMENT.colors[0]; _colors_t[1] = SEGMENT.colors[1]; _colors_t[2] = SEGMENT.colors[2]; + if (!IS_SEGMENT_ON) _bri_t = 0; + for (uint8_t t = 0; t < MAX_NUM_TRANSITIONS; t++) { + if ((transitions[t].segment & 0x3F) != i) continue; + uint8_t slot = transitions[t].segment >> 6; + if (slot == 0) _bri_t = transitions[t].currentBri(); + _colors_t[slot] = transitions[t].currentColor(SEGMENT.colors[slot]); } - - SEGENV.next_time = nowUp + delay; + for (uint8_t c = 0; c < 3; c++) _colors_t[c] = gamma32(_colors_t[c]); + handle_palette(); + delay = (this->*_mode[SEGMENT.mode])(); //effect function + if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++; } + + SEGENV.next_time = nowUp + delay; } } _virtualSegmentLength = 0; @@ -165,17 +173,12 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) uint16_t skip = _skipFirstMode ? LED_SKIP_AMOUNT : 0; if (SEGLEN) {//from segment - //color_blend(getpixel, col, SEGMENT.opacity); (pseudocode for future blending of segments) - if (IS_SEGMENT_ON) - { - if (SEGMENT.opacity < 255) { - col.R = scale8(col.R, SEGMENT.opacity); - col.G = scale8(col.G, SEGMENT.opacity); - col.B = scale8(col.B, SEGMENT.opacity); - col.W = scale8(col.W, SEGMENT.opacity); - } - } else { - col = BLACK; + //color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments) + if (_bri_t < 255) { + col.R = scale8(col.R, _bri_t); + col.G = scale8(col.G, _bri_t); + col.B = scale8(col.B, _bri_t); + col.W = scale8(col.W, _bri_t); } /* Set all the pixels in the group, ensuring _skipFirstMode is honored */ @@ -347,7 +350,7 @@ uint8_t WS2812FX::getPaletteCount() return 13 + GRADIENT_PALETTE_COUNT; } -//TODO transitions +//TODO effect transitions bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) { @@ -395,14 +398,15 @@ void WS2812FX::setColor(uint8_t slot, uint32_t c) { for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { if (_segments[i].isSelected()) { - _segments[i].colors[slot] = c; + _segments[i].setColor(slot, c, i); applied = true; } } } if (!applyToAllSelected || !applied) { - _segments[getMainSegmentId()].colors[slot] = c; + uint8_t mainseg = getMainSegmentId(); + _segments[mainseg].setColor(slot, c, mainseg); } } @@ -605,6 +609,11 @@ void WS2812FX::setShowCallback(show_callback cb) _callback = cb; } +void WS2812FX::setTransition(uint16_t t) +{ + _transitionDur = t; +} + void WS2812FX::setTransitionMode(bool t) { unsigned long waitMax = millis() + 20; //refresh after 20 ms if transition enabled @@ -620,24 +629,26 @@ void WS2812FX::setTransitionMode(bool t) /* * color blend function */ -uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint8_t blend) { +uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16) { if(blend == 0) return color1; - if(blend == 255) return color2; + uint16_t blendmax = b16 ? 0xFFFF : 0xFF; + if(blend == blendmax) return color2; + uint8_t shift = b16 ? 16 : 8; - uint32_t w1 = (color1 >> 24) & 0xff; - uint32_t r1 = (color1 >> 16) & 0xff; - uint32_t g1 = (color1 >> 8) & 0xff; - uint32_t b1 = color1 & 0xff; + uint32_t w1 = (color1 >> 24) & 0xFF; + uint32_t r1 = (color1 >> 16) & 0xFF; + uint32_t g1 = (color1 >> 8) & 0xFF; + uint32_t b1 = color1 & 0xFF; - uint32_t w2 = (color2 >> 24) & 0xff; - uint32_t r2 = (color2 >> 16) & 0xff; - uint32_t g2 = (color2 >> 8) & 0xff; - uint32_t b2 = color2 & 0xff; + uint32_t w2 = (color2 >> 24) & 0xFF; + uint32_t r2 = (color2 >> 16) & 0xFF; + uint32_t g2 = (color2 >> 8) & 0xFF; + uint32_t b2 = color2 & 0xFF; - uint32_t w3 = ((w2 * blend) + (w1 * (255 - blend))) >> 8; - uint32_t r3 = ((r2 * blend) + (r1 * (255 - blend))) >> 8; - uint32_t g3 = ((g2 * blend) + (g1 * (255 - blend))) >> 8; - uint32_t b3 = ((b2 * blend) + (b1 * (255 - blend))) >> 8; + uint32_t w3 = ((w2 * blend) + (w1 * (blendmax - blend))) >> shift; + uint32_t r3 = ((r2 * blend) + (r1 * (blendmax - blend))) >> shift; + uint32_t g3 = ((g2 * blend) + (g1 * (blendmax - blend))) >> shift; + uint32_t b3 = ((b2 * blend) + (b1 * (blendmax - blend))) >> shift; return ((w3 << 24) | (r3 << 16) | (g3 << 8) | (b3)); } @@ -1044,4 +1055,4 @@ uint32_t WS2812FX::gamma32(uint32_t color) return ((w << 24) | (r << 16) | (g << 8) | (b)); } -uint16_t WS2812FX::_usedSegmentData = 0; +WS2812FX* WS2812FX::instance = nullptr; \ No newline at end of file diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 4e27f129..c789211b 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -110,7 +110,7 @@ void setValuesFromMainSeg(); void resetTimebase(); void toggleOnOff(); void setAllLeds(); -void setLedsStandard(bool justColors = false); +void setLedsStandard(); bool colorChanged(); void colorUpdated(int callMode); void updateInterfaces(uint8_t callMode); diff --git a/wled00/json.cpp b/wled00/json.cpp index 7c3ce05f..79d182f1 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -23,13 +23,13 @@ void deserializeSegment(JsonObject elem, byte it) int segbri = elem["bri"] | -1; if (segbri == 0) { - seg.setOption(SEG_OPTION_ON, 0); + seg.setOption(SEG_OPTION_ON, 0, id); } else if (segbri > 0) { - seg.opacity = segbri; - seg.setOption(SEG_OPTION_ON, 1); + seg.setOpacity(segbri, id); + seg.setOption(SEG_OPTION_ON, 1, id); } - seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON)); + seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON), id); JsonArray colarr = elem[F("col")]; if (!colarr.isNull()) @@ -45,7 +45,7 @@ void deserializeSegment(JsonObject elem, byte it) if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400 int kelvin = colarr[i] | -1; if (kelvin < 0) continue; - if (kelvin == 0) seg.colors[i] = 0; + if (kelvin == 0) seg.setColor(i, 0, id); if (kelvin > 0) colorKtoRGB(kelvin, brgbw); colValid = true; } else { //HEX string, e.g. "FFAA00" @@ -57,7 +57,7 @@ void deserializeSegment(JsonObject elem, byte it) if (sz == 0) continue; //do nothing on empty array byte cp = copyArray(colX, rgbw, 4); - if (cp == 1 && rgbw[0] == 0) seg.colors[i] = 0; + if (cp == 1 && rgbw[0] == 0) seg.setColor(i, 0, id); colValid = true; } @@ -66,8 +66,8 @@ void deserializeSegment(JsonObject elem, byte it) { if (i == 0) {col[0] = rgbw[0]; col[1] = rgbw[1]; col[2] = rgbw[2]; col[3] = rgbw[3];} if (i == 1) {colSec[0] = rgbw[0]; colSec[1] = rgbw[1]; colSec[2] = rgbw[2]; colSec[3] = rgbw[3];} - } else { //normal case, apply directly to segment (=> no transition!) - seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF))); + } else { //normal case, apply directly to segment + seg.setColor(i, ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF))), id); if (seg.mode == FX_MODE_STATIC) strip.trigger(); //instant refresh } } @@ -168,6 +168,7 @@ bool deserializeState(JsonObject root) { transitionDelay = tr; transitionDelay *= 100; + transitionDelayTemp = transitionDelay; } tr = root[F("tt")] | -1; @@ -177,6 +178,7 @@ bool deserializeState(JsonObject root) transitionDelayTemp *= 100; jsonTransitionOnce = true; } + strip.setTransition(transitionDelayTemp); int cy = root[F("pl")] | -2; if (cy > -2) presetCyclingEnabled = (cy >= 0); diff --git a/wled00/led.cpp b/wled00/led.cpp index 1b59d86c..32e38f7d 100644 --- a/wled00/led.cpp +++ b/wled00/led.cpp @@ -51,24 +51,20 @@ void setAllLeds() { } if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY) { - colorRGBtoRGBW(colT); - colorRGBtoRGBW(colSecT); + colorRGBtoRGBW(col); + colorRGBtoRGBW(colSec); + } + strip.setColor(0, col[0], col[1], col[2], col[3]); + strip.setColor(1, colSec[0], colSec[1], colSec[2], colSec[3]); + if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY) + { + col[3] = 0; colSec[3] = 0; } - strip.setColor(0, colT[0], colT[1], colT[2], colT[3]); - strip.setColor(1, colSecT[0], colSecT[1], colSecT[2], colSecT[3]); } -void setLedsStandard(bool justColors) +void setLedsStandard() { - for (byte i=0; i<4; i++) - { - colOld[i] = col[i]; - colT[i] = col[i]; - colSecOld[i] = colSec[i]; - colSecT[i] = colSec[i]; - } - if (justColors) return; briOld = bri; briT = bri; setAllLeds(); @@ -145,7 +141,7 @@ void colorUpdated(int callMode) } if (briT == 0) { - setLedsStandard(true); //do not color transition if starting from off + //setLedsStandard(true); //do not color transition if starting from off! if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning } @@ -160,15 +156,11 @@ void colorUpdated(int callMode) //set correct delay if not using notification delay if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; jsonTransitionOnce = false; + strip.setTransition(transitionDelayTemp); if (transitionDelayTemp == 0) {setLedsStandard(); strip.trigger(); return;} if (transitionActive) { - for (byte i=0; i<4; i++) - { - colOld[i] = colT[i]; - colSecOld[i] = colSecT[i]; - } briOld = briT; tperLast = 0; } @@ -177,6 +169,7 @@ void colorUpdated(int callMode) transitionStartTime = millis(); } else { + strip.setTransition(0); setLedsStandard(); strip.trigger(); } @@ -222,11 +215,6 @@ void handleTransitions() } if (tper - tperLast < 0.004) return; tperLast = tper; - for (byte i=0; i<4; i++) - { - colT[i] = colOld[i]+((col[i] - colOld[i])*tper); - colSecT[i] = colSecOld[i]+((colSec[i] - colSecOld[i])*tper); - } briT = briOld +((bri - briOld )*tper); setAllLeds(); diff --git a/wled00/lx_parser.cpp b/wled00/lx_parser.cpp index cc25a046..806bd74a 100644 --- a/wled00/lx_parser.cpp +++ b/wled00/lx_parser.cpp @@ -70,7 +70,7 @@ void parseLxJson(int lxValue, byte segId, bool secondary) } else { DEBUG_PRINT(F("LX: segment ")); DEBUG_PRINTLN(segId); - strip.getSegment(segId).colors[secondary] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF))); + strip.getSegment(segId).setColor(secondary, ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF))), segId); } } } diff --git a/wled00/ntp.cpp b/wled00/ntp.cpp index 877ab11e..d40cbab9 100644 --- a/wled00/ntp.cpp +++ b/wled00/ntp.cpp @@ -244,7 +244,7 @@ bool checkCountdown() if (countdownMode) localTime = n - countdownTime + utcOffsetSecs; if (!countdownOverTriggered) { - if (macroCountdown != 0) applyMacro(macroCountdown); + if (macroCountdown != 0) applyPreset(macroCountdown); countdownOverTriggered = true; return true; } diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 7fd2e5d2..a4635bca 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -6,6 +6,7 @@ bool applyPreset(byte index) { + if (index == 0) return false; if (fileDoc) { errorFlag = readObjectFromFileUsingId("/presets.json", index, fileDoc) ? ERR_NONE : ERR_FS_PLOAD; JsonObject fdo = fileDoc->as(); diff --git a/wled00/set.cpp b/wled00/set.cpp index c66abdb3..7a2e3102 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -541,7 +541,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) strip.applyToAllSelected = true; strip.setColor(2, t[0], t[1], t[2], t[3]); } else { - strip.getSegment(selectedSeg).colors[2] = ((t[0] << 16) + (t[1] << 8) + t[2] + (t[3] << 24)); + strip.getSegment(selectedSeg).setColor(2,((t[0] << 16) + (t[1] << 8) + t[2] + (t[3] << 24)), selectedSeg); } } @@ -667,9 +667,9 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) pos = req.indexOf(F("SB=")); if (pos > 0) { byte segbri = getNumVal(&req, pos); - strip.getSegment(selectedSeg).setOption(SEG_OPTION_ON, segbri); + strip.getSegment(selectedSeg).setOption(SEG_OPTION_ON, segbri, selectedSeg); if (segbri) { - strip.getSegment(selectedSeg).opacity = segbri; + strip.getSegment(selectedSeg).setOpacity(segbri, selectedSeg); } } diff --git a/wled00/wled.h b/wled00/wled.h index 81155ab9..70c5c03c 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2101040 +#define VERSION 2101080 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG @@ -342,11 +342,7 @@ WLED_GLOBAL bool interfacesInited _INIT(false); WLED_GLOBAL bool wasConnected _INIT(false); // color -WLED_GLOBAL byte colOld[] _INIT_N(({ 0, 0, 0, 0 })); // color before transition -WLED_GLOBAL byte colT[] _INIT_N(({ 0, 0, 0, 0 })); // color that is currently displayed on the LEDs WLED_GLOBAL byte colIT[] _INIT_N(({ 0, 0, 0, 0 })); // color that was last sent to LEDs -WLED_GLOBAL byte colSecT[] _INIT_N(({ 0, 0, 0, 0 })); -WLED_GLOBAL byte colSecOld[] _INIT_N(({ 0, 0, 0, 0 })); WLED_GLOBAL byte colSecIT[] _INIT_N(({ 0, 0, 0, 0 })); WLED_GLOBAL byte lastRandomIndex _INIT(0); // used to save last random color so the new one is not the same