DWM22量产测试

This commit is contained in:
2026-07-29 18:32:18 +08:00
parent 99d4844c01
commit ee68f37f04
44 changed files with 4934 additions and 4483 deletions
@@ -189,6 +189,9 @@ void Lock_Pwm7xd();
void Delay_50us();
void Encoder_key();
void rf433_clear_code(void);
uint8_t rf433_start_pairing(void);
void rf433_cancel_pairing(void);
uint8_t rf433_paired_count(void);
#endif
@@ -8,6 +8,7 @@
#include "pwm.h"
#include "rf433_decoder.h"
#include "timeslice.h"
#include "usr_server.h"
union rf433_flag rf_flag = {0};
unsigned char high_level_time;
unsigned char low_level_time;
@@ -96,6 +97,7 @@ static uint8_t pair_deferred_command;
static uint8_t pair_deferred_res_data;
static uint32_t pair_deferred_receive_data;
static uint8_t pair_command_replay;
static uint8_t app_pairing_requested;
#define PAIR_HOLD_FRAME_COUNT 4U
#define PAIR_FRAME_SILENCE_TICKS 100U
@@ -258,6 +260,48 @@ static void Pairing_Candidate_Reset(void)
pair_deferred_command = 0U;
}
uint8_t rf433_paired_count(void)
{
uint8_t count = 0U;
uint8_t i;
for(i = 0U; i < 5U; i++)
{
if(!Pairing_Address_IsEmpty(adress_H_array[i], adress_L_array[i]))
count++;
}
return count;
}
uint8_t rf433_start_pairing(void)
{
if(pairing_feedback_active)
{
ble_remote_event_notify(0x0DU, 0U, rf433_paired_count());
return 0U;
}
ssse = 0U;
time_5s = 1U;
pair_last_frame_sequence = rf_frame_sequence;
Pairing_Candidate_Reset();
app_pairing_requested = 1U;
ble_remote_event_notify(0x0DU, 1U, rf433_paired_count());
return 1U;
}
void rf433_cancel_pairing(void)
{
ssse = 1U;
time_5s = PAIRING_WINDOW_TICKS + 1U;
Pairing_Candidate_Reset();
if(app_pairing_requested)
{
app_pairing_requested = 0U;
ble_remote_event_notify(0x0DU, 0U, rf433_paired_count());
}
}
void rf433_clear_code(void)
{
uint8_t i;
@@ -276,7 +320,9 @@ void rf433_clear_code(void)
time_5s = PAIRING_WINDOW_TICKS + 1U;
Pairing_Candidate_Reset();
Pairing_Feedback_Start(200U);
app_pairing_requested = 0U;
set_TaskComps_timer(2U, 2000U);
ble_remote_event_notify(0x0EU, 1U, 0U);
}
@@ -284,6 +330,13 @@ void rf433_clear_code(void)
static void Encoder_key_NoCode(){
uint16_t times_s=0;
uint8_t pairing_data_changed=0U;
if(app_pairing_requested &&
(ssse != 0U || time_5s > PAIRING_WINDOW_TICKS))
{
app_pairing_requested = 0U;
ble_remote_event_notify(0x0DU, 0U, rf433_paired_count());
}
if(pair_frame_silence_ticks < 0xffU) pair_frame_silence_ticks++;
if(pair_frame_silence_ticks > PAIR_FRAME_SILENCE_TICKS)
@@ -383,6 +436,17 @@ static void Encoder_key_NoCode(){
ssse=1;
if(pairing_data_changed) set_TaskComps_timer(2,2000);
if(app_pairing_requested)
{
app_pairing_requested = 0U;
if(res_data==Brightness_H ||
res_data==B_Brightness_H ||
res_data==F_Brightness_10)
ble_remote_event_notify(0x0DU, 2U,
rf433_paired_count());
else
ble_remote_event_notify(0x0EU, 1U, 0U);
}
}
}
@@ -521,20 +521,13 @@ __RAM_CODE void Bridge_Service_1ms(void)
pwm_duty = (uint16_t)((total * BRIDGE_PWM_SCALE +
(BRIDGE_MIX_SCALE / 2U)) / BRIDGE_MIX_SCALE);
/*
* A mixed H-bridge frame has 450 us of active time after deadtime.
* 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.
* Use the same 450 us maximum energy as mixed light for every
* single-color output. Switching between the hardware-PWM and
* Timer3 mixed-light paths therefore does not change total energy.
*/
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);
}
pwm_duty = (uint16_t)(
((uint32_t)pwm_duty * BRIDGE_DUAL_ACTIVE_US +
(BRIDGE_FRAME_US / 2U)) / BRIDGE_FRAME_US);
if (output_mode == BRIDGE_MODE_SINGLE &&
active_state == single_state &&
@@ -561,22 +554,8 @@ __RAM_CODE void Bridge_Service_1ms(void)
* split evenly between W->C and C->W, which both absorbs interrupt
* latency and spreads the two optical pulses across the 500 us frame.
*/
if (Mode == mode3 && choose_mode_falsg == 8U) {
/*
* The overlap gradient intentionally carries only 40% combined
* output through its crossover. Base that section on the complete
* 500 us frame so entering/leaving dual output does not create a
* 10% brightness step. The 450 us safety ceiling still applies.
*/
total_on_us = (BRIDGE_FRAME_US * total +
(BRIDGE_MIX_SCALE / 2U)) / BRIDGE_MIX_SCALE;
if (total_on_us > BRIDGE_DUAL_ACTIVE_US) {
total_on_us = BRIDGE_DUAL_ACTIVE_US;
}
} else {
total_on_us = (BRIDGE_DUAL_ACTIVE_US * total +
(BRIDGE_MIX_SCALE / 2U)) / BRIDGE_MIX_SCALE;
}
total_on_us = (BRIDGE_DUAL_ACTIVE_US * total +
(BRIDGE_MIX_SCALE / 2U)) / BRIDGE_MIX_SCALE;
/* Keep a non-zero timer interval without imposing a brightness floor. */
if (total_on_us < (2U * BRIDGE_MIN_DUAL_PULSE_US)) {
total_on_us = 2U * BRIDGE_MIN_DUAL_PULSE_US;
@@ -6,16 +6,11 @@ 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 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
@@ -120,11 +115,6 @@ 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;
@@ -343,44 +333,7 @@ void Light_Transition_BeginModeChange(void)
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;
}
mode_transition_gamma_curve = TRANSITION_CURVE_GAMMA_S;
Light_Transition_ModeActive = 1U;
}
@@ -418,10 +371,9 @@ void Light_Transition_Task(void)
uint16_t weak_mix;
uint16_t required_total;
uint16_t floor_w;
uint16_t color_progress_q12;
uint32_t scaled_w_q12;
uint32_t scaled_c_q12;
uint32_t scale_delta;
uint16_t endpoint_curve_q12;
uint8_t power_transitioning;
/*
@@ -440,36 +392,7 @@ 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
@@ -491,18 +414,28 @@ void Light_Transition_Task(void)
/*
* Continuous CCT uses one shared brightness envelope. Derive one
* side from the other so every visible step is strictly complementary
* and W + C remains constant throughout the sweep.
* and W + C remains constant throughout the sweep. Map the color
* position through the same symmetric Gamma curve used by static
* transitions so the ends of each sweep are also eased.
*/
target_total = (uint16_t)(
((uint32_t)LIGHT_OUTPUT_SCALE * brightness_scale + 2048U) >> 12);
target_w = (uint16_t)(
((uint32_t)target_total * W_PWM + 50U) / 100U);
if(target_w > target_total)
target_w = target_total;
target_c = target_total - target_w;
color_progress_q12 =
transition_gamma_s_q12[(C_PWM <= 100U) ? C_PWM : 100U];
target_c = (uint16_t)(
((uint32_t)target_total * color_progress_q12 + 2048U) >> 12);
if(target_c > target_total)
target_c = target_total;
target_w = target_total - target_c;
}
else if(Mode == mode1)
else if(Mode == mode1 ||
(Mode == mode3 && choose_mode_falsg == 8U))
{
/*
* Breathing and overlap-gradient amplitudes are perceptual light
* transitions, so both use the Gamma table instead of raw linear
* channel levels. Jump/flash modes remain outside this branch.
*/
target_w = (uint16_t)(
((uint32_t)effect_gamma_output(W_PWM) *
brightness_scale + 2048U) >> 12);
@@ -575,66 +508,16 @@ void Light_Transition_Task(void)
if(Light_Transition_ModeActive && powered_on && !power_transitioning)
{
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)
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_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) ||
@@ -7,7 +7,6 @@ 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)
@@ -174,6 +174,17 @@ void scan_uart(uint8_t *arr)
case 12:
power_restore_policy_set(user_rx_buf[1]);
break;
case 13:
if(user_rx_buf[1] == 0x01U)
rf433_start_pairing();
else
rf433_cancel_pairing();
break;
case 14:
/* A5 guard prevents accidental clear. */
if(user_rx_buf[1] == 0xA5U)
rf433_clear_code();
break;
case 9:
break;
@@ -102,6 +102,10 @@ static uint8_t ble_last_brightness;
static uint8_t ble_last_speed;
static uint8_t ble_last_temperature;
static uint8_t ble_last_power_mode;
static volatile uint8_t ble_remote_event_pending;
static volatile uint8_t ble_remote_event_command;
static volatile uint8_t ble_remote_event_status;
static volatile uint8_t ble_remote_event_paired_count;
static uint8_t ble_temperature_value(void)
{
@@ -112,10 +116,22 @@ static uint8_t ble_temperature_value(void)
void ble_state_disconnect(void)
{
custom_svc_tx_char_notify = DISABLE;
ble_remote_event_pending = 0U;
send_flag = 1U;
ble_state_dirty = BLE_STATE_DIRTY_ALL;
}
void ble_remote_event_notify(uint8_t command, uint8_t status,
uint8_t paired_count)
{
if(!custom_svc_tx_char_notify) return;
ble_remote_event_command = command;
ble_remote_event_status = status;
ble_remote_event_paired_count = paired_count;
ble_remote_event_pending = 1U;
}
void ble_state_sync_poll(void)
{
uint8_t data[4] = {0U, 0U, 0U, 0U};
@@ -138,7 +154,24 @@ void ble_state_sync_poll(void)
if(power_restore_policy != ble_last_power_mode)
ble_state_dirty |= BLE_STATE_DIRTY_POWER_MODE;
if(!send_flag || !ble_state_dirty) return;
if(!send_flag) return;
/*
* Remote pairing/clear acknowledgements have priority over periodic
* state synchronization so the APP receives operation results promptly.
*/
if(ble_remote_event_pending)
{
data[0] = ble_remote_event_status;
data[1] = ble_remote_event_paired_count;
data[3] = ble_remote_event_command;
if(slave_send_data(data, sizeof(data),
CUSTOM_SVC_TX_CHAR_VAL) == GATT_NO_ERROR)
ble_remote_event_pending = 0U;
return;
}
if(!ble_state_dirty) return;
if(ble_state_dirty & BLE_STATE_DIRTY_POWER)
{
@@ -49,4 +49,6 @@ uint8_t custom_svc_add(void);
uint8_t slave_send_data(uint8_t *data, uint8_t len, uint8_t att_idx);
void ble_state_sync_poll(void);
void ble_state_disconnect(void);
void ble_remote_event_notify(uint8_t command, uint8_t status,
uint8_t paired_count);
#endif // _USR_SERVER_H_