This commit is contained in:
Blaz Kristan 2023-08-05 17:35:14 +02:00
parent 937e3d0b94
commit 9a87a2ff0d
4 changed files with 45 additions and 46 deletions

View File

@ -382,10 +382,8 @@ typedef struct Segment {
static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions) static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions)
typedef struct TemporarySegmentData { typedef struct TemporarySegmentData {
uint16_t _optionsT;
uint32_t _colorT[NUM_COLORS]; uint32_t _colorT[NUM_COLORS];
//uint8_t _opacityT;
//uint8_t _cctT; // temporary CCT
//uint16_t _optionsT;
uint8_t _speedT; uint8_t _speedT;
uint8_t _intensityT; uint8_t _intensityT;
uint8_t _custom1T, _custom2T; // custom FX parameters/sliders uint8_t _custom1T, _custom2T; // custom FX parameters/sliders
@ -560,8 +558,8 @@ typedef struct Segment {
// transition functions // transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change void startTransition(uint16_t dur); // transition has to start before actual segment values change
void handleTransition(void); void handleTransition(void);
void saveSegenv(tmpsegd_t *tmpSegD); void saveSegenv(tmpsegd_t *tmpSegD = nullptr);
void restoreSegenv(tmpsegd_t *tmpSegD); void restoreSegenv(tmpsegd_t *tmpSegD = nullptr);
uint16_t progress(void); //transition progression between 0-65535 uint16_t progress(void); //transition progression between 0-65535
uint8_t currentBri(uint8_t briNew, bool useCct = false); uint8_t currentBri(uint8_t briNew, bool useCct = false);
uint8_t currentMode(uint8_t modeNew); uint8_t currentMode(uint8_t modeNew);

View File

@ -216,23 +216,27 @@ void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
y *= groupLength(); // expand to physical pixels y *= groupLength(); // expand to physical pixels
if (x >= width() || y >= height()) return; // if pixel would fall out of segment just exit if (x >= width() || y >= height()) return; // if pixel would fall out of segment just exit
uint32_t tmpCol = col;
for (int j = 0; j < grouping; j++) { // groupping vertically for (int j = 0; j < grouping; j++) { // groupping vertically
for (int g = 0; g < grouping; g++) { // groupping horizontally for (int g = 0; g < grouping; g++) { // groupping horizontally
uint16_t xX = (x+g), yY = (y+j); uint16_t xX = (x+g), yY = (y+j);
if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end
strip.setPixelColorXY(start + xX, startY + yY, col); // if blending modes, blend with underlying pixel
if (transitional && _t && currentMode(mode) != _t->_modeT) tmpCol = color_blend(strip.getPixelColorXY(start + xX, startY + yY), col, progress(), true);
strip.setPixelColorXY(start + xX, startY + yY, tmpCol);
if (mirror) { //set the corresponding horizontally mirrored pixel if (mirror) { //set the corresponding horizontally mirrored pixel
if (transpose) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col); if (transpose) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, tmpCol);
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col); else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, tmpCol);
} }
if (mirror_y) { //set the corresponding vertically mirrored pixel if (mirror_y) { //set the corresponding vertically mirrored pixel
if (transpose) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col); if (transpose) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, tmpCol);
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col); else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, tmpCol);
} }
if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel
strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, col); strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, tmpCol);
} }
} }
} }

View File

@ -288,9 +288,7 @@ void Segment::startTransition(uint16_t dur) {
_t = new Transition(dur); // no previous transition running _t = new Transition(dur); // no previous transition running
if (!_t) return; // failed to allocate data if (!_t) return; // failed to allocate data
DEBUG_PRINT(F("-- Saving transition environment. ")); saveSegenv();
DEBUG_PRINTLN(on ? opacity : 0);
saveSegenv(&(_t->_tmpSeg));
CRGBPalette16 _palT = CRGBPalette16(DEFAULT_COLOR); loadPalette(_palT, palette); CRGBPalette16 _palT = CRGBPalette16(DEFAULT_COLOR); loadPalette(_palT, palette);
_t->_palT = _palT; _t->_palT = _palT;
_t->_modeT = mode; _t->_modeT = mode;
@ -328,18 +326,14 @@ uint8_t Segment::currentBri(uint8_t briNew, bool useCct) {
} }
uint8_t Segment::currentMode(uint8_t newMode) { uint8_t Segment::currentMode(uint8_t newMode) {
uint16_t prog = progress(); uint16_t prog = progress(); // implicit check for transitional & _t in progress()
if (prog < 0xFFFFU) { // implicit check for transitional & _t in progress() if (prog < 0xFFFFU) return _t->_modeT;
restoreSegenv(&(_t->_tmpSeg));
opacity -= (uint32_t)opacity * prog / 0xFFFFU;
return _t->_modeT;
}
return newMode; return newMode;
} }
void Segment::saveSegenv(tmpsegd_t *tmpSeg) { void Segment::saveSegenv(tmpsegd_t *tmpSeg) {
//tmpSeg._opacityT = on ? opacity : 0; if (tmpSeg == nullptr) { if (_t) tmpSeg = &(_t->_tmpSeg); else return; }
//tmpSeg._optionsT = options; tmpSeg->_optionsT = options;
for (size_t i=0; i<NUM_COLORS; i++) tmpSeg->_colorT[i] = colors[i]; for (size_t i=0; i<NUM_COLORS; i++) tmpSeg->_colorT[i] = colors[i];
tmpSeg->_speedT = speed; tmpSeg->_speedT = speed;
tmpSeg->_intensityT = intensity; tmpSeg->_intensityT = intensity;
@ -358,17 +352,19 @@ void Segment::saveSegenv(tmpsegd_t *tmpSeg) {
} }
void Segment::restoreSegenv(tmpsegd_t *tmpSeg) { void Segment::restoreSegenv(tmpsegd_t *tmpSeg) {
if (tmpSeg == nullptr) {
if (_t) tmpSeg = &(_t->_tmpSeg);
else return;
} else {
if (&(_t->_tmpSeg) != tmpSeg) { if (&(_t->_tmpSeg) != tmpSeg) {
DEBUG_PRINTF("Temp: %p != %p\n", &(_t->_tmpSeg), tmpSeg);
DEBUG_PRINTLN(F("-- Restoring OLD environment."));
// update possibly changed variables to keep old effect running correctly // update possibly changed variables to keep old effect running correctly
_t->_tmpSeg._aux0T = aux0; _t->_tmpSeg._aux0T = aux0;
_t->_tmpSeg._aux1T = aux1; _t->_tmpSeg._aux1T = aux1;
_t->_tmpSeg._stepT = step; _t->_tmpSeg._stepT = step;
_t->_tmpSeg._callT = call; _t->_tmpSeg._callT = call;
} }
//opacity = tmpSeg._opacityT; }
//options = tmpSeg._optionsT; options = tmpSeg->_optionsT;
for (size_t i=0; i<NUM_COLORS; i++) colors[i] = tmpSeg->_colorT[i]; for (size_t i=0; i<NUM_COLORS; i++) colors[i] = tmpSeg->_colorT[i];
speed = tmpSeg->_speedT; speed = tmpSeg->_speedT;
intensity = tmpSeg->_intensityT; intensity = tmpSeg->_intensityT;
@ -703,6 +699,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
} }
i += start; // starting pixel in a group i += start; // starting pixel in a group
uint32_t tmpCol = col;
// set all the pixels in the group // set all the pixels in the group
for (int j = 0; j < grouping; j++) { for (int j = 0; j < grouping; j++) {
uint16_t indexSet = i + ((reverse) ? -j : j); uint16_t indexSet = i + ((reverse) ? -j : j);
@ -711,11 +708,13 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
uint16_t indexMir = stop - indexSet + start - 1; uint16_t indexMir = stop - indexSet + start - 1;
indexMir += offset; // offset/phase indexMir += offset; // offset/phase
if (indexMir >= stop) indexMir -= len; // wrap if (indexMir >= stop) indexMir -= len; // wrap
strip.setPixelColor(indexMir, col); if (transitional && _t && currentMode(mode) != _t->_modeT) tmpCol = color_blend(strip.getPixelColor(indexMir), col, progress(), true);
strip.setPixelColor(indexMir, tmpCol);
} }
indexSet += offset; // offset/phase indexSet += offset; // offset/phase
if (indexSet >= stop) indexSet -= len; // wrap if (indexSet >= stop) indexSet -= len; // wrap
strip.setPixelColor(indexSet, col); if (transitional && _t && currentMode(mode) != _t->_modeT) tmpCol = color_blend(strip.getPixelColor(indexSet), col, progress(), true);
strip.setPixelColor(indexSet, tmpCol);
} }
} }
} }
@ -1176,24 +1175,22 @@ void WS2812FX::service() {
for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]); for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]);
// Effect blending (execute previous effect then new effect while in transition) // Effect blending (execute previous effect then new effect while in transition)
// WARNING: seg.currentMode(mode) (while in transition) will overwrite SEGENV variables!!! // If two effects are being blended (each may have different segment settings), those
// so they need to be saved first and then restored before running new mode. // settings need to be saved first and then restored before running new mode.
// The seetings need to be applied from transition buffer for previous effect.
// The blending will largely depend on the effect behaviour since actual output (LEDs) may be // The blending will largely depend on the effect behaviour since actual output (LEDs) may be
// overwritten by later effect. To enable seamless blending for every effect, additional LED buffer // overwritten by later effect. To enable seamless blending for every effect, additional LED buffer
// would need to be allocated for each effect and then blended together for each pixel. // would need to be allocated for each effect and then blended together for each pixel.
Segment::tmpsegd_t _tmpSegData; Segment::tmpsegd_t _tmpSegData;
seg.saveSegenv(&_tmpSegData); seg.saveSegenv(&_tmpSegData);
uint8_t newMode = seg.mode;
uint8_t newOpacity = seg.opacity;
uint8_t tmpMode = seg.currentMode(seg.mode); uint8_t tmpMode = seg.currentMode(seg.mode);
if (seg.mode != tmpMode) seg.restoreSegenv(nullptr); // restore transition data (including temporary opacity)
delay = (*_mode[tmpMode])(); // run old mode delay = (*_mode[tmpMode])(); // run old mode
if (newMode != tmpMode) { if (seg.mode != tmpMode) {
if (tmpMode != FX_MODE_HALLOWEEN_EYES) seg.call++; if (tmpMode != FX_MODE_HALLOWEEN_EYES) seg.call++;
seg.restoreSegenv(&_tmpSegData); // restore mode state seg.restoreSegenv(&_tmpSegData); // restore mode state
seg.opacity = (uint32_t)newOpacity * seg.progress() / 0xFFFFU; uint16_t d2 = (*_mode[seg.mode])(); // run new mode
delay += (*_mode[seg.mode])(); // run new mode delay = MIN(delay,d2); // use shortest delay
delay /= 2; // average the delay
seg.opacity = newOpacity;
} }
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++; if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition

View File

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