使用PDM平滑三色呼吸低亮度
This commit is contained in:
@@ -19,8 +19,6 @@ uint8_t Mode=mode0; //mode0 1 2 3 4
|
|||||||
uint8_t Speed=5; //速度
|
uint8_t Speed=5; //速度
|
||||||
uint8_t direction = 1; // 呼吸灯的亮度变化方向,1表示增加,0表示减小
|
uint8_t direction = 1; // 呼吸灯的亮度变化方向,1表示增加,0表示减小
|
||||||
|
|
||||||
#define THREE_COLOR_SINGLE_JOIN_LEVEL 41U
|
|
||||||
|
|
||||||
uint8_t choose_mode_falsg=0; //模式值
|
uint8_t choose_mode_falsg=0; //模式值
|
||||||
uint8_t choose_mode_bh=0; //模式变化
|
uint8_t choose_mode_bh=0; //模式变化
|
||||||
static uint8_t mode_entry_initialized;
|
static uint8_t mode_entry_initialized;
|
||||||
@@ -232,7 +230,7 @@ void Mode1(){ //
|
|||||||
breathespeed_flag=0;
|
breathespeed_flag=0;
|
||||||
W_PWM -= 1;
|
W_PWM -= 1;
|
||||||
C_PWM = 0;
|
C_PWM = 0;
|
||||||
if (W_PWM <= THREE_COLOR_SINGLE_JOIN_LEVEL) {
|
if (W_PWM <= 1) {
|
||||||
direction = 2;
|
direction = 2;
|
||||||
driveMode=0;
|
driveMode=0;
|
||||||
W_PWM = 1;
|
W_PWM = 1;
|
||||||
@@ -257,7 +255,7 @@ void Mode1(){ //
|
|||||||
driveMode=2;
|
driveMode=2;
|
||||||
direction = 4;
|
direction = 4;
|
||||||
W_PWM = 0;
|
W_PWM = 0;
|
||||||
C_PWM = THREE_COLOR_SINGLE_JOIN_LEVEL;
|
C_PWM = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
@@ -274,10 +272,10 @@ void Mode1(){ //
|
|||||||
breathespeed_flag=0;
|
breathespeed_flag=0;
|
||||||
W_PWM = 0;
|
W_PWM = 0;
|
||||||
C_PWM -= 1;
|
C_PWM -= 1;
|
||||||
if (C_PWM <= THREE_COLOR_SINGLE_JOIN_LEVEL){
|
if (C_PWM <=1){
|
||||||
direction = 0;
|
direction = 0;
|
||||||
driveMode=1;
|
driveMode=1;
|
||||||
W_PWM = THREE_COLOR_SINGLE_JOIN_LEVEL;
|
W_PWM = 1;
|
||||||
C_PWM = 0;
|
C_PWM = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
* OFF -> W pulse -> OFF -> C pulse -> OFF to frame end.
|
* OFF -> W pulse -> OFF -> C pulse -> OFF to frame end.
|
||||||
* The available OFF time is distributed around both direction changes and
|
* The available OFF time is distributed around both direction changes and
|
||||||
* each W/C transition retains at least 25 us protection.
|
* each W/C transition retains at least 25 us protection.
|
||||||
* Both non-zero colors therefore produce exactly one pulse per frame (2 kHz).
|
* Normal dual-color output produces one pulse per color per frame (2 kHz).
|
||||||
|
* Low-level three-color breathing keeps 50 us pulses but density-modulates
|
||||||
|
* them across frames so the average output can fade below that pulse width.
|
||||||
*/
|
*/
|
||||||
#define BRIDGE_PWM_SCALE 1000U
|
#define BRIDGE_PWM_SCALE 1000U
|
||||||
#define BRIDGE_PWM_PERIOD 6U
|
#define BRIDGE_PWM_PERIOD 6U
|
||||||
@@ -26,8 +28,11 @@
|
|||||||
#define BRIDGE_DEADTIME_US 25U
|
#define BRIDGE_DEADTIME_US 25U
|
||||||
#define BRIDGE_DUAL_ACTIVE_US 450U
|
#define BRIDGE_DUAL_ACTIVE_US 450U
|
||||||
#define BRIDGE_MIN_DUAL_PULSE_US 1U
|
#define BRIDGE_MIN_DUAL_PULSE_US 1U
|
||||||
|
#define BRIDGE_TRICOLOR_PDM_PULSE_US 50U
|
||||||
#define BRIDGE_TIMER_TICKS_PER_US 16U
|
#define BRIDGE_TIMER_TICKS_PER_US 16U
|
||||||
#define BRIDGE_PDM_THRESHOLD (BRIDGE_MIX_SCALE * 4096UL)
|
#define BRIDGE_PDM_THRESHOLD (BRIDGE_MIX_SCALE * 4096UL)
|
||||||
|
#define BRIDGE_TRICOLOR_PDM_THRESHOLD \
|
||||||
|
(BRIDGE_TRICOLOR_PDM_PULSE_US * BRIDGE_PDM_THRESHOLD)
|
||||||
|
|
||||||
#define BRIDGE_GPIO_PORT 0U
|
#define BRIDGE_GPIO_PORT 0U
|
||||||
#define BRIDGE_GPIO_MASK ((1UL << IO_PWM_W) | (1UL << IO_PWM_C))
|
#define BRIDGE_GPIO_MASK ((1UL << IO_PWM_W) | (1UL << IO_PWM_C))
|
||||||
@@ -65,9 +70,11 @@ static volatile uint16_t next_wc_off_us;
|
|||||||
static volatile uint16_t next_cw_off_us;
|
static volatile uint16_t next_cw_off_us;
|
||||||
static volatile uint32_t next_pdm_w_step;
|
static volatile uint32_t next_pdm_w_step;
|
||||||
static volatile uint32_t next_pdm_c_step;
|
static volatile uint32_t next_pdm_c_step;
|
||||||
|
static volatile uint32_t next_pdm_threshold;
|
||||||
static volatile uint8_t next_pdm_enabled;
|
static volatile uint8_t next_pdm_enabled;
|
||||||
static volatile uint32_t pdm_w_accumulator;
|
static volatile uint32_t pdm_w_accumulator;
|
||||||
static volatile uint32_t pdm_c_accumulator;
|
static volatile uint32_t pdm_c_accumulator;
|
||||||
|
static volatile uint32_t frame_pdm_threshold;
|
||||||
static volatile uint8_t frame_pdm_enabled;
|
static volatile uint8_t frame_pdm_enabled;
|
||||||
static volatile uint8_t frame_w_emit;
|
static volatile uint8_t frame_w_emit;
|
||||||
static volatile uint8_t frame_c_emit;
|
static volatile uint8_t frame_c_emit;
|
||||||
@@ -226,9 +233,11 @@ void Bridge_Off(void)
|
|||||||
next_cw_off_us = 0U;
|
next_cw_off_us = 0U;
|
||||||
next_pdm_w_step = 0U;
|
next_pdm_w_step = 0U;
|
||||||
next_pdm_c_step = 0U;
|
next_pdm_c_step = 0U;
|
||||||
|
next_pdm_threshold = 0U;
|
||||||
next_pdm_enabled = 0U;
|
next_pdm_enabled = 0U;
|
||||||
pdm_w_accumulator = 0U;
|
pdm_w_accumulator = 0U;
|
||||||
pdm_c_accumulator = 0U;
|
pdm_c_accumulator = 0U;
|
||||||
|
frame_pdm_threshold = 0U;
|
||||||
frame_pdm_enabled = 0U;
|
frame_pdm_enabled = 0U;
|
||||||
frame_w_emit = 0U;
|
frame_w_emit = 0U;
|
||||||
frame_c_emit = 0U;
|
frame_c_emit = 0U;
|
||||||
@@ -242,6 +251,7 @@ __RAM_CODE void Bridge_Deadtime_Expired(void)
|
|||||||
{
|
{
|
||||||
uint32_t w_step;
|
uint32_t w_step;
|
||||||
uint32_t c_step;
|
uint32_t c_step;
|
||||||
|
uint32_t pdm_threshold;
|
||||||
uint8_t pdm_enabled;
|
uint8_t pdm_enabled;
|
||||||
|
|
||||||
if (!bridge_ready ||
|
if (!bridge_ready ||
|
||||||
@@ -262,25 +272,29 @@ __RAM_CODE void Bridge_Deadtime_Expired(void)
|
|||||||
pdm_enabled = next_pdm_enabled;
|
pdm_enabled = next_pdm_enabled;
|
||||||
w_step = next_pdm_w_step;
|
w_step = next_pdm_w_step;
|
||||||
c_step = next_pdm_c_step;
|
c_step = next_pdm_c_step;
|
||||||
|
pdm_threshold = next_pdm_threshold;
|
||||||
|
|
||||||
if (pdm_enabled && !frame_pdm_enabled) {
|
if (pdm_enabled &&
|
||||||
pdm_w_accumulator = BRIDGE_PDM_THRESHOLD - w_step;
|
(!frame_pdm_enabled ||
|
||||||
pdm_c_accumulator = BRIDGE_PDM_THRESHOLD - c_step;
|
frame_pdm_threshold != pdm_threshold)) {
|
||||||
|
pdm_w_accumulator = pdm_threshold - w_step;
|
||||||
|
pdm_c_accumulator = pdm_threshold - c_step;
|
||||||
}
|
}
|
||||||
frame_pdm_enabled = pdm_enabled;
|
frame_pdm_enabled = pdm_enabled;
|
||||||
|
frame_pdm_threshold = pdm_enabled ? pdm_threshold : 0U;
|
||||||
|
|
||||||
if (frame_pdm_enabled) {
|
if (frame_pdm_enabled) {
|
||||||
pdm_w_accumulator += w_step;
|
pdm_w_accumulator += w_step;
|
||||||
if (pdm_w_accumulator >= BRIDGE_PDM_THRESHOLD) {
|
if (pdm_w_accumulator >= frame_pdm_threshold) {
|
||||||
pdm_w_accumulator -= BRIDGE_PDM_THRESHOLD;
|
pdm_w_accumulator -= frame_pdm_threshold;
|
||||||
frame_w_emit = 1U;
|
frame_w_emit = 1U;
|
||||||
} else {
|
} else {
|
||||||
frame_w_emit = 0U;
|
frame_w_emit = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdm_c_accumulator += c_step;
|
pdm_c_accumulator += c_step;
|
||||||
if (pdm_c_accumulator >= BRIDGE_PDM_THRESHOLD) {
|
if (pdm_c_accumulator >= frame_pdm_threshold) {
|
||||||
pdm_c_accumulator -= BRIDGE_PDM_THRESHOLD;
|
pdm_c_accumulator -= frame_pdm_threshold;
|
||||||
frame_c_emit = 1U;
|
frame_c_emit = 1U;
|
||||||
} else {
|
} else {
|
||||||
frame_c_emit = 0U;
|
frame_c_emit = 0U;
|
||||||
@@ -367,6 +381,36 @@ __RAM_CODE void Bridge_Service_1ms(void)
|
|||||||
(uint16_t)(total_off_us - next_wc_off_us);
|
(uint16_t)(total_off_us - next_wc_off_us);
|
||||||
next_pdm_w_step = pdm_w_step;
|
next_pdm_w_step = pdm_w_step;
|
||||||
next_pdm_c_step = pdm_c_step;
|
next_pdm_c_step = pdm_c_step;
|
||||||
|
next_pdm_threshold = BRIDGE_PDM_THRESHOLD;
|
||||||
|
next_pdm_enabled = 1U;
|
||||||
|
cached_w_mix = (uint16_t)w_mix;
|
||||||
|
cached_c_mix = (uint16_t)c_mix;
|
||||||
|
goto dual_output_ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The low part of the three-color breathing effect cannot use short
|
||||||
|
* continuous W/C pulses reliably. Emit verified 50 us pulses and vary
|
||||||
|
* their density across the fixed 2 kHz frames instead. At the configured
|
||||||
|
* minimum output this gives about 450 emitted pulses per second.
|
||||||
|
*/
|
||||||
|
if (deviceStatus != POWEROFF &&
|
||||||
|
Mode == mode1 && choose_mode_falsg == 5U &&
|
||||||
|
w_mix != 0U && c_mix != 0U &&
|
||||||
|
pdm_w_step != 0U && pdm_c_step != 0U &&
|
||||||
|
pdm_w_step < BRIDGE_TRICOLOR_PDM_THRESHOLD &&
|
||||||
|
pdm_c_step < BRIDGE_TRICOLOR_PDM_THRESHOLD) {
|
||||||
|
next_w_us = BRIDGE_TRICOLOR_PDM_PULSE_US;
|
||||||
|
next_c_us = BRIDGE_TRICOLOR_PDM_PULSE_US;
|
||||||
|
total_off_us =
|
||||||
|
BRIDGE_FRAME_US -
|
||||||
|
(2U * BRIDGE_TRICOLOR_PDM_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_threshold = BRIDGE_TRICOLOR_PDM_THRESHOLD;
|
||||||
next_pdm_enabled = 1U;
|
next_pdm_enabled = 1U;
|
||||||
cached_w_mix = (uint16_t)w_mix;
|
cached_w_mix = (uint16_t)w_mix;
|
||||||
cached_c_mix = (uint16_t)c_mix;
|
cached_c_mix = (uint16_t)c_mix;
|
||||||
@@ -380,6 +424,7 @@ __RAM_CODE void Bridge_Service_1ms(void)
|
|||||||
next_pdm_enabled = 0U;
|
next_pdm_enabled = 0U;
|
||||||
next_pdm_w_step = 0U;
|
next_pdm_w_step = 0U;
|
||||||
next_pdm_c_step = 0U;
|
next_pdm_c_step = 0U;
|
||||||
|
next_pdm_threshold = 0U;
|
||||||
|
|
||||||
if (total == 0U) {
|
if (total == 0U) {
|
||||||
Bridge_Off();
|
Bridge_Off();
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ volatile uint32_t Light_Transition_C_Output_Q12;
|
|||||||
#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 102U
|
#define DUAL_MIN_STABLE_CHANNEL_OUTPUT 102U
|
||||||
#define THREE_COLOR_JOIN_OUTPUT (2U * DUAL_MIN_STABLE_CHANNEL_OUTPUT)
|
#define THREE_COLOR_MIN_CHANNEL_OUTPUT 25U
|
||||||
|
#define THREE_COLOR_MIN_SINGLE_OUTPUT 45U
|
||||||
#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
|
||||||
@@ -355,19 +356,26 @@ void Light_Transition_Task(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The three-color breathing effect joins a single-color phase to a
|
* Three-color breathing uses 50 us pulse-density modulation below the
|
||||||
* 50:50 phase. Keep the single-color side at the same physical minimum
|
* normal dual-color pulse range. Keep both sides of each color join at
|
||||||
* as the stable dual-color side, otherwise the first mixed step jumps
|
* the same low physical on-time: 45/1000 of a 500 us single-color frame,
|
||||||
* from about 10/1000 to at least 204/1000.
|
* or 25 + 25 over the 450 us dual-color active interval.
|
||||||
*/
|
*/
|
||||||
if(Mode == mode1 && choose_mode_falsg == 5U)
|
if(Mode == mode1 && choose_mode_falsg == 5U)
|
||||||
{
|
{
|
||||||
if(W_PWM != 0U && C_PWM == 0U &&
|
if(W_PWM != 0U && C_PWM == 0U &&
|
||||||
target_w < THREE_COLOR_JOIN_OUTPUT)
|
target_w < THREE_COLOR_MIN_SINGLE_OUTPUT)
|
||||||
target_w = THREE_COLOR_JOIN_OUTPUT;
|
target_w = THREE_COLOR_MIN_SINGLE_OUTPUT;
|
||||||
else if(C_PWM != 0U && W_PWM == 0U &&
|
else if(C_PWM != 0U && W_PWM == 0U &&
|
||||||
target_c < THREE_COLOR_JOIN_OUTPUT)
|
target_c < THREE_COLOR_MIN_SINGLE_OUTPUT)
|
||||||
target_c = THREE_COLOR_JOIN_OUTPUT;
|
target_c = THREE_COLOR_MIN_SINGLE_OUTPUT;
|
||||||
|
else if(W_PWM != 0U && C_PWM != 0U)
|
||||||
|
{
|
||||||
|
if(target_w < THREE_COLOR_MIN_CHANNEL_OUTPUT)
|
||||||
|
target_w = THREE_COLOR_MIN_CHANNEL_OUTPUT;
|
||||||
|
if(target_c < THREE_COLOR_MIN_CHANNEL_OUTPUT)
|
||||||
|
target_c = THREE_COLOR_MIN_CHANNEL_OUTPUT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -376,7 +384,8 @@ void Light_Transition_Task(void)
|
|||||||
* A ratio that cannot provide 102/1000 to its weak side even at full
|
* A ratio that cannot provide 102/1000 to its weak side even at full
|
||||||
* brightness is treated as single color.
|
* brightness is treated as single color.
|
||||||
*/
|
*/
|
||||||
if(W_PWM != 0U && C_PWM != 0U)
|
if(W_PWM != 0U && C_PWM != 0U &&
|
||||||
|
!(Mode == mode1 && choose_mode_falsg == 5U))
|
||||||
{
|
{
|
||||||
mix_total = (uint16_t)(W_PWM + C_PWM);
|
mix_total = (uint16_t)(W_PWM + C_PWM);
|
||||||
weak_mix = (W_PWM < C_PWM) ? W_PWM : C_PWM;
|
weak_mix = (W_PWM < C_PWM) ? W_PWM : C_PWM;
|
||||||
|
|||||||
Reference in New Issue
Block a user