Allocate segment data based on currently active segments (#2217)

This commit is contained in:
Christian Schwinne 2021-09-20 21:22:50 +02:00 committed by GitHub
parent baf49b88f4
commit 8fae964ee8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 26 deletions

View File

@ -2614,7 +2614,7 @@ uint16_t WS2812FX::mode_glitter()
//each needs 11 bytes
//each needs 12 bytes
//Spark type is used for popcorn, 1D fireworks, and drip
typedef struct Spark {
float pos;
@ -2629,7 +2629,7 @@ typedef struct Spark {
*/
uint16_t WS2812FX::mode_popcorn(void) {
//allocate segment data
uint16_t maxNumPopcorn = 22; // max 22 on 18 segment ESP8266
uint16_t maxNumPopcorn = 21; // max 21 on 16 segment ESP8266
uint16_t dataSize = sizeof(spark) * maxNumPopcorn;
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
@ -2688,7 +2688,7 @@ uint16_t WS2812FX::candle(bool multi)
if (multi)
{
//allocate segment data
uint16_t dataSize = (SEGLEN -1) *3; // max length of segment on 18 segment ESP8266 is 75 pixels
uint16_t dataSize = (SEGLEN -1) *3; //max. 1365 pixels (ESP8266)
if (!SEGENV.allocateData(dataSize)) return candle(false); //allocation failed
}
@ -2776,13 +2776,11 @@ uint16_t WS2812FX::mode_candle_multi()
/ Speed sets frequency of new starbursts, intensity is the intensity of the burst
*/
#ifdef ESP8266
#define STARBURST_MAX_FRAG 4
#define STARBURST_MAX_STARS 6
#define STARBURST_MAX_FRAG 8 //52 bytes / star
#else
#define STARBURST_MAX_FRAG 10
#define STARBURST_MAX_STARS 11
#define STARBURST_MAX_FRAG 10 //60 bytes / star
#endif
//each needs 18+STARBURST_MAX_FRAG*4 bytes
//each needs 20+STARBURST_MAX_FRAG*4 bytes
typedef struct particle {
CRGB color;
uint32_t birth =0;
@ -2793,8 +2791,14 @@ typedef struct particle {
} star;
uint16_t WS2812FX::mode_starburst(void) {
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
uint8_t segs = getActiveSegmentsNum();
if (segs <= (MAX_NUM_SEGMENTS /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs
if (segs <= (MAX_NUM_SEGMENTS /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
uint16_t maxStars = maxData / sizeof(star); //ESP8266: max. 4/9/19 stars/seg, ESP32: max. 10/21/42 stars/seg
uint8_t numStars = 1 + (SEGLEN >> 3);
if (numStars > STARBURST_MAX_STARS) numStars = STARBURST_MAX_STARS; // 11 * 58 * 32 = 19k (ESP32), 6 * 34 * 18 = 4k (ESP8266)
if (numStars > maxStars) numStars = maxStars;
uint16_t dataSize = sizeof(star) * numStars;
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
@ -2902,18 +2906,24 @@ uint16_t WS2812FX::mode_starburst(void) {
* Exploding fireworks effect
* adapted from: http://www.anirama.com/1000leds/1d-fireworks/
*/
#ifdef ESP8266
#define MAX_SPARKS 20 // number of fragments
#else
#define MAX_SPARKS 58 // number of fragments
#endif
uint16_t WS2812FX::mode_exploding_fireworks(void)
{
//allocate segment data
uint16_t numSparks = min(2 + (SEGLEN >> 1), MAX_SPARKS); // max 58 for 32 segment ESP32, 20 for 18 segment ESP8266
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
uint8_t segs = getActiveSegmentsNum();
if (segs <= (MAX_NUM_SEGMENTS /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs
if (segs <= (MAX_NUM_SEGMENTS /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
int maxSparks = maxData / sizeof(spark); //ESP8266: max. 21/42/85 sparks/seg, ESP32: max. 53/106/213 sparks/seg
uint16_t numSparks = min(2 + (SEGLEN >> 1), maxSparks);
uint16_t dataSize = sizeof(spark) * numSparks;
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
if (dataSize != SEGENV.aux1) { //reset to flare if sparks were reallocated
SEGENV.aux0 = 0;
SEGENV.aux1 = dataSize;
}
fill(BLACK);
bool actuallyReverse = SEGMENT.getOption(SEG_OPTION_REVERSED);

View File

@ -66,6 +66,10 @@
#define MAX_SEGMENT_DATA 20480
#endif
/* How much data bytes each segment should max allocate to leave enough space for other segments,
assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */
#define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / MAX_NUM_SEGMENTS)
#define LED_SKIP_AMOUNT 1
#define MIN_SHOW_DELAY 15
@ -657,6 +661,7 @@ class WS2812FX {
getModeCount(void),
getPaletteCount(void),
getMaxSegments(void),
getActiveSegmentsNum(void),
//getFirstSelectedSegment(void),
getMainSegmentId(void),
gamma8(uint8_t),

View File

@ -129,25 +129,20 @@ void WS2812FX::finalizeInit(uint16_t countPixels)
if (autoSegments) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) {
_segments[i].start = segStarts[i];
_segments[i].stop = segStops [i];
setSegment(i, segStarts[i], segStops[i]);
}
} else {
//expand the main seg to the entire length, but only if there are no other segments
uint8_t mainSeg = getMainSegmentId();
bool isMultipleSegs = false;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (i != mainSeg && _segments[i].isActive()) isMultipleSegs = true;
}
if (!isMultipleSegs) {
_segments[mainSeg].start = 0; _segments[mainSeg].stop = _length;
if (getActiveSegmentsNum() < 2) {
setSegment(mainSeg, 0, _length);
} else {
//there are multiple segments, leave them, but prune length to total
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].start > _length) _segments[i].stop = 0;
if (_segments[i].stop > _length) _segments[i].stop = _length;
if (_segments[i].start >= _length) setSegment(i, 0, 0);
if (_segments[i].stop > _length) setSegment(i, _segments[i].start, _length);
}
}
}
@ -545,6 +540,15 @@ uint8_t WS2812FX::getMainSegmentId(void) {
return 0;
}
uint8_t WS2812FX::getActiveSegmentsNum(void) {
uint8_t c = 0;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive()) c++;
}
return c;
}
uint32_t WS2812FX::getColor(void) {
return _segments[getMainSegmentId()].colors[0];
}