@@ -563,19 +563,15 @@ void BusPwm::show() {
563
563
const unsigned maxBri = (1 <<_depth); // possible values: 16384 (14), 8192 (13), 4096 (12), 2048 (11), 1024 (10), 512 (9) and 256 (8)
564
564
[[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)
565
565
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
568
567
// 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
579
575
}
580
576
581
577
[[maybe_unused]] unsigned hPoint = 0 ; // phase shift (0 - maxBri)
0 commit comments