Transition struct (reduced RAM footprint).

This commit is contained in:
Blaz Kristan 2022-07-30 14:50:11 +02:00
parent f16558c126
commit eb9eda1f6d
3 changed files with 57 additions and 48 deletions

View File

@ -426,7 +426,7 @@ typedef struct Segment {
static uint16_t _usedSegmentData; static uint16_t _usedSegmentData;
// transition data, valid only if getOption(SEG_OPTION_TRANSITIONAL)==true, holds values during transition // transition data, valid only if getOption(SEG_OPTION_TRANSITIONAL)==true, holds values during transition
//struct Transition { struct Transition {
uint32_t _colorT[NUM_COLORS]; uint32_t _colorT[NUM_COLORS];
uint8_t _briT; // temporary brightness uint8_t _briT; // temporary brightness
uint8_t _cctT; // temporary CCT uint8_t _cctT; // temporary CCT
@ -434,11 +434,11 @@ typedef struct Segment {
//uint8_t _modeP; // previous mode/effect (transitioning effects is way more complex than this) //uint8_t _modeP; // previous mode/effect (transitioning effects is way more complex than this)
uint32_t _start; uint32_t _start;
uint16_t _dur; uint16_t _dur;
// Transition(uint16_t dur=750) : _briT(255), _cctT(127), _palT(CRGBPalette16(CRGB::Black)), _modeP(FX_MODE_STATIC), _start(millis()), _dur(dur) {} Transition(uint16_t dur=750) : _briT(255), _cctT(127), _palT(CRGBPalette16(CRGB::Black)), /*_modeP(FX_MODE_STATIC),*/ _start(millis()), _dur(dur) {}
// Transition(uint16_t d, uint8_t b, uint8_t c, const uint32_t *o) : _briT(b), _cctT(c), _palT(CRGBPalette16(CRGB::Black)), _modeP(FX_MODE_STATIC), _start(millis()), _dur(d) { Transition(uint16_t d, uint8_t b, uint8_t c, const uint32_t *o) : _briT(b), _cctT(c), _palT(CRGBPalette16(CRGB::Black)), /*_modeP(FX_MODE_STATIC),*/ _start(millis()), _dur(d) {
// for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = o[i]; for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = o[i];
// } }
//} *_t; // this struct will bootloop ESP } *_t; // this struct will bootloop ESP
public: public:
@ -469,8 +469,8 @@ typedef struct Segment {
aux1(0), aux1(0),
data(nullptr), data(nullptr),
_capabilities(0), _capabilities(0),
_dataLen(0) _dataLen(0),
//_t(nullptr) _t(nullptr)
{ {
refreshLightCapabilities(); refreshLightCapabilities();
} }
@ -491,7 +491,7 @@ typedef struct Segment {
Serial.println(); Serial.println();
#endif #endif
if (name) delete[] name; if (name) delete[] name;
//if (_t) delete _t; if (_t) delete _t;
deallocateData(); deallocateData();
} }

View File

@ -75,29 +75,32 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
uint16_t Segment::_usedSegmentData = 0U; // amount of RAM all segments use for their data[] uint16_t Segment::_usedSegmentData = 0U; // amount of RAM all segments use for their data[]
// copy constructor
Segment::Segment(const Segment &orig) { Segment::Segment(const Segment &orig) {
DEBUG_PRINTLN(F("-- Segment duplicated --")); DEBUG_PRINTLN(F("-- Segment duplicated --"));
memcpy(this, &orig, sizeof(Segment)); memcpy(this, &orig, sizeof(Segment));
name = nullptr; name = nullptr;
data = nullptr; data = nullptr;
_dataLen = 0; _dataLen = 0;
//_t = nullptr; _t = nullptr;
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) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); } if (orig.data) { if (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(" Original data: %p (%d)\n", orig.data, (int)orig._dataLen); DEBUG_PRINTF(" Original data: %p (%d)\n", orig.data, (int)orig._dataLen);
DEBUG_PRINTF(" Constructed data: %p (%d)\n", data, (int)_dataLen); DEBUG_PRINTF(" Constructed data: %p (%d)\n", data, (int)_dataLen);
} }
// move constructor
Segment::Segment(Segment &&orig) noexcept { Segment::Segment(Segment &&orig) noexcept {
DEBUG_PRINTLN(F("-- Move constructor --")); DEBUG_PRINTLN(F("-- Move constructor --"));
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._dataLen = 0;
//orig._t = nullptr; orig._t = nullptr;
} }
// copy assignment
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) {
@ -105,22 +108,23 @@ Segment& Segment::operator= (const Segment &orig) {
DEBUG_PRINTF(" Copy Deleting %s (%p)\n", name, name); DEBUG_PRINTF(" Copy Deleting %s (%p)\n", name, name);
delete[] name; delete[] name;
} }
//if (_t) delete _t; if (_t) delete _t;
deallocateData(); deallocateData();
memcpy(this, &orig, sizeof(Segment)); memcpy(this, &orig, sizeof(Segment));
name = nullptr; name = nullptr;
data = nullptr; data = nullptr;
_dataLen = 0; _dataLen = 0;
//_t = nullptr; _t = nullptr;
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) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); } if (orig.data) { if (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(" Original data: %p (%d)\n", orig.data, (int)orig._dataLen); DEBUG_PRINTF(" Original data: %p (%d)\n", orig.data, (int)orig._dataLen);
DEBUG_PRINTF(" Copied data: %p (%d)\n", data, (int)_dataLen); DEBUG_PRINTF(" Copied data: %p (%d)\n", data, (int)_dataLen);
} }
return *this; return *this;
} }
// move assignment
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) {
@ -128,13 +132,13 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
DEBUG_PRINTF(" Move Deleting %s (%p)\n", name, name); DEBUG_PRINTF(" Move Deleting %s (%p)\n", name, name);
delete[] name; // free old name delete[] name; // free old name
} }
//if (_t) delete _t;
deallocateData(); // free old runtime data deallocateData(); // free old runtime data
if (_t) delete _t;
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._dataLen = 0;
//orig._t = nullptr; orig._t = nullptr;
} }
return *this; return *this;
} }
@ -184,49 +188,51 @@ void Segment::resetIfRequired() {
} }
void Segment::startTransition(uint16_t dur) { void Segment::startTransition(uint16_t dur) {
if (transitional || _t) return; // already in transition
// starting a transition has to occur before change so we get current values 1st // starting a transition has to occur before change so we get current values 1st
/*uint8_t*/ _briT = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0); // comment out uint8_t if not using Transition struct uint8_t _briT = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0); // comment out uint8_t if not using Transition struct
/*uint8_t*/ _cctT = currentBri(cct, true); // comment out uint8_t if not using Transition struct uint8_t _cctT = currentBri(cct, true); // comment out uint8_t if not using Transition struct
/*CRGBPalette16 _palT;*/ loadPalette(_palT, palette); CRGBPalette16 _palT; loadPalette(_palT, palette);
///*uint8_t*/ _modeP = mode; // comment out uint8_t if not using Transition struct ///*uint8_t*/ _modeP = mode; // comment out uint8_t if not using Transition struct
//uint32_t _colorT[NUM_COLORS]; // comment out if not using Transition struct uint32_t _colorT[NUM_COLORS]; // comment out if not using Transition struct
for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = currentColor(i, colors[i]); for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = currentColor(i, colors[i]);
// using transition struct // using transition struct
//if (!_t) _t = new Transition(dur); // no previous transition running if (!_t) _t = new Transition(dur); // no previous transition running
//if (!_t) return; // failed to allocat data if (!_t) return; // failed to allocat data
//_t->_briT = _briT; _t->_briT = _briT;
//_t->_cctT = _cctT; _t->_cctT = _cctT;
//_t->_palT = _palT; _t->_palT = _palT;
//_t->_modeT = _modeP; //_t->_modeT = _modeP;
//for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = _colorT[i]; for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = _colorT[i];
// comment out if using transition struct as it is done in constructor // comment out if using transition struct as it is done in constructor
_dur = dur; //_dur = dur;
_start = millis(); //_start = millis();
setOption(SEG_OPTION_TRANSITIONAL, true); setOption(SEG_OPTION_TRANSITIONAL, true);
} }
uint16_t Segment::progress() { //transition progression between 0-65535 uint16_t Segment::progress() { //transition progression between 0-65535
//if (!_t) return 0xFFFFU; if (!transitional || !_t) return 0xFFFFU;
uint32_t timeNow = millis(); uint32_t timeNow = millis();
if (timeNow - /*_t->*/_start > /*_t->*/_dur) return 0xFFFFU; if (timeNow - _t->_start > _t->_dur) return 0xFFFFU;
return (timeNow - /*_t->*/_start) * 0xFFFFU / /*_t->*/_dur; return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
} }
uint8_t Segment::currentBri(uint8_t briNew, bool useCct) { uint8_t Segment::currentBri(uint8_t briNew, bool useCct) {
//if (_t) { if (transitional && _t) {
if (getOption(SEG_OPTION_TRANSITIONAL)) { //if (getOption(SEG_OPTION_TRANSITIONAL)) {
uint32_t prog = progress() + 1; uint32_t prog = progress() + 1;
if (useCct) return ((briNew * prog) + /*_t->*/_cctT * (0x10000 - prog)) >> 16; if (useCct) return ((briNew * prog) + _t->_cctT * (0x10000 - prog)) >> 16;
else return ((briNew * prog) + /*_t->*/_briT * (0x10000 - prog)) >> 16; else return ((briNew * prog) + _t->_briT * (0x10000 - prog)) >> 16;
} else { } else {
return briNew; return briNew;
} }
} }
uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) { uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) {
return getOption(SEG_OPTION_TRANSITIONAL) /*&& _t*/ ? color_blend(/*_t->*/_colorT[slot], colorNew, progress(), true) : colorNew; return transitional && _t ? color_blend(_t->_colorT[slot], colorNew, progress(), true) : colorNew;
} }
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
@ -309,23 +315,26 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) { CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
loadPalette(targetPalette, pal); loadPalette(targetPalette, pal);
//if (_t && progress() < 0xFFFFU) { if (transitional && _t && progress() < 0xFFFFU) {
if (strip.paletteFade && getOption(SEG_OPTION_TRANSITIONAL) && progress() < 0xFFFFU) { // TODO: get rid of //if (strip.paletteFade && getOption(SEG_OPTION_TRANSITIONAL) && progress() < 0xFFFFU) {
// blend palettes // blend palettes
uint8_t blends = map(_dur, 0, 0xFFFF, 48, 6); // do not blend palettes too quickly (0-65.5s) uint8_t blends = map(_t->_dur, 0, 0xFFFF, 48, 6); // do not blend palettes too quickly (0-65.5s)
nblendPaletteTowardPalette(/*_t->*/_palT, targetPalette, blends); nblendPaletteTowardPalette(_t->_palT, targetPalette, blends);
targetPalette = /*_t->*/_palT; // copy transitioning/temporary palette targetPalette = _t->_palT; // copy transitioning/temporary palette
} }
return targetPalette; return targetPalette;
} }
void Segment::handleTransition() { void Segment::handleTransition() {
if (!getOption(SEG_OPTION_TRANSITIONAL)) return; if (!transitional) return;
unsigned long maxWait = millis() + 20; unsigned long maxWait = millis() + 20;
if (mode == FX_MODE_STATIC && next_time > maxWait) next_time = maxWait; if (mode == FX_MODE_STATIC && next_time > maxWait) next_time = maxWait;
if (progress() == 0xFFFFU) { if (progress() == 0xFFFFU) {
//if (_t) { delete _t; _t = nullptr; } if (_t) {
setOption(SEG_OPTION_TRANSITIONAL, false); // finish transitioning segment delete _t;
_t = nullptr;
}
transitional = false; // finish transitioning segment
} }
} }
@ -753,8 +762,8 @@ uint32_t IRAM_ATTR Segment::color_from_palette(uint16_t i, bool mapping, bool wr
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end" if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
CRGB fastled_col; CRGB fastled_col;
CRGBPalette16 curPal; CRGBPalette16 curPal;
if (transitional) curPal = /*_t->*/_palT; if (transitional && _t) curPal = _t->_palT;
else loadPalette(curPal, palette); else loadPalette(curPal, palette);
fastled_col = ColorFromPalette(curPal, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global fastled_col = ColorFromPalette(curPal, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global
return RGBW32(fastled_col.r, fastled_col.g, fastled_col.b, 0); return RGBW32(fastled_col.r, fastled_col.g, fastled_col.b, 0);

View File

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