diff --git a/wled00/FX.h b/wled00/FX.h index e4272fe1..a7906f8d 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -419,14 +419,20 @@ typedef struct Segment { static CRGBPalette16 _randomPalette; // actual random palette static CRGBPalette16 _newRandomPalette; // target random palette static unsigned long _lastPaletteChange; // last random palette change time in millis() + #ifndef WLED_DISABLE_MODE_BLEND static bool _modeBlend; // mode/effect blending semaphore + #endif // transition data, valid only if transitional==true, holds values during transition (72 bytes) struct Transition { + #ifndef WLED_DISABLE_MODE_BLEND tmpsegd_t _segT; // previous segment environment + uint8_t _modeT; // previous mode/effect + #else + uint32_t _colorT[NUM_COLORS]; + #endif uint8_t _briT; // temporary brightness uint8_t _cctT; // temporary CCT - uint8_t _modeT; // previous mode/effect CRGBPalette16 _palT; // temporary palette uint8_t _prevPaletteBlends; // number of previous palette blends (there are max 255 belnds possible) unsigned long _start; // must accommodate millis() @@ -522,7 +528,9 @@ typedef struct Segment { static uint16_t getUsedSegmentData(void) { return _usedSegmentData; } static void addUsedSegmentData(int len) { _usedSegmentData += len; } + #ifndef WLED_DISABLE_MODE_BLEND static void modeBlend(bool blend) { _modeBlend = blend; } + #endif static void handleRandomPalette(); void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, uint8_t segId = 255); @@ -552,8 +560,10 @@ typedef struct Segment { void startTransition(uint16_t dur); // transition has to start before actual segment values change void stopTransition(void); void handleTransition(void); + #ifndef WLED_DISABLE_MODE_BLEND void swapSegenv(tmpsegd_t &tmpSegD); void restoreSegenv(tmpsegd_t &tmpSegD); + #endif uint16_t progress(void); //transition progression between 0-65535 uint8_t currentBri(uint8_t briNew, bool useCct = false); uint8_t currentMode(uint8_t modeNew); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 9043646f..9cab445c 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -222,8 +222,10 @@ void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col) uint16_t xX = (x+g), yY = (y+j); if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end +#ifndef WLED_DISABLE_MODE_BLEND // if blending modes, blend with underlying pixel if (_modeBlend) tmpCol = color_blend(strip.getPixelColorXY(start + xX, startY + yY), col, 0xFFFFU - progress(), true); +#endif strip.setPixelColorXY(start + xX, startY + yY, tmpCol); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index bbb5cd5d..f31b1899 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -81,7 +81,9 @@ CRGBPalette16 Segment::_randomPalette = CRGBPalette16(DEFAULT_COLOR); CRGBPalette16 Segment::_newRandomPalette = CRGBPalette16(DEFAULT_COLOR); unsigned long Segment::_lastPaletteChange = 0; // perhaps it should be per segment +#ifndef WLED_DISABLE_MODE_BLEND bool Segment::_modeBlend = false; +#endif // copy constructor Segment::Segment(const Segment &orig) { @@ -116,7 +118,9 @@ Segment& Segment::operator= (const Segment &orig) { transitional = false; // copied segment cannot be in transition if (name) delete[] name; if (_t) { + #ifndef WLED_DISABLE_MODE_BLEND if (_t->_segT._dataT) free(_t->_segT._dataT); + #endif delete _t; } deallocateData(); @@ -144,7 +148,9 @@ Segment& Segment::operator= (Segment &&orig) noexcept { if (name) { delete[] name; name = nullptr; } // free old name deallocateData(); // free old runtime data if (_t) { + #ifndef WLED_DISABLE_MODE_BLEND if (_t->_segT._dataT) free(_t->_segT._dataT); + #endif delete _t; _t = nullptr; } @@ -298,12 +304,13 @@ void Segment::startTransition(uint16_t dur) { if (!_t) return; // failed to allocate data //DEBUG_PRINTF("-- Started transition: %p\n", this); - swapSegenv(_t->_segT); CRGBPalette16 _palT = CRGBPalette16(DEFAULT_COLOR); loadPalette(_palT, palette); _t->_palT = _palT; - _t->_modeT = mode; _t->_briT = on ? opacity : 0; _t->_cctT = cct; +#ifndef WLED_DISABLE_MODE_BLEND + swapSegenv(_t->_segT); + _t->_modeT = mode; _t->_segT._optionsT |= 0b0000000001000000; // mark old segment transitional _t->_segT._dataLenT = 0; _t->_segT._dataT = nullptr; @@ -315,6 +322,9 @@ void Segment::startTransition(uint16_t dur) { _t->_segT._dataLenT = _dataLen; } } +#else + for (size_t i=0; i_colorT[i] = colors[i]; +#endif transitional = true; // setOption(SEG_OPTION_TRANSITIONAL, true); } @@ -323,11 +333,13 @@ void Segment::stopTransition() { transitional = false; // finish transitioning segment //DEBUG_PRINTF("-- Stopping transition: %p\n", this); if (_t) { + #ifndef WLED_DISABLE_MODE_BLEND if (_t->_segT._dataT && _t->_segT._dataLenT > 0) { //DEBUG_PRINTF("-- Released duplicate data (%d): %p\n", _t->_segT._dataLenT, _t->_segT._dataT); free(_t->_segT._dataT); _t->_segT._dataT = nullptr; } + #endif delete _t; _t = nullptr; } @@ -348,6 +360,7 @@ uint16_t Segment::progress() { return 0xFFFFU; } +#ifndef WLED_DISABLE_MODE_BLEND void Segment::swapSegenv(tmpsegd_t &tmpSeg) { if (!_t) return; //DEBUG_PRINTF("-- Saving temp seg: %p (%p)\n", this, tmpSeg); @@ -419,6 +432,7 @@ void Segment::restoreSegenv(tmpsegd_t &tmpSeg) { _dataLen = tmpSeg._dataLenT; //DEBUG_PRINTF("-- temp seg data: %p (%d,%p)\n", this, _dataLen, data); } +#endif uint8_t Segment::currentBri(uint8_t briNew, bool useCct) { uint32_t prog = progress(); @@ -430,13 +444,19 @@ uint8_t Segment::currentBri(uint8_t briNew, bool useCct) { } uint8_t Segment::currentMode(uint8_t newMode) { +#ifndef WLED_DISABLE_MODE_BLEND uint16_t prog = progress(); // implicit check for transitional & _t in progress() if (prog < 0xFFFFU) return _t->_modeT; +#endif return newMode; } uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) { +#ifndef WLED_DISABLE_MODE_BLEND return transitional && _t ? color_blend(_t->_segT._colorT[slot], colorNew, progress(), true) : colorNew; +#else + return transitional && _t ? color_blend(_t->_colorT[slot], colorNew, progress(), true) : colorNew; +#endif } CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) { @@ -552,7 +572,6 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { // if we have a valid mode & is not reserved if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) { if (fx != mode) { - if (!transitional) { DEBUG_PRINT(F("-- Started mode transition. ")); DEBUG_PRINTLN(opacity);} if (fadeTransition) startTransition(strip.getTransition()); // set effect transitions mode = fx; // load default values from effect string @@ -744,12 +763,16 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) uint16_t indexMir = stop - indexSet + start - 1; indexMir += offset; // offset/phase if (indexMir >= stop) indexMir -= len; // wrap +#ifndef WLED_DISABLE_MODE_BLEND if (_modeBlend) tmpCol = color_blend(strip.getPixelColor(indexMir), col, 0xFFFFU - progress(), true); +#endif strip.setPixelColor(indexMir, tmpCol); } indexSet += offset; // offset/phase if (indexSet >= stop) indexSet -= len; // wrap +#ifndef WLED_DISABLE_MODE_BLEND if (_modeBlend) tmpCol = color_blend(strip.getPixelColor(indexSet), col, 0xFFFFU - progress(), true); +#endif strip.setPixelColor(indexSet, tmpCol); } } @@ -1216,8 +1239,9 @@ void WS2812FX::service() { // The blending will largely depend on the effect behaviour since actual output (LEDs) may be // overwritten by later effect. To enable seamless blending for every effect, additional LED buffer // would need to be allocated for each effect and then blended together for each pixel. - uint8_t tmpMode = seg.currentMode(seg.mode); // this will return old mode while in transition + [[maybe_unused]] uint8_t tmpMode = seg.currentMode(seg.mode); // this will return old mode while in transition delay = (*_mode[seg.mode])(); // run new/current mode +#ifndef WLED_DISABLE_MODE_BLEND if (seg.mode != tmpMode) { Segment::tmpsegd_t _tmpSegData; Segment::modeBlend(true); // set semaphore @@ -1227,6 +1251,7 @@ void WS2812FX::service() { delay = MIN(delay,d2); // use shortest delay Segment::modeBlend(false); // unset semaphore } +#endif if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++; if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition }