mirror of
https://github.com/wled/WLED.git
synced 2025-07-15 23:06:36 +00:00
Tackle CCT issue caused by segment blending
- wled#4734
This commit is contained in:
parent
0f00c95aba
commit
9dbd5f89b6
@ -802,7 +802,7 @@ class Segment {
|
||||
friend class WS2812FX;
|
||||
};
|
||||
|
||||
// main "strip" class (104 bytes)
|
||||
// main "strip" class (108 bytes)
|
||||
class WS2812FX {
|
||||
typedef uint16_t (*mode_ptr)(); // pointer to mode function
|
||||
typedef void (*show_callback)(); // pre show callback
|
||||
@ -829,6 +829,7 @@ class WS2812FX {
|
||||
cctFromRgb(false),
|
||||
// true private variables
|
||||
_pixels(nullptr),
|
||||
_pixelCCT(nullptr),
|
||||
_suspend(false),
|
||||
_brightness(DEFAULT_BRIGHTNESS),
|
||||
_length(DEFAULT_LED_COUNT),
|
||||
@ -857,6 +858,7 @@ class WS2812FX {
|
||||
|
||||
~WS2812FX() {
|
||||
d_free(_pixels);
|
||||
d_free(_pixelCCT); // just in case
|
||||
d_free(customMappingTable);
|
||||
_mode.clear();
|
||||
_modeData.clear();
|
||||
@ -1004,6 +1006,7 @@ class WS2812FX {
|
||||
|
||||
private:
|
||||
uint32_t *_pixels;
|
||||
uint8_t *_pixelCCT;
|
||||
std::vector<Segment> _segments;
|
||||
|
||||
volatile bool _suspend;
|
||||
|
@ -1224,11 +1224,6 @@ void WS2812FX::service() {
|
||||
unsigned frameDelay = FRAMETIME;
|
||||
|
||||
if (!seg.freeze) { //only run effect function if not frozen
|
||||
int oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based)
|
||||
// when correctWB is true we need to correct/adjust RGB value according to desired CCT value, but it will also affect actual WW/CW ratio
|
||||
// when cctFromRgb is true we implicitly calculate WW and CW from RGB values
|
||||
if (cctFromRgb) BusManager::setSegmentCCT(-1);
|
||||
else BusManager::setSegmentCCT(seg.currentCCT(), correctWB);
|
||||
// Effect blending
|
||||
uint16_t prog = seg.progress();
|
||||
seg.beginDraw(prog); // set up parameters for get/setPixelColor() (will also blend colors and palette if blend style is FADE)
|
||||
@ -1249,7 +1244,6 @@ void WS2812FX::service() {
|
||||
Segment::modeBlend(false); // unset semaphore
|
||||
}
|
||||
if (seg.isInTransition() && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition
|
||||
BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments
|
||||
}
|
||||
|
||||
seg.next_time = nowUp + frameDelay;
|
||||
@ -1324,6 +1318,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
|
||||
const unsigned progress = topSegment.progress();
|
||||
const unsigned progInv = 0xFFFFU - progress;
|
||||
uint8_t opacity = topSegment.currentBri(); // returns transitioned opacity for style FADE
|
||||
uint8_t cct = topSegment.currentCCT();
|
||||
|
||||
Segment::setClippingRect(0, 0); // disable clipping by default
|
||||
|
||||
@ -1396,6 +1391,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
|
||||
const int baseY = topSegment.startY + y;
|
||||
size_t indx = XY(baseX, baseY); // absolute address on strip
|
||||
_pixels[indx] = color_blend(_pixels[indx], blend(c, _pixels[indx]), o);
|
||||
if (_pixelCCT) _pixelCCT[indx] = cct;
|
||||
// Apply mirroring
|
||||
if (topSegment.mirror || topSegment.mirror_y) {
|
||||
const int mirrorX = topSegment.start + width - x - 1;
|
||||
@ -1406,6 +1402,11 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
|
||||
if (topSegment.mirror) _pixels[idxMX] = color_blend(_pixels[idxMX], blend(c, _pixels[idxMX]), o);
|
||||
if (topSegment.mirror_y) _pixels[idxMY] = color_blend(_pixels[idxMY], blend(c, _pixels[idxMY]), o);
|
||||
if (topSegment.mirror && topSegment.mirror_y) _pixels[idxMM] = color_blend(_pixels[idxMM], blend(c, _pixels[idxMM]), o);
|
||||
if (_pixelCCT) {
|
||||
if (topSegment.mirror) _pixelCCT[idxMX] = cct;
|
||||
if (topSegment.mirror_y) _pixelCCT[idxMY] = cct;
|
||||
if (topSegment.mirror && topSegment.mirror_y) _pixelCCT[idxMM] = cct;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1477,10 +1478,12 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
|
||||
indxM += topSegment.offset; // offset/phase
|
||||
if (indxM >= topSegment.stop) indxM -= length; // wrap
|
||||
_pixels[indxM] = color_blend(_pixels[indxM], blend(c, _pixels[indxM]), o);
|
||||
if (_pixelCCT) _pixelCCT[indxM] = cct;
|
||||
}
|
||||
indx += topSegment.offset; // offset/phase
|
||||
if (indx >= topSegment.stop) indx -= length; // wrap
|
||||
_pixels[indx] = color_blend(_pixels[indx], blend(c, _pixels[indx]), o);
|
||||
if (_pixelCCT) _pixelCCT[indx] = cct;
|
||||
};
|
||||
|
||||
// if we blend using "push" style we need to "shift" canvas to left/right/
|
||||
@ -1588,6 +1591,9 @@ void WS2812FX::show() {
|
||||
size_t diff = showNow - _lastShow;
|
||||
|
||||
size_t totalLen = getLengthTotal();
|
||||
_pixelCCT = static_cast<uint8_t*>(d_malloc(totalLen * sizeof(uint8_t))); // allocate CCT buffer if necessary
|
||||
if (_pixelCCT) memset(_pixelCCT, 127, totalLen); // set neutral (50:50) CCT
|
||||
|
||||
if (realtimeMode == REALTIME_MODE_INACTIVE || useMainSegmentOnly || realtimeOverride > REALTIME_OVERRIDE_NONE) {
|
||||
// clear frame buffer
|
||||
for (size_t i = 0; i < totalLen; i++) _pixels[i] = BLACK; // memset(_pixels, 0, sizeof(uint32_t) * getLengthTotal());
|
||||
@ -1606,7 +1612,23 @@ void WS2812FX::show() {
|
||||
if (newBri != _brightness) BusManager::setBrightness(newBri);
|
||||
|
||||
// paint actuall pixels
|
||||
for (size_t i = 0; i < totalLen; i++) BusManager::setPixelColor(getMappedPixelIndex(i), realtimeMode && arlsDisableGammaCorrection ? _pixels[i] : gamma32(_pixels[i]));
|
||||
// WARNING: as WLED doesn't handle CCT on pixel level but on Segment level instead
|
||||
// we need to determine to which segment a pixel belongs (may belong to several!!!)
|
||||
// and then set appropriate CCT from that segment for a particular pixel.
|
||||
int oldCCT = Bus::getCCT(); // store original CCT value (since it is global)
|
||||
for (size_t i = 0; i < totalLen; i++) {
|
||||
// when cctFromRgb is true we implicitly calculate WW and CW from RGB values (cct==-1)
|
||||
// when correctWB is true setSegmentCCT() will convert CCT into K with which we can then
|
||||
// correct/adjust RGB value according to desired CCT value, it will still affect actual WW/CW ratio
|
||||
if (_pixelCCT) {
|
||||
if (i == 0 || _pixelCCT[i-1] != _pixelCCT[i]) BusManager::setSegmentCCT(cctFromRgb ? -1 : _pixelCCT[i], correctWB);
|
||||
}
|
||||
BusManager::setPixelColor(getMappedPixelIndex(i), realtimeMode && arlsDisableGammaCorrection ? _pixels[i] : gamma32(_pixels[i]));
|
||||
}
|
||||
Bus::setCCT(oldCCT); // restore old CCT for ABL adjustments
|
||||
|
||||
d_free(_pixelCCT);
|
||||
_pixelCCT = nullptr;
|
||||
|
||||
// some buses send asynchronously and this method will return before
|
||||
// all of the data has been sent.
|
||||
|
Loading…
x
Reference in New Issue
Block a user