@@ -563,19 +563,15 @@ void BusPwm::show() {
563563 const unsigned maxBri = (1 <<_depth); // possible values: 16384 (14), 8192 (13), 4096 (12), 2048 (11), 1024 (10), 512 (9) and 256 (8)
564564 [[maybe_unused]] const unsigned bitShift = dithering * 4 ; // if dithering, _depth is 12 bit but LEDC channel is set to 8 bit (using 4 fractional bits)
565565
566- // use CIE brightness formula (cubic) to fit (or approximate linearity of) human eye perceived brightness
567- // the formula is based on 12 bit resolution as there is no need for greater precision
566+ // use CIE brightness formula (linear + cubic) to approximate human eye perceived brightness
568567 // see: https://en.wikipedia.org/wiki/Lightness
569- unsigned pwmBri = (unsigned )_bri * 100 ; // enlarge to use integer math for linear response
570- if (pwmBri < 2040 ) {
571- // linear response for values [0-20]
572- pwmBri = ((pwmBri << 12 ) + 115043 ) / 230087 ; // adding '0.5' before division for correct rounding
573- } else {
574- // cubic response for values [21-255]
575- pwmBri += 4080 ;
576- float temp = (float )pwmBri / 29580 .0f ;
577- temp = temp * temp * temp * (float )maxBri;
578- pwmBri = (unsigned )temp; // pwmBri is in range [0-maxBri]
568+ unsigned pwmBri = _bri;
569+ if (pwmBri < 21 ) { // linear response for values [0-20]
570+ pwmBri = (pwmBri * maxBri + 2300 / 2 ) / 2300 ; // adding '0.5' before division for correct rounding, 2300 gives a good match to CIE curve
571+ } else { // cubic response for values [21-255]
572+ float temp = float (pwmBri + 41 ) / float (255 + 41 ); // 41 is to match offset & slope to linear part
573+ temp = temp * temp * temp * (float )maxBri;
574+ pwmBri = (unsigned )temp; // pwmBri is in range [0-maxBri] C
579575 }
580576
581577 [[maybe_unused]] unsigned hPoint = 0 ; // phase shift (0 - maxBri)
0 commit comments