@@ -1224,11 +1224,6 @@ void WS2812FX::service() {
12241224 unsigned frameDelay = FRAMETIME;
12251225
12261226 if (!seg.freeze ) { // only run effect function if not frozen
1227- int oldCCT = BusManager::getSegmentCCT (); // store original CCT value (actually it is not Segment based)
1228- // 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
1229- // when cctFromRgb is true we implicitly calculate WW and CW from RGB values
1230- if (cctFromRgb) BusManager::setSegmentCCT (-1 );
1231- else BusManager::setSegmentCCT (seg.currentCCT (), correctWB);
12321227 // Effect blending
12331228 uint16_t prog = seg.progress ();
12341229 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() {
12491244 Segment::modeBlend (false ); // unset semaphore
12501245 }
12511246 if (seg.isInTransition () && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition
1252- BusManager::setSegmentCCT (oldCCT); // restore old CCT for ABL adjustments
12531247 }
12541248
12551249 seg.next_time = nowUp + frameDelay;
@@ -1324,6 +1318,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
13241318 const unsigned progress = topSegment.progress ();
13251319 const unsigned progInv = 0xFFFFU - progress;
13261320 uint8_t opacity = topSegment.currentBri (); // returns transitioned opacity for style FADE
1321+ uint8_t cct = topSegment.currentCCT ();
13271322
13281323 Segment::setClippingRect (0 , 0 ); // disable clipping by default
13291324
@@ -1396,6 +1391,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
13961391 const int baseY = topSegment.startY + y;
13971392 size_t indx = XY (baseX, baseY); // absolute address on strip
13981393 _pixels[indx] = color_blend (_pixels[indx], blend (c, _pixels[indx]), o);
1394+ if (_pixelCCT) _pixelCCT[indx] = cct;
13991395 // Apply mirroring
14001396 if (topSegment.mirror || topSegment.mirror_y ) {
14011397 const int mirrorX = topSegment.start + width - x - 1 ;
@@ -1406,6 +1402,11 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
14061402 if (topSegment.mirror ) _pixels[idxMX] = color_blend (_pixels[idxMX], blend (c, _pixels[idxMX]), o);
14071403 if (topSegment.mirror_y ) _pixels[idxMY] = color_blend (_pixels[idxMY], blend (c, _pixels[idxMY]), o);
14081404 if (topSegment.mirror && topSegment.mirror_y ) _pixels[idxMM] = color_blend (_pixels[idxMM], blend (c, _pixels[idxMM]), o);
1405+ if (_pixelCCT) {
1406+ if (topSegment.mirror ) _pixelCCT[idxMX] = cct;
1407+ if (topSegment.mirror_y ) _pixelCCT[idxMY] = cct;
1408+ if (topSegment.mirror && topSegment.mirror_y ) _pixelCCT[idxMM] = cct;
1409+ }
14091410 }
14101411 };
14111412
@@ -1477,10 +1478,12 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
14771478 indxM += topSegment.offset ; // offset/phase
14781479 if (indxM >= topSegment.stop ) indxM -= length; // wrap
14791480 _pixels[indxM] = color_blend (_pixels[indxM], blend (c, _pixels[indxM]), o);
1481+ if (_pixelCCT) _pixelCCT[indxM] = cct;
14801482 }
14811483 indx += topSegment.offset ; // offset/phase
14821484 if (indx >= topSegment.stop ) indx -= length; // wrap
14831485 _pixels[indx] = color_blend (_pixels[indx], blend (c, _pixels[indx]), o);
1486+ if (_pixelCCT) _pixelCCT[indx] = cct;
14841487 };
14851488
14861489 // if we blend using "push" style we need to "shift" canvas to left/right/
@@ -1588,6 +1591,13 @@ void WS2812FX::show() {
15881591 size_t diff = showNow - _lastShow;
15891592
15901593 size_t totalLen = getLengthTotal ();
1594+ // WARNING: as WLED doesn't handle CCT on pixel level but on Segment level instead
1595+ // we need to keep track of each pixel's CCT when blending segments (if CCT is present)
1596+ // and then set appropriate CCT from that pixel during paint (see below).
1597+ if ((hasCCTBus () || correctWB) && !cctFromRgb)
1598+ _pixelCCT = static_cast <uint8_t *>(d_malloc (totalLen * sizeof (uint8_t ))); // allocate CCT buffer if necessary
1599+ if (_pixelCCT) memset (_pixelCCT, 127 , totalLen); // set neutral (50:50) CCT
1600+
15911601 if (realtimeMode == REALTIME_MODE_INACTIVE || useMainSegmentOnly || realtimeOverride > REALTIME_OVERRIDE_NONE) {
15921602 // clear frame buffer
15931603 for (size_t i = 0 ; i < totalLen; i++) _pixels[i] = BLACK; // memset(_pixels, 0, sizeof(uint32_t) * getLengthTotal());
@@ -1605,8 +1615,22 @@ void WS2812FX::show() {
16051615 uint8_t newBri = estimateCurrentAndLimitBri (_brightness, _pixels);
16061616 if (newBri != _brightness) BusManager::setBrightness (newBri);
16071617
1608- // paint actuall pixels
1609- for (size_t i = 0 ; i < totalLen; i++) BusManager::setPixelColor (getMappedPixelIndex (i), realtimeMode && arlsDisableGammaCorrection ? _pixels[i] : gamma32 (_pixels[i]));
1618+ // paint actual pixels
1619+ int oldCCT = Bus::getCCT (); // store original CCT value (since it is global)
1620+ // when cctFromRgb is true we implicitly calculate WW and CW from RGB values (cct==-1)
1621+ if (cctFromRgb) BusManager::setSegmentCCT (-1 );
1622+ for (size_t i = 0 ; i < totalLen; i++) {
1623+ // when correctWB is true setSegmentCCT() will convert CCT into K with which we can then
1624+ // correct/adjust RGB value according to desired CCT value, it will still affect actual WW/CW ratio
1625+ if (_pixelCCT) { // cctFromRgb already exluded at allocation
1626+ if (i == 0 || _pixelCCT[i-1 ] != _pixelCCT[i]) BusManager::setSegmentCCT (_pixelCCT[i], correctWB);
1627+ }
1628+ BusManager::setPixelColor (getMappedPixelIndex (i), realtimeMode && arlsDisableGammaCorrection ? _pixels[i] : gamma32 (_pixels[i]));
1629+ }
1630+ Bus::setCCT (oldCCT); // restore old CCT for ABL adjustments
1631+
1632+ d_free (_pixelCCT);
1633+ _pixelCCT = nullptr ;
16101634
16111635 // some buses send asynchronously and this method will return before
16121636 // all of the data has been sent.
0 commit comments