Bugfixes.

This commit is contained in:
Blaz Kristan 2022-07-19 16:16:43 +02:00
parent 6c6849d8d7
commit a46894f395
15 changed files with 2399 additions and 2320 deletions

View File

@ -103,7 +103,7 @@ class Animated_Staircase : public Usermod {
void updateSegments() { void updateSegments() {
mainSegmentId = strip.getMainSegmentId(); mainSegmentId = strip.getMainSegmentId();
for (int i = 0; i < strip.getActiveSegmentsNum(); i++) { for (int i = 0; i < strip.getSegmentsNum(); i++) {
Segment &seg = strip.getSegment(i); Segment &seg = strip.getSegment(i);
if (!seg.isActive()) { if (!seg.isActive()) {
maxSegmentId = i - 1; maxSegmentId = i - 1;
@ -289,7 +289,7 @@ class Animated_Staircase : public Usermod {
} }
} else { } else {
// Restore segment options // Restore segment options
for (int i = 0; i < strip.getActiveSegmentsNum(); i++) { for (int i = 0; i < strip.getSegmentsNum(); i++) {
Segment &seg = strip.getSegment(i); Segment &seg = strip.getSegment(i);
if (!seg.isActive()) { if (!seg.isActive()) {
maxSegmentId = i - 1; maxSegmentId = i - 1;

View File

@ -528,7 +528,7 @@ public:
effectCurrent = modes_alpha_indexes[effectCurrentIndex]; effectCurrent = modes_alpha_indexes[effectCurrentIndex];
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getActiveSegmentsNum(); i++) { for (byte i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
strip.setMode(i, effectCurrent); strip.setMode(i, effectCurrent);
@ -556,7 +556,7 @@ public:
effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0); effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0);
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getActiveSegmentsNum(); i++) { for (byte i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.speed = effectSpeed; seg.speed = effectSpeed;
@ -584,7 +584,7 @@ public:
effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0); effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0);
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getActiveSegmentsNum(); i++) { for (byte i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.intensity = effectIntensity; seg.intensity = effectIntensity;
@ -619,7 +619,7 @@ public:
case 2: val = sid.custom2 = max(min((increase ? sid.custom2+fadeAmount : sid.custom2-fadeAmount), 255), 0); break; case 2: val = sid.custom2 = max(min((increase ? sid.custom2+fadeAmount : sid.custom2-fadeAmount), 255), 0); break;
default: val = sid.custom1 = max(min((increase ? sid.custom1+fadeAmount : sid.custom1-fadeAmount), 255), 0); break; default: val = sid.custom1 = max(min((increase ? sid.custom1+fadeAmount : sid.custom1-fadeAmount), 255), 0); break;
} }
for (byte i=0; i<strip.getActiveSegmentsNum(); i++) { for (byte i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || i == id) continue; if (!seg.isActive() || i == id) continue;
switch (par) { switch (par) {
@ -658,7 +658,7 @@ public:
effectPalette = palettes_alpha_indexes[effectPaletteIndex]; effectPalette = palettes_alpha_indexes[effectPaletteIndex];
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getActiveSegmentsNum(); i++) { for (byte i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.palette = effectPalette; seg.palette = effectPalette;
@ -687,7 +687,7 @@ public:
colorHStoRGB(currentHue1*256, currentSat1, col); colorHStoRGB(currentHue1*256, currentSat1, col);
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getActiveSegmentsNum(); i++) { for (byte i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]); seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
@ -716,7 +716,7 @@ public:
currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0); currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0);
colorHStoRGB(currentHue1*256, currentSat1, col); colorHStoRGB(currentHue1*256, currentSat1, col);
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getActiveSegmentsNum(); i++) { for (byte i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]); seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
@ -776,7 +776,7 @@ public:
#endif #endif
currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0); currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0);
// if (applyToAll) { // if (applyToAll) {
for (byte i=0; i<strip.getActiveSegmentsNum(); i++) { for (byte i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.setCCT(currentCCT); seg.setCCT(currentCCT);

View File

@ -426,39 +426,38 @@ typedef struct Segment {
public: public:
Segment(uint16_t sStart=0, uint16_t sStop=30) : start(sStart), stop(sStop) { Segment(uint16_t sStart=0, uint16_t sStop=30) :
mode = DEFAULT_MODE; start(sStart),
colors[0] = DEFAULT_COLOR; stop(sStop),
colors[1] = BLACK; offset(0),
colors[2] = BLACK; speed(DEFAULT_SPEED),
startY = 0; intensity(DEFAULT_INTENSITY),
stopY = 1; palette(0),
speed = DEFAULT_SPEED; mode(DEFAULT_MODE),
intensity = DEFAULT_INTENSITY; options(SELECTED | SEGMENT_ON),
custom1 = DEFAULT_C1; grouping(1),
custom2 = DEFAULT_C2; spacing(0),
custom3 = DEFAULT_C3; opacity(255),
grouping = 1; colors{DEFAULT_COLOR,BLACK,BLACK},
spacing = 0; cct(127),
offset = 0; custom1(DEFAULT_C1),
opacity = 255; custom2(DEFAULT_C2),
cct = 127; custom3(DEFAULT_C3),
name = nullptr; startY(0),
options = NO_OPTIONS; stopY(1),
setOption(SEG_OPTION_SELECTED, 1); name(nullptr),
setOption(SEG_OPTION_ON, 1); next_time(0),
call = 0; step(0),
step = 0; call(0),
next_time = 0; aux0(0),
aux0 = 0; aux1(0),
aux1 = 0; data(nullptr),
data = nullptr; _capabilities(0),
_dataLen = 0; _dataLen(0)
//_t = nullptr; //_t(nullptr)
} {}
Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) { Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) : Segment(sStartX, sStopX) {
Segment(sStartX, sStopX);
startY = sStartY; startY = sStartY;
stopY = sStopY; stopY = sStopY;
} }
@ -467,8 +466,12 @@ typedef struct Segment {
Segment(Segment &&orig) noexcept; // move constructor Segment(Segment &&orig) noexcept; // move constructor
~Segment() { ~Segment() {
Serial.print(F("Destroying segment: ")); #ifdef WLED_DEBUG
if (name) Serial.println(name); else Serial.println(); Serial.print(F("Destroying segment."));
if (name) Serial.printf(" %s (%p)", name, name);
if (data) Serial.printf(" %p", data);
Serial.println();
#endif
if (name) delete[] name; if (name) delete[] name;
//if (_t) delete _t; //if (_t) delete _t;
deallocateData(); deallocateData();
@ -495,8 +498,9 @@ typedef struct Segment {
// runtime data functions // runtime data functions
bool allocateData(uint16_t len); bool allocateData(uint16_t len);
void deallocateData(); void deallocateData(void);
void resetIfRequired(); inline uint16_t dataSize(void) { return _dataLen; }
void resetIfRequired(void);
/** /**
* Flags that before the next effect is calculated, * Flags that before the next effect is calculated,
* the internal segment state should be reset. * the internal segment state should be reset.
@ -581,7 +585,56 @@ class WS2812FX { // 96 bytes
public: public:
WS2812FX() { WS2812FX() :
gammaCorrectBri(false),
gammaCorrectCol(true),
paletteFade(0),
paletteBlend(0),
milliampsPerLed(55),
cctBlending(0),
ablMilliampsMax(ABL_MILLIAMPS_DEFAULT),
currentMilliamps(0),
now(millis()),
timebase(0),
isMatrix(false),
#ifndef WLED_DISABLE_2D
hPanels(1),
vPanels(1),
panelH(8),
panelW(8),
matrixWidth(DEFAULT_LED_COUNT),
matrixHeight(1),
matrix{0,0,0,0},
panel{{0,0,0,0}},
#endif
currentPalette(CRGBPalette16(CRGB::Black)),
targetPalette(CloudColors_p),
_bri_t(0),
_colors_t{0,0,0},
_virtualSegmentLength(0),
_length(DEFAULT_LED_COUNT),
_rand16seed(0),
_brightness(DEFAULT_BRIGHTNESS),
_usedSegmentData(0),
_transitionDur(750),
_targetFps(WLED_FPS),
_frametime(FRAMETIME_FIXED),
_cumulativeFps(2),
_isServicing(false),
_isOffRefreshRequired(false),
_hasWhiteChannel(false),
_triggered(false),
_no_rgb(false),
_modeCount(MODE_COUNT),
_callback(nullptr),
customMappingTable(nullptr),
customMappingSize(0),
_lastPaletteChange(0),
_lastShow(0),
_segment_index(0),
_segment_index_palette_last(99),
_mainSegment(0)
{
WS2812FX::instance = this; WS2812FX::instance = this;
_mode.reserve(_modeCount); _mode.reserve(_modeCount);
_modeData.reserve(_modeCount); _modeData.reserve(_modeCount);
@ -593,21 +646,15 @@ class WS2812FX { // 96 bytes
if (_mode && _modeData) setupEffectData(); if (_mode && _modeData) setupEffectData();
else _modeCount = 1; // only Solid will work else _modeCount = 1; // only Solid will work
*/ */
_brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black);
targetPalette = CloudColors_p;
ablMilliampsMax = ABL_MILLIAMPS_DEFAULT;
currentMilliamps = 0;
timebase = 0;
_usedSegmentData = 0;
//resetSegments(); // no need here
} }
~WS2812FX() { ~WS2812FX() {
if (customMappingTable) delete[] customMappingTable;
//delete[] _mode; //delete[] _mode;
//delete[] _modeData; //delete[] _modeData;
_mode.clear(); _mode.clear();
_modeData.clear(); _modeData.clear();
_segments.clear();
} }
static WS2812FX* getInstance(void) { return instance; } static WS2812FX* getInstance(void) { return instance; }
@ -649,23 +696,24 @@ class WS2812FX { // 96 bytes
inline void addUsedSegmentData(int16_t size) { _usedSegmentData += size; } inline void addUsedSegmentData(int16_t size) { _usedSegmentData += size; }
bool bool
gammaCorrectBri = false, gammaCorrectBri,
gammaCorrectCol = true, gammaCorrectCol,
checkSegmentAlignment(void), checkSegmentAlignment(void),
hasRGBWBus(void), hasRGBWBus(void),
hasCCTBus(void), hasCCTBus(void),
// return true if the strip is being sent pixel updates // return true if the strip is being sent pixel updates
isUpdating(void); isUpdating(void);
inline bool isServicing(void) { return _isServicing; }
inline bool hasWhiteChannel(void) {return _hasWhiteChannel;} inline bool hasWhiteChannel(void) {return _hasWhiteChannel;}
inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;} inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;}
uint8_t uint8_t
paletteFade = 0, paletteFade,
paletteBlend = 0, paletteBlend,
milliampsPerLed = 55, milliampsPerLed,
cctBlending = 0, cctBlending,
//getActiveSegmentsNum(void), getActiveSegmentsNum(void),
getFirstSelectedSegId(void), getFirstSelectedSegId(void),
getLastActiveSegmentId(void), getLastActiveSegmentId(void),
setPixelSegment(uint8_t n), setPixelSegment(uint8_t n),
@ -674,7 +722,7 @@ class WS2812FX { // 96 bytes
inline uint8_t getBrightness(void) { return _brightness; } inline uint8_t getBrightness(void) { return _brightness; }
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value) inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
inline uint8_t getActiveSegmentsNum(void) { return _segments.size(); } // returns currently active (present) segments inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments
inline uint8_t getCurrSegmentId(void) { return _segment_index; } inline uint8_t getCurrSegmentId(void) { return _segment_index; }
inline uint8_t getMainSegmentId(void) { return _mainSegment; } inline uint8_t getMainSegmentId(void) { return _mainSegment; }
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; }
@ -709,27 +757,26 @@ class WS2812FX { // 96 bytes
const char ** const char **
getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data
//inline Segment& getSegment(uint8_t id) { return _segments[id >= getMaxSegments() ? getMainSegmentId() : id]; } Segment& getSegment(uint8_t id);
inline Segment& getSegment(uint8_t id) { return _segments[id >= _segments.size() ? getMainSegmentId() : id]; } // vectors
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; } inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; }
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; } inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
inline Segment* getSegments(void) { return &(_segments[0]); } inline Segment* getSegments(void) { return &(_segments[0]); }
// 2D support (panels) // 2D support (panels)
bool bool
isMatrix = false; isMatrix;
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
#define WLED_MAX_PANELS 64 #define WLED_MAX_PANELS 64
uint8_t uint8_t
hPanels = 1, hPanels,
vPanels = 1; vPanels;
uint16_t uint16_t
panelH = 8, panelH,
panelW = 8, panelW,
matrixWidth = DEFAULT_LED_COUNT, matrixWidth,
matrixHeight = 1; matrixHeight;
typedef struct panel_bitfield_t { typedef struct panel_bitfield_t {
unsigned char unsigned char
@ -739,8 +786,8 @@ class WS2812FX { // 96 bytes
serpentine : 1; // is serpentine? serpentine : 1; // is serpentine?
} Panel; } Panel;
Panel Panel
matrix = {0,0,0,0}, matrix,
panel[WLED_MAX_PANELS] = {{0,0,0,0}}; panel[WLED_MAX_PANELS];
#endif #endif
void void
@ -776,37 +823,43 @@ class WS2812FX { // 96 bytes
uint16_t _rand16seed; uint16_t _rand16seed;
uint8_t _brightness; uint8_t _brightness;
uint16_t _usedSegmentData; uint16_t _usedSegmentData;
uint16_t _transitionDur = 750; uint16_t _transitionDur;
uint8_t _targetFps = 42; uint8_t _targetFps;
uint16_t _frametime = (1000/42); uint16_t _frametime;
uint16_t _cumulativeFps = 2; uint16_t _cumulativeFps;
// will require only 1 byte
// struct {
// byte _isServicing : 1;
// byte _isOffRefreshRequired : 1;
// byte _hasWhiteChannel : 1;
// byte _triggered : 1;
// byte _no_rgb : 1;
// };
bool bool
_isOffRefreshRequired = false, //periodic refresh is required for the strip to remain off. _isServicing,
_hasWhiteChannel = false, _isOffRefreshRequired, //periodic refresh is required for the strip to remain off.
_triggered; _hasWhiteChannel,
_triggered,
_no_rgb;
uint8_t _modeCount = MODE_COUNT; uint8_t _modeCount;
//mode_ptr *_mode; // SRAM footprint: 4 bytes per element //mode_ptr *_mode; // SRAM footprint: 4 bytes per element
//const char **_modeData; // mode (effect) name and its slider control data array //const char **_modeData; // mode (effect) name and its slider control data array
std::vector<mode_ptr> _mode; // SRAM footprint: 4 bytes per element std::vector<mode_ptr> _mode; // SRAM footprint: 4 bytes per element
std::vector<const char*> _modeData; // mode (effect) name and its slider control data array std::vector<const char*> _modeData; // mode (effect) name and its slider control data array
//std::vector<ModeData> _modes; // this will require substantial rewrite of code show_callback _callback;
show_callback _callback = nullptr; uint16_t* customMappingTable;
uint16_t customMappingSize;
uint16_t* customMappingTable = nullptr; uint32_t _lastPaletteChange;
uint16_t customMappingSize = 0; uint32_t _lastShow;
uint32_t _lastPaletteChange = 0; uint8_t _segment_index;
uint32_t _lastShow = 0; uint8_t _segment_index_palette_last;
bool _no_rgb = false;
uint8_t _segment_index = 0;
uint8_t _segment_index_palette_last = 99;
uint8_t _mainSegment; uint8_t _mainSegment;
void void

View File

@ -93,13 +93,17 @@ Segment::Segment(Segment &&orig) noexcept {
memcpy(this, &orig, sizeof(Segment)); memcpy(this, &orig, sizeof(Segment));
orig.name = nullptr; orig.name = nullptr;
orig.data = nullptr; orig.data = nullptr;
orig._dataLen = 0;
//orig._t = nullptr; //orig._t = nullptr;
} }
Segment& Segment::operator= (const Segment &orig) { Segment& Segment::operator= (const Segment &orig) {
DEBUG_PRINTLN(F("-- Segment copied --")); DEBUG_PRINTLN(F("-- Segment copied --"));
if (this != &orig) { if (this != &orig) {
if (name) delete[] name; if (name) {
DEBUG_PRINTF(" Copy Deleting %s (%p)\n", name, name);
delete[] name;
}
//if (_t) delete _t; //if (_t) delete _t;
deallocateData(); deallocateData();
memcpy(this, &orig, sizeof(Segment)); memcpy(this, &orig, sizeof(Segment));
@ -110,8 +114,8 @@ Segment& Segment::operator= (const Segment &orig) {
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
if (orig.data) { allocateData(orig._dataLen); memcpy(data, orig.data, orig._dataLen); } if (orig.data) { allocateData(orig._dataLen); memcpy(data, orig.data, orig._dataLen); }
//if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); } //if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
DEBUG_PRINTF(" Copied data: %p (%d)\n", orig.data, (int)orig._dataLen); DEBUG_PRINTF(" Original data: %p (%d)\n", orig.data, (int)orig._dataLen);
DEBUG_PRINTF(" New data: %p (%d)\n", data, (int)_dataLen); DEBUG_PRINTF(" Copied data: %p (%d)\n", data, (int)_dataLen);
} }
return *this; return *this;
} }
@ -119,12 +123,16 @@ Segment& Segment::operator= (const Segment &orig) {
Segment& Segment::operator= (Segment &&orig) noexcept { Segment& Segment::operator= (Segment &&orig) noexcept {
DEBUG_PRINTLN(F("-- Moving segment --")); DEBUG_PRINTLN(F("-- Moving segment --"));
if (this != &orig) { if (this != &orig) {
if (name) delete[] name; // free old name if (name) {
DEBUG_PRINTF(" Move Deleting %s (%p)\n", name, name);
delete[] name; // free old name
}
//if (_t) delete _t; //if (_t) delete _t;
deallocateData(); // free old runtime data deallocateData(); // free old runtime data
memcpy(this, &orig, sizeof(Segment)); memcpy(this, &orig, sizeof(Segment));
orig.name = nullptr; orig.name = nullptr;
orig.data = nullptr; orig.data = nullptr;
orig._dataLen = 0;
//orig._t = nullptr; //orig._t = nullptr;
} }
return *this; return *this;
@ -132,8 +140,8 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
bool Segment::allocateData(uint16_t len) { bool Segment::allocateData(uint16_t len) {
if (data && _dataLen == len) return true; //already allocated if (data && _dataLen == len) return true; //already allocated
DEBUG_PRINTF("-- Allocating data (size:%d) --\n", len);
deallocateData(); deallocateData();
// TODO: move out to WS2812FX class: for (seg : _segments) sum += seg.dataSize();
if (strip.getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory if (strip.getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
// if possible use SPI RAM on ESP32 // if possible use SPI RAM on ESP32
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
@ -143,19 +151,23 @@ bool Segment::allocateData(uint16_t len) {
#endif #endif
data = (byte*) malloc(len); data = (byte*) malloc(len);
if (!data) return false; //allocation failed if (!data) return false; //allocation failed
strip.addUsedSegmentData(len); strip.addUsedSegmentData(len); // TODO: move out to WS2812FX class: for (seg : _segments) sum += seg.dataSize();
_dataLen = len; _dataLen = len;
memset(data, 0, len); memset(data, 0, len);
DEBUG_PRINTF("-- Allocated data %p (%d)\n", data, (int)len);
return true; return true;
} }
void Segment::deallocateData() { void Segment::deallocateData() {
// NOTE: deallocating data sometimes produces corrupt heap.
if (!data) return; if (!data) return;
DEBUG_PRINTF("-- Deallocating data: %p (%d) --\n", data, (int)_dataLen); DEBUG_PRINTF("-- Deallocating data: %p (%d)\n", data, (int)_dataLen);
free(data); free(data);
DEBUG_PRINTLN(F("-- Data freed."));
data = nullptr; data = nullptr;
strip.addUsedSegmentData(-(int16_t)_dataLen); strip.addUsedSegmentData(-(int16_t)_dataLen); // TODO: move out to WS2812FX class: for (seg : _segments) sum -= seg.dataSize();
_dataLen = 0; _dataLen = 0;
DEBUG_PRINTLN(F("-- Dealocated data."));
} }
/** /**
@ -168,7 +180,6 @@ void Segment::deallocateData() {
void Segment::resetIfRequired() { void Segment::resetIfRequired() {
if (reset) { // (getOption(SEG_OPTION_RESET)) if (reset) { // (getOption(SEG_OPTION_RESET))
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
deallocateData();
reset = false; // setOption(SEG_OPTION_RESET, false); reset = false; // setOption(SEG_OPTION_RESET, false);
} }
} }
@ -653,12 +664,12 @@ void WS2812FX::service() {
if (nowUp - _lastShow < MIN_SHOW_DELAY) return; if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
bool doShow = false; bool doShow = false;
_isServicing = true;
_segment_index = 0; _segment_index = 0;
for (segment &seg : _segments) { for (segment &seg : _segments) {
// for (int i = 0; i < getMaxSegments(); i++) { // for (int i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i); // Segment &seg = getSegment(i);
// reset the segment runtime data if needed, called before isActive to ensure deleted // reset the segment runtime data if needed
// segment's buffers are cleared
seg.resetIfRequired(); seg.resetIfRequired();
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
@ -700,6 +711,7 @@ void WS2812FX::service() {
show(); show();
} }
_triggered = false; _triggered = false;
_isServicing = false;
} }
void WS2812FX::setPixelColor(int i, uint32_t col) void WS2812FX::setPixelColor(int i, uint32_t col)
@ -987,13 +999,14 @@ uint8_t WS2812FX::getLastActiveSegmentId(void) {
return _segments.size()-1; return _segments.size()-1;
} }
//uint8_t WS2812FX::getActiveSegmentsNum(void) { uint8_t WS2812FX::getActiveSegmentsNum(void) {
// uint8_t c = 0; uint8_t c = 0;
// for (uint8_t i = 0; i < getMaxSegments(); i++) { // for (uint8_t i = 0; i < getMaxSegments(); i++) {
// if (_segments[i].isActive()) c++; for (int i = 0; i < _segments.size(); i++) {
// } if (_segments[i].isActive()) c++;
// return c; }
//} return c;
}
uint16_t WS2812FX::getLengthPhysical(void) { uint16_t WS2812FX::getLengthPhysical(void) {
uint16_t len = 0; uint16_t len = 0;
@ -1037,17 +1050,26 @@ bool WS2812FX::hasCCTBus(void) {
} }
void WS2812FX::purgeSegments(void) { void WS2812FX::purgeSegments(void) {
// remove inactive segments at the back
//while (_segments.back().stop == 0 && _segments.size() > 1) _segments.pop_back();
// remove all inactive segments (from the back) // remove all inactive segments (from the back)
int deleted = 0; int deleted = 0;
for (int i = _segments.size()-1; i > 0; i--) if (_segments[i].stop == 0) { DEBUG_PRINT(F(" Removing segment: ")); DEBUG_PRINTLN(i); deleted++; _segments.erase(_segments.begin() + i); } if (_segments.size() <= 1 || _isServicing) return;
for (int i = _segments.size()-1; i > 0; i--)
if (_segments[i].stop == 0) {
DEBUG_PRINT(F("-- Removing segment: ")); DEBUG_PRINTLN(i);
deleted++;
_segments.erase(_segments.begin() + i);
}
if (deleted) { if (deleted) {
_segments.shrink_to_fit(); _segments.shrink_to_fit();
if (_mainSegment >= _segments.size()) setMainSegmentId(0); if (_mainSegment >= _segments.size()) setMainSegmentId(0);
} }
} }
Segment& WS2812FX::getSegment(uint8_t id) {
// return _segments[id >= getMaxSegments() ? getMainSegmentId() : id];
return _segments[id >= _segments.size() ? getMainSegmentId() : id]; // vectors
}
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset, uint16_t startY, uint16_t stopY) { void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset, uint16_t startY, uint16_t stopY) {
if (n >= _segments.size()) return; if (n >= _segments.size()) return;
// if (n >= getMaxSegments()) return; // if (n >= getMaxSegments()) return;
@ -1067,12 +1089,12 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
if (i2 <= i1) //disable segment if (i2 <= i1) //disable segment
{ {
// disabled segments should get removed using purgeSegments() // disabled segments should get removed using purgeSegments()
DEBUG_PRINTLN(F(" Segment marked inactive.")); DEBUG_PRINT(F("-- Segment ")); DEBUG_PRINT(n); DEBUG_PRINTLN(F(" marked inactive."));
seg.stop = 0; seg.stop = 0;
if (seg.name) { //if (seg.name) {
delete[] seg.name; // delete[] seg.name;
seg.name = nullptr; // seg.name = nullptr;
} //}
// if main segment is deleted, set first active as main segment // if main segment is deleted, set first active as main segment
if (n == _mainSegment) setMainSegmentId(0); if (n == _mainSegment) setMainSegmentId(0);
seg.markForReset(); seg.markForReset();
@ -1216,9 +1238,8 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
void WS2812FX::fixInvalidSegments() { void WS2812FX::fixInvalidSegments() {
//make sure no segment is longer than total (sanity check) //make sure no segment is longer than total (sanity check)
size_t i = 0; for (int i = _segments.size()-1; i > 0; i--) {
for (std::vector<Segment>::iterator it = _segments.begin(); it != _segments.end(); i++, it++) { if (_segments[i].start >= _length) { _segments.erase(_segments.begin()+i); continue; }
if (_segments[i].start >= _length) { _segments.erase(it); i--; it--; continue; }
if (_segments[i].stop > _length) _segments[i].stop = _length; if (_segments[i].stop > _length) _segments[i].stop = _length;
// this is always called as the last step after finalizeInit(), update covered bus types // this is always called as the last step after finalizeInit(), update covered bus types
_segments[i].refreshLightCapabilities(); _segments[i].refreshLightCapabilities();

View File

@ -1179,7 +1179,8 @@ function makeWS() {
function readState(s,command=false) function readState(s,command=false)
{ {
if (!s) return false; if (!s || s.error) return false;
if (s.success) return true; // no data to process
isOn = s.on; isOn = s.on;
gId('sliderBri').value = s.bri; gId('sliderBri').value = s.bri;
@ -1224,7 +1225,7 @@ function readState(s,command=false)
if (!i) { if (!i) {
showToast('No Segments!', true); showToast('No Segments!', true);
updateUI(); updateUI();
return; return true;
} }
var cd = gId('csl').children; var cd = gId('csl').children;
@ -1271,6 +1272,7 @@ function readState(s,command=false)
selectedFx = i.fx; selectedFx = i.fx;
redrawPalPrev(); // if any color changed (random palette did at least) redrawPalPrev(); // if any color changed (random palette did at least)
updateUI(); updateUI();
return true;
} }
// WLEDSR: control HTML elements for Slider and Color Control // WLEDSR: control HTML elements for Slider and Color Control

File diff suppressed because it is too large Load Diff

View File

@ -89,7 +89,7 @@ byte relativeChange(byte property, int8_t amount, byte lowerBoundary, byte highe
void changeEffect(uint8_t fx) void changeEffect(uint8_t fx)
{ {
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
strip.setMode(i, fx); strip.setMode(i, fx);
@ -105,7 +105,7 @@ void changeEffect(uint8_t fx)
void changePalette(uint8_t pal) void changePalette(uint8_t pal)
{ {
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.palette = pal; seg.palette = pal;
@ -124,7 +124,7 @@ void changeEffectSpeed(int8_t amount)
int16_t new_val = (int16_t) effectSpeed + amount; int16_t new_val = (int16_t) effectSpeed + amount;
effectSpeed = (byte)constrain(new_val,0,255); effectSpeed = (byte)constrain(new_val,0,255);
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.speed = effectSpeed; seg.speed = effectSpeed;
@ -147,7 +147,7 @@ void changeEffectSpeed(int8_t amount)
prim_hsv.h = (byte)new_val; prim_hsv.h = (byte)new_val;
hsv2rgb_rainbow(prim_hsv, fastled_col); hsv2rgb_rainbow(prim_hsv, fastled_col);
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0])); seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
@ -171,7 +171,7 @@ void changeEffectIntensity(int8_t amount)
int16_t new_val = (int16_t) effectIntensity + amount; int16_t new_val = (int16_t) effectIntensity + amount;
effectIntensity = (byte)constrain(new_val,0,255); effectIntensity = (byte)constrain(new_val,0,255);
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.intensity = effectIntensity; seg.intensity = effectIntensity;
@ -192,7 +192,7 @@ void changeEffectIntensity(int8_t amount)
prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255 prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255
hsv2rgb_rainbow(prim_hsv, fastled_col); hsv2rgb_rainbow(prim_hsv, fastled_col);
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0])); seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
@ -214,7 +214,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
{ {
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
// main segment may not be selected! // main segment may not be selected!
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
byte capabilities = seg.getLightCapabilities(); byte capabilities = seg.getLightCapabilities();

View File

@ -14,11 +14,10 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
int stop = elem["stop"] | -1; int stop = elem["stop"] | -1;
// if using vectors use this code to append segment // if using vectors use this code to append segment
if (id >= strip.getActiveSegmentsNum()) { if (id >= strip.getSegmentsNum()) {
if (stop <= 0) return; // ignore empty/inactive segments if (stop <= 0) return; // ignore empty/inactive segments
DEBUG_PRINT(F("Adding segment: ")); DEBUG_PRINTLN(id);
strip.appendSegment(Segment(0, strip.getLengthTotal())); strip.appendSegment(Segment(0, strip.getLengthTotal()));
id = strip.getActiveSegmentsNum()-1; // segments are added at the end of list id = strip.getSegmentsNum()-1; // segments are added at the end of list
} }
Segment& seg = strip.getSegment(id); Segment& seg = strip.getSegment(id);
@ -258,7 +257,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff(); if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
if (bri && !onBefore) { // unfreeze all segments when turning on if (bri && !onBefore) { // unfreeze all segments when turning on
for (uint8_t s=0; s < strip.getActiveSegmentsNum(); s++) { for (uint8_t s=0; s < strip.getSegmentsNum(); s++) {
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false); strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false);
} }
if (realtimeMode && !realtimeOverride && useMainSegmentOnly) { // keep live segment frozen if live if (realtimeMode && !realtimeOverride && useMainSegmentOnly) { // keep live segment frozen if live
@ -336,7 +335,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (id < 0) { if (id < 0) {
//apply all selected segments //apply all selected segments
//bool didSet = false; //bool didSet = false;
for (byte s = 0; s < strip.getActiveSegmentsNum(); s++) { for (byte s = 0; s < strip.getSegmentsNum(); s++) {
Segment &sg = strip.getSegment(s); Segment &sg = strip.getSegment(s);
if (sg.isSelected()) { if (sg.isSelected()) {
deserializeSegment(segVar, s, presetId); deserializeSegment(segVar, s, presetId);
@ -350,14 +349,10 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
} }
} else { } else {
JsonArray segs = segVar.as<JsonArray>(); JsonArray segs = segVar.as<JsonArray>();
for (JsonObject elem : segs) for (JsonObject elem : segs) {
{
DEBUG_PRINT(F(" Deserializing segment: ")); DEBUG_PRINTLN(it);
deserializeSegment(elem, it, presetId); deserializeSegment(elem, it, presetId);
it++; it++;
} }
// DEBUG_PRINTLN(F(" Purging segments."));
// strip.purgeSegments(); // prune inactive segments (resets ESP if effect running)
} }
usermods.readFromJsonState(root); usermods.readFromJsonState(root);
@ -505,7 +500,7 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
bool selectedSegmentsOnly = root[F("sc")] | false; bool selectedSegmentsOnly = root[F("sc")] | false;
JsonArray seg = root.createNestedArray("seg"); JsonArray seg = root.createNestedArray("seg");
for (byte s = 0; s < strip.getMaxSegments(); s++) { for (byte s = 0; s < strip.getMaxSegments(); s++) {
if (s >= strip.getActiveSegmentsNum()) { if (s >= strip.getSegmentsNum()) {
if (forPreset && segmentBounds) { //disable segments not part of preset if (forPreset && segmentBounds) { //disable segments not part of preset
JsonObject seg0 = seg.createNestedObject(); JsonObject seg0 = seg.createNestedObject();
seg0["stop"] = 0; seg0["stop"] = 0;
@ -537,7 +532,7 @@ void serializeInfo(JsonObject root)
leds["fps"] = strip.getFps(); leds["fps"] = strip.getFps();
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
leds[F("maxseg")] = strip.getMaxSegments(); leds[F("maxseg")] = strip.getMaxSegments();
leds[F("actseg")] = strip.getActiveSegmentsNum(); //leds[F("actseg")] = strip.getActiveSegmentsNum();
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config //leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D

View File

@ -31,7 +31,7 @@ void applyValuesToSelectedSegs()
// copy of first selected segment to tell if value was updated // copy of first selected segment to tell if value was updated
uint8_t firstSel = strip.getFirstSelectedSegId(); uint8_t firstSel = strip.getFirstSelectedSegId();
Segment selsegPrev = strip.getSegment(firstSel); Segment selsegPrev = strip.getSegment(firstSel);
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue; if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;

View File

@ -608,7 +608,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("SS=")); pos = req.indexOf(F("SS="));
if (pos > 0) { if (pos > 0) {
byte t = getNumVal(&req, pos); byte t = getNumVal(&req, pos);
if (t < strip.getActiveSegmentsNum()) { if (t < strip.getSegmentsNum()) {
selectedSeg = t; selectedSeg = t;
singleSegment = true; singleSegment = true;
} }
@ -618,7 +618,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("SV=")); //segment selected pos = req.indexOf(F("SV=")); //segment selected
if (pos > 0) { if (pos > 0) {
byte t = getNumVal(&req, pos); byte t = getNumVal(&req, pos);
if (t == 2) for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments if (t == 2) for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments
selseg.setOption(SEG_OPTION_SELECTED, t); selseg.setOption(SEG_OPTION_SELECTED, t);
} }
@ -824,7 +824,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged); stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged);
// apply to main and all selected segments to prevent #1618. // apply to main and all selected segments to prevent #1618.
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
if (fxModeChanged) strip.setMode(i, effectIn); if (fxModeChanged) strip.setMode(i, effectIn);

View File

@ -91,10 +91,12 @@ void notify(byte callMode, bool followUp)
udpOut[39] = strip.getActiveSegmentsNum(); udpOut[39] = strip.getActiveSegmentsNum();
udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment) udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment)
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { int s = 0;
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment &selseg = strip.getSegment(i); Segment &selseg = strip.getSegment(i);
uint16_t ofs = 41 + i*UDP_SEG_SIZE; //start of segment offset byte if (!selseg.isActive()) continue;
udpOut[0 +ofs] = i; uint16_t ofs = 41 + s*UDP_SEG_SIZE; //start of segment offset byte
udpOut[0 +ofs] = s;
udpOut[1 +ofs] = selseg.start >> 8; udpOut[1 +ofs] = selseg.start >> 8;
udpOut[2 +ofs] = selseg.start & 0xFF; udpOut[2 +ofs] = selseg.start & 0xFF;
udpOut[3 +ofs] = selseg.stop >> 8; udpOut[3 +ofs] = selseg.stop >> 8;
@ -122,6 +124,7 @@ void notify(byte callMode, bool followUp)
udpOut[25+ofs] = B(selseg.colors[2]); udpOut[25+ofs] = B(selseg.colors[2]);
udpOut[26+ofs] = W(selseg.colors[2]); udpOut[26+ofs] = W(selseg.colors[2]);
udpOut[27+ofs] = selseg.cct; udpOut[27+ofs] = selseg.cct;
++s;
} }
//uint16_t offs = SEG_OFFSET; //uint16_t offs = SEG_OFFSET;
@ -155,7 +158,7 @@ void realtimeLock(uint32_t timeoutMs, byte md)
for (uint16_t i = start; i < stop; i++) strip.setPixelColor(i,0,0,0,0); for (uint16_t i = start; i < stop; i++) strip.setPixelColor(i,0,0,0,0);
// if WLED was off and using main segment only, freeze non-main segments so they stay off // if WLED was off and using main segment only, freeze non-main segments so they stay off
if (useMainSegmentOnly && bri == 0) { if (useMainSegmentOnly && bri == 0) {
for (uint8_t s=0; s < strip.getActiveSegmentsNum(); s++) { for (uint8_t s=0; s < strip.getSegmentsNum(); s++) {
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true); strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true);
} }
} }
@ -342,7 +345,7 @@ void handleNotifications()
for (uint8_t i = 0; i < numSrcSegs; i++) { for (uint8_t i = 0; i < numSrcSegs; i++) {
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
uint8_t id = udpIn[0 +ofs]; uint8_t id = udpIn[0 +ofs];
if (id > strip.getActiveSegmentsNum()) break; if (id > strip.getSegmentsNum()) break;
Segment& selseg = strip.getSegment(id); Segment& selseg = strip.getSegment(id);
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]); uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]);
uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]); uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]);
@ -377,7 +380,7 @@ void handleNotifications()
// simple effect sync, applies to all selected segments // simple effect sync, applies to all selected segments
if (applyEffects && (version < 11 || !receiveSegmentOptions)) { if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) { for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]); if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);

View File

@ -118,7 +118,6 @@ void WLED::loop()
if (stripMillis > maxStripMillis) maxStripMillis = stripMillis; if (stripMillis > maxStripMillis) maxStripMillis = stripMillis;
#endif #endif
} }
if (offMode) strip.purgeSegments(); // remove inactive segments from memory (no effects running)
yield(); yield();
#ifdef ESP8266 #ifdef ESP8266
@ -694,6 +693,7 @@ void WLED::handleConnection()
DEBUG_PRINT(F("Heap too low! ")); DEBUG_PRINT(F("Heap too low! "));
DEBUG_PRINTLN(heap); DEBUG_PRINTLN(heap);
forceReconnect = true; forceReconnect = true;
strip.purgeSegments(); // remove inactive segments from memory
} }
lastHeap = heap; lastHeap = heap;
heapTime = now; heapTime = now;

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2207171 #define VERSION 2207191
//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

View File

@ -58,6 +58,10 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
if (verboseResponse) { if (verboseResponse) {
sendDataWs(client); sendDataWs(client);
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500); lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
} else {
// we have to send something back otherwise WS connection closes
client->text(F("{\"success\":true}"));
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
} }
} }
} else { } else {