Multiple fixes

- increase WLED_MAX_BUSSES for C3 (fixes #4215)
- fix for #4228
- fix for very long running effect (strip.now, strip.timebase)
- C++ API change to allow `seg.setColor().setOpacity()`
This commit is contained in:
Blaž Kristan 2024-10-26 15:16:11 +02:00
parent 832599b8c5
commit 4cc2cc4ad4
11 changed files with 62 additions and 70 deletions

View File

@ -96,7 +96,7 @@ void setup() {
jsonTransitionOnce = true; jsonTransitionOnce = true;
strip.setTransition(0); //no transition strip.setTransition(0); //no transition
effectCurrent = FX_MODE_COLOR_WIPE; effectCurrent = FX_MODE_COLOR_WIPE;
resetTimebase(); //make sure wipe starts from beginning strip.resetTimebase(); //make sure wipe starts from beginning
//set wipe direction //set wipe direction
Segment& seg = strip.getSegment(0); Segment& seg = strip.getSegment(0);

View File

@ -86,7 +86,7 @@ void startWipe()
bri = briLast; //turn on bri = briLast; //turn on
transitionDelayTemp = 0; //no transition transitionDelayTemp = 0; //no transition
effectCurrent = FX_MODE_COLOR_WIPE; effectCurrent = FX_MODE_COLOR_WIPE;
resetTimebase(); //make sure wipe starts from beginning strip.resetTimebase(); //make sure wipe starts from beginning
//set wipe direction //set wipe direction
Segment& seg = strip.getSegment(0); Segment& seg = strip.getSegment(0);

View File

@ -525,12 +525,12 @@ typedef struct Segment {
inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; } inline static const CRGBPalette16 &getCurrentPalette() { 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); 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 Segment &setColor(uint8_t slot, uint32_t c);
void setCCT(uint16_t k); Segment &setCCT(uint16_t k);
void setOpacity(uint8_t o); Segment &setOpacity(uint8_t o);
void setOption(uint8_t n, bool val); Segment &setOption(uint8_t n, bool val);
void setMode(uint8_t fx, bool loadDefaults = false); Segment &setMode(uint8_t fx, bool loadDefaults = false);
void setPalette(uint8_t pal); Segment &setPalette(uint8_t pal);
uint8_t differs(Segment& b) const; uint8_t differs(Segment& b) const;
void refreshLightCapabilities(); void refreshLightCapabilities();
@ -545,7 +545,7 @@ typedef struct Segment {
* Call resetIfRequired before calling the next effect function. * Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests. * Safe to call from interrupts and network requests.
*/ */
inline void markForReset() { reset = true; } // setOption(SEG_OPTION_RESET, true) inline Segment &markForReset() { reset = true; return *this; } // setOption(SEG_OPTION_RESET, true)
// transition functions // transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change void startTransition(uint16_t dur); // transition has to start before actual segment values change
@ -599,9 +599,15 @@ typedef struct Segment {
} }
// 2D matrix // 2D matrix
[[gnu::hot]] uint16_t virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing) [[gnu::hot]] unsigned virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing)
[[gnu::hot]] uint16_t virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing) [[gnu::hot]] unsigned virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing)
uint16_t nrOfVStrips() const; // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D) inline unsigned nrOfVStrips() const { // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
#ifndef WLED_DISABLE_2D
return (is2D() && map1D2D == M12_pBar) ? virtualWidth() : 1;
#else
return 1;
#endif
}
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
[[gnu::hot]] uint16_t XY(int x, int y); // support function to get relative index within segment [[gnu::hot]] uint16_t XY(int x, int y); // support function to get relative index within segment
[[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color [[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
@ -778,7 +784,8 @@ class WS2812FX { // 96 bytes
setTargetFps(uint8_t fps), setTargetFps(uint8_t fps),
setupEffectData(); // add default effects to the list; defined in FX.cpp setupEffectData(); // add default effects to the list; defined in FX.cpp
inline void restartRuntime() { for (Segment &seg : _segments) seg.markForReset(); } inline void resetTimebase() { timebase = 0UL - millis(); }
inline void restartRuntime() { for (Segment &seg : _segments) { seg.markForReset().resetIfRequired(); } }
inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); } inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); }
inline void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); } inline void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); }
inline void setPixelColor(unsigned n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } inline void setPixelColor(unsigned n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
@ -834,10 +841,8 @@ class WS2812FX { // 96 bytes
inline uint16_t getLength() const { return _length; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H) inline uint16_t getLength() const { return _length; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H)
inline uint16_t getTransition() const { return _transitionDur; } // returns currently set transition time (in ms) inline uint16_t getTransition() const { return _transitionDur; } // returns currently set transition time (in ms)
uint32_t unsigned long now, timebase;
now, uint32_t getPixelColor(unsigned) const;
timebase,
getPixelColor(uint16_t) const;
inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call
inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; } // returns currently valid color (for slot i) AKA SEGCOLOR(); may be blended between two colors while in transition inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; } // returns currently valid color (for slot i) AKA SEGCOLOR(); may be blended between two colors while in transition

View File

@ -156,7 +156,7 @@ uint16_t IRAM_ATTR_YN Segment::XY(int x, int y)
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col)
{ {
if (!isActive()) return; // not active if (!isActive()) return; // not active
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit if ((unsigned)x >= virtualWidth() || (unsigned)y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
uint8_t _bri_t = currentBri(); uint8_t _bri_t = currentBri();
if (_bri_t < 255) { if (_bri_t < 255) {
@ -251,7 +251,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
// returns RGBW values of pixel // returns RGBW values of pixel
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
if (!isActive()) return 0; // not active if (!isActive()) return 0; // not active
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit if ((unsigned)x >= virtualWidth() || (unsigned)y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
if (reverse ) x = virtualWidth() - x - 1; if (reverse ) x = virtualWidth() - x - 1;
if (reverse_y) y = virtualHeight() - y - 1; if (reverse_y) y = virtualHeight() - y - 1;
if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed

View File

@ -509,46 +509,53 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
} }
bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed Segment &Segment::setColor(uint8_t slot, uint32_t c) {
if (slot >= NUM_COLORS || c == colors[slot]) return false; if (slot >= NUM_COLORS || c == colors[slot]) return *this;
if (!_isRGB && !_hasW) { if (!_isRGB && !_hasW) {
if (slot == 0 && c == BLACK) return false; // on/off segment cannot have primary color black if (slot == 0 && c == BLACK) return *this; // on/off segment cannot have primary color black
if (slot == 1 && c != BLACK) return false; // on/off segment cannot have secondary color non black if (slot == 1 && c != BLACK) return *this; // on/off segment cannot have secondary color non black
} }
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
colors[slot] = c; colors[slot] = c;
stateChanged = true; // send UDP/WS broadcast stateChanged = true; // send UDP/WS broadcast
return true; return *this;
} }
void Segment::setCCT(uint16_t k) { Segment &Segment::setCCT(uint16_t k) {
if (k > 255) { //kelvin value, convert to 0-255 if (k > 255) { //kelvin value, convert to 0-255
if (k < 1900) k = 1900; if (k < 1900) k = 1900;
if (k > 10091) k = 10091; if (k > 10091) k = 10091;
k = (k - 1900) >> 5; k = (k - 1900) >> 5;
} }
if (cct == k) return; if (cct != k) {
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change //DEBUGFX_PRINTF_P(PSTR("- Starting CCT transition: %d\n"), k);
cct = k; startTransition(strip.getTransition()); // start transition prior to change
stateChanged = true; // send UDP/WS broadcast cct = k;
stateChanged = true; // send UDP/WS broadcast
}
return *this;
} }
void Segment::setOpacity(uint8_t o) { Segment &Segment::setOpacity(uint8_t o) {
if (opacity == o) return; if (opacity != o) {
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change //DEBUGFX_PRINTF_P(PSTR("- Starting opacity transition: %d\n"), o);
opacity = o; startTransition(strip.getTransition()); // start transition prior to change
stateChanged = true; // send UDP/WS broadcast opacity = o;
stateChanged = true; // send UDP/WS broadcast
}
return *this;
} }
void Segment::setOption(uint8_t n, bool val) { Segment &Segment::setOption(uint8_t n, bool val) {
bool prevOn = on; bool prevOn = on;
if (fadeTransition && 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; if (val) options |= 0x01 << n;
else options &= ~(0x01 << n); else options &= ~(0x01 << n);
if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET)) stateChanged = true; // send UDP/WS broadcast if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET)) stateChanged = true; // send UDP/WS broadcast
return *this;
} }
void Segment::setMode(uint8_t fx, bool loadDefaults) { Segment &Segment::setMode(uint8_t fx, bool loadDefaults) {
// skip reserved // skip reserved
while (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4) == 0) fx++; while (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4) == 0) fx++;
if (fx >= strip.getModeCount()) fx = 0; // set solid mode if (fx >= strip.getModeCount()) fx = 0; // set solid mode
@ -580,9 +587,10 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
markForReset(); markForReset();
stateChanged = true; // send UDP/WS broadcast stateChanged = true; // send UDP/WS broadcast
} }
return *this;
} }
void Segment::setPalette(uint8_t pal) { Segment &Segment::setPalette(uint8_t pal) {
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes
if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes
if (pal != palette) { if (pal != palette) {
@ -590,37 +598,24 @@ void Segment::setPalette(uint8_t pal) {
palette = pal; palette = pal;
stateChanged = true; // send UDP/WS broadcast stateChanged = true; // send UDP/WS broadcast
} }
return *this;
} }
// 2D matrix // 2D matrix
uint16_t IRAM_ATTR Segment::virtualWidth() const { unsigned IRAM_ATTR Segment::virtualWidth() const {
unsigned groupLen = groupLength(); unsigned groupLen = groupLength();
unsigned vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen; unsigned vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vWidth; return vWidth;
} }
uint16_t IRAM_ATTR Segment::virtualHeight() const { unsigned IRAM_ATTR Segment::virtualHeight() const {
unsigned groupLen = groupLength(); unsigned groupLen = groupLength();
unsigned vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen; unsigned vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen;
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vHeight; return vHeight;
} }
uint16_t IRAM_ATTR_YN Segment::nrOfVStrips() const {
unsigned vLen = 1;
#ifndef WLED_DISABLE_2D
if (is2D()) {
switch (map1D2D) {
case M12_pBar:
vLen = virtualWidth();
break;
}
}
#endif
return vLen;
}
// Constants for mapping mode "Pinwheel" // Constants for mapping mode "Pinwheel"
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16 constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16
@ -1187,10 +1182,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
//do not call this method from system context (network callback) //do not call this method from system context (network callback)
void WS2812FX::finalizeInit() { void WS2812FX::finalizeInit() {
//reset segment runtimes //reset segment runtimes
for (segment &seg : _segments) { restartRuntime();
seg.markForReset();
seg.resetIfRequired();
}
// for the lack of better place enumerate ledmaps here // for the lack of better place enumerate ledmaps here
// if we do it in json.cpp (serializeInfo()) we are getting flashes on LEDs // if we do it in json.cpp (serializeInfo()) we are getting flashes on LEDs
@ -1402,7 +1394,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(unsigned i, uint32_t col) {
BusManager::setPixelColor(i, col); BusManager::setPixelColor(i, col);
} }
uint32_t IRAM_ATTR WS2812FX::getPixelColor(uint16_t i) const { uint32_t IRAM_ATTR WS2812FX::getPixelColor(unsigned i) const {
i = getMappedPixelIndex(i); i = getMappedPixelIndex(i);
if (i >= _length) return 0; if (i >= _length) return 0;
return BusManager::getPixelColor(i); return BusManager::getPixelColor(i);

View File

@ -215,6 +215,7 @@ void handleAnalog(uint8_t b)
briLast = bri; briLast = bri;
bri = 0; bri = 0;
} else { } else {
if (bri == 0) strip.restartRuntime();
bri = aRead; bri = aRead;
} }
} else if (macroDoublePress[b] == 249) { } else if (macroDoublePress[b] == 249) {

View File

@ -53,7 +53,7 @@
#else #else
#define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX) #define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX)
#if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM #if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM
#define WLED_MAX_BUSSES 4 // will allow 2 digital & 2 analog RGB #define WLED_MAX_BUSSES 6 // will allow 2 digital & 2 analog RGB or 6 PWM white
#define WLED_MAX_DIGITAL_CHANNELS 2 #define WLED_MAX_DIGITAL_CHANNELS 2
//#define WLED_MAX_ANALOG_CHANNELS 6 //#define WLED_MAX_ANALOG_CHANNELS 6
#define WLED_MIN_VIRTUAL_BUSSES 3 #define WLED_MIN_VIRTUAL_BUSSES 3

View File

@ -169,7 +169,6 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient = 0);
void setValuesFromSegment(uint8_t s); void setValuesFromSegment(uint8_t s);
void setValuesFromMainSeg(); void setValuesFromMainSeg();
void setValuesFromFirstSelectedSeg(); void setValuesFromFirstSelectedSeg();
void resetTimebase();
void toggleOnOff(); void toggleOnOff();
void applyBri(); void applyBri();
void applyFinalBri(); void applyFinalBri();

View File

@ -346,7 +346,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
} }
} }
int tr = -1; long tr = -1;
if (!presetId || currentPlaylist < 0) { //do not apply transition time from preset if playlist active, as it would override playlist transition times if (!presetId || currentPlaylist < 0) { //do not apply transition time from preset if playlist active, as it would override playlist transition times
tr = root[F("transition")] | -1; tr = root[F("transition")] | -1;
if (tr >= 0) { if (tr >= 0) {
@ -363,7 +363,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
} }
tr = root[F("tb")] | -1; tr = root[F("tb")] | -1;
if (tr >= 0) strip.timebase = ((uint32_t)tr) - millis(); if (tr >= 0) strip.timebase = (unsigned long)tr - millis();
JsonObject nl = root["nl"]; JsonObject nl = root["nl"];
nightlightActive = getBoolVal(nl["on"], nightlightActive); nightlightActive = getBoolVal(nl["on"], nightlightActive);

View File

@ -47,17 +47,12 @@ void applyValuesToSelectedSegs()
} }
void resetTimebase()
{
strip.timebase = 0 - millis();
}
void toggleOnOff() void toggleOnOff()
{ {
if (bri == 0) if (bri == 0)
{ {
bri = briLast; bri = briLast;
strip.restartRuntime();
} else } else
{ {
briLast = bri; briLast = bri;
@ -122,7 +117,7 @@ void stateUpdated(byte callMode) {
nightlightStartTime = millis(); nightlightStartTime = millis();
} }
if (briT == 0) { if (briT == 0) {
if (callMode != CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning if (callMode != CALL_MODE_NOTIFICATION) strip.resetTimebase(); //effect start from beginning
} }
if (bri > 0) briLast = bri; if (bri > 0) briLast = bri;

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2410140 #define VERSION 2410260
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG