From 9b1455209d401018ddeaefbeecf8423628a6c26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E7=90=AA?= Date: Mon, 27 Jul 2026 17:57:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E6=B7=B7=E8=89=B2=E6=AF=94=E4=BE=8B?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=AE=BE=E7=BD=AE=E6=9C=80=E4=BD=8E=E4=BA=AE?= =?UTF-8?q?=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ble_peripheral/app/src/light_transition.c | 58 ++++++++++++------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/project/example/ble/ble_peripheral/app/src/light_transition.c b/project/example/ble/ble_peripheral/app/src/light_transition.c index fda6d8e..0638635 100644 --- a/project/example/ble/ble_peripheral/app/src/light_transition.c +++ b/project/example/ble/ble_peripheral/app/src/light_transition.c @@ -8,7 +8,8 @@ volatile uint8_t Light_Transition_FadeActive; #define OUTPUT_SMOOTH_SHIFT 4U #define LIGHT_OUTPUT_SCALE 1000U #define BREATH_MIN_OUTPUT (LIGHT_OUTPUT_SCALE / 100U) -#define DUAL_CHANNEL_MIN_OUTPUT (LIGHT_OUTPUT_SCALE / 10U) +#define DUAL_MIN_COMBINED_OUTPUT (LIGHT_OUTPUT_SCALE / 10U) +#define DUAL_MIN_STABLE_CHANNEL_OUTPUT 17U #define POWER_FADE_Q12_MAX 4096U #define POWER_FADE_ON_TICKS 140U #define POWER_FADE_OFF_TICKS 160U @@ -195,6 +196,10 @@ void Light_Transition_Task(void) uint16_t target_brightness_scale; uint16_t brightness_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; /* @@ -220,32 +225,43 @@ void Light_Transition_Task(void) (LIGHT_OUTPUT_SCALE / 100U) + 2048U) >> 12); /* - * In mixed light, each active direction has a 10% floor. Scale both - * directions together from the weaker side so the requested W:C ratio is - * preserved whenever the stronger side remains within 100%. Single-color - * output keeps the 1% Gamma minimum. + * Mixed light starts from a 10% combined floor. If the weaker direction + * would be below 17/1000 (about 15 us of the 900 us active window), raise + * the combined floor just enough to preserve the requested W:C ratio. + * Ratios that cannot satisfy this even at 100% are treated as single + * color. Single-color output keeps the 1% Gamma minimum. */ - if(W_PWM != 0U && C_PWM != 0U && - (target_w < DUAL_CHANNEL_MIN_OUTPUT || - target_c < DUAL_CHANNEL_MIN_OUTPUT)) + if(W_PWM != 0U && C_PWM != 0U) { - if(W_PWM <= C_PWM) + 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) { - target_w = DUAL_CHANNEL_MIN_OUTPUT; - target_c = (uint16_t)( - ((uint32_t)DUAL_CHANNEL_MIN_OUTPUT * C_PWM + - (W_PWM / 2U)) / W_PWM); - if(target_c > LIGHT_OUTPUT_SCALE) - target_c = LIGHT_OUTPUT_SCALE; + if(W_PWM < C_PWM) + target_w = 0U; + else + target_c = 0U; } else { - target_c = DUAL_CHANNEL_MIN_OUTPUT; - target_w = (uint16_t)( - ((uint32_t)DUAL_CHANNEL_MIN_OUTPUT * W_PWM + - (C_PWM / 2U)) / C_PWM); - if(target_w > LIGHT_OUTPUT_SCALE) - target_w = LIGHT_OUTPUT_SCALE; + if(required_total < DUAL_MIN_COMBINED_OUTPUT) + required_total = DUAL_MIN_COMBINED_OUTPUT; + + 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; + } } }