From 191db46c4f9d49ae4042f851e17f6e3a6660e9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Fri, 29 Jul 2022 12:15:56 +0200 Subject: [PATCH] Code optimisation & cleanup. Minor fixes. --- wled00/FX.cpp | 4 +-- wled00/FX.h | 82 ++++++++++++++++++----------------------------- wled00/FX_fcn.cpp | 49 +++++++++++++++------------- wled00/json.cpp | 2 +- wled00/led.cpp | 4 +-- wled00/set.cpp | 3 +- wled00/wled.h | 12 +++---- 7 files changed, 70 insertions(+), 86 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 00f9a4236..4292f4a29 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5615,7 +5615,7 @@ uint16_t mode_2Dcrazybees(void) { uint8_t posX, posY, aimX, aimY, hue; int8_t deltaX, deltaY, signX, signY, error; void aimed(uint16_t w, uint16_t h) { - randomSeed(millis()); + random16_set_seed(millis()); aimX = random8(0, w); aimY = random8(0, h); hue = random8(); @@ -5709,7 +5709,7 @@ uint16_t mode_2Dghostrider(void) { SEGENV.aux0 = cols; SEGENV.aux1 = rows; SEGMENT.fill_solid(leds, CRGB::Black); - randomSeed(strip.now); + random16_set_seed(strip.now); lighter->angleSpeed = random8(0,20) - 10; lighter->Vspeed = 5; lighter->gPosX = (cols/2) * 10; diff --git a/wled00/FX.h b/wled00/FX.h index 0318e93e4..5ec252e8e 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -434,10 +434,10 @@ typedef struct Segment { uint8_t _briT; // temporary brightness uint8_t _cctT; // temporary CCT CRGBPalette16 _palT; // temporary palette - uint8_t _modeP; // previous mode/effect + //uint8_t _modeP; // previous mode/effect (transitioning effects is way more complex than this) uint32_t _start; uint16_t _dur; - // Transition(uint16_t dur=10) : _briT(255), _cctT(127), _palT(CRGBPalette16(CRGB::Black)), _modeP(FX_MODE_STATIC), _start(millis()), _dur(dur) {} + // Transition(uint16_t dur=750) : _briT(255), _cctT(127), _palT(CRGBPalette16(CRGB::Black)), _modeP(FX_MODE_STATIC), _start(millis()), _dur(dur) {} // Transition(uint16_t d, uint8_t b, uint8_t c, const uint32_t *o) : _briT(b), _cctT(c), _palT(CRGBPalette16(CRGB::Black)), _modeP(FX_MODE_STATIC), _start(millis()), _dur(d) { // for (size_t i=0; i> n) & 0x01); } - inline bool isSelected() { return getOption(0); } - inline bool isActive() { return stop > start; } - inline uint16_t width() { return stop - start; } - inline uint16_t height() { return stopY - startY; } - inline uint16_t length() { return width(); } - inline uint16_t groupLength() { return grouping + spacing; } - inline uint8_t getLightCapabilities() { return _capabilities; } + inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); } + inline bool isSelected(void) { return getOption(0); } + inline bool isActive(void) { return stop > start; } + inline uint16_t width(void) { return stop - start; } + inline uint16_t height(void) { return stopY - startY; } + inline uint16_t length(void) { return width(); } + inline uint16_t groupLength(void) { return grouping + spacing; } + inline uint8_t getLightCapabilities(void) { return _capabilities; } bool setColor(uint8_t slot, uint32_t c); //returns true if changed void setCCT(uint16_t k); void setOpacity(uint8_t o); void setOption(uint8_t n, bool val); uint8_t differs(Segment& b); - void refreshLightCapabilities(); + void refreshLightCapabilities(void); // runtime data functions bool allocateData(uint16_t len); @@ -528,19 +528,19 @@ typedef struct Segment { * Call resetIfRequired before calling the next effect function. * Safe to call from interrupts and network requests. */ - inline void markForReset() { reset = true; } // setOption(SEG_OPTION_RESET, true) + inline void markForReset(void) { reset = true; } // setOption(SEG_OPTION_RESET, true) // transition functions void startTransition(uint16_t dur); // transition has to start before actual segment values change void handleTransition(void); - uint16_t progress(); //transition progression between 0-65535 + uint16_t progress(void); //transition progression between 0-65535 uint8_t currentBri(uint8_t briNew, bool useCct = false); uint32_t currentColor(uint8_t slot, uint32_t colorNew) { return getOption(SEG_OPTION_TRANSITIONAL) /*&& !_t*/ ? color_blend(/*_t->*/_colorT[slot], colorNew, progress(), true) : colorNew; } - CRGBPalette16 loadPalette(uint8_t pal); - CRGBPalette16 currentPalette(uint8_t pal); + CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal); + CRGBPalette16 ¤tPalette(CRGBPalette16 &tgt, uint8_t paletteID); // 1D strip - uint16_t virtualLength(); + uint16_t virtualLength(void); void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } // automatically inline void setPixelColor(int n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); } // automatically inline @@ -560,8 +560,8 @@ typedef struct Segment { uint32_t color_wheel(uint8_t pos); // 2D matrix - uint16_t virtualWidth(); - uint16_t virtualHeight(); + uint16_t virtualWidth(void); + uint16_t virtualHeight(void); uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[]) void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline @@ -599,9 +599,10 @@ class WS2812FX { // 96 bytes typedef uint16_t (*mode_ptr)(void); // pointer to mode function typedef void (*show_callback)(void); // pre show callback typedef struct ModeData { + uint8_t _id; // mode (effect) id mode_ptr _fcn; // mode (effect) function - const char *_data; // mode (effect) name and its slider control data array - ModeData(uint16_t (*fcn)(void), const char *data) : _fcn(fcn), _data(data) {} + const char *_data; // mode (effect) name and its UI control data + ModeData(uint8_t id, uint16_t (*fcn)(void), const char *data) : _id(id), _fcn(fcn), _data(data) {} } mode_data_t; static WS2812FX* instance; @@ -630,12 +631,13 @@ class WS2812FX { // 96 bytes matrix{0,0,0,0}, panel{{0,0,0,0}}, #endif + // semi-private (just obscured) used in effect functions through macros _currentPalette(CRGBPalette16(CRGB::Black)), _bri_t(0), _colors_t{0,0,0}, _virtualSegmentLength(0), + // true private variables _length(DEFAULT_LED_COUNT), - _rand16seed(0), _brightness(DEFAULT_BRIGHTNESS), _usedSegmentData(0), _transitionDur(750), @@ -652,29 +654,21 @@ class WS2812FX { // 96 bytes customMappingSize(0), _lastShow(0), _segment_index(0), - _segment_index_palette_last(99), _mainSegment(0) { WS2812FX::instance = this; - _mode.reserve(_modeCount); - _modeData.reserve(_modeCount); + _mode.reserve(_modeCount); // allocate memory to prevent initial fragmentation + _modeData.reserve(_modeCount); // allocate memory to prevent initial fragmentation if (_mode.capacity() <= 1 || _modeData.capacity() <= 1) _modeCount = 1; else setupEffectData(); - /* - _mode = new mode_ptr[_modeCount]; - _modeData = new const char*[_modeCount]; - if (_mode && _modeData) setupEffectData(); - else _modeCount = 1; // only Solid will work - */ } ~WS2812FX() { if (customMappingTable) delete[] customMappingTable; - //delete[] _mode; - //delete[] _modeData; _mode.clear(); _modeData.clear(); _segments.clear(); + customPalettes.clear(); } static WS2812FX* getInstance(void) { return instance; } @@ -823,9 +817,9 @@ class WS2812FX { // 96 bytes // end 2D support - void loadCustomPalettes(); // loads custom palettes from JSON + void loadCustomPalettes(void); // loads custom palettes from JSON CRGBPalette16 _currentPalette; // palette used for current effect (includes transition) - std::vector customPalettes; + 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) // and color transitions @@ -833,20 +827,16 @@ class WS2812FX { // 96 bytes uint32_t _colors_t[3]; // color used for effect (includes transition) uint16_t _virtualSegmentLength; - //segment _segments[MAX_NUM_SEGMENTS]; // SRAM footprint: 88 bytes per element - std::vector _segments; // deleting a segment while effects play crashes ESP + std::vector _segments; friend class Segment; - //size_t segSize = sizeof(Segment); - //size_t segsSize = sizeof(_segments); private: uint16_t _length; - uint16_t _rand16seed; - uint8_t _brightness; + uint8_t _brightness; uint16_t _usedSegmentData; uint16_t _transitionDur; - uint8_t _targetFps; + uint8_t _targetFps; uint16_t _frametime; uint16_t _cumulativeFps; @@ -857,15 +847,8 @@ class WS2812FX { // 96 bytes bool _hasWhiteChannel : 1; bool _triggered : 1; }; -// bool -// _isServicing, -// _isOffRefreshRequired, //periodic refresh is required for the strip to remain off. -// _hasWhiteChannel, -// _triggered; - uint8_t _modeCount; - //mode_ptr *_mode; // SRAM footprint: 4 bytes per element - //const char **_modeData; // mode (effect) name and its slider control data array + uint8_t _modeCount; std::vector _mode; // SRAM footprint: 4 bytes per element std::vector _modeData; // mode (effect) name and its slider control data array @@ -877,7 +860,6 @@ class WS2812FX { // 96 bytes uint32_t _lastShow; uint8_t _segment_index; - uint8_t _segment_index_palette_last; uint8_t _mainSegment; void diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index a751e524e..2a1fd9807 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -188,12 +188,12 @@ void Segment::startTransition(uint16_t dur) { // starting a transition has to occur before change so we get current values 1st /*uint8_t*/ _briT = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0); // comment out uint8_t if not using Transition struct /*uint8_t*/ _cctT = currentBri(cct, true); // comment out uint8_t if not using Transition struct - /*CRGBPalette16*/ _palT = loadPalette(palette); - /*uint8_t*/ _modeP = mode; // comment out uint8_t if not using Transition struct + /*CRGBPalette16 _palT;*/ loadPalette(_palT, palette); + ///*uint8_t*/ _modeP = mode; // comment out uint8_t if not using Transition struct //uint32_t _colorT[NUM_COLORS]; // comment out if not using Transition struct for (size_t i=0; i_briT = _briT; @@ -201,6 +201,9 @@ void Segment::startTransition(uint16_t dur) { //_t->_palT = _palT; //_t->_modeT = _modeP; //for (size_t i=0; i_colorT[i] = _colorT[i]; + // comment out if using transition struct as it is done in constructor + _dur = dur; + _start = millis(); setOption(SEG_OPTION_TRANSITIONAL, true); } @@ -223,11 +226,11 @@ uint8_t Segment::currentBri(uint8_t briNew, bool useCct) { } } -CRGBPalette16 Segment::loadPalette(uint8_t pal) { +CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { static unsigned long _lastPaletteChange = 0; // perhaps it should be per segment byte tcp[72]; - CRGBPalette16 targetPalette; - if (pal>245 && (strip.customPalettes.size() == 0 || 255-pal > strip.customPalettes.size()-1)) pal = 0; + if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; + if (pal > 245 && (strip.customPalettes.size() == 0 || 255-pal > strip.customPalettes.size()-1)) pal = 0; //default palette. Differs depending on effect if (pal == 0) switch (mode) { case FX_MODE_FIRE_2012 : pal = 35; break; // heat palette @@ -301,17 +304,16 @@ CRGBPalette16 Segment::loadPalette(uint8_t pal) { return targetPalette; } -CRGBPalette16 Segment::currentPalette(uint8_t pal) { - pal = (!getOption(SEG_OPTION_TRANSITIONAL) || progress() == 0xFFFFU) ? palette : constrain(pal, 0, GRADIENT_PALETTE_COUNT-1); - CRGBPalette16 targetPalette = loadPalette(pal); +CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) { + loadPalette(targetPalette, pal); //if (_t && progress() < 0xFFFFU) { - if (getOption(SEG_OPTION_TRANSITIONAL) && progress() < 0xFFFFU) { + if (paletteFade && getOption(SEG_OPTION_TRANSITIONAL) && progress() < 0xFFFFU) { // blend palettes - nblendPaletteTowardPalette(/*_t->*/_palT, targetPalette, 48); - return /*_t->*/_palT; - } else { - return targetPalette; + uint8_t blends = map(_dur, 0, 0xFFFF, 48, 1); // do not blend palettes too quickly (0-65.5s) + nblendPaletteTowardPalette(/*_t->*/_palT, targetPalette, blends); + targetPalette = /*_t->*/_palT; // copy transitioning/temporary palette } + return targetPalette; } void Segment::handleTransition() { @@ -326,7 +328,7 @@ void Segment::handleTransition() { bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed if (slot >= NUM_COLORS || c == colors[slot]) return false; - startTransition(strip.getTransition()); // start transition prior to change + if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change colors[slot] = c; return true; } @@ -338,19 +340,19 @@ void Segment::setCCT(uint16_t k) { k = (k - 1900) >> 5; } if (cct == k) return; - startTransition(strip.getTransition()); // start transition prior to change + if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change cct = k; } void Segment::setOpacity(uint8_t o) { if (opacity == o) return; - startTransition(strip.getTransition()); // start transition prior to change + if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change opacity = o; } void Segment::setOption(uint8_t n, bool val) { bool prevOn = getOption(SEG_OPTION_ON); - if (n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change + if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change if (val) options |= 0x01 << n; else options &= ~(0x01 << n); } @@ -845,7 +847,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]); - _currentPalette = seg.currentPalette(seg.palette); + seg.currentPalette(_currentPalette, seg.palette); seg.handleTransition(); @@ -854,7 +856,8 @@ void WS2812FX::service() { _colors_t[c] = gamma32(_colors_t[c]); } - //effect blending (execute previous effect) + // effect blending (execute previous effect) + // actual code may be a bit more involved as effects have runtime data including allocated memory //if (getOption(SEG_OPTION_TRANSITIONAL) && seg._modeP) (*_mode[seg._modeP])(progress()); delay = (*_mode[seg.mode])(); if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++; @@ -1071,7 +1074,7 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) { if (m >= getModeCount()) m = getModeCount() - 1; if (_segments[segid].mode != m) { - //_segments[segid].startTransition(strip.getTransition()); // set effect transitions + //_segments[segid].startTransition(_transitionDur); // set effect transitions _segments[segid].markForReset(); _segments[segid].mode = m; } @@ -1457,10 +1460,10 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) void WS2812FX::setTransitionMode(bool t) { - for (segment &seg : _segments) seg.startTransition(t ? getTransition() : 0); + for (segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); // for (uint8_t i = 0; i < getMaxSegments(); i++) { // Segment &seg = getSegment(i); -// seg.startTransition(t ? getTransition() : 0); +// seg.startTransition(t ? _transitionDur : 0); // } } diff --git a/wled00/json.cpp b/wled00/json.cpp index 251fa6f8a..f32c35931 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -322,6 +322,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) } } + // temporary transition (applies only once) tr = root[F("tt")] | -1; if (tr >= 0) { @@ -514,7 +515,6 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme root["on"] = (bri > 0); root["bri"] = briLast; root[F("transition")] = transitionDelay/100; //in 100ms - //root[F("tdd")] = transitionDelayDefault/100; //in 100ms } if (!forPreset) { diff --git a/wled00/led.cpp b/wled00/led.cpp index 028235fff..720f11e17 100644 --- a/wled00/led.cpp +++ b/wled00/led.cpp @@ -130,7 +130,7 @@ void stateUpdated(byte callMode) { if (fadeTransition) { //set correct delay if not using notification delay - if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; + if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; // load actual transition duration jsonTransitionOnce = false; strip.setTransition(transitionDelayTemp); if (transitionDelayTemp == 0) { @@ -143,7 +143,7 @@ void stateUpdated(byte callMode) { briOld = briT; tperLast = 0; } - strip.setTransitionMode(true); + strip.setTransitionMode(true); // force all segments to transition mode transitionActive = true; transitionStartTime = millis(); } else { diff --git a/wled00/set.cpp b/wled00/set.cpp index ee97de1b6..89af15514 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -188,8 +188,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) fadeTransition = request->hasArg(F("TF")); t = request->arg(F("TD")).toInt(); - if (t >= 0) transitionDelay = t; - transitionDelayDefault = t; + if (t >= 0) transitionDelayDefault = t; strip.paletteFade = request->hasArg(F("PF")); nightlightTargetBri = request->arg(F("TB")).toInt(); diff --git a/wled00/wled.h b/wled00/wled.h index 230c23651..f8017e582 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2207271 +#define VERSION 2207291 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG @@ -458,12 +458,12 @@ WLED_GLOBAL bool wasConnected _INIT(false); WLED_GLOBAL byte lastRandomIndex _INIT(0); // used to save last random color so the new one is not the same // transitions -WLED_GLOBAL bool transitionActive _INIT(false); -WLED_GLOBAL uint16_t transitionDelayDefault _INIT(transitionDelay); -WLED_GLOBAL uint16_t transitionDelayTemp _INIT(transitionDelay); +WLED_GLOBAL bool transitionActive _INIT(false); +WLED_GLOBAL uint16_t transitionDelayDefault _INIT(transitionDelay); // default transition time (storec in cfg.json) +WLED_GLOBAL uint16_t transitionDelayTemp _INIT(transitionDelay); // actual transition duration (overrides transitionDelay in certain cases) WLED_GLOBAL unsigned long transitionStartTime; -WLED_GLOBAL float tperLast _INIT(0); // crossfade transition progress, 0.0f - 1.0f -WLED_GLOBAL bool jsonTransitionOnce _INIT(false); +WLED_GLOBAL float tperLast _INIT(0.0f); // crossfade transition progress, 0.0f - 1.0f +WLED_GLOBAL bool jsonTransitionOnce _INIT(false); // flag to override transitionDelay (playlist, JSON API: "live" & "seg":{"i"} & "tt") // nightlight WLED_GLOBAL bool nightlightActive _INIT(false);