diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index 3da0ba83..5ddd214d 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -725,6 +725,10 @@ PROGMEM const char* const custom_reset_string[] = { #define LIGHT_USE_GAMMA 0 // Use gamma correction for color channels #define LIGHT_USE_CSS 1 // Use CSS style to report colors (1=> "#FF0000", 0=> "255,0,0") #define LIGHT_USE_RGB 0 // Use RGB color selector (1=> RGB, 0=> HSV) +#ifndef LIGHT_WHITE_FACTOR +#define LIGHT_WHITE_FACTOR 1 // When using LIGHT_USE_WHITE with uneven brightness LEDs, + // this factor is used to scale the white channel to match brightness +#endif #define LIGHT_USE_TRANSITIONS 1 // Transitions between colors #define LIGHT_TRANSITION_STEP 10 // Time in millis between each transtion step diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 440249e5..9fb1e074 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -636,6 +636,7 @@ #define MY92XX_DCKI_PIN 14 #define MY92XX_COMMAND MY92XX_COMMAND_DEFAULT #define MY92XX_MAPPING 4, 3, 5, 0, 1 + #define LIGHT_WHITE_FACTOR (0.1) // White LEDs are way more bright in the B1 #elif defined(ITEAD_SONOFF_LED) diff --git a/code/espurna/light.ino b/code/espurna/light.ino index 5aff8a2c..017ce428 100644 --- a/code/espurna/light.ino +++ b/code/espurna/light.ino @@ -89,31 +89,28 @@ void _generateBrightness() { // Convert RGB to RGBW if (_light_has_color && _light_use_white) { - unsigned char white, max_in, max_out; - double factor = 0; - - white = std::min(_light_channel[0].inputValue, std::min(_light_channel[1].inputValue, _light_channel[2].inputValue)); - max_in = std::max(_light_channel[0].inputValue, std::max(_light_channel[1].inputValue, _light_channel[2].inputValue)); - + // Substract the common part from RGB channels and add it to white channel. So [250,150,50] -> [200,100,0,50 + unsigned char white = std::min(_light_channel[0].inputValue, std::min(_light_channel[1].inputValue, _light_channel[2].inputValue)); for (unsigned int i=0; i < 3; i++) { _light_channel[i].value = _light_channel[i].inputValue - white; } _light_channel[3].value = white; _light_channel[3].inputValue = 0; - max_out = std::max(std::max(_light_channel[0].value, _light_channel[1].value), std::max(_light_channel[2].value, _light_channel[3].value)); - if (max_out > 0) { - factor = (double) (max_in / max_out); - } - // Scale up to equal input values. So [250,150,50] -> [200,100,0,50] -> [250, 125, 0, 63] + unsigned char max_in = std::max(_light_channel[0].inputValue, std::max(_light_channel[1].inputValue, _light_channel[2].inputValue)); + unsigned char max_out = std::max(std::max(_light_channel[0].value, _light_channel[1].value), std::max(_light_channel[2].value, _light_channel[3].value)); + double factor = (max_out > 0) ? (double) (max_in / max_out) : 0; for (unsigned int i=0; i < 4; i++) { _light_channel[i].value = round((double) _light_channel[i].value * factor * brightness); } - // Don't apply brightness, it is already in the inputValue: - if (_light_channel.size() == 5) { - _light_channel[4].value = _light_channel[4].inputValue; + // Scale white channel to match brightness + _light_channel[3].value = constrain(_light_channel[3].value * LIGHT_WHITE_FACTOR, 0, 255); + + // For the rest of channels, don't apply brightness, it is already in the inputValue: + for (unsigned char i=4; i < _light_channel.size(); i++) { + _light_channel[i].value = _light_channel[i].inputValue; } } else {