Convert to RGB model (folds W/WW power back into RGB so the brightness limiter doesn't under-budget). Issue #2558 update: the white-channel mW values are no longer dropped. They're distributed evenly across the three RGB channels, which: - matches the brightness limiter's assumption that each RGB byte has a fixed mW cost at full drive (the limiter caps total predicted mW against a budget), - over
| 132 | /// accounting using all 5 mW values directly) is the right long-term |
| 133 | /// fix — see Phase G in issue #2558. |
| 134 | constexpr PowerModelRGB toRGB() const { |
| 135 | // Distribute white-channel mW evenly across R/G/B. Clamp to 255 (u8 |
| 136 | // max) on overflow — a wrapping static_cast<u8> here would make the |
| 137 | // brightness limiter *less* conservative on the highest-draw configs |
| 138 | // (where it most needs to be conservative). The worst-case |
| 139 | // under-budget per channel from the floor division is 2 mW. |
| 140 | return PowerModelRGB( |
| 141 | static_cast<fl::u8>( |
| 142 | (red_mW + (white_mW + warm_white_mW) / 3) > 255 |
| 143 | ? 255 : (red_mW + (white_mW + warm_white_mW) / 3)), |
| 144 | static_cast<fl::u8>( |
| 145 | (green_mW + (white_mW + warm_white_mW) / 3) > 255 |
| 146 | ? 255 : (green_mW + (white_mW + warm_white_mW) / 3)), |
| 147 | static_cast<fl::u8>( |
| 148 | (blue_mW + (white_mW + warm_white_mW) / 3) > 255 |
| 149 | ? 255 : (blue_mW + (white_mW + warm_white_mW) / 3)), |
| 150 | dark_mW, |
| 151 | exponent); |
| 152 | } |
| 153 | }; |
| 154 | |
| 155 | /// Set custom RGB LED power consumption model |
nothing calls this directly
no test coverage detected