增加模式切换柔和过渡

This commit is contained in:
2026-07-27 22:54:20 +08:00
parent 70979d3023
commit b85b15df17
3 changed files with 100 additions and 17 deletions
@@ -21,6 +21,7 @@ uint8_t direction = 1; //
uint8_t choose_mode_falsg=0; //模式值
uint8_t choose_mode_bh=0; //模式变化
static uint8_t mode_entry_initialized;
uint16_t Color_table_static[3][2]={
{100,0}, // warm light
@@ -113,31 +114,32 @@ void set_mode(){
break;
case 6:
//暖光跳变
W_PWM=Color_table[0][0];
C_PWM=Color_table[0][1];
W_PWM=0;
C_PWM=0;
driveMode=1;//切换为暖光的底层输出
direction=1;//呼吸方向恢复默认值
direction=0;//呼吸方向恢复默认值
Mode=mode2;
break;
case 7:
//中性光跳变
W_PWM=Color_table[1][0];
C_PWM=Color_table[1][1];
W_PWM=0;
C_PWM=0;
driveMode=0;//切换为中性光的底层输出
direction=0;
Mode=mode2;
break;
case 8:
//冷光跳变
W_PWM=Color_table[2][0];
C_PWM=Color_table[2][1];
W_PWM=0;
C_PWM=0;
driveMode=2;//切换为中性光的底层输出
direction=1;//呼吸方向恢复默认值
direction=0;//呼吸方向恢复默认值
Mode=mode2;
break;
case 9:
//暖光中性光冷交替跳变,先从暖光跳变
W_PWM=Color_table[0][0];
C_PWM=Color_table[0][1];
W_PWM=0;
C_PWM=0;
driveMode=1;//切换为暖光的底层输出
direction=1;//呼吸方向恢复默认值
Mode=mode2;
@@ -147,6 +149,15 @@ void set_mode(){
Mode=mode0;
break;
}
if(mode_entry_initialized)
{
Light_Transition_BeginModeChange();
startTimer(&timer1,1);
}
else
{
mode_entry_initialized=1;
}
}
}
void Mode0(){ //常量
@@ -353,6 +364,7 @@ pfunc modefunctin[] = { //ģʽ
Mode3,
};
void choice_mode(){
if(Light_Transition_ModeActive) return;
if (!timer1.active && timer1.count == 0){
if(Mode==mode0){
startTimer(&timer1,1);
@@ -3,11 +3,13 @@
#include "light_transition.h"
volatile uint8_t Light_Transition_FadeActive;
volatile uint8_t Light_Transition_ModeActive;
volatile uint32_t Light_Transition_W_Output_Q12;
volatile uint32_t Light_Transition_C_Output_Q12;
#define BRIGHTNESS_SMOOTH_SHIFT 4U
#define OUTPUT_SMOOTH_SHIFT 4U
#define MODE_TRANSITION_TICKS 40U
#define LIGHT_OUTPUT_SCALE 1000U
#define BREATH_MIN_OUTPUT (LIGHT_OUTPUT_SCALE / 100U)
#define DUAL_MIN_STABLE_CHANNEL_OUTPUT 102U
@@ -81,6 +83,9 @@ static uint16_t power_fade_progress_q12;
static uint16_t power_fade_remainder;
static uint8_t power_fade_direction;
static uint8_t transition_sync_pending;
static uint16_t mode_transition_start_w;
static uint16_t mode_transition_start_c;
static uint8_t mode_transition_tick;
static uint16_t brightness_scale_for_level(uint8_t level)
{
@@ -142,6 +147,35 @@ static uint16_t approach_target(uint16_t current, uint16_t target)
return current - step;
}
static uint16_t interpolate_mode_output(uint16_t start, uint16_t target,
uint8_t tick)
{
uint32_t delta;
if(tick >= MODE_TRANSITION_TICKS) return target;
if(target >= start)
{
delta = (uint32_t)(target - start) * tick;
return (uint16_t)(start +
((delta + (MODE_TRANSITION_TICKS / 2U)) /
MODE_TRANSITION_TICKS));
}
delta = (uint32_t)(start - target) * tick;
return (uint16_t)(start -
((delta + (MODE_TRANSITION_TICKS / 2U)) /
MODE_TRANSITION_TICKS));
}
static uint16_t effect_gamma_output(uint16_t level)
{
if(level == 0U) return 0U;
if(level > 100U) level = 100U;
return (uint16_t)(
((uint32_t)brightness_gamma_q12[level - 1U] *
LIGHT_OUTPUT_SCALE + 2048U) >> 12);
}
static uint16_t power_fade_scale(uint16_t progress_q12)
{
uint32_t position;
@@ -220,6 +254,14 @@ void Light_Transition_SyncBrightness(uint8_t level)
transition_sync_pending = 1U;
}
void Light_Transition_BeginModeChange(void)
{
mode_transition_start_w = W_PWM_duty;
mode_transition_start_c = C_PWM_duty;
mode_transition_tick = 0U;
Light_Transition_ModeActive = 1U;
}
void Light_Transition_Task(void)
{
uint8_t powered_on = deviceStatus != POWEROFF;
@@ -236,6 +278,9 @@ void Light_Transition_Task(void)
uint32_t scaled_c_q12;
uint8_t power_transitioning;
if(!powered_on)
Light_Transition_ModeActive = 0U;
/*
* Keep APP brightness tracking while off. Power fading is a separate
* envelope, so on/off duration does not change with the saved brightness.
@@ -251,12 +296,24 @@ void Light_Transition_Task(void)
powered_on ? (power_fade_progress_q12 < POWER_FADE_Q12_MAX)
: (power_fade_progress_q12 != 0U);
target_w =
(uint16_t)(((uint32_t)W_PWM * brightness_scale *
(LIGHT_OUTPUT_SCALE / 100U) + 2048U) >> 12);
target_c =
(uint16_t)(((uint32_t)C_PWM * brightness_scale *
(LIGHT_OUTPUT_SCALE / 100U) + 2048U) >> 12);
if(Mode == mode1)
{
target_w = (uint16_t)(
((uint32_t)effect_gamma_output(W_PWM) *
brightness_scale + 2048U) >> 12);
target_c = (uint16_t)(
((uint32_t)effect_gamma_output(C_PWM) *
brightness_scale + 2048U) >> 12);
}
else
{
target_w =
(uint16_t)(((uint32_t)W_PWM * brightness_scale *
(LIGHT_OUTPUT_SCALE / 100U) + 2048U) >> 12);
target_c =
(uint16_t)(((uint32_t)C_PWM * brightness_scale *
(LIGHT_OUTPUT_SCALE / 100U) + 2048U) >> 12);
}
/*
* Keep the weaker mixed-light direction at the measured stable threshold.
@@ -307,7 +364,19 @@ void Light_Transition_Task(void)
target_c = BREATH_MIN_OUTPUT;
}
if((Mode == mode2 && powered_on) || power_transitioning ||
if(Light_Transition_ModeActive && powered_on && !power_transitioning)
{
mode_transition_tick++;
W_PWM_duty =
interpolate_mode_output(mode_transition_start_w, target_w,
mode_transition_tick);
C_PWM_duty =
interpolate_mode_output(mode_transition_start_c, target_c,
mode_transition_tick);
if(mode_transition_tick >= MODE_TRANSITION_TICKS)
Light_Transition_ModeActive = 0U;
}
else if((Mode == mode2 && powered_on) || power_transitioning ||
transition_sync_pending)
{
W_PWM_duty = target_w;
@@ -4,6 +4,7 @@
#include <stdint.h>
extern volatile uint8_t Light_Transition_FadeActive;
extern volatile uint8_t Light_Transition_ModeActive;
extern volatile uint32_t Light_Transition_W_Output_Q12;
extern volatile uint32_t Light_Transition_C_Output_Q12;
@@ -12,5 +13,6 @@ extern volatile uint32_t Light_Transition_C_Output_Q12;
void Light_Transition_Task(void);
void Light_Transition_SyncBrightness(uint8_t level);
void Light_Transition_BeginModeChange(void);
#endif