diff --git a/wled00/FX.h b/wled00/FX.h index 53096b7e0..8f2ba95ba 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -44,10 +44,17 @@ #define WLED_FPS 42 #define FRAMETIME (1000/WLED_FPS) -/* each segment uses 37 bytes of SRAM memory, so if you're application fails because of +/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ #define MAX_NUM_SEGMENTS 10 +/* How much data bytes all segments combined may allocate */ +#ifdef ESP8266 +#define MAX_SEGMENT_DATA 2048 +#else +#define MAX_SEGMENT_DATA 8192 +#endif + #define NUM_COLORS 3 /* number of colors per segment */ #define SEGMENT _segments[_segment_index] #define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x]) @@ -221,13 +228,35 @@ class WS2812FX { } segment; // segment runtime parameters - typedef struct Segment_runtime { // 16 bytes + typedef struct Segment_runtime { // 28 bytes unsigned long next_time; uint32_t step; uint32_t call; uint16_t aux0; uint16_t aux1; - void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;}; + byte* data = nullptr; + bool allocateData(uint16_t len){ + if (data && _dataLen == len) return true; //already allocated + deallocateData(); + if (WS2812FX::_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory + data = new (std::nothrow) byte[len]; + if (!data) return false; //allocation failed + WS2812FX::_usedSegmentData += len; + _dataLen = len; + memset(data, 0, len); + return true; + } + void deallocateData(){ + if (data) { + delete[] data; + } + data = nullptr; + WS2812FX::_usedSegmentData -= _dataLen; + _dataLen = 0; + } + void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; deallocateData();} + private: + uint16_t _dataLen = 0; } segment_runtime; WS2812FX() { @@ -518,6 +547,7 @@ class WS2812FX { uint16_t _length, _lengthRaw, _usableCount; uint16_t _rand16seed; uint8_t _brightness; + static uint16_t _usedSegmentData; void handle_palette(void); void fill(uint32_t); @@ -564,7 +594,8 @@ class WS2812FX { // start, stop, speed, intensity, palette, mode, options, 3 unused bytes (group, spacing, opacity), color[] { 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}} }; - segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element + segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element + friend class Segment_runtime; }; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 2b7d6ec1d..7fa6eae89 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -473,7 +473,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) { void WS2812FX::resetSegments() { memset(_segments, 0, sizeof(_segments)); - memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); + //memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); _segment_index = 0; _segments[0].mode = DEFAULT_MODE; _segments[0].colors[0] = DEFAULT_COLOR; @@ -484,7 +484,9 @@ void WS2812FX::resetSegments() { for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) { _segments[i].colors[0] = color_wheel(i*51); + _segment_runtimes[i].reset(); } + _segment_runtimes[0].reset(); } void WS2812FX::setIndividual(uint16_t i, uint32_t col) @@ -862,3 +864,5 @@ uint32_t WS2812FX::gamma32(uint32_t color) b = gammaT[b]; return ((w << 24) | (r << 16) | (g << 8) | (b)); } + +uint16_t WS2812FX::_usedSegmentData = 0; diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 0d120292f..6a1a7b072 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912291 +#define VERSION 1912311 char versionString[] = "0.9.0-b2";