mirror of https://github.com/arendst/Tasmota.git
Fix Improved fade linearity with gamma correction
This commit is contained in:
parent
287b3b97f1
commit
579a76ced6
|
@ -5,6 +5,7 @@
|
||||||
- Add support for ``AdcParam`` parameters to control ADC0 Current Transformer Apparent Power formula by Jodi Dillon (#7100)
|
- Add support for ``AdcParam`` parameters to control ADC0 Current Transformer Apparent Power formula by Jodi Dillon (#7100)
|
||||||
- Fix LCD line and column positioning (#7387)
|
- Fix LCD line and column positioning (#7387)
|
||||||
- Fix Display handling of hexadecimal escape characters (#7387)
|
- Fix Display handling of hexadecimal escape characters (#7387)
|
||||||
|
- Fix Improved fade linearity with gamma correction
|
||||||
|
|
||||||
### 8.1.0.1 20191225
|
### 8.1.0.1 20191225
|
||||||
|
|
||||||
|
|
|
@ -185,9 +185,8 @@ const gamma_table_t gamma_table[] = { // don't put in PROGMEM for performance
|
||||||
|
|
||||||
// simplified Gamma table for Fade, cheating a little at low brightness
|
// simplified Gamma table for Fade, cheating a little at low brightness
|
||||||
const gamma_table_t gamma_table_fast[] = {
|
const gamma_table_t gamma_table_fast[] = {
|
||||||
{ 0, 0 },
|
{ 384, 192 },
|
||||||
{ 384, 67 },
|
{ 768, 576 },
|
||||||
{ 768, 467 },
|
|
||||||
{ 1023, 1023 },
|
{ 1023, 1023 },
|
||||||
{ 0xFFFF, 0xFFFF } // fail-safe if out of range
|
{ 0xFFFF, 0xFFFF } // fail-safe if out of range
|
||||||
};
|
};
|
||||||
|
@ -264,6 +263,7 @@ struct LIGHT {
|
||||||
bool update = true;
|
bool update = true;
|
||||||
bool pwm_multi_channels = false; // SetOption68, treat each PWM channel as an independant dimmer
|
bool pwm_multi_channels = false; // SetOption68, treat each PWM channel as an independant dimmer
|
||||||
|
|
||||||
|
bool fade_initialized = false; // dont't fade at startup
|
||||||
bool fade_running = false;
|
bool fade_running = false;
|
||||||
uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0};
|
uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0};
|
||||||
uint16_t fade_cur_10[LST_MAX];
|
uint16_t fade_cur_10[LST_MAX];
|
||||||
|
@ -1110,9 +1110,20 @@ uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) {
|
||||||
from_gamma = to_gamma;
|
from_gamma = to_gamma;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 10_10 bits, fast fade mode
|
// Calculate the reverse gamma value for LEDS
|
||||||
uint16_t ledGamma10_10_fast(uint16_t v) {
|
uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) {
|
||||||
return ledGamma_internal(v, gamma_table_fast);
|
uint16_t from_src = 0;
|
||||||
|
uint16_t from_gamma = 0;
|
||||||
|
|
||||||
|
for (const gamma_table_t *gt = gt_ptr; ; gt++) {
|
||||||
|
uint16_t to_src = gt->to_src;
|
||||||
|
uint16_t to_gamma = gt->to_gamma;
|
||||||
|
if (vg <= to_gamma) {
|
||||||
|
return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src);
|
||||||
|
}
|
||||||
|
from_src = to_src;
|
||||||
|
from_gamma = to_gamma;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10 bits in, 10 bits out
|
// 10 bits in, 10 bits out
|
||||||
|
@ -1740,11 +1751,12 @@ void LightAnimate(void)
|
||||||
cur_col_10[i] = orig_col_10bits[Light.color_remap[i]];
|
cur_col_10[i] = orig_col_10bits[Light.color_remap[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Settings.light_fade || power_off) { // no fade
|
if (!Settings.light_fade || power_off || (!Light.fade_initialized)) { // no fade
|
||||||
// record the current value for a future Fade
|
// record the current value for a future Fade
|
||||||
memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10));
|
memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10));
|
||||||
// push the final values at 8 and 10 bits resolution to the PWMs
|
// push the final values at 8 and 10 bits resolution to the PWMs
|
||||||
LightSetOutputs(cur_col_10);
|
LightSetOutputs(cur_col_10);
|
||||||
|
Light.fade_initialized = true; // it is now ok to fade
|
||||||
} else { // fade on
|
} else { // fade on
|
||||||
if (Light.fade_running) {
|
if (Light.fade_running) {
|
||||||
// if fade is running, we take the curring value as the start for the next fade
|
// if fade is running, we take the curring value as the start for the next fade
|
||||||
|
@ -1768,6 +1780,33 @@ void LightAnimate(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isChannelGammaCorrected(uint32_t channel) {
|
||||||
|
if (!Settings.light_correction) { return false; } // Gamma correction not activated
|
||||||
|
if (channel >= Light.subtype) { return false; } // Out of range
|
||||||
|
|
||||||
|
if (PHILIPS == my_module_type) {
|
||||||
|
if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } // PMW reserved for CT
|
||||||
|
if ((LST_RGBWC == Light.subtype) && (4 == channel)) { return false; } // PMW reserved for CT
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the Gamma correction, if any, for fading, using the fast Gamma curve (10 bits in+out)
|
||||||
|
uint16_t fadeGamma(uint32_t channel, uint16_t v) {
|
||||||
|
if (isChannelGammaCorrected(channel)) {
|
||||||
|
return ledGamma_internal(v, gamma_table_fast);
|
||||||
|
} else {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg) {
|
||||||
|
if (isChannelGammaCorrected(channel)) {
|
||||||
|
return ledGammaReverse_internal(vg, gamma_table_fast);
|
||||||
|
} else {
|
||||||
|
return vg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool LightApplyFade(void) { // did the value chanegd and needs to be applied
|
bool LightApplyFade(void) { // did the value chanegd and needs to be applied
|
||||||
static uint32_t last_millis = 0;
|
static uint32_t last_millis = 0;
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
|
@ -1783,7 +1822,7 @@ bool LightApplyFade(void) { // did the value chanegd and needs to be applied
|
||||||
// compute the distance between start and and color (max of distance for each channel)
|
// compute the distance between start and and color (max of distance for each channel)
|
||||||
uint32_t distance = 0;
|
uint32_t distance = 0;
|
||||||
for (uint32_t i = 0; i < Light.subtype; i++) {
|
for (uint32_t i = 0; i < Light.subtype; i++) {
|
||||||
int32_t channel_distance = Light.fade_end_10[i] - Light.fade_start_10[i];
|
int32_t channel_distance = fadeGammaReverse(i, Light.fade_end_10[i]) - fadeGammaReverse(i, Light.fade_start_10[i]);
|
||||||
if (channel_distance < 0) { channel_distance = - channel_distance; }
|
if (channel_distance < 0) { channel_distance = - channel_distance; }
|
||||||
if (channel_distance > distance) { distance = channel_distance; }
|
if (channel_distance > distance) { distance = channel_distance; }
|
||||||
}
|
}
|
||||||
|
@ -1810,9 +1849,14 @@ bool LightApplyFade(void) { // did the value chanegd and needs to be applied
|
||||||
if (fade_current <= Light.fade_duration) { // fade not finished
|
if (fade_current <= Light.fade_duration) { // fade not finished
|
||||||
//Serial.printf("Fade: %d / %d - ", fade_current, Light.fade_duration);
|
//Serial.printf("Fade: %d / %d - ", fade_current, Light.fade_duration);
|
||||||
for (uint32_t i = 0; i < Light.subtype; i++) {
|
for (uint32_t i = 0; i < Light.subtype; i++) {
|
||||||
Light.fade_cur_10[i] = changeUIntScale(fade_current,
|
Light.fade_cur_10[i] = fadeGamma(i,
|
||||||
0, Light.fade_duration,
|
changeUIntScale(fadeGammaReverse(i, fade_current),
|
||||||
Light.fade_start_10[i], Light.fade_end_10[i]);
|
0, Light.fade_duration,
|
||||||
|
fadeGammaReverse(i, Light.fade_start_10[i]),
|
||||||
|
fadeGammaReverse(i, Light.fade_end_10[i])));
|
||||||
|
// Light.fade_cur_10[i] = changeUIntScale(fade_current,
|
||||||
|
// 0, Light.fade_duration,
|
||||||
|
// Light.fade_start_10[i], Light.fade_end_10[i]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// stop fade
|
// stop fade
|
||||||
|
|
Loading…
Reference in New Issue