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;
uint16_t customMappingSize = 0;
uint32_t _lastPaletteChange = 0; uint32_t _lastPaletteChange;
uint32_t _lastShow = 0; uint32_t _lastShow;
bool _no_rgb = false;
uint8_t _segment_index = 0; uint8_t _segment_index;
uint8_t _segment_index_palette_last = 99; uint8_t _segment_index_palette_last;
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

@ -1,406 +1,406 @@
#ifndef WLED_CONST_H #ifndef WLED_CONST_H
#define WLED_CONST_H #define WLED_CONST_H
/* /*
* Readability defines and their associated numerical values + compile-time constants * Readability defines and their associated numerical values + compile-time constants
*/ */
#define GRADIENT_PALETTE_COUNT 58 #define GRADIENT_PALETTE_COUNT 58
//Defaults //Defaults
#define DEFAULT_CLIENT_SSID "Your_Network" #define DEFAULT_CLIENT_SSID "Your_Network"
#define DEFAULT_AP_PASS "wled1234" #define DEFAULT_AP_PASS "wled1234"
#define DEFAULT_OTA_PASS "wledota" #define DEFAULT_OTA_PASS "wledota"
//increase if you need more //increase if you need more
#ifndef WLED_MAX_USERMODS #ifndef WLED_MAX_USERMODS
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_USERMODS 4 #define WLED_MAX_USERMODS 4
#else #else
#define WLED_MAX_USERMODS 6 #define WLED_MAX_USERMODS 6
#endif #endif
#endif #endif
#ifndef WLED_MAX_BUSSES #ifndef WLED_MAX_BUSSES
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_BUSSES 3 #define WLED_MAX_BUSSES 3
#else #else
#ifdef CONFIG_IDF_TARGET_ESP32S2 #ifdef CONFIG_IDF_TARGET_ESP32S2
#define WLED_MAX_BUSSES 5 #define WLED_MAX_BUSSES 5
#else #else
#define WLED_MAX_BUSSES 10 #define WLED_MAX_BUSSES 10
#endif #endif
#endif #endif
#endif #endif
#ifndef WLED_MAX_BUTTONS #ifndef WLED_MAX_BUTTONS
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_BUTTONS 2 #define WLED_MAX_BUTTONS 2
#else #else
#define WLED_MAX_BUTTONS 4 #define WLED_MAX_BUTTONS 4
#endif #endif
#endif #endif
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_COLOR_ORDER_MAPPINGS 5 #define WLED_MAX_COLOR_ORDER_MAPPINGS 5
#else #else
#define WLED_MAX_COLOR_ORDER_MAPPINGS 10 #define WLED_MAX_COLOR_ORDER_MAPPINGS 10
#endif #endif
//Usermod IDs //Usermod IDs
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present #define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID #define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
#define USERMOD_ID_EXAMPLE 2 //Usermod "usermod_v2_example.h" #define USERMOD_ID_EXAMPLE 2 //Usermod "usermod_v2_example.h"
#define USERMOD_ID_TEMPERATURE 3 //Usermod "usermod_temperature.h" #define USERMOD_ID_TEMPERATURE 3 //Usermod "usermod_temperature.h"
#define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h" #define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h"
#define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h" #define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h"
#define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h" #define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h"
#define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h #define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h
#define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h" #define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h"
#define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h" #define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h"
#define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h" #define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h"
#define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h" #define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h"
#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h" #define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h"
#define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h" #define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h"
#define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h" #define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h"
#define USERMOD_ID_RTC 15 //Usermod "usermod_rtc.h" #define USERMOD_ID_RTC 15 //Usermod "usermod_rtc.h"
#define USERMOD_ID_ELEKSTUBE_IPS 16 //Usermod "usermod_elekstube_ips.h" #define USERMOD_ID_ELEKSTUBE_IPS 16 //Usermod "usermod_elekstube_ips.h"
#define USERMOD_ID_SN_PHOTORESISTOR 17 //Usermod "usermod_sn_photoresistor.h" #define USERMOD_ID_SN_PHOTORESISTOR 17 //Usermod "usermod_sn_photoresistor.h"
#define USERMOD_ID_BATTERY_STATUS_BASIC 18 //Usermod "usermod_v2_battery_status_basic.h" #define USERMOD_ID_BATTERY_STATUS_BASIC 18 //Usermod "usermod_v2_battery_status_basic.h"
#define USERMOD_ID_PWM_FAN 19 //Usermod "usermod_PWM_fan.h" #define USERMOD_ID_PWM_FAN 19 //Usermod "usermod_PWM_fan.h"
#define USERMOD_ID_BH1750 20 //Usermod "usermod_bh1750.h" #define USERMOD_ID_BH1750 20 //Usermod "usermod_bh1750.h"
#define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21 //Usermod "usermod_v2_seven_segment_display.h" #define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21 //Usermod "usermod_v2_seven_segment_display.h"
#define USERMOD_RGB_ROTARY_ENCODER 22 //Usermod "rgb-rotary-encoder.h" #define USERMOD_RGB_ROTARY_ENCODER 22 //Usermod "rgb-rotary-encoder.h"
#define USERMOD_ID_QUINLED_AN_PENTA 23 //Usermod "quinled-an-penta.h" #define USERMOD_ID_QUINLED_AN_PENTA 23 //Usermod "quinled-an-penta.h"
#define USERMOD_ID_SSDR 24 //Usermod "usermod_v2_seven_segment_display_reloaded.h" #define USERMOD_ID_SSDR 24 //Usermod "usermod_v2_seven_segment_display_reloaded.h"
#define USERMOD_ID_CRONIXIE 25 //Usermod "usermod_cronixie.h" #define USERMOD_ID_CRONIXIE 25 //Usermod "usermod_cronixie.h"
#define USERMOD_ID_WIZLIGHTS 26 //Usermod "wizlights.h" #define USERMOD_ID_WIZLIGHTS 26 //Usermod "wizlights.h"
#define USERMOD_ID_WORDCLOCK 27 //Usermod "usermod_v2_word_clock.h" #define USERMOD_ID_WORDCLOCK 27 //Usermod "usermod_v2_word_clock.h"
#define USERMOD_ID_MY9291 28 //Usermod "usermod_MY9291.h" #define USERMOD_ID_MY9291 28 //Usermod "usermod_MY9291.h"
#define USERMOD_ID_SI7021_MQTT_HA 29 //Usermod "usermod_si7021_mqtt_ha.h" #define USERMOD_ID_SI7021_MQTT_HA 29 //Usermod "usermod_si7021_mqtt_ha.h"
#define USERMOD_ID_AUDIOREACTIVE 30 //Usermod "audioreactive.h" #define USERMOD_ID_AUDIOREACTIVE 30 //Usermod "audioreactive.h"
//Access point behavior //Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost) #define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost)
#define AP_BEHAVIOR_ALWAYS 2 //Always open #define AP_BEHAVIOR_ALWAYS 2 //Always open
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec #define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
//Notifier callMode //Notifier callMode
#define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates #define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
#define CALL_MODE_DIRECT_CHANGE 1 #define CALL_MODE_DIRECT_CHANGE 1
#define CALL_MODE_BUTTON 2 //default button actions applied to selected segments #define CALL_MODE_BUTTON 2 //default button actions applied to selected segments
#define CALL_MODE_NOTIFICATION 3 #define CALL_MODE_NOTIFICATION 3
#define CALL_MODE_NIGHTLIGHT 4 #define CALL_MODE_NIGHTLIGHT 4
#define CALL_MODE_NO_NOTIFY 5 #define CALL_MODE_NO_NOTIFY 5
#define CALL_MODE_FX_CHANGED 6 //no longer used #define CALL_MODE_FX_CHANGED 6 //no longer used
#define CALL_MODE_HUE 7 #define CALL_MODE_HUE 7
#define CALL_MODE_PRESET_CYCLE 8 #define CALL_MODE_PRESET_CYCLE 8
#define CALL_MODE_BLYNK 9 #define CALL_MODE_BLYNK 9
#define CALL_MODE_ALEXA 10 #define CALL_MODE_ALEXA 10
#define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only #define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only
#define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro #define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro
//RGB to RGBW conversion mode //RGB to RGBW conversion mode
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider #define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
#define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel #define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel
#define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel #define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel
#define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0) #define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0)
#define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support #define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support
//realtime modes //realtime modes
#define REALTIME_MODE_INACTIVE 0 #define REALTIME_MODE_INACTIVE 0
#define REALTIME_MODE_GENERIC 1 #define REALTIME_MODE_GENERIC 1
#define REALTIME_MODE_UDP 2 #define REALTIME_MODE_UDP 2
#define REALTIME_MODE_HYPERION 3 #define REALTIME_MODE_HYPERION 3
#define REALTIME_MODE_E131 4 #define REALTIME_MODE_E131 4
#define REALTIME_MODE_ADALIGHT 5 #define REALTIME_MODE_ADALIGHT 5
#define REALTIME_MODE_ARTNET 6 #define REALTIME_MODE_ARTNET 6
#define REALTIME_MODE_TPM2NET 7 #define REALTIME_MODE_TPM2NET 7
#define REALTIME_MODE_DDP 8 #define REALTIME_MODE_DDP 8
//realtime override modes //realtime override modes
#define REALTIME_OVERRIDE_NONE 0 #define REALTIME_OVERRIDE_NONE 0
#define REALTIME_OVERRIDE_ONCE 1 #define REALTIME_OVERRIDE_ONCE 1
#define REALTIME_OVERRIDE_ALWAYS 2 #define REALTIME_OVERRIDE_ALWAYS 2
//E1.31 DMX modes //E1.31 DMX modes
#define DMX_MODE_DISABLED 0 //not used #define DMX_MODE_DISABLED 0 //not used
#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels) #define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels)
#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels) #define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels)
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels) #define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels)
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels) #define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels)
#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels) #define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels)
#define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels) #define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels)
//Light capability byte (unused) 0bRCCCTTTT //Light capability byte (unused) 0bRCCCTTTT
//bits 0/1/2/3: specifies a type of LED driver. A single "driver" may have different chip models but must have the same protocol/behavior //bits 0/1/2/3: specifies a type of LED driver. A single "driver" may have different chip models but must have the same protocol/behavior
//bits 4/5/6: specifies the class of LED driver - 0b000 (dec. 0-15) unconfigured/reserved //bits 4/5/6: specifies the class of LED driver - 0b000 (dec. 0-15) unconfigured/reserved
// - 0b001 (dec. 16-31) digital (data pin only) // - 0b001 (dec. 16-31) digital (data pin only)
// - 0b010 (dec. 32-47) analog (PWM) // - 0b010 (dec. 32-47) analog (PWM)
// - 0b011 (dec. 48-63) digital (data + clock / SPI) // - 0b011 (dec. 48-63) digital (data + clock / SPI)
// - 0b100 (dec. 64-79) unused/reserved // - 0b100 (dec. 64-79) unused/reserved
// - 0b101 (dec. 80-95) virtual network busses // - 0b101 (dec. 80-95) virtual network busses
// - 0b110 (dec. 96-111) unused/reserved // - 0b110 (dec. 96-111) unused/reserved
// - 0b111 (dec. 112-127) unused/reserved // - 0b111 (dec. 112-127) unused/reserved
//bit 7 is reserved and set to 0 //bit 7 is reserved and set to 0
#define TYPE_NONE 0 //light is not configured #define TYPE_NONE 0 //light is not configured
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light #define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
//Digital types (data pin only) (16-31) //Digital types (data pin only) (16-31)
#define TYPE_WS2812_1CH 20 //white-only chips #define TYPE_WS2812_1CH 20 //white-only chips
#define TYPE_WS2812_WWA 21 //amber + warm + cold white #define TYPE_WS2812_WWA 21 //amber + warm + cold white
#define TYPE_WS2812_RGB 22 #define TYPE_WS2812_RGB 22
#define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern) #define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern)
#define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units #define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units
#define TYPE_SK6812_RGBW 30 #define TYPE_SK6812_RGBW 30
#define TYPE_TM1814 31 #define TYPE_TM1814 31
//"Analog" types (PWM) (32-47) //"Analog" types (PWM) (32-47)
#define TYPE_ONOFF 40 //binary output (relays etc.) #define TYPE_ONOFF 40 //binary output (relays etc.)
#define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel #define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel
#define TYPE_ANALOG_2CH 42 //analog WW + CW #define TYPE_ANALOG_2CH 42 //analog WW + CW
#define TYPE_ANALOG_3CH 43 //analog RGB #define TYPE_ANALOG_3CH 43 //analog RGB
#define TYPE_ANALOG_4CH 44 //analog RGBW #define TYPE_ANALOG_4CH 44 //analog RGBW
#define TYPE_ANALOG_5CH 45 //analog RGB + WW + CW #define TYPE_ANALOG_5CH 45 //analog RGB + WW + CW
//Digital types (data + clock / SPI) (48-63) //Digital types (data + clock / SPI) (48-63)
#define TYPE_WS2801 50 #define TYPE_WS2801 50
#define TYPE_APA102 51 #define TYPE_APA102 51
#define TYPE_LPD8806 52 #define TYPE_LPD8806 52
#define TYPE_P9813 53 #define TYPE_P9813 53
//Network types (master broadcast) (80-95) //Network types (master broadcast) (80-95)
#define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus) #define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus)
#define TYPE_NET_E131_RGB 81 //network E131 RGB bus (master broadcast bus) #define TYPE_NET_E131_RGB 81 //network E131 RGB bus (master broadcast bus)
#define TYPE_NET_ARTNET_RGB 82 //network ArtNet RGB bus (master broadcast bus) #define TYPE_NET_ARTNET_RGB 82 //network ArtNet RGB bus (master broadcast bus)
#define IS_DIGITAL(t) ((t) & 0x10) //digital are 16-31 and 48-63 #define IS_DIGITAL(t) ((t) & 0x10) //digital are 16-31 and 48-63
#define IS_PWM(t) ((t) > 40 && (t) < 46) #define IS_PWM(t) ((t) > 40 && (t) < 46)
#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only #define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only
#define IS_2PIN(t) ((t) > 47) #define IS_2PIN(t) ((t) > 47)
//Color orders //Color orders
#define COL_ORDER_GRB 0 //GRB(w),defaut #define COL_ORDER_GRB 0 //GRB(w),defaut
#define COL_ORDER_RGB 1 //common for WS2811 #define COL_ORDER_RGB 1 //common for WS2811
#define COL_ORDER_BRG 2 #define COL_ORDER_BRG 2
#define COL_ORDER_RBG 3 #define COL_ORDER_RBG 3
#define COL_ORDER_BGR 4 #define COL_ORDER_BGR 4
#define COL_ORDER_GBR 5 #define COL_ORDER_GBR 5
#define COL_ORDER_MAX 5 #define COL_ORDER_MAX 5
//Button type //Button type
#define BTN_TYPE_NONE 0 #define BTN_TYPE_NONE 0
#define BTN_TYPE_RESERVED 1 #define BTN_TYPE_RESERVED 1
#define BTN_TYPE_PUSH 2 #define BTN_TYPE_PUSH 2
#define BTN_TYPE_PUSH_ACT_HIGH 3 #define BTN_TYPE_PUSH_ACT_HIGH 3
#define BTN_TYPE_SWITCH 4 #define BTN_TYPE_SWITCH 4
#define BTN_TYPE_PIR_SENSOR 5 #define BTN_TYPE_PIR_SENSOR 5
#define BTN_TYPE_TOUCH 6 #define BTN_TYPE_TOUCH 6
#define BTN_TYPE_ANALOG 7 #define BTN_TYPE_ANALOG 7
#define BTN_TYPE_ANALOG_INVERTED 8 #define BTN_TYPE_ANALOG_INVERTED 8
//Ethernet board types //Ethernet board types
#define WLED_NUM_ETH_TYPES 8 #define WLED_NUM_ETH_TYPES 8
#define WLED_ETH_NONE 0 #define WLED_ETH_NONE 0
#define WLED_ETH_WT32_ETH01 1 #define WLED_ETH_WT32_ETH01 1
#define WLED_ETH_ESP32_POE 2 #define WLED_ETH_ESP32_POE 2
#define WLED_ETH_WESP32 3 #define WLED_ETH_WESP32 3
#define WLED_ETH_QUINLED 4 #define WLED_ETH_QUINLED 4
#define WLED_ETH_TWILIGHTLORD 5 #define WLED_ETH_TWILIGHTLORD 5
#define WLED_ETH_ESP32DEUX 6 #define WLED_ETH_ESP32DEUX 6
//Hue error codes //Hue error codes
#define HUE_ERROR_INACTIVE 0 #define HUE_ERROR_INACTIVE 0
#define HUE_ERROR_UNAUTHORIZED 1 #define HUE_ERROR_UNAUTHORIZED 1
#define HUE_ERROR_LIGHTID 3 #define HUE_ERROR_LIGHTID 3
#define HUE_ERROR_PUSHLINK 101 #define HUE_ERROR_PUSHLINK 101
#define HUE_ERROR_JSON_PARSING 250 #define HUE_ERROR_JSON_PARSING 250
#define HUE_ERROR_TIMEOUT 251 #define HUE_ERROR_TIMEOUT 251
#define HUE_ERROR_ACTIVE 255 #define HUE_ERROR_ACTIVE 255
//Segment option byte bits //Segment option byte bits
#define SEG_OPTION_SELECTED 0 #define SEG_OPTION_SELECTED 0
#define SEG_OPTION_REVERSED 1 #define SEG_OPTION_REVERSED 1
#define SEG_OPTION_ON 2 #define SEG_OPTION_ON 2
#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment #define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment
#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor #define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed #define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
#define SEG_OPTION_RESET 6 //Segment runtime requires reset #define SEG_OPTION_RESET 6 //Segment runtime requires reset
#define SEG_OPTION_TRANSITIONAL 7 #define SEG_OPTION_TRANSITIONAL 7
#define SEG_OPTION_REVERSED_Y 8 #define SEG_OPTION_REVERSED_Y 8
#define SEG_OPTION_MIRROR_Y 9 #define SEG_OPTION_MIRROR_Y 9
#define SEG_OPTION_TRANSPOSED 10 #define SEG_OPTION_TRANSPOSED 10
//Segment differs return byte //Segment differs return byte
#define SEG_DIFFERS_BRI 0x01 #define SEG_DIFFERS_BRI 0x01
#define SEG_DIFFERS_OPT 0x02 #define SEG_DIFFERS_OPT 0x02
#define SEG_DIFFERS_COL 0x04 #define SEG_DIFFERS_COL 0x04
#define SEG_DIFFERS_FX 0x08 #define SEG_DIFFERS_FX 0x08
#define SEG_DIFFERS_BOUNDS 0x10 #define SEG_DIFFERS_BOUNDS 0x10
#define SEG_DIFFERS_GSO 0x20 #define SEG_DIFFERS_GSO 0x20
#define SEG_DIFFERS_SEL 0x80 #define SEG_DIFFERS_SEL 0x80
//Playlist option byte //Playlist option byte
#define PL_OPTION_SHUFFLE 0x01 #define PL_OPTION_SHUFFLE 0x01
// WLED Error modes // WLED Error modes
#define ERR_NONE 0 // All good :) #define ERR_NONE 0 // All good :)
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?) #define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
#define ERR_JSON 9 // JSON parsing failed (input too large?) #define ERR_JSON 9 // JSON parsing failed (input too large?)
#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?) #define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?)
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached #define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached
#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist #define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist
#define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist #define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured #define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented) #define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented) #define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented) #define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented)
//Timer mode types //Timer mode types
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness #define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
#define NL_MODE_FADE 1 //Fade to target brightness gradually #define NL_MODE_FADE 1 //Fade to target brightness gradually
#define NL_MODE_COLORFADE 2 //Fade to target brightness and secondary color gradually #define NL_MODE_COLORFADE 2 //Fade to target brightness and secondary color gradually
#define NL_MODE_SUN 3 //Sunrise/sunset. Target brightness is set immediately, then Sunrise effect is started. Max 60 min. #define NL_MODE_SUN 3 //Sunrise/sunset. Target brightness is set immediately, then Sunrise effect is started. Max 60 min.
#define NTP_PACKET_SIZE 48 #define NTP_PACKET_SIZE 48
//maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses //maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses
#ifndef MAX_LEDS #ifndef MAX_LEDS
#ifdef ESP8266 #ifdef ESP8266
#define MAX_LEDS 1664 //can't rely on memory limit to limit this to 1600 LEDs #define MAX_LEDS 1664 //can't rely on memory limit to limit this to 1600 LEDs
#else #else
#define MAX_LEDS 8192 #define MAX_LEDS 8192
#endif #endif
#endif #endif
#ifndef MAX_LED_MEMORY #ifndef MAX_LED_MEMORY
#ifdef ESP8266 #ifdef ESP8266
#define MAX_LED_MEMORY 4000 #define MAX_LED_MEMORY 4000
#else #else
#define MAX_LED_MEMORY 64000 #define MAX_LED_MEMORY 64000
#endif #endif
#endif #endif
#ifndef MAX_LEDS_PER_BUS #ifndef MAX_LEDS_PER_BUS
#define MAX_LEDS_PER_BUS 2048 // may not be enough for fast LEDs (i.e. APA102) #define MAX_LEDS_PER_BUS 2048 // may not be enough for fast LEDs (i.e. APA102)
#endif #endif
// string temp buffer (now stored in stack locally) // string temp buffer (now stored in stack locally)
#ifdef ESP8266 #ifdef ESP8266
#define SETTINGS_STACK_BUF_SIZE 2048 #define SETTINGS_STACK_BUF_SIZE 2048
#else #else
#define SETTINGS_STACK_BUF_SIZE 3096 #define SETTINGS_STACK_BUF_SIZE 3096
#endif #endif
#ifdef WLED_USE_ETHERNET #ifdef WLED_USE_ETHERNET
#define E131_MAX_UNIVERSE_COUNT 20 #define E131_MAX_UNIVERSE_COUNT 20
#else #else
#ifdef ESP8266 #ifdef ESP8266
#define E131_MAX_UNIVERSE_COUNT 9 #define E131_MAX_UNIVERSE_COUNT 9
#else #else
#define E131_MAX_UNIVERSE_COUNT 12 #define E131_MAX_UNIVERSE_COUNT 12
#endif #endif
#endif #endif
#ifndef ABL_MILLIAMPS_DEFAULT #ifndef ABL_MILLIAMPS_DEFAULT
#define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit #define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit
#else #else
#if ABL_MILLIAMPS_DEFAULT < 250 // make sure value is at least 250 #if ABL_MILLIAMPS_DEFAULT < 250 // make sure value is at least 250
#define ABL_MILLIAMPS_DEFAULT 250 #define ABL_MILLIAMPS_DEFAULT 250
#endif #endif
#endif #endif
// PWM settings // PWM settings
#ifndef WLED_PWM_FREQ #ifndef WLED_PWM_FREQ
#ifdef ESP8266 #ifdef ESP8266
#define WLED_PWM_FREQ 880 //PWM frequency proven as good for LEDs #define WLED_PWM_FREQ 880 //PWM frequency proven as good for LEDs
#else #else
#define WLED_PWM_FREQ 19531 #define WLED_PWM_FREQ 19531
#endif #endif
#endif #endif
#define TOUCH_THRESHOLD 32 // limit to recognize a touch, higher value means more sensitive #define TOUCH_THRESHOLD 32 // limit to recognize a touch, higher value means more sensitive
// Size of buffer for API JSON object (increase for more segments) // Size of buffer for API JSON object (increase for more segments)
#ifdef ESP8266 #ifdef ESP8266
#define JSON_BUFFER_SIZE 10240 #define JSON_BUFFER_SIZE 10240
#else #else
#define JSON_BUFFER_SIZE 24576 #define JSON_BUFFER_SIZE 24576
#endif #endif
#define MIN_HEAP_SIZE (MAX_LED_MEMORY+2048) #define MIN_HEAP_SIZE (MAX_LED_MEMORY+2048)
// Maximum size of node map (list of other WLED instances) // Maximum size of node map (list of other WLED instances)
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_NODES 24 #define WLED_MAX_NODES 24
#else #else
#define WLED_MAX_NODES 150 #define WLED_MAX_NODES 150
#endif #endif
//this is merely a default now and can be changed at runtime //this is merely a default now and can be changed at runtime
#ifndef LEDPIN #ifndef LEDPIN
#if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)) #if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM))
#define LEDPIN 2 // GPIO2 (D4) on Wemod D1 mini compatible boards #define LEDPIN 2 // GPIO2 (D4) on Wemod D1 mini compatible boards
#else #else
#define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards #define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards
#endif #endif
#endif #endif
#ifdef WLED_ENABLE_DMX #ifdef WLED_ENABLE_DMX
#if (LEDPIN == 2) #if (LEDPIN == 2)
#undef LEDPIN #undef LEDPIN
#define LEDPIN 1 #define LEDPIN 1
#warning "Pin conflict compiling with DMX and LEDs on pin 2. The default LED pin has been changed to pin 1." #warning "Pin conflict compiling with DMX and LEDs on pin 2. The default LED pin has been changed to pin 1."
#endif #endif
#endif #endif
#ifndef DEFAULT_LED_COUNT #ifndef DEFAULT_LED_COUNT
#define DEFAULT_LED_COUNT 30 #define DEFAULT_LED_COUNT 30
#endif #endif
#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates #define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates
#if defined(ESP8266) && defined(HW_PIN_SCL) #if defined(ESP8266) && defined(HW_PIN_SCL)
#undef HW_PIN_SCL #undef HW_PIN_SCL
#endif #endif
#if defined(ESP8266) && defined(HW_PIN_SDA) #if defined(ESP8266) && defined(HW_PIN_SDA)
#undef HW_PIN_SDA #undef HW_PIN_SDA
#endif #endif
#ifndef HW_PIN_SCL #ifndef HW_PIN_SCL
#ifdef ESP8266 #ifdef ESP8266
#define HW_PIN_SCL 5 #define HW_PIN_SCL 5
#else #else
#define HW_PIN_SCL 22 #define HW_PIN_SCL 22
#endif #endif
#endif #endif
#ifndef HW_PIN_SDA #ifndef HW_PIN_SDA
#ifdef ESP8266 #ifdef ESP8266
#define HW_PIN_SDA 4 #define HW_PIN_SDA 4
#else #else
#define HW_PIN_SDA 21 #define HW_PIN_SDA 21
#endif #endif
#endif #endif
#if defined(ESP8266) && defined(HW_PIN_CLOCKSPI) #if defined(ESP8266) && defined(HW_PIN_CLOCKSPI)
#undef HW_PIN_CLOCKSPI #undef HW_PIN_CLOCKSPI
#endif #endif
#if defined(ESP8266) && defined(HW_PIN_DATASPI) #if defined(ESP8266) && defined(HW_PIN_DATASPI)
#undef HW_PIN_DATASPI #undef HW_PIN_DATASPI
#endif #endif
#ifndef HW_PIN_CLOCKSPI #ifndef HW_PIN_CLOCKSPI
#ifdef ESP8266 #ifdef ESP8266
#define HW_PIN_CLOCKSPI 14 #define HW_PIN_CLOCKSPI 14
#else #else
#define HW_PIN_CLOCKSPI 18 #define HW_PIN_CLOCKSPI 18
#endif #endif
#endif #endif
#ifndef HW_PIN_DATASPI #ifndef HW_PIN_DATASPI
#ifdef ESP8266 #ifdef ESP8266
#define HW_PIN_DATASPI 13 #define HW_PIN_DATASPI 13
#else #else
#define HW_PIN_DATASPI 23 #define HW_PIN_DATASPI 23
#endif #endif
#endif #endif
#endif #endif

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 {