Skip to content

Commit b8e8028

Browse files
authored
Merge pull request wled#2184 from Aircoookie/fx-mods
FX optimisations and segment names
2 parents 3cefb14 + c5eac29 commit b8e8028

File tree

10 files changed

+2474
-2462
lines changed

10 files changed

+2474
-2462
lines changed

wled00/FX.cpp

Lines changed: 115 additions & 146 deletions
Large diffs are not rendered by default.

wled00/FX.h

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
Modified for WLED
2525
*/
2626

27-
#include "wled.h"
28-
2927
#ifndef WS2812FX_h
3028
#define WS2812FX_h
3129

@@ -55,17 +53,17 @@
5553
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
5654
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
5755
#ifdef ESP8266
58-
#define MAX_NUM_SEGMENTS 12
56+
#define MAX_NUM_SEGMENTS 16
5957
/* How many color transitions can run at once */
6058
#define MAX_NUM_TRANSITIONS 8
6159
/* How much data bytes all segments combined may allocate */
62-
#define MAX_SEGMENT_DATA 2048
60+
#define MAX_SEGMENT_DATA 4096
6361
#else
64-
#ifndef MAX_NUM_SEGMENTS
65-
#define MAX_NUM_SEGMENTS 16
66-
#endif
67-
#define MAX_NUM_TRANSITIONS 16
68-
#define MAX_SEGMENT_DATA 8192
62+
#ifndef MAX_NUM_SEGMENTS
63+
#define MAX_NUM_SEGMENTS 32
64+
#endif
65+
#define MAX_NUM_TRANSITIONS 24
66+
#define MAX_SEGMENT_DATA 20480
6967
#endif
7068

7169
#define LED_SKIP_AMOUNT 1
@@ -245,7 +243,7 @@ class WS2812FX {
245243

246244
// segment parameters
247245
public:
248-
typedef struct Segment { // 25 (28 in memory?) bytes
246+
typedef struct Segment { // 29 (32 in memory?) bytes
249247
uint16_t start;
250248
uint16_t stop; //segment invalid if stop == 0
251249
uint16_t offset;
@@ -257,6 +255,7 @@ class WS2812FX {
257255
uint8_t grouping, spacing;
258256
uint8_t opacity;
259257
uint32_t colors[NUM_COLORS];
258+
char *name;
260259
bool setColor(uint8_t slot, uint32_t c, uint8_t segn) { //returns true if changed
261260
if (slot >= NUM_COLORS || segn >= MAX_NUM_SEGMENTS) return false;
262261
if (c == colors[slot]) return false;
@@ -296,19 +295,19 @@ class WS2812FX {
296295
{
297296
return ((options >> n) & 0x01);
298297
}
299-
bool isSelected()
298+
inline bool isSelected()
300299
{
301300
return getOption(0);
302301
}
303-
bool isActive()
302+
inline bool isActive()
304303
{
305304
return stop > start;
306305
}
307-
uint16_t length()
306+
inline uint16_t length()
308307
{
309308
return stop - start;
310309
}
311-
uint16_t groupLength()
310+
inline uint16_t groupLength()
312311
{
313312
return grouping + spacing;
314313
}
@@ -345,25 +344,31 @@ class WS2812FX {
345344

346345
// segment runtime parameters
347346
typedef struct Segment_runtime { // 28 bytes
348-
unsigned long next_time;
349-
uint32_t step;
350-
uint32_t call;
351-
uint16_t aux0;
352-
uint16_t aux1;
347+
unsigned long next_time; // millis() of next update
348+
uint32_t step; // custom "step" var
349+
uint32_t call; // call counter
350+
uint16_t aux0; // custom var
351+
uint16_t aux1; // custom var
353352
byte* data = nullptr;
354353
bool allocateData(uint16_t len){
355354
if (data && _dataLen == len) return true; //already allocated
356355
deallocateData();
357356
if (WS2812FX::instance->_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory
358-
data = new (std::nothrow) byte[len];
357+
// if possible use SPI RAM on ESP32
358+
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
359+
if (psramFound())
360+
data = (byte*) ps_malloc(len);
361+
else
362+
#endif
363+
data = (byte*) malloc(len);
359364
if (!data) return false; //allocation failed
360365
WS2812FX::instance->_usedSegmentData += len;
361366
_dataLen = len;
362367
memset(data, 0, len);
363368
return true;
364369
}
365370
void deallocateData(){
366-
delete[] data;
371+
free(data);
367372
data = nullptr;
368373
WS2812FX::instance->_usedSegmentData -= _dataLen;
369374
_dataLen = 0;
@@ -389,7 +394,7 @@ class WS2812FX {
389394
* the internal segment state should be reset.
390395
* Call resetIfRequired before calling the next effect function.
391396
*/
392-
void reset() { _requiresReset = true; }
397+
inline void reset() { _requiresReset = true; }
393398
private:
394399
uint16_t _dataLen = 0;
395400
bool _requiresReset = false;
@@ -622,11 +627,12 @@ class WS2812FX {
622627
trigger(void),
623628
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0),
624629
resetSegments(),
630+
populateDefaultSegments(),
625631
setPixelColor(uint16_t n, uint32_t c),
626632
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
627633
show(void),
628-
setColorOrder(uint8_t co),
629-
setPixelSegment(uint8_t n);
634+
setPixelSegment(uint8_t n),
635+
deserializeMap(uint8_t n=0);
630636

631637
bool
632638
isRgbw = false,
@@ -644,8 +650,6 @@ class WS2812FX {
644650
paletteFade = 0,
645651
paletteBlend = 0,
646652
milliampsPerLed = 55,
647-
// getStripType(uint8_t strip=0),
648-
// setStripType(uint8_t type, uint8_t strip=0),
649653
getBrightness(void),
650654
getMode(void),
651655
getSpeed(void),
@@ -654,24 +658,17 @@ class WS2812FX {
654658
getMaxSegments(void),
655659
//getFirstSelectedSegment(void),
656660
getMainSegmentId(void),
657-
getColorOrder(void),
658661
gamma8(uint8_t),
659662
gamma8_cal(uint8_t, float),
660663
sin_gap(uint16_t),
661664
get_random_wheel_index(uint8_t);
662665

663666
int8_t
664-
// setStripPin(uint8_t strip, int8_t pin),
665-
// getStripPin(uint8_t strip=0),
666-
// setStripPinClk(uint8_t strip, int8_t pin),
667-
// getStripPinClk(uint8_t strip=0),
668667
tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec);
669668

670669
uint16_t
671670
ablMilliampsMax,
672671
currentMilliamps,
673-
// setStripLen(uint8_t strip, uint16_t len),
674-
// getStripLen(uint8_t strip=0),
675672
triwave16(uint16_t),
676673
getFps();
677674

@@ -849,16 +846,15 @@ class WS2812FX {
849846
color_wipe(bool, bool),
850847
dynamic(bool),
851848
scan(bool),
852-
theater_chase(uint32_t, uint32_t, bool),
853849
running_base(bool,bool),
854850
larson_scanner(bool),
855851
sinelon_base(bool,bool),
856852
dissolve(uint32_t),
857853
chase(uint32_t, uint32_t, uint32_t, bool),
858854
gradient_base(bool),
859855
ripple_base(bool),
860-
police_base(uint32_t, uint32_t, bool),
861-
running(uint32_t, uint32_t),
856+
police_base(uint32_t, uint32_t, uint16_t),
857+
running(uint32_t, uint32_t, bool theatre=false),
862858
tricolor_chase(uint32_t, uint32_t),
863859
twinklefox_base(bool),
864860
spots_base(uint16_t),
@@ -869,8 +865,7 @@ class WS2812FX {
869865

870866
void
871867
blendPixelColor(uint16_t n, uint32_t color, uint8_t blend),
872-
startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot),
873-
deserializeMap(void);
868+
startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot);
874869

875870
uint16_t* customMappingTable = nullptr;
876871
uint16_t customMappingSize = 0;

wled00/FX_fcn.cpp

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
2424
Modified heavily for WLED
2525
*/
26-
26+
#include "wled.h"
2727
#include "FX.h"
2828
#include "palettes.h"
2929

@@ -40,7 +40,7 @@
4040
another example. Switches direction every 5 LEDs.
4141
{"map":[
4242
0, 1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13, 14,
43-
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25]
43+
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25]}
4444
*/
4545

4646
//factory defaults LED setup
@@ -218,14 +218,13 @@ uint16_t WS2812FX::realPixelIndex(uint16_t i) {
218218
int16_t realIndex = iGroup;
219219
if (IS_REVERSE) {
220220
if (IS_MIRROR) {
221-
realIndex = (SEGMENT.length() -1) / 2 - iGroup; //only need to index half the pixels
221+
realIndex = (SEGMENT.length() - 1) / 2 - iGroup; //only need to index half the pixels
222222
} else {
223-
realIndex = SEGMENT.length() - iGroup - 1;
223+
realIndex = (SEGMENT.length() - 1) - iGroup;
224224
}
225225
}
226226

227227
realIndex += SEGMENT.start;
228-
229228
return realIndex;
230229
}
231230

@@ -246,7 +245,6 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
246245
}
247246

248247
if (SEGLEN) {//from segment
249-
250248
//color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
251249
if (_bri_t < 255) {
252250
r = scale8(r, _bri_t);
@@ -256,12 +254,12 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
256254
}
257255
uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b));
258256

259-
bool reversed = IS_REVERSE;
257+
/* Set all the pixels in the group */
260258
uint16_t realIndex = realPixelIndex(i);
261259
uint16_t len = SEGMENT.length();
262260

263261
for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
264-
int indexSet = realIndex + (reversed ? -j : j);
262+
uint16_t indexSet = realIndex + (IS_REVERSE ? -j : j);
265263
if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) {
266264
if (IS_MIRROR) { //set the corresponding mirrored pixel
267265
uint16_t indexMir = SEGMENT.stop - indexSet + SEGMENT.start - 1;
@@ -273,16 +271,15 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
273271
busses.setPixelColor(indexMir, col);
274272
}
275273
/* offset/phase */
276-
indexSet += SEGMENT.offset;
277-
if (indexSet >= SEGMENT.stop) indexSet -= len;
274+
indexSet += SEGMENT.offset;
275+
if (indexSet >= SEGMENT.stop) indexSet -= len;
278276

279277
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
280278
busses.setPixelColor(indexSet, col);
281279
}
282280
}
283281
} else { //live data, etc.
284282
if (i < customMappingSize) i = customMappingTable[i];
285-
286283
uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b));
287284
busses.setPixelColor(i, col);
288285
}
@@ -563,6 +560,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
563560
}
564561

565562
if (i < customMappingSize) i = customMappingTable[i];
563+
if (i >= _length) return 0;
566564

567565
return busses.getPixelColor(i);
568566
}
@@ -584,15 +582,6 @@ uint32_t WS2812FX::getLastShow(void) {
584582
return _lastShow;
585583
}
586584

587-
//TODO these need to be on a per-strip basis
588-
uint8_t WS2812FX::getColorOrder(void) {
589-
return COL_ORDER_GRB;
590-
}
591-
592-
void WS2812FX::setColorOrder(uint8_t co) {
593-
//bus->SetColorOrder(co);
594-
}
595-
596585
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
597586
if (n >= MAX_NUM_SEGMENTS) return;
598587
Segment& seg = _segments[n];
@@ -603,7 +592,11 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
603592
if (seg.stop) setRange(seg.start, seg.stop -1, 0); //turn old segment range off
604593
if (i2 <= i1) //disable segment
605594
{
606-
seg.stop = 0;
595+
seg.stop = 0;
596+
if (seg.name) {
597+
delete[] seg.name;
598+
seg.name = nullptr;
599+
}
607600
if (n == mainSegment) //if main segment is deleted, set first active as main segment
608601
{
609602
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
@@ -628,6 +621,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
628621
}
629622

630623
void WS2812FX::resetSegments() {
624+
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) if (_segments[i].name) delete _segments[i].name;
631625
mainSegment = 0;
632626
memset(_segments, 0, sizeof(_segments));
633627
//memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
@@ -656,6 +650,25 @@ void WS2812FX::resetSegments() {
656650
_segment_runtimes[0].reset();
657651
}
658652

653+
void WS2812FX::populateDefaultSegments() {
654+
uint16_t length = 0;
655+
for (uint8_t i=0; i<busses.getNumBusses(); i++) {
656+
Bus *bus = busses.getBus(i);
657+
if (bus == nullptr) continue;
658+
_segments[i].start = bus->getStart();
659+
length += bus->getLength();
660+
_segments[i].stop = _segments[i].start + bus->getLength();
661+
_segments[i].mode = DEFAULT_MODE;
662+
_segments[i].colors[0] = DEFAULT_COLOR;
663+
_segments[i].speed = DEFAULT_SPEED;
664+
_segments[i].intensity = DEFAULT_INTENSITY;
665+
_segments[i].grouping = 1;
666+
_segments[i].setOption(SEG_OPTION_SELECTED, 1);
667+
_segments[i].setOption(SEG_OPTION_ON, 1);
668+
_segments[i].opacity = 255;
669+
}
670+
}
671+
659672
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
660673
void WS2812FX::setPixelSegment(uint8_t n)
661674
{
@@ -1033,18 +1046,34 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8
10331046

10341047

10351048
//load custom mapping table from JSON file
1036-
void WS2812FX::deserializeMap(void) {
1037-
if (!WLED_FS.exists("/ledmap.json")) return;
1038-
DynamicJsonDocument doc(JSON_BUFFER_SIZE); // full sized buffer for larger maps
1049+
void WS2812FX::deserializeMap(uint8_t n) {
1050+
char fileName[32];
1051+
strcpy_P(fileName, PSTR("/ledmap"));
1052+
if (n) sprintf(fileName +7, "%d", n);
1053+
strcat(fileName, ".json");
1054+
bool isFile = WLED_FS.exists(fileName);
1055+
1056+
if (!isFile) {
1057+
// erase custom mapping if selecting nonexistent ledmap.json (n==0)
1058+
if (!n && customMappingTable != nullptr) {
1059+
customMappingSize = 0;
1060+
delete[] customMappingTable;
1061+
customMappingTable = nullptr;
1062+
}
1063+
return;
1064+
}
10391065

1040-
DEBUG_PRINTLN(F("Reading LED map from /ledmap.json..."));
1066+
DynamicJsonDocument doc(JSON_BUFFER_SIZE); // full sized buffer for larger maps
1067+
DEBUG_PRINT(F("Reading LED map from "));
1068+
DEBUG_PRINTLN(fileName);
10411069

1042-
if (!readObjectFromFile("/ledmap.json", nullptr, &doc)) return; //if file does not exist just exit
1070+
if (!readObjectFromFile(fileName, nullptr, &doc)) return; //if file does not exist just exit
10431071

1072+
// erase old custom ledmap
10441073
if (customMappingTable != nullptr) {
1074+
customMappingSize = 0;
10451075
delete[] customMappingTable;
10461076
customMappingTable = nullptr;
1047-
customMappingSize = 0;
10481077
}
10491078

10501079
JsonArray map = doc[F("map")];

0 commit comments

Comments
 (0)