@@ -1224,11 +1224,6 @@ void WS2812FX::service() {
1224
1224
unsigned frameDelay = FRAMETIME;
1225
1225
1226
1226
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);
1232
1227
// Effect blending
1233
1228
uint16_t prog = seg.progress ();
1234
1229
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() {
1249
1244
Segment::modeBlend (false ); // unset semaphore
1250
1245
}
1251
1246
if (seg.isInTransition () && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition
1252
- BusManager::setSegmentCCT (oldCCT); // restore old CCT for ABL adjustments
1253
1247
}
1254
1248
1255
1249
seg.next_time = nowUp + frameDelay;
@@ -1324,6 +1318,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
1324
1318
const unsigned progress = topSegment.progress ();
1325
1319
const unsigned progInv = 0xFFFFU - progress;
1326
1320
uint8_t opacity = topSegment.currentBri (); // returns transitioned opacity for style FADE
1321
+ uint8_t cct = topSegment.currentCCT ();
1327
1322
1328
1323
Segment::setClippingRect (0 , 0 ); // disable clipping by default
1329
1324
@@ -1396,6 +1391,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
1396
1391
const int baseY = topSegment.startY + y;
1397
1392
size_t indx = XY (baseX, baseY); // absolute address on strip
1398
1393
_pixels[indx] = color_blend (_pixels[indx], blend (c, _pixels[indx]), o);
1394
+ if (_pixelCCT) _pixelCCT[indx] = cct;
1399
1395
// Apply mirroring
1400
1396
if (topSegment.mirror || topSegment.mirror_y ) {
1401
1397
const int mirrorX = topSegment.start + width - x - 1 ;
@@ -1406,6 +1402,11 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
1406
1402
if (topSegment.mirror ) _pixels[idxMX] = color_blend (_pixels[idxMX], blend (c, _pixels[idxMX]), o);
1407
1403
if (topSegment.mirror_y ) _pixels[idxMY] = color_blend (_pixels[idxMY], blend (c, _pixels[idxMY]), o);
1408
1404
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
+ }
1409
1410
}
1410
1411
};
1411
1412
@@ -1477,10 +1478,12 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
1477
1478
indxM += topSegment.offset ; // offset/phase
1478
1479
if (indxM >= topSegment.stop ) indxM -= length; // wrap
1479
1480
_pixels[indxM] = color_blend (_pixels[indxM], blend (c, _pixels[indxM]), o);
1481
+ if (_pixelCCT) _pixelCCT[indxM] = cct;
1480
1482
}
1481
1483
indx += topSegment.offset ; // offset/phase
1482
1484
if (indx >= topSegment.stop ) indx -= length; // wrap
1483
1485
_pixels[indx] = color_blend (_pixels[indx], blend (c, _pixels[indx]), o);
1486
+ if (_pixelCCT) _pixelCCT[indx] = cct;
1484
1487
};
1485
1488
1486
1489
// if we blend using "push" style we need to "shift" canvas to left/right/
@@ -1588,6 +1591,13 @@ void WS2812FX::show() {
1588
1591
size_t diff = showNow - _lastShow;
1589
1592
1590
1593
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
+
1591
1601
if (realtimeMode == REALTIME_MODE_INACTIVE || useMainSegmentOnly || realtimeOverride > REALTIME_OVERRIDE_NONE) {
1592
1602
// clear frame buffer
1593
1603
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() {
1605
1615
uint8_t newBri = estimateCurrentAndLimitBri (_brightness, _pixels);
1606
1616
if (newBri != _brightness) BusManager::setBrightness (newBri);
1607
1617
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 ;
1610
1634
1611
1635
// some buses send asynchronously and this method will return before
1612
1636
// all of the data has been sent.
0 commit comments