From 64b1d768935b2bbae70021fcd5ae410de7a3882a Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Wed, 15 May 2024 15:34:53 +0200 Subject: [PATCH] Palette loading optimisation - fixes #3978 - FX: Firenoise can use selected palette --- wled00/FX.cpp | 20 ++++++++++---------- wled00/FX.h | 10 ++++++---- wled00/FX_fcn.cpp | 21 +++++++++------------ wled00/wled.h | 2 +- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 0565c0b2..b4ddf801 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5096,25 +5096,25 @@ uint16_t mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline SEGMENT.fill(BLACK); } - uint16_t xscale = SEGMENT.intensity*4; - uint32_t yscale = SEGMENT.speed*8; - uint8_t indexx = 0; + unsigned xscale = SEGMENT.intensity*4; + unsigned yscale = SEGMENT.speed*8; + unsigned indexx = 0; - SEGPALETTE = CRGBPalette16( CRGB(0,0,0), CRGB(0,0,0), CRGB(0,0,0), CRGB(0,0,0), - CRGB::Red, CRGB::Red, CRGB::Red, CRGB::DarkOrange, - CRGB::DarkOrange,CRGB::DarkOrange, CRGB::Orange, CRGB::Orange, - CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow); + CRGBPalette16 pal = SEGMENT.check1 ? SEGPALETTE : CRGBPalette16(CRGB::Black, CRGB::Black, CRGB::Black, CRGB::Black, + CRGB::Red, CRGB::Red, CRGB::Red, CRGB::DarkOrange, + CRGB::DarkOrange,CRGB::DarkOrange, CRGB::Orange, CRGB::Orange, + CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow); for (int j=0; j < cols; j++) { for (int i=0; i < rows; i++) { - indexx = inoise8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map. - SEGMENT.setPixelColorXY(j, i, ColorFromPalette(SEGPALETTE, min(i*(indexx)>>4, 255), i*255/cols, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED. + indexx = inoise8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map. + SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*(indexx)>>4, 255U), i*255/cols, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED. } // for i } // for j return FRAMETIME; } // mode_2Dfirenoise() -static const char _data_FX_MODE_2DFIRENOISE[] PROGMEM = "Firenoise@X scale,Y scale;;!;2;pal=0"; //WLEDMM pal=0 +static const char _data_FX_MODE_2DFIRENOISE[] PROGMEM = "Firenoise@X scale,Y scale,,,,Palette;;!;2;pal=0"; //WLEDMM pal=0 ////////////////////////////// diff --git a/wled00/FX.h b/wled00/FX.h index acd03139..b8864db4 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -106,7 +106,7 @@ bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn. //#define SEGCOLOR(x) strip._segments[strip.getCurrSegmentId()].currentColor(x, strip._segments[strip.getCurrSegmentId()].colors[x]) //#define SEGLEN strip._segments[strip.getCurrSegmentId()].virtualLength() #define SEGCOLOR(x) strip.segColor(x) /* saves us a few kbytes of code */ -#define SEGPALETTE strip._currentPalette +#define SEGPALETTE Segment::getCurrentPalette() #define SEGLEN strip._virtualSegmentLength /* saves us a few kbytes of code */ #define SPEED_FORMULA_L (5U + (50U*(255U - SEGMENT.speed))/SEGLEN) @@ -428,6 +428,9 @@ typedef struct Segment { size_t _dataLen; // WLEDMM uint16_t is too small static size_t _usedSegmentData; // WLEDMM uint16_t is too small + // perhaps this should be per segment, not static + static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette()) + // transition data, valid only if transitional==true, holds values during transition struct Transition { uint32_t _colorT[NUM_COLORS]; @@ -561,6 +564,7 @@ typedef struct Segment { static void addUsedSegmentData(int len) { _usedSegmentData += len; } void allocLeds(); //WLEDMM + inline static const CRGBPalette16 &getCurrentPalette(void) { return Segment::_currentPalette; } 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); bool setColor(uint8_t slot, uint32_t c); //returns true if changed @@ -605,7 +609,7 @@ typedef struct Segment { uint8_t currentMode(uint8_t modeNew); uint32_t currentColor(uint8_t slot, uint32_t colorNew); CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal); - CRGBPalette16 ¤tPalette(CRGBPalette16 &tgt, uint8_t paletteID); + void setCurrentPalette(void); // 1D strip uint16_t virtualLength(void) const; @@ -759,7 +763,6 @@ class WS2812FX { // 96 bytes panels(1), #endif // semi-private (just obscured) used in effect functions through macros - _currentPalette(CRGBPalette16(CRGB::Black)), _colors_t{0,0,0}, _virtualSegmentLength(0), // true private variables @@ -978,7 +981,6 @@ class WS2812FX { // 96 bytes // end 2D support void loadCustomPalettes(void); // loads custom palettes from JSON - CRGBPalette16 _currentPalette; // palette used for current effect (includes transition) std::vector customPalettes; // TODO: move custom palettes out of WS2812FX class // using public variables to reduce code size increase due to inline function getSegment() (with bounds checking) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 9ce628bd..cd5b69cf 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -95,6 +95,8 @@ CRGB *Segment::_globalLeds = nullptr; uint16_t Segment::maxWidth = DEFAULT_LED_COUNT; uint16_t Segment::maxHeight = 1; +CRGBPalette16 Segment::_currentPalette = CRGBPalette16(CRGB::Black); + // copy constructor - creates a new segment by copy from orig, but does not copy buffers. Does not modify orig! Segment::Segment(const Segment &orig) { DEBUG_PRINTLN(F("-- Copy segment constructor --")); @@ -295,7 +297,7 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { static CRGBPalette16 prevRandomPalette = CRGBPalette16(CRGB(BLACK)); byte tcp[76] = { 255 }; //WLEDMM: prevent out-of-range access in loadDynamicGradientPalette() if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; - if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; + if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // TODO remove strip dependency by moving customPalettes out of strip //default palette. Differs depending on effect if (pal == 0) switch (mode) { case FX_MODE_FIRE_2012 : pal = 35; break; // heat palette @@ -458,18 +460,17 @@ uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) { return transitional && _t ? color_blend(_t->_colorT[slot], colorNew, progress(), true) : colorNew; } -CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) { - loadPalette(targetPalette, pal); +void Segment::setCurrentPalette() { + loadPalette(_currentPalette, palette); if (transitional && _t && progress() < 0xFFFFU) { // blend palettes // there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time) // minimum blend time is 100ms maximum is 65535ms unsigned long timeMS = millis() - _t->_start; uint16_t noOfBlends = (255U * timeMS / _t->_dur) - _t->_prevPaletteBlends; - for (int i=0; i_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, targetPalette, 48); - targetPalette = _t->_palT; // copy transitioning/temporary palette + for (unsigned i = 0; i < noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, _currentPalette, 48); + _currentPalette = _t->_palT; // copy transitioning/temporary palette } - return targetPalette; } void Segment::handleTransition() { @@ -1517,11 +1518,7 @@ uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, u uint_fast16_t vLen = mapping ? virtualLength() : 1; if (mapping && vLen > 1) paletteIndex = (i*255)/(vLen -1); if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end" - CRGB fastled_col; - CRGBPalette16 curPal; - if (transitional && _t) curPal = _t->_palT; - else loadPalette(curPal, palette); - fastled_col = ColorFromPalette(curPal, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global + CRGB fastled_col = ColorFromPalette(_currentPalette, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global return RGBW32(fastled_col.r, fastled_col.g, fastled_col.b, 0); } @@ -1799,7 +1796,7 @@ void WS2812FX::service() { _colors_t[0] = seg.currentColor(0, seg.colors[0]); _colors_t[1] = seg.currentColor(1, seg.colors[1]); _colors_t[2] = seg.currentColor(2, seg.colors[2]); - seg.currentPalette(_currentPalette, seg.palette); + seg.setCurrentPalette(); // load actual palette if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB); for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]); diff --git a/wled00/wled.h b/wled00/wled.h index a0e4283e..b69956bd 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2405040 +#define VERSION 2405150 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_