DWM22测试板

This commit is contained in:
2026-07-29 17:37:05 +08:00
parent 6d114add28
commit 99d4844c01
100 changed files with 6604 additions and 4433 deletions
@@ -102,7 +102,12 @@ static uint8_t pair_command_replay;
#define PAIRING_WINDOW_TICKS 50000UL
#define RF433_RELEASE_TIMEOUT_TICKS 1500U
#define RF433_MS_TO_SAMPLE_TICKS(ms) ((uint16_t)((ms) * (1000U / RF433_DECODER_SAMPLE_US)))
#define RF433_MODE_REPEAT_TICKS ((uint32_t)RF433_MS_TO_SAMPLE_TICKS(500U))
uint8_t long_flag_s=0;
static volatile uint32_t rf433_sample_ticks;
static uint32_t rf433_mode_last_action_tick;
static uint8_t rf433_mode_last_key;
static uint8_t rf433_mode_action_valid;
void _433_fun(void);
@@ -422,8 +427,38 @@ static void set_click(){
}
}
static uint8_t rf433_is_mode_step_command(uint8_t command)
{
return command == Mode_add || command == Mode_dow;
}
/*
* Act immediately on the first valid mode frame. Repeated frames carrying
* the same key are accepted at most once every 500 ms. Keep this independent
* from the generic 150 ms release detector so an occasional missing RF frame
* cannot turn one physical hold into several rapid short presses.
*/
static uint8_t rf433_mode_step_ready(uint8_t command)
{
uint32_t now = rf433_sample_ticks;
if(!rf433_mode_action_valid ||
rf433_mode_last_key != command ||
(uint32_t)(now - rf433_mode_last_action_tick) >=
RF433_MODE_REPEAT_TICKS)
{
rf433_mode_last_key = command;
rf433_mode_last_action_tick = now;
rf433_mode_action_valid = 1U;
return 1U;
}
return 0U;
}
void rf433_receive(void)//RF433 sample, called every 100 us
{
rf433_sample_ticks++;
rf433_decoder_sample((RF_DATA == HIGH_LEVEL) ? 1U : 0U);
if(long_time > 0U)
@@ -473,8 +508,15 @@ void _433_fun(){
pair_deferred_receive_data = receive_data;
return;
}
if(Key_TypeDef.KEY_STATE_Click==1||KEY_STATE_re==1) return;
set_click();
if(rf433_is_mode_step_command(res_data))
{
if(!rf433_mode_step_ready(res_data)) return;
}
else
{
if(Key_TypeDef.KEY_STATE_Click==1||KEY_STATE_re==1) return;
set_click();
}
switch(res_data){
//椭圆
case ON://单击
@@ -390,7 +390,6 @@ int main(void)
#endif
wdt_init();
/* Set the broadcast address of the device. */
board_init();
xc_fmc_spi_init_oprt( );
@@ -398,6 +397,8 @@ int main(void)
fmc_spi_read();
power_restore_apply_on_boot();
/* Start the watchdog after the optional boot-time Flash update. */
wdt_init();
timer0_2_init();
bluetooth_init();
@@ -522,13 +522,18 @@ __RAM_CODE void Bridge_Service_1ms(void)
(BRIDGE_MIX_SCALE / 2U)) / BRIDGE_MIX_SCALE);
/*
* A mixed H-bridge frame has 450 us of active time after deadtime.
* Use the same 450/500 energy at both single-color endpoints of the
* continuous gradient so its total brightness does not jump there.
* Continuous CCT always uses the same 450/500 endpoint energy.
* A static color transition also reaches its single-color endpoint
* at 90%, then light_transition.c restores it to 100% over 900 ms.
*/
if (Mode == mode3 && choose_mode_falsg == 7U) {
pwm_duty = (uint16_t)(
((uint32_t)pwm_duty * BRIDGE_DUAL_ACTIVE_US +
(BRIDGE_FRAME_US / 2U)) / BRIDGE_FRAME_US);
} else if (Mode == mode0 && choose_mode_falsg <= 2U) {
pwm_duty = (uint16_t)(
((uint32_t)pwm_duty *
Light_Transition_StaticEndpointScale_Q12 + 2048U) >> 12);
}
if (output_mode == BRIDGE_MODE_SINGLE &&
@@ -289,14 +289,9 @@ void power_restore_apply_on_boot(void)
power_cycle_next_mode = (uint8_t)((mode_index + 1U) % 3U);
/*
* Save the next startup mode before timers, BLE and the H-bridge start.
* A deferred flash erase/write masks interrupts long enough to stretch
* one Timer3-controlled dual-color pulse and causes a visible flash.
* Cycle-static is also a remembered state. Start PWM, BLE and the
* H-bridge through the same path as full-memory restore, then persist
* the next static mode through the normal deferred Flash state machine.
*/
wright_user_data();
GLOBAL_INT_DISABLE();
xc_fmc_spi_flash_erase_page(USER_DATA_FLASH_ADDR);
xc_fmc_spi_flash_write_page(USER_DATA_FLASH_ADDR,
app_data, FLASH_PAGE_SIZE);
GLOBAL_INT_RESTORE();
set_TaskComps_timer(2U, POWER_POLICY_SAVE_DELAY_MS);
}
@@ -6,10 +6,19 @@ 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;
volatile uint16_t Light_Transition_StaticEndpointScale_Q12 = 4096U;
#define BRIGHTNESS_SMOOTH_SHIFT 4U
#define OUTPUT_SMOOTH_SHIFT 4U
#define MODE_TRANSITION_TICKS 40U
#define MODE_TRANSITION_TICKS 100U
#define CCT_RING_TRANSITION_TICKS 40U
#define STATIC_ENDPOINT_SCALE_START_Q12 3686U
#define STATIC_ENDPOINT_SCALE_MAX_Q12 4096U
#define STATIC_PRE_TRANSITION_TICKS 50U
#define STATIC_ENDPOINT_RECOVERY_TICKS 180U
#define TRANSITION_CURVE_LINEAR 0U
#define TRANSITION_CURVE_GAMMA_S 1U
#define TRANSITION_CURVE_GAMMA_OUT 2U
#define LIGHT_OUTPUT_SCALE 1000U
#define BREATH_MIN_OUTPUT (LIGHT_OUTPUT_SCALE / 100U)
#define DUAL_MIN_STABLE_CHANNEL_OUTPUT 102U
@@ -78,6 +87,29 @@ static const uint16_t power_fade_gamma_q12[101] = {
4096U
};
/*
* Symmetric Gamma 1.8 transition curve:
* q = p^1.8 / (p^1.8 + (1-p)^1.8)
*
* Unlike applying Gamma independently to W and C, q and (1-q) remain
* complementary. The transition therefore eases in and out without causing
* a brightness dip in the middle. A table keeps the 5 ms task free of
* floating-point and power calculations.
*/
static const uint16_t transition_gamma_s_q12[101] = {
0U, 1U, 4U, 8U, 13U, 20U, 29U, 39U, 50U, 63U,
77U, 93U, 110U, 130U, 150U, 173U, 197U, 223U, 251U, 281U,
312U, 345U, 381U, 418U, 457U, 498U, 541U, 586U, 633U, 681U,
732U, 784U, 839U, 895U, 953U, 1012U, 1073U, 1136U, 1200U, 1265U,
1332U, 1400U, 1469U, 1539U, 1610U, 1682U, 1754U, 1827U, 1901U, 1974U,
2048U, 2122U, 2195U, 2269U, 2342U, 2414U, 2486U, 2557U, 2627U, 2696U,
2764U, 2831U, 2896U, 2960U, 3023U, 3084U, 3143U, 3201U, 3257U, 3312U,
3364U, 3415U, 3463U, 3510U, 3555U, 3598U, 3639U, 3678U, 3715U, 3751U,
3784U, 3815U, 3845U, 3873U, 3899U, 3923U, 3946U, 3966U, 3986U, 4003U,
4019U, 4033U, 4046U, 4057U, 4067U, 4076U, 4083U, 4088U, 4092U, 4095U,
4096U
};
static uint16_t current_brightness_q12;
static uint16_t power_fade_progress_q12;
static uint16_t power_fade_remainder;
@@ -86,6 +118,13 @@ 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 uint8_t mode_transition_total_ticks;
static uint8_t mode_transition_gamma_curve;
static uint8_t static_pre_transition_active;
static uint8_t static_pre_transition_tick;
static uint16_t static_pre_transition_start_scale_q12;
static uint8_t static_endpoint_recovery_active;
static uint8_t static_endpoint_recovery_tick;
static volatile uint8_t feedback_active;
static volatile uint8_t feedback_on;
@@ -153,24 +192,54 @@ static uint16_t approach_target(uint16_t current, uint16_t target)
return current - step;
}
static uint16_t transition_gamma_s_scale(uint8_t tick, uint8_t total_ticks)
{
uint16_t index;
if(total_ticks == 0U || tick >= total_ticks) return 4096U;
index = (uint16_t)(((uint16_t)tick * 100U +
(total_ticks / 2U)) / total_ticks);
if(index > 100U) index = 100U;
return transition_gamma_s_q12[index];
}
static uint16_t transition_gamma_out_scale(uint8_t tick, uint8_t total_ticks)
{
uint16_t index;
if(total_ticks == 0U || tick >= total_ticks) return 4096U;
index = (uint16_t)(((uint16_t)tick * 100U +
(total_ticks / 2U)) / total_ticks);
if(index > 100U) index = 100U;
return (uint16_t)(4096U - power_fade_gamma_q12[100U - index]);
}
static uint16_t interpolate_mode_output(uint16_t start, uint16_t target,
uint8_t tick)
{
uint32_t delta;
uint16_t progress_q12;
uint8_t total_ticks = mode_transition_total_ticks;
if(total_ticks == 0U || tick >= total_ticks) return target;
if(mode_transition_gamma_curve == TRANSITION_CURVE_GAMMA_S)
progress_q12 = transition_gamma_s_scale(tick, total_ticks);
else if(mode_transition_gamma_curve == TRANSITION_CURVE_GAMMA_OUT)
progress_q12 = transition_gamma_out_scale(tick, total_ticks);
else
progress_q12 = (uint16_t)(
((uint32_t)tick * 4096U + (total_ticks / 2U)) / total_ticks);
if(tick >= MODE_TRANSITION_TICKS) return target;
if(target >= start)
{
delta = (uint32_t)(target - start) * tick;
delta = (uint32_t)(target - start) * progress_q12;
return (uint16_t)(start +
((delta + (MODE_TRANSITION_TICKS / 2U)) /
MODE_TRANSITION_TICKS));
((delta + 2048U) >> 12));
}
delta = (uint32_t)(start - target) * tick;
delta = (uint32_t)(start - target) * progress_q12;
return (uint16_t)(start -
((delta + (MODE_TRANSITION_TICKS / 2U)) /
MODE_TRANSITION_TICKS));
((delta + 2048U) >> 12));
}
static uint16_t effect_gamma_output(uint16_t level)
@@ -265,6 +334,53 @@ void Light_Transition_BeginModeChange(void)
mode_transition_start_w = W_PWM_duty;
mode_transition_start_c = C_PWM_duty;
mode_transition_tick = 0U;
mode_transition_total_ticks =
(choose_mode_falsg == CUSTOM_TEMPERATURE_MODE)
? CCT_RING_TRANSITION_TICKS : MODE_TRANSITION_TICKS;
if(Mode == mode0 && choose_mode_falsg <= 2U)
mode_transition_gamma_curve = TRANSITION_CURVE_GAMMA_S;
else if(Mode == mode0 &&
choose_mode_falsg == CUSTOM_TEMPERATURE_MODE)
mode_transition_gamma_curve = TRANSITION_CURVE_GAMMA_OUT;
else
mode_transition_gamma_curve = TRANSITION_CURVE_LINEAR;
if(Mode == mode0 && choose_mode_falsg <= 2U)
{
/*
* A dual-color bridge frame has only 450 us of active time, while a
* single-color hardware-PWM frame has the full 500 us. If the current
* output is single color, first fade its frame energy from 100% to
* 90% without changing color. The following mixed-light transition
* can then start at the same 450 us energy without an abrupt drop.
*/
static_pre_transition_active = 0U;
static_pre_transition_tick = 0U;
static_pre_transition_start_scale_q12 =
Light_Transition_StaticEndpointScale_Q12;
if(((mode_transition_start_w == 0U) ^
(mode_transition_start_c == 0U)) &&
Light_Transition_StaticEndpointScale_Q12 >
STATIC_ENDPOINT_SCALE_START_Q12)
{
static_pre_transition_active = 1U;
}
else
{
Light_Transition_StaticEndpointScale_Q12 =
STATIC_ENDPOINT_SCALE_START_Q12;
}
static_endpoint_recovery_active = 0U;
static_endpoint_recovery_tick = 0U;
}
else
{
Light_Transition_StaticEndpointScale_Q12 =
STATIC_ENDPOINT_SCALE_MAX_Q12;
static_pre_transition_active = 0U;
static_pre_transition_tick = 0U;
static_endpoint_recovery_active = 0U;
static_endpoint_recovery_tick = 0U;
}
Light_Transition_ModeActive = 1U;
}
@@ -304,6 +420,8 @@ void Light_Transition_Task(void)
uint16_t floor_w;
uint32_t scaled_w_q12;
uint32_t scaled_c_q12;
uint32_t scale_delta;
uint16_t endpoint_curve_q12;
uint8_t power_transitioning;
/*
@@ -322,7 +440,36 @@ void Light_Transition_Task(void)
}
if(!powered_on)
{
Light_Transition_ModeActive = 0U;
Light_Transition_StaticEndpointScale_Q12 =
STATIC_ENDPOINT_SCALE_MAX_Q12;
static_pre_transition_active = 0U;
static_pre_transition_tick = 0U;
static_endpoint_recovery_active = 0U;
static_endpoint_recovery_tick = 0U;
}
if(static_endpoint_recovery_active)
{
scale_delta =
STATIC_ENDPOINT_SCALE_MAX_Q12 -
STATIC_ENDPOINT_SCALE_START_Q12;
static_endpoint_recovery_tick++;
endpoint_curve_q12 = transition_gamma_s_scale(
static_endpoint_recovery_tick,
STATIC_ENDPOINT_RECOVERY_TICKS);
Light_Transition_StaticEndpointScale_Q12 = (uint16_t)(
STATIC_ENDPOINT_SCALE_START_Q12 +
((scale_delta * endpoint_curve_q12 + 2048U) >> 12));
if(static_endpoint_recovery_tick >= STATIC_ENDPOINT_RECOVERY_TICKS)
{
Light_Transition_StaticEndpointScale_Q12 =
STATIC_ENDPOINT_SCALE_MAX_Q12;
static_endpoint_recovery_active = 0U;
}
}
/*
* Keep APP brightness tracking while off. Power fading is a separate
@@ -428,15 +575,67 @@ void Light_Transition_Task(void)
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)
if(static_pre_transition_active)
{
uint16_t pre_curve_q12;
uint32_t pre_scale_delta;
static_pre_transition_tick++;
pre_curve_q12 = transition_gamma_s_scale(
static_pre_transition_tick,
STATIC_PRE_TRANSITION_TICKS);
pre_scale_delta =
static_pre_transition_start_scale_q12 -
STATIC_ENDPOINT_SCALE_START_Q12;
Light_Transition_StaticEndpointScale_Q12 = (uint16_t)(
static_pre_transition_start_scale_q12 -
((pre_scale_delta * pre_curve_q12 + 2048U) >> 12));
W_PWM_duty = mode_transition_start_w;
C_PWM_duty = mode_transition_start_c;
if(static_pre_transition_tick >= STATIC_PRE_TRANSITION_TICKS)
{
Light_Transition_StaticEndpointScale_Q12 =
STATIC_ENDPOINT_SCALE_START_Q12;
static_pre_transition_active = 0U;
}
}
else
{
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);
}
/*
* At low brightness, integer PWM resolution can reach the requested
* single-color endpoint before the nominal transition tick ends.
* Begin the 90%->100% envelope at that physical endpoint instead of
* waiting and creating a visible pause followed by a final lift.
*/
if(!static_pre_transition_active &&
!static_endpoint_recovery_active &&
Mode == mode0 && choose_mode_falsg <= 2U &&
((target_w == 0U && W_PWM_duty == 0U) ||
(target_c == 0U && C_PWM_duty == 0U)))
{
static_endpoint_recovery_tick = 0U;
static_endpoint_recovery_active = 1U;
}
if(!static_pre_transition_active &&
mode_transition_tick >= mode_transition_total_ticks)
{
Light_Transition_ModeActive = 0U;
if(!static_endpoint_recovery_active &&
Mode == mode0 && choose_mode_falsg <= 2U &&
(target_w == 0U || target_c == 0U))
{
static_endpoint_recovery_tick = 0U;
static_endpoint_recovery_active = 1U;
}
}
}
else if(((Mode == mode2 || Mode == mode3) && powered_on) ||
power_transitioning ||
@@ -7,6 +7,7 @@ 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;
extern volatile uint16_t Light_Transition_StaticEndpointScale_Q12;
#define Light_Transition_RequestOn() (Light_Transition_FadeActive = 0U)
#define Light_Transition_RequestOff() (Light_Transition_FadeActive = 1U)