平滑混合光关机尾段

This commit is contained in:
2026-07-27 22:22:34 +08:00
parent f06b247c0d
commit 70979d3023
3 changed files with 113 additions and 4 deletions
@@ -27,6 +27,7 @@
#define BRIDGE_DUAL_ACTIVE_US 450U
#define BRIDGE_MIN_DUAL_PULSE_US 1U
#define BRIDGE_TIMER_TICKS_PER_US 16U
#define BRIDGE_PDM_THRESHOLD (BRIDGE_MIX_SCALE * 4096UL)
#define BRIDGE_GPIO_PORT 0U
#define BRIDGE_GPIO_MASK ((1UL << IO_PWM_W) | (1UL << IO_PWM_C))
@@ -62,6 +63,14 @@ static volatile uint16_t next_w_us;
static volatile uint16_t next_c_us;
static volatile uint16_t next_wc_off_us;
static volatile uint16_t next_cw_off_us;
static volatile uint32_t next_pdm_w_step;
static volatile uint32_t next_pdm_c_step;
static volatile uint8_t next_pdm_enabled;
static volatile uint32_t pdm_w_accumulator;
static volatile uint32_t pdm_c_accumulator;
static volatile uint8_t frame_pdm_enabled;
static volatile uint8_t frame_w_emit;
static volatile uint8_t frame_c_emit;
static uint16_t cached_w_mix = 0xFFFFU;
static uint16_t cached_c_mix = 0xFFFFU;
static uint8_t bridge_ready;
@@ -215,6 +224,14 @@ void Bridge_Off(void)
next_c_us = 0U;
next_wc_off_us = 0U;
next_cw_off_us = 0U;
next_pdm_w_step = 0U;
next_pdm_c_step = 0U;
next_pdm_enabled = 0U;
pdm_w_accumulator = 0U;
pdm_c_accumulator = 0U;
frame_pdm_enabled = 0U;
frame_w_emit = 0U;
frame_c_emit = 0U;
cached_w_mix = 0xFFFFU;
cached_c_mix = 0xFFFFU;
bridge_force_off();
@@ -223,6 +240,10 @@ void Bridge_Off(void)
__RAM_CODE void Bridge_Deadtime_Expired(void)
{
uint32_t w_step;
uint32_t c_step;
uint8_t pdm_enabled;
if (!bridge_ready ||
(deviceStatus == POWEROFF && !Light_Transition_FadeActive)) {
Bridge_Off();
@@ -238,7 +259,43 @@ __RAM_CODE void Bridge_Deadtime_Expired(void)
frame_c_us = next_c_us;
frame_wc_off_us = next_wc_off_us;
frame_cw_off_us = next_cw_off_us;
pdm_enabled = next_pdm_enabled;
w_step = next_pdm_w_step;
c_step = next_pdm_c_step;
if (pdm_enabled && !frame_pdm_enabled) {
pdm_w_accumulator = BRIDGE_PDM_THRESHOLD - w_step;
pdm_c_accumulator = BRIDGE_PDM_THRESHOLD - c_step;
}
frame_pdm_enabled = pdm_enabled;
if (frame_pdm_enabled) {
pdm_w_accumulator += w_step;
if (pdm_w_accumulator >= BRIDGE_PDM_THRESHOLD) {
pdm_w_accumulator -= BRIDGE_PDM_THRESHOLD;
frame_w_emit = 1U;
} else {
frame_w_emit = 0U;
}
pdm_c_accumulator += c_step;
if (pdm_c_accumulator >= BRIDGE_PDM_THRESHOLD) {
pdm_c_accumulator -= BRIDGE_PDM_THRESHOLD;
frame_c_emit = 1U;
} else {
frame_c_emit = 0U;
}
} else {
pdm_w_accumulator = 0U;
pdm_c_accumulator = 0U;
frame_w_emit = 1U;
frame_c_emit = 1U;
}
if (frame_w_emit)
bridge_gpio_state(BRIDGE_W);
else
bridge_gpio_off();
timer_stage = BRIDGE_STAGE_END_W;
bridge_timer_start(frame_w_us);
} else if (timer_stage == BRIDGE_STAGE_END_W) {
@@ -246,7 +303,10 @@ __RAM_CODE void Bridge_Deadtime_Expired(void)
timer_stage = BRIDGE_STAGE_START_C;
bridge_timer_start(frame_wc_off_us);
} else if (timer_stage == BRIDGE_STAGE_START_C) {
if (frame_c_emit)
bridge_gpio_state(BRIDGE_C);
else
bridge_gpio_off();
timer_stage = BRIDGE_STAGE_END_C;
bridge_timer_start(frame_c_us);
} else if (timer_stage == BRIDGE_STAGE_END_C) {
@@ -268,6 +328,8 @@ __RAM_CODE void Bridge_Service_1ms(void)
uint32_t total;
uint32_t total_on_us;
uint32_t total_off_us;
uint32_t pdm_w_step;
uint32_t pdm_c_step;
uint16_t pwm_duty;
uint8_t single_state;
@@ -283,6 +345,42 @@ __RAM_CODE void Bridge_Service_1ms(void)
c_mix = clamp_mix_value(C_PWM_duty);
total = w_mix + c_mix;
/*
* Below a physical 1 us pulse, keep the pulse width valid and distribute
* 1 us pulses across 2 kHz frames. This extends a mixed-light power-off
* fade below the normal timer resolution without creating sub-us edges.
*/
pdm_w_step =
BRIDGE_DUAL_ACTIVE_US * Light_Transition_W_Output_Q12;
pdm_c_step =
BRIDGE_DUAL_ACTIVE_US * Light_Transition_C_Output_Q12;
if (deviceStatus == POWEROFF && Light_Transition_FadeActive &&
pdm_w_step != 0U && pdm_c_step != 0U &&
pdm_w_step < BRIDGE_PDM_THRESHOLD &&
pdm_c_step < BRIDGE_PDM_THRESHOLD) {
next_w_us = BRIDGE_MIN_DUAL_PULSE_US;
next_c_us = BRIDGE_MIN_DUAL_PULSE_US;
total_off_us =
BRIDGE_FRAME_US - (2U * BRIDGE_MIN_DUAL_PULSE_US);
next_wc_off_us = (uint16_t)(total_off_us / 2U);
next_cw_off_us =
(uint16_t)(total_off_us - next_wc_off_us);
next_pdm_w_step = pdm_w_step;
next_pdm_c_step = pdm_c_step;
next_pdm_enabled = 1U;
cached_w_mix = (uint16_t)w_mix;
cached_c_mix = (uint16_t)c_mix;
goto dual_output_ready;
}
if (next_pdm_enabled) {
cached_w_mix = 0xFFFFU;
cached_c_mix = 0xFFFFU;
}
next_pdm_enabled = 0U;
next_pdm_w_step = 0U;
next_pdm_c_step = 0U;
if (total == 0U) {
Bridge_Off();
return;
@@ -351,6 +449,7 @@ __RAM_CODE void Bridge_Service_1ms(void)
cached_c_mix = (uint16_t)c_mix;
}
dual_output_ready:
if (output_mode == BRIDGE_MODE_DUAL &&
timer_stage != BRIDGE_STAGE_IDLE) {
return;
@@ -3,6 +3,8 @@
#include "light_transition.h"
volatile uint8_t Light_Transition_FadeActive;
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
@@ -230,6 +232,8 @@ void Light_Transition_Task(void)
uint16_t weak_mix;
uint16_t required_total;
uint16_t floor_w;
uint32_t scaled_w_q12;
uint32_t scaled_c_q12;
uint8_t power_transitioning;
/*
@@ -288,8 +292,12 @@ void Light_Transition_Task(void)
}
}
target_w = (uint16_t)(((uint32_t)target_w * fade_scale + 2048U) >> 12);
target_c = (uint16_t)(((uint32_t)target_c * fade_scale + 2048U) >> 12);
scaled_w_q12 = (uint32_t)target_w * fade_scale;
scaled_c_q12 = (uint32_t)target_c * fade_scale;
Light_Transition_W_Output_Q12 = scaled_w_q12;
Light_Transition_C_Output_Q12 = scaled_c_q12;
target_w = (uint16_t)((scaled_w_q12 + 2048U) >> 12);
target_c = (uint16_t)((scaled_c_q12 + 2048U) >> 12);
if(Mode == mode1 && powered_on && !power_transitioning)
{
@@ -4,6 +4,8 @@
#include <stdint.h>
extern volatile uint8_t Light_Transition_FadeActive;
extern volatile uint32_t Light_Transition_W_Output_Q12;
extern volatile uint32_t Light_Transition_C_Output_Q12;
#define Light_Transition_RequestOn() (Light_Transition_FadeActive = 0U)
#define Light_Transition_RequestOff() (Light_Transition_FadeActive = 1U)