按65微秒稳定阈值映射混合光亮度

This commit is contained in:
2026-07-27 21:23:11 +08:00
parent bf2b8e4796
commit 7263ad9ebc
@@ -8,6 +8,7 @@ volatile uint8_t Light_Transition_FadeActive;
#define OUTPUT_SMOOTH_SHIFT 4U #define OUTPUT_SMOOTH_SHIFT 4U
#define LIGHT_OUTPUT_SCALE 1000U #define LIGHT_OUTPUT_SCALE 1000U
#define BREATH_MIN_OUTPUT (LIGHT_OUTPUT_SCALE / 100U) #define BREATH_MIN_OUTPUT (LIGHT_OUTPUT_SCALE / 100U)
#define DUAL_MIN_STABLE_CHANNEL_OUTPUT 145U
#define POWER_FADE_Q12_MAX 4096U #define POWER_FADE_Q12_MAX 4096U
#define POWER_FADE_ON_TICKS 140U #define POWER_FADE_ON_TICKS 140U
#define POWER_FADE_OFF_TICKS 160U #define POWER_FADE_OFF_TICKS 160U
@@ -34,6 +35,25 @@ static const uint16_t brightness_gamma_q12[100] = {
3457U, 3525U, 3595U, 3664U, 3735U, 3806U, 3878U, 3950U, 4023U, 4096U 3457U, 3525U, 3595U, 3664U, 3735U, 3806U, 3878U, 3950U, 4023U, 4096U
}; };
/*
* Mixed-light Gamma table. Its first level equals the original 50% APP level
* (1184/4096), where a 50:50 mix measures about 65 us per direction at 2 kHz.
* The remaining range is expanded to 100%, so all brightness levels remain
* distinct instead of clamping the lower levels to one fixed output.
*/
static const uint16_t mixed_brightness_gamma_q12[100] = {
1184U, 1185U, 1187U, 1189U, 1193U, 1198U, 1203U, 1208U, 1216U, 1223U,
1231U, 1240U, 1249U, 1259U, 1270U, 1282U, 1293U, 1306U, 1319U, 1333U,
1348U, 1363U, 1378U, 1394U, 1411U, 1428U, 1446U, 1465U, 1484U, 1504U,
1524U, 1544U, 1565U, 1587U, 1609U, 1632U, 1655U, 1680U, 1703U, 1728U,
1753U, 1780U, 1806U, 1833U, 1860U, 1888U, 1916U, 1946U, 1975U, 2005U,
2036U, 2067U, 2097U, 2130U, 2162U, 2195U, 2228U, 2262U, 2296U, 2331U,
2366U, 2402U, 2438U, 2474U, 2512U, 2549U, 2587U, 2626U, 2665U, 2704U,
2744U, 2785U, 2826U, 2867U, 2908U, 2951U, 2993U, 3036U, 3080U, 3124U,
3168U, 3213U, 3259U, 3304U, 3351U, 3397U, 3444U, 3492U, 3539U, 3588U,
3637U, 3686U, 3736U, 3786U, 3837U, 3888U, 3939U, 3991U, 4044U, 4096U
};
/* /*
* Gamma 1.8 envelope for power-on/off. The transition progress is advanced * Gamma 1.8 envelope for power-on/off. The transition progress is advanced
* independently of the requested brightness, so every turn-on takes about * independently of the requested brightness, so every turn-on takes about
@@ -68,6 +88,18 @@ static uint16_t brightness_scale_for_level(uint8_t level)
return brightness_gamma_q12[level - 1U]; return brightness_gamma_q12[level - 1U];
} }
static uint16_t output_brightness_scale_for_level(uint8_t level)
{
if(level == 0U) return 0U;
if(level < BRIGHTNESS_MIN_PERCENT) level = BRIGHTNESS_MIN_PERCENT;
if(level > BRIGHTNESS_MAX_PERCENT) level = BRIGHTNESS_MAX_PERCENT;
if(W_PWM != 0U && C_PWM != 0U)
return mixed_brightness_gamma_q12[level - 1U];
return brightness_scale_for_level(level);
}
static uint16_t approach_brightness_scale(uint16_t current, uint16_t target) static uint16_t approach_brightness_scale(uint16_t current, uint16_t target)
{ {
uint16_t delta; uint16_t delta;
@@ -178,7 +210,7 @@ static void update_power_fade(uint8_t powered_on)
void Light_Transition_SyncBrightness(uint8_t level) void Light_Transition_SyncBrightness(uint8_t level)
{ {
current_brightness_q12 = brightness_scale_for_level(level); current_brightness_q12 = output_brightness_scale_for_level(level);
power_fade_progress_q12 = power_fade_progress_q12 =
level == 0U ? 0U : POWER_FADE_Q12_MAX; level == 0U ? 0U : POWER_FADE_Q12_MAX;
power_fade_remainder = 0U; power_fade_remainder = 0U;
@@ -194,13 +226,17 @@ void Light_Transition_Task(void)
uint16_t target_brightness_scale; uint16_t target_brightness_scale;
uint16_t brightness_scale; uint16_t brightness_scale;
uint16_t fade_scale; uint16_t fade_scale;
uint16_t mix_total;
uint16_t weak_mix;
uint16_t required_total;
uint16_t floor_w;
uint8_t power_transitioning; uint8_t power_transitioning;
/* /*
* Keep APP brightness tracking while off. Power fading is a separate * Keep APP brightness tracking while off. Power fading is a separate
* envelope, so on/off duration does not change with the saved brightness. * envelope, so on/off duration does not change with the saved brightness.
*/ */
target_brightness_scale = brightness_scale_for_level(Brightness); target_brightness_scale = output_brightness_scale_for_level(Brightness);
current_brightness_q12 = current_brightness_q12 =
approach_brightness_scale(current_brightness_q12, approach_brightness_scale(current_brightness_q12,
target_brightness_scale); target_brightness_scale);
@@ -218,6 +254,40 @@ void Light_Transition_Task(void)
(uint16_t)(((uint32_t)C_PWM * brightness_scale * (uint16_t)(((uint32_t)C_PWM * brightness_scale *
(LIGHT_OUTPUT_SCALE / 100U) + 2048U) >> 12); (LIGHT_OUTPUT_SCALE / 100U) + 2048U) >> 12);
/*
* Keep the weaker mixed-light direction at the measured stable threshold.
* Raise the combined output only when the requested W:C ratio needs it.
* A ratio that cannot provide 145/1000 to its weak side even at full
* brightness is treated as single color.
*/
if(W_PWM != 0U && C_PWM != 0U)
{
mix_total = (uint16_t)(W_PWM + C_PWM);
weak_mix = (W_PWM < C_PWM) ? W_PWM : C_PWM;
required_total = (uint16_t)(
((uint32_t)DUAL_MIN_STABLE_CHANNEL_OUTPUT * mix_total +
weak_mix - 1U) / weak_mix);
if(required_total > LIGHT_OUTPUT_SCALE)
{
if(W_PWM < C_PWM)
target_w = 0U;
else
target_c = 0U;
}
else if((uint16_t)(target_w + target_c) < required_total)
{
floor_w = (uint16_t)(
((uint32_t)required_total * W_PWM +
(mix_total / 2U)) / mix_total);
if(floor_w == 0U) floor_w = 1U;
if(floor_w >= required_total)
floor_w = required_total - 1U;
target_w = floor_w;
target_c = required_total - floor_w;
}
}
target_w = (uint16_t)(((uint32_t)target_w * fade_scale + 2048U) >> 12); target_w = (uint16_t)(((uint32_t)target_w * fade_scale + 2048U) >> 12);
target_c = (uint16_t)(((uint32_t)target_c * fade_scale + 2048U) >> 12); target_c = (uint16_t)(((uint32_t)target_c * fade_scale + 2048U) >> 12);