#include "hsf.h" #include "hfconfig.h" #if defined(CONFIG_PWM_SUPPORT_LPM) #include "pm_veto.h" #endif #include "pinctrl.h" #include "gpio.h" #include "pinctrl.h" #include "pwm.h" #include "timer.h" #include "soc_osal.h" #include "systick.h" // #include "tcxo.h" #include "spotlight.h" // 函数前向声明 static void init_timer_system(void); static void init_fade_ctx(void); static void init_breath_ctx(void); static void stop_fade_task(void); static void stop_breath_task(void); static void stop_breath_timer(void); static void stop_spotlight_main_task(void); static void check_net_cfg_timeout(void); static void check_net_cfg_power_on_keep_time(void); static void set_light2breathtimeout(void); static void set_light2net_cfg_done(void); static void start_breath_timer(void); void calculate_pwm_duty(void); void update_pwm_output(void); // 定义上报函数类型 typedef void (*report_func_t)(void); static void start_report_task(report_func_t report_func); static void report_fade_complete_status(void); static uint32_t calculate_checksum(const device_data_t* data); static bool write_device_data_to_addr(uint32_t addr, const device_data_t* data);; static void report_device_online_status(void); #define BRIGHTNESS_PIN GPIO_04 // 冷白LED (CW) #define CCT_PIN GPIO_00 // 暖白LED (WW) #define SWITCH_PIN GPIO_13 #define CONFIG_PWM_GROUP_ID 2 #define OPEN_LIGHT GPIO_LEVEL_HIGH #define CLOSE_LIGHT GPIO_LEVEL_LOW // 状态上报任务相关变量 #define REPORT_TASK_PRIO 80 #define REPORT_TASK_STACK_SIZE 0x1000 static osal_task *report_task_handle = NULL; static bool report_task_running = false; // 添加任务运行状态标志 // 灯渐变任务相关定义 #define FADE_TASK_PRIO 80 #define FADE_TASK_STACK_SIZE 0x1000 // 呼吸灯任务相关定义 #define BREATH_TASK_PRIO 80 #define BREATH_TASK_STACK_SIZE 0x1000 // PWM频率和周期定义 #define PWM_FREQUENCY 2000 // PWM频率 2KHz static uint32_t pwm_period_cnt = 0; // PWM周期 40us static uint8_t channel_id_cw = 0; // 冷白LED通道ID static uint8_t channel_id_ww = 0; // 暖白LED通道ID void save_device_data(void); void read_device_data(void); void req_save_device_data(void); static void stop_breath_timer(void); device_control_t g_device_control = DEFAULT_DEVICE_DATA; // 配网状态定义 typedef enum { NET_CFG_IDLE = 0, // 空闲状态 NET_CFG_BREATHING, // 呼吸灯状态,配网中 NET_CFG_TIMEOUT, // 超时状态 } net_cfg_state_e; // 配网状态相关变量 static net_cfg_state_e g_net_breath_state = NET_CFG_IDLE; // 配网状态 static uint64_t g_net_cfg_start_time = 0; // 配网开始时间 // 保存任务相关变量 static osal_task *save_task_handle = NULL; static bool save_task_running = false; static osal_semaphore save_data_sem; // 打印频率限制相关定义 #define PRINT_INTERVAL_MS 1000 // 最小打印间隔(ms) typedef struct { uint64_t last_print_time; // 上次打印时间 const char *prefix; // 打印前缀 } print_limiter_t; // 渐变控制相关变量 static struct { // 渐变控制参数 int32_t target_brightness; int32_t target_cct; int32_t current_brightness; int32_t current_cct; int32_t step_brightness; int32_t step_cct; bool is_fading; bool fade_completed; uint32_t smooth_time_us; // 渐变总时长(us) uint32_t update_interval; // 更新间隔(us) // 任务相关 osal_task *task_handle; bool task_running; osal_semaphore sem; timer_handle_t timer_handle; // 打印限制器 print_limiter_t print_limiter; } fade_ctx = {0}; // 呼吸灯控制相关变量 static struct { // 呼吸灯控制参数 int32_t duty; int32_t step; uint32_t update_interval; // 更新间隔(us) bool is_initial_breath; // 是否是初始3秒呼吸 // 任务相关 osal_task *task_handle; bool task_running; osal_semaphore sem; timer_handle_t timer_handle; uint32_t start_time_ms; uint32_t breath_cnt; // 打印限制器 print_limiter_t print_limiter; } breath_ctx = {0}; print_limiter_t pwm_limiter = { .last_print_time = 0, .prefix = "[pwm]", }; // 定时器初始化标志 static bool timer_initialized = false; // 初始化定时器系统 static void init_timer_system(void) { if (!timer_initialized) { uapi_timer_init(); int ret = uapi_timer_adapter(TIMER_INDEX_1, TIMER_1_IRQN, 1); if (ret != 0) { e_printf("定时器适配器初始化失败\r\n"); return; } timer_initialized = true; } } // 初始化打印限制器 static void init_print_limiter(print_limiter_t *limiter, const char *prefix) { limiter->last_print_time = 0; limiter->prefix = prefix; } // 带频率限制的打印函数 static bool should_print(print_limiter_t *limiter) { uint64_t current_time = uapi_systick_get_ms(); if (current_time - limiter->last_print_time >= PRINT_INTERVAL_MS) { limiter->last_print_time = current_time; return true; } return false; } // 渐变灯任务函数 static void *fade_task(const char *arg) { unused(arg); e_printf("[fade_task] Task started\r\n"); while (fade_ctx.task_running) { // 等待渐变信号 if (osal_sem_down_timeout(&fade_ctx.sem, 100*1000) != OSAL_SUCCESS) { continue; } if (!fade_ctx.is_fading) { continue; } // 使用打印限制器控制打印频率 if (should_print(&fade_ctx.print_limiter)) { e_printf("%s Brightness: curr:%d, target:%d, step:%d, cct:curr:%d, target:%d, step:%d\r\n", fade_ctx.print_limiter.prefix, fade_ctx.current_brightness, fade_ctx.target_brightness, fade_ctx.step_brightness, fade_ctx.current_cct, fade_ctx.target_cct,fade_ctx.step_cct); } // 检查是否达到目标值 bool brightness_reached = (fade_ctx.step_brightness > 0) ? (fade_ctx.current_brightness >= fade_ctx.target_brightness) : (fade_ctx.current_brightness <= fade_ctx.target_brightness); bool cct_reached = (fade_ctx.step_cct > 0) ? (fade_ctx.current_cct >= fade_ctx.target_cct) : (fade_ctx.current_cct <= fade_ctx.target_cct); // 更新当前值 if (!brightness_reached) { fade_ctx.current_brightness += fade_ctx.step_brightness; } if (!cct_reached) { fade_ctx.current_cct += fade_ctx.step_cct; } // 如果达到目标值,停止渐变 if (brightness_reached && cct_reached) { e_printf("[fade_task] Fade completed, Final brightness: %d, CCT: %d\r\n", fade_ctx.target_brightness, fade_ctx.target_cct); fade_ctx.is_fading = false; fade_ctx.fade_completed = true; fade_ctx.current_brightness = fade_ctx.target_brightness; fade_ctx.current_cct = fade_ctx.target_cct; uapi_timer_stop(fade_ctx.timer_handle); } BRIGHTNESS_LITME_RANGE(fade_ctx.current_brightness); CCT_LITME_RANGE(fade_ctx.current_cct); // 更新PWM输出 g_device_control.brightness_local = fade_ctx.current_brightness; g_device_control.cct_local = fade_ctx.current_cct; calculate_pwm_duty(); update_pwm_output(); if (fade_ctx.fade_completed) { fade_ctx.fade_completed = false; e_printf("[fade_task] Status report: local brightness=%d, CCT=%d\r\n", g_device_control.brightness_local, g_device_control.cct_local); // 启动状态上报任务,使用渐变完成状态上报函数 start_report_task(report_device_online_status); req_save_device_data(); } } e_printf("[fade_task] Task exited\r\n"); return NULL; } // 呼吸灯任务函数 static void *breath_task(const char *arg) { unused(arg); e_printf("[breath_task] Task started\r\n"); while (breath_ctx.task_running) { // 等待呼吸信号 if (osal_sem_down_timeout(&breath_ctx.sem, 100*1000) != OSAL_SUCCESS) { continue; } if (g_net_breath_state != NET_CFG_BREATHING) { continue; } // 检查是否超过呼吸灯持续时间 uint32_t current_time = uapi_systick_get_ms(); uint32_t elapsed_time = current_time - g_net_cfg_start_time; if (elapsed_time >= NET_CFG_BREATH_DURATION) { set_light2breathtimeout(); stop_breath_timer(); continue; } // 检查是否需要改变方向 if (breath_ctx.duty >= BRIGHTNESS_LOCAL_MAX) { breath_ctx.duty = BRIGHTNESS_LOCAL_MAX; breath_ctx.step = -1 * breath_ctx.step; e_printf("%s breathing %d, down %dms\n", breath_ctx.print_limiter.prefix, breath_ctx.breath_cnt, uapi_systick_get_ms() - breath_ctx.start_time_ms); } else if (breath_ctx.duty <= 0) { breath_ctx.duty = 0; breath_ctx.step = -1 * breath_ctx.step; e_printf("%s breathing %d, up %dms\n", breath_ctx.print_limiter.prefix, breath_ctx.breath_cnt, uapi_systick_get_ms() - breath_ctx.start_time_ms); } // 更新亮度 breath_ctx.duty += breath_ctx.step; int32_t brightness_pwm = breath_ctx.duty; // 设置黄白灯交替呼吸 g_device_control.duty_ww = brightness_pwm; g_device_control.duty_cw = PWM_DUTY_RATIO_MAX - brightness_pwm; update_pwm_output(); } e_printf("[breath_task] Task exited\r\n"); return NULL; } // 渐变定时器回调函数 static void fade_timer_callback(uintptr_t data) { osal_sem_up(&fade_ctx.sem); uapi_timer_start(fade_ctx.timer_handle, fade_ctx.update_interval, fade_timer_callback, 0); } // 呼吸灯定时器回调函数 static void breath_timer_callback(uintptr_t data) { osal_sem_up(&breath_ctx.sem); uapi_timer_start(breath_ctx.timer_handle, breath_ctx.update_interval, breath_timer_callback, 0); } // 初始化渐变控制 static void init_fade_ctx(void) { init_timer_system(); int ret = uapi_timer_create(TIMER_INDEX_1, &fade_ctx.timer_handle); if (ret != 0) { e_printf("渐变定时器创建失败\r\n"); } // 初始化信号量 if (osal_sem_init(&fade_ctx.sem, 0) != OSAL_SUCCESS) { e_printf("[init_fade_ctx] Failed to init semaphore\n"); return; } // 初始化打印限制器 init_print_limiter(&fade_ctx.print_limiter, "[fade_task]"); // 创建渐变任务 osal_kthread_lock(); fade_ctx.task_handle = osal_kthread_create((osal_kthread_handler)fade_task, NULL, "FadeTask", FADE_TASK_STACK_SIZE); if (fade_ctx.task_handle != NULL) { fade_ctx.task_running = true; osal_kthread_set_priority(fade_ctx.task_handle, FADE_TASK_PRIO); e_printf("[init_fade_ctx] Fade task created successfully\n"); } else { e_printf("[init_fade_ctx] Failed to create fade task\n"); osal_sem_destroy(&fade_ctx.sem); } osal_kthread_unlock(); // 设置默认更新间隔 fade_ctx.update_interval = FADE_INTERVAL_MIN; } // 初始化呼吸灯控制 static void init_breath_ctx(void) { init_timer_system(); int ret = uapi_timer_create(TIMER_INDEX_1, &breath_ctx.timer_handle); if (ret != 0) { e_printf("呼吸灯定时器创建失败\r\n"); } // 初始化信号量 if (osal_sem_init(&breath_ctx.sem, 0) != OSAL_SUCCESS) { e_printf("[init_breath_ctx] Failed to init semaphore\n"); return; } // 初始化打印限制器 init_print_limiter(&breath_ctx.print_limiter, "[breath_task]"); breath_ctx.duty = g_device_control.brightness_local; breath_ctx.step = BREARTH_STEP == 0 ? 1 : BREARTH_STEP; breath_ctx.update_interval = BREARTH_INTERVAL; breath_ctx.is_initial_breath = true; breath_ctx.start_time_ms = uapi_systick_get_ms(); e_printf("Breath task: brightness=%d, step=%d, update_interval=%d, is_initial_breath=%d\n", breath_ctx.duty, breath_ctx.step, breath_ctx.update_interval, breath_ctx.is_initial_breath); // 创建呼吸灯任务 osal_kthread_lock(); breath_ctx.task_handle = osal_kthread_create((osal_kthread_handler)breath_task, NULL, "BreathTask", BREATH_TASK_STACK_SIZE); if (breath_ctx.task_handle != NULL) { breath_ctx.task_running = true; osal_kthread_set_priority(breath_ctx.task_handle, BREATH_TASK_PRIO); e_printf("[init_breath_ctx] Breath task created successfully\n"); } else { e_printf("[init_breath_ctx] Failed to create breath task\n"); osal_sem_destroy(&breath_ctx.sem); } osal_kthread_unlock(); } // 停止渐变任务 static void stop_fade_task(void) { if (fade_ctx.task_handle == NULL) { return; } fade_ctx.task_running = false; osal_sem_up(&fade_ctx.sem); // 唤醒任务以使其退出 osal_kthread_lock(); osal_kthread_destroy(fade_ctx.task_handle, 0); fade_ctx.task_handle = NULL; osal_kthread_unlock(); osal_sem_destroy(&fade_ctx.sem); e_printf("[stop_fade_task] Fade task stopped\n"); } // 停止呼吸灯任务 static void stop_breath_task(void) { if (breath_ctx.task_handle == NULL) { return; } breath_ctx.task_running = false; osal_sem_up(&breath_ctx.sem); // 唤醒任务以使其退出 osal_kthread_lock(); osal_kthread_destroy(breath_ctx.task_handle, 0); breath_ctx.task_handle = NULL; osal_kthread_unlock(); osal_sem_destroy(&breath_ctx.sem); e_printf("[stop_breath_task] Breath task stopped\n"); } // 修改stop_breath_timer函数 static void stop_breath_timer(void) { uapi_timer_stop(breath_ctx.timer_handle); uapi_timer_delete(breath_ctx.timer_handle); stop_breath_task(); } // 计算PWM占空比 void calculate_pwm_duty(void) { // 如果开关关闭,则占空比为0 uint32_t total_brightness_pwm = g_device_control.brightness_local; // 计算色温比例 (0-10000) uint16_t cct_ratio = ((g_device_control.cct_local - CCT_LOCAL_MIN) * 10000) / CCT_RANGE; // 根据色温比例计算CW和WW的占空比 // 总亮度保持不变,只调整CW和WW的比例 g_device_control.duty_cw = (total_brightness_pwm * cct_ratio) / 10000; g_device_control.duty_ww = total_brightness_pwm - g_device_control.duty_cw; } // 更新PWM输出 void update_pwm_output(void) { pwm_config_t cfg_repeat = {0}; cfg_repeat.repeat = true; if (g_device_control.duty_cw > PWM_DUTY_RATIO_MAX) { g_device_control.duty_cw = PWM_DUTY_RATIO_MAX; } if (g_device_control.duty_ww > PWM_DUTY_RATIO_MAX) { g_device_control.duty_ww = PWM_DUTY_RATIO_MAX; } uint32_t high_cnt_cw = (pwm_period_cnt * g_device_control.duty_cw) / PWM_DUTY_RATIO_MAX; uint32_t low_cnt_cw = pwm_period_cnt - high_cnt_cw; uint32_t high_cnt_ww = (pwm_period_cnt * g_device_control.duty_ww) / PWM_DUTY_RATIO_MAX; uint32_t low_cnt_ww = pwm_period_cnt - high_cnt_ww; // uapi_pwm_stop_group(CONFIG_PWM_GROUP_ID); // uapi_pwm_clear_group(CONFIG_PWM_GROUP_ID); if (!g_device_control.on) { // 如果开关关闭,则占空比为0 e_printf("spotlight off\r\n"); high_cnt_cw = 0; low_cnt_cw = 0; high_cnt_ww = 0; low_cnt_ww = 0; } cfg_repeat.high_time = high_cnt_cw; cfg_repeat.low_time = low_cnt_cw; uapi_pwm_open(channel_id_cw, &cfg_repeat); // 配置第二个通道 cfg_repeat.high_time = high_cnt_ww; cfg_repeat.low_time = low_cnt_ww; cfg_repeat.offset_time = high_cnt_cw;//配置互补形成相位 uapi_pwm_open(channel_id_ww, &cfg_repeat); // 设置PWM组 uint8_t channel_ids[2] = {channel_id_cw, channel_id_ww}; // uapi_pwm_set_group(CONFIG_PWM_GROUP_ID, channel_ids, 2); // // 更新PWM占空比 // uapi_pwm_update_duty_ratio(channel_id_cw, low_cnt_cw, high_cnt_cw); // uapi_pwm_update_duty_ratio(channel_id_ww, low_cnt_ww, high_cnt_ww); // 启动PWM组 uapi_pwm_start_group(CONFIG_PWM_GROUP_ID); if (should_print(&pwm_limiter)) { e_printf("cw:high:%u, low:%u, duty:%u/1000, ww:high:%u, low:%u, duty:%u/1000, offset_time:%u\r\n", high_cnt_cw, low_cnt_cw, g_device_control.duty_cw, high_cnt_ww, low_cnt_ww, g_device_control.duty_ww, cfg_repeat.offset_time); } } #define ABS(x) ((x) < 0 ? -(x) : (x)) // 计算渐变步长 static void calculate_fade_steps(void) { // 从g_device_control获取渐变时间 fade_ctx.smooth_time_us = g_device_control.fade_time * 1000 * 1000;//s->us e_printf("fade brightness: curr:%d, target:%d, cct: curr:%d, target:%d\r\n", fade_ctx.current_brightness, fade_ctx.target_brightness, fade_ctx.current_cct, fade_ctx.target_cct); // 计算亮度渐变步长 int32_t brightness_diff = fade_ctx.target_brightness - fade_ctx.current_brightness; int32_t cct_diff = fade_ctx.target_cct - fade_ctx.current_cct; // 计算需要的总步数(取亮度和色温中变化较大的那个) uint32_t max_diff = (ABS(brightness_diff) > ABS(cct_diff)) ? ABS(brightness_diff) : ABS(cct_diff); uint32_t min_steps = 0; uint32_t available_interval = 0; // 如果变化太小,直接设置目标值 EKKO:这里需要确认是直接设置目标值还是强制等待渐变时长 if (max_diff == 0) { fade_ctx.step_brightness = 0; fade_ctx.step_cct = 0; fade_ctx.update_interval = fade_ctx.smooth_time_us; goto lab_exit; } min_steps = max_diff; // 计算实际可用的时间间隔 available_interval = fade_ctx.smooth_time_us / min_steps; // 如果时间间隔太小(小于允许的最小更新间隔),则增加步长 if (available_interval < FADE_INTERVAL_MIN) { // 重新计算步长,确保在指定时间内完成 fade_ctx.update_interval = FADE_INTERVAL_MIN; int32_t actual_steps = fade_ctx.smooth_time_us / fade_ctx.update_interval; // 计算新的步长 fade_ctx.step_brightness = brightness_diff / actual_steps; fade_ctx.step_cct = cct_diff / actual_steps; // 确保至少有一个最小步长 if (fade_ctx.step_brightness == 0 && brightness_diff != 0) { fade_ctx.step_brightness = (brightness_diff > 0) ? 1 : -1; } if (fade_ctx.step_cct == 0 && cct_diff != 0) { fade_ctx.step_cct = (cct_diff > 0) ? 1 : -1; } } else { // 使用计算出的时间间隔 fade_ctx.update_interval = available_interval; fade_ctx.step_brightness = (brightness_diff > 0) ? 1 : -1; fade_ctx.step_cct = (cct_diff > 0) ? 1 : -1; } // 如果亮度或色温没有变化,则步长为0 if (brightness_diff == 0) { fade_ctx.step_brightness = 0; } if (cct_diff == 0) { fade_ctx.step_cct = 0; } lab_exit: if (should_print(&fade_ctx.print_limiter)) { e_printf("max_diff:%d, fade time:%uus, Brightness: diff:%d, step:%d, CCT: diff:%d, step:%d, update_interval:%uus\r\n", max_diff, fade_ctx.smooth_time_us, brightness_diff, fade_ctx.step_brightness, cct_diff, fade_ctx.step_cct, fade_ctx.update_interval); } } static void cancel_current_light_fade(void) { uapi_timer_stop(fade_ctx.timer_handle); } // 计算校验和 static uint32_t calculate_checksum(const device_data_t* data) { uint32_t sum = 0; const uint32_t* ptr = (const uint32_t*)(((char*)data) + sizeof(data->checksum)); size_t len = sizeof(device_data_t) - sizeof(data->checksum); // 减去checksum字段的大小 for (size_t i = 0; i < len / 4; i++) { sum ^= ptr[i]; } return sum; } // 验证数据有效性 static bool verify_device_data(const device_data_t* data) { if (data->magic != DEVICE_DATA_MAGIC) { e_printf("magic error:%x\n", data->magic); return false; } if (data->version > DEVICE_DATA_VERSION) { e_printf("versoin missmatch:%x\n", data->version); return false; } uint32_t checksum = calculate_checksum(data); if (checksum != data->checksum) { e_printf("check sum error:%x\n", data->version); return false; } return true; } // 从指定地址读取设备数据 static bool read_device_data_from_addr(uint32_t addr, device_data_t* data) { int ret = hfuflash_read(addr, (char*)data, sizeof(device_data_t)); if (ret != sizeof(device_data_t)) { e_printf("从地址0x%x读取设备数据失败,实际读取长度:%d\r\n", addr, ret); return false; } if (!verify_device_data(data)) { e_printf("地址0x%x的数据无效\r\n", addr); return false; } return true; } // 写入数据到指定地址 static bool write_device_data_to_addr(uint32_t addr, const device_data_t* data) { int ret = hfuflash_erase_page(addr, 1); if (ret != HF_SUCCESS) { e_printf("擦除地址0x%x的Flash页失败,错误码:%d\r\n", addr, ret); return false; } ret = hfuflash_write(addr, (char*)data, sizeof(device_data_t)); if (ret != sizeof(device_data_t)) { e_printf("写入数据到地址0x%x失败,实际写入长度:%d\r\n", addr, ret); return false; } return true; } void read_device_data(void) { #if SUPPORT_SAVE_TO_FLASH device_data_t data; bool main_valid = false; bool backup_valid = false; // 尝试读取主数据区 main_valid = read_device_data_from_addr(DEVICE_DATA_FLASH_ADDR, &data); // 如果主数据区无效,尝试读取备份区 if (!main_valid) { backup_valid = read_device_data_from_addr(DEVICE_DATA_BACKUP_ADDR, &data); } if (!main_valid && backup_valid) { // 如果主数据区无效但备份区有效,从备份区恢复 e_printf("从备份区恢复数据\r\n"); write_device_data_to_addr(DEVICE_DATA_FLASH_ADDR, &data); } else if (!main_valid && !backup_valid) { // 如果两个区域都无效,使用默认值 e_printf("主数据和备份数据都无效,使用默认值\r\n"); // 只打印g_device_control的当前值,不打印data.control // e_printf("读取完成状态: %d\r\n", g_device_control.read_done); e_printf("上电次数: %d\r\n", g_device_control.power_on_cnt); e_printf("配网状态: %d\r\n", g_device_control.is_networked); e_printf("开关状态: %d\r\n", g_device_control.on); e_printf("灯光模式: %d\r\n", g_device_control.elightMode); e_printf("亮度: %d\r\n", g_device_control.brightness_local); e_printf("色温: %d\r\n", g_device_control.cct_local); e_printf("冷白LED: %d\r\n", g_device_control.duty_cw); e_printf("暖白LED: %d\r\n", g_device_control.duty_ww); e_printf("渐变时间: %d\r\n", g_device_control.fade_time); goto lab_exit; } // 更新设备控制状态 e_printf("设备状态恢复:\r\n"); // e_printf("读取完成状态: %d => %d\r\n", g_device_control.read_done, data.control.read_done); e_printf("上电次数: %d => %d\r\n", g_device_control.power_on_cnt, data.control.power_on_cnt); e_printf("配网状态: %d => %d\r\n", g_device_control.is_networked, data.control.is_networked); e_printf("开关状态: %d => %d\r\n", g_device_control.on, data.control.on); e_printf("灯光模式: %d => %d\r\n", g_device_control.elightMode, data.control.elightMode); e_printf("亮度: %d => %d\r\n", g_device_control.brightness_local, data.control.brightness_local); e_printf("色温: %d => %d\r\n", g_device_control.cct_local, data.control.cct_local); e_printf("冷白LED: %d => %d\r\n", g_device_control.duty_cw, data.control.duty_cw); e_printf("暖白LED: %d => %d\r\n", g_device_control.duty_ww, data.control.duty_ww); e_printf("渐变时间: %d => %d\r\n", g_device_control.fade_time, data.control.fade_time); g_device_control = data.control; lab_exit: #endif g_device_control.read_done = true; e_printf("读取设备数据成功\r\n"); } void save_device_data(void) { e_printf("Starting to save device data\n"); #if SUPPORT_SAVE_TO_FLASH // 使用静态变量保存上一次的数据状态 static device_control_t last_control = {0}; static bool is_first_save = true; // 需要比较的字段(根据注释标记的持久化维持部分) bool need_save = is_first_save || last_control.on != g_device_control.on || last_control.elightMode != g_device_control.elightMode || last_control.brightness_local != g_device_control.brightness_local || last_control.fade_time != g_device_control.fade_time || last_control.cct_local != g_device_control.cct_local || last_control.power_on_cnt != g_device_control.power_on_cnt || last_control.is_networked != g_device_control.is_networked; if (!need_save) { e_printf("No changes detected, skip saving\n"); return; } device_data_t data; // 准备要保存的数据 data.magic = DEVICE_DATA_MAGIC; data.version = DEVICE_DATA_VERSION; data.control = g_device_control; data.checksum = calculate_checksum(&data); // 先写入备份区 if (!write_device_data_to_addr(DEVICE_DATA_BACKUP_ADDR, &data)) { e_printf("Failed to write backup data\n"); return; } // 再写入主数据区 if (!write_device_data_to_addr(DEVICE_DATA_FLASH_ADDR, &data)) { e_printf("Failed to write main data, but backup data saved\n"); } // 更新上一次的数据状态 last_control = g_device_control; is_first_save = false; e_printf("Device data saved successfully\n"); #endif e_printf("Save device data done\n"); } void req_save_device_data(void) { osal_sem_up(&save_data_sem); } // 保存任务函数 static void *save_data_task(const char *arg) { e_printf("[save_data_task] Save task started\n"); while (save_task_running) { // 等待保存信号 if (osal_sem_down_timeout(&save_data_sem, 100*1000) != OSAL_SUCCESS) { continue; } while(OSAL_SUCCESS == osal_sem_trydown(&save_data_sem));//消耗所有的信号一次性刷入 save_device_data(); } e_printf("[save_data_task] Save task exited\n"); return NULL; } // 初始化保存任务 static void init_save_task(void) { if (save_task_handle != NULL) { return; } // 初始化信号量 if (osal_sem_init(&save_data_sem, 0) != OSAL_SUCCESS) { e_printf("[init_save_task] Failed to init semaphore\n"); return; } // 创建保存任务 osal_kthread_lock(); save_task_handle = osal_kthread_create((osal_kthread_handler)save_data_task, NULL, "SaveDataTask", SAVE_TASK_STACK_SIZE); if (save_task_handle != NULL) { save_task_running = true; osal_kthread_set_priority(save_task_handle, SAVE_TASK_PRIO); e_printf("[init_save_task] Save task created successfully\n"); } else { e_printf("[init_save_task] Failed to create save task\n"); osal_sem_destroy(&save_data_sem); } osal_kthread_unlock(); } // 停止保存任务 static void stop_save_task(void) { if (save_task_handle == NULL) { return; } save_task_running = false; osal_sem_up(&save_data_sem); // 唤醒任务以使其退出 osal_kthread_lock(); osal_kthread_destroy(save_task_handle, 0); save_task_handle = NULL; osal_kthread_unlock(); osal_sem_destroy(&save_data_sem); e_printf("[stop_save_task] Save task stopped\n"); } // 设置灯光状态(统一控制函数) int set_light(int32_t brightness_local, int32_t cct_local) { // 如果任一参数大于等于0,则更新对应值 e_printf("ligMode:%d, local brightness: curr:%d, target:%d, local cct: curr:%d, target:%d\r\n", g_device_control.elightMode, g_device_control.brightness_local, brightness_local, g_device_control.cct_local, cct_local); fade_ctx.current_brightness = g_device_control.brightness_local; fade_ctx.current_cct = g_device_control.cct_local; fade_ctx.target_brightness = fade_ctx.current_brightness ; fade_ctx.target_cct = fade_ctx.current_cct; if (brightness_local >= 0) { BRIGHTNESS_LITME_RANGE(brightness_local); if (g_device_control.elightMode == LIGHT_MODE_CUSTOMER) { fade_ctx.target_brightness = brightness_local; } else { g_device_control.brightness_local = brightness_local; } } if (cct_local >= 0) { CCT_LITME_RANGE(cct_local); if (g_device_control.elightMode == LIGHT_MODE_CUSTOMER) { fade_ctx.target_cct = cct_local; } else { g_device_control.cct_local = cct_local; } } switch (g_device_control.elightMode) { case LIGHT_MODE_CUSTOMER: if (g_device_control.fade_time) { fade_ctx.is_fading = true; fade_ctx.fade_completed = false; // 计算渐变步长 calculate_fade_steps(); e_printf("start fade\r\n"); // 启动渐变定时器 set_switch(true); uapi_timer_start(fade_ctx.timer_handle, fade_ctx.update_interval, fade_timer_callback, 0); #if 0 等待渐变完成 while (!fade_ctx.fade_completed) { msleep(10); } return 0; // 同步上报 #else return -111; // 异步上报 #endif } // no break; // 如果渐变时间是0则直接一步完成 default: //情景模式直接切换到对应的色温和亮度 set_switch(true); } start_report_task(report_device_online_status);//直接全量上报 return -111; // 异步上报 } // 设置开关状态 int set_switch(bool open) { g_device_control.on = open; if (fade_ctx.is_fading) //打断当前的渐变计划 { cancel_current_light_fade(); } calculate_pwm_duty(); update_pwm_output(); uapi_gpio_set_val(SWITCH_PIN, open ? OPEN_LIGHT : CLOSE_LIGHT); // 保存设备状态 req_save_device_data(); return 0; } static void gpio_init(pin_t pin) { /* PINCTRL init. */ uapi_pin_init(); uapi_pin_set_mode(pin, HAL_PIO_FUNC_GPIO); uapi_gpio_set_dir(pin, GPIO_DIRECTION_OUTPUT); uapi_pin_set_ds(pin, PIN_DS_3); uapi_pin_set_pull(pin, PIN_PULL_TYPE_DOWN); uapi_gpio_set_val(pin, CLOSE_LIGHT); } static void pwm_sys_init(void) { uapi_pwm_deinit(); } static void pwm_init(pin_t pin, pin_t pin1) { pwm_config_t cfg_repeat = {0}; cfg_repeat.repeat = true; uapi_pin_set_mode(pin, PIN_MODE_1); uapi_pin_set_mode(pin1, PIN_MODE_1); uapi_pwm_init(); uint32_t frequency = uapi_pwm_get_frequency(pin%8); // uint32_t pwm_base_period_ns = 1000 * 1000 * 1000 / frequency; // uint32_t pwm_base_period_ns = 1000 * 1000 * 1000 / (80 * 1000 * 1000);// 80MHZ // uint32_t pwm_target_period_ns = 1000 * 1000 * 1000 / PWM_FREQUENCY; pwm_period_cnt = ((80 * 1000 * 1000) / PWM_FREQUENCY); // 设置PWM组 channel_id_cw = pin%8; channel_id_ww = pin1%8; uint8_t channel_ids[2] = {channel_id_cw, channel_id_ww}; uapi_pwm_open(channel_id_cw, &cfg_repeat); uapi_pwm_open(channel_id_ww, &cfg_repeat); uapi_pwm_set_group(CONFIG_PWM_GROUP_ID, channel_ids, sizeof(channel_ids)); uapi_pwm_start_group(CONFIG_PWM_GROUP_ID); e_printf("PWM基础时钟频率: %dHz, 目标时钟频率: %dHz, 周期计数: %d\r\n", frequency, PWM_FREQUENCY, pwm_period_cnt); } // 配网状态管理相关函数 static void handle_network_status(void) { // 如果已经配网,直接返回 if (g_device_control.is_networked) { return; } // 增加上电计数 g_device_control.power_on_cnt++; e_printf("现在是第 %d 次上电\r\n", g_device_control.power_on_cnt); // 检查是否需要进入配网状态 if (g_device_control.power_on_cnt >= NET_CFG_ENTRY_CNT) { e_printf("进入配网状态,上电次数:%d\r\n", g_device_control.power_on_cnt); g_device_control.power_on_cnt = 0;// extern int start_hilink_ble_net_config(int32_t net_cfg_time_s); int ret = start_hilink_ble_net_config(NET_CFG_TOTAL_TIMEOUT/1000); if (ret) { // FIXME: 这里简单恢复之前等待配网的灯效即可 e_printf("start net_cfg fail:%n\r\n", ret); req_save_device_data(); // extern int HILINK_RestoreFactorySettings(void); // HILINK_RestoreFactorySettings(); return; } // 初始化呼吸灯控制 init_breath_ctx(); start_breath_timer(); } // 保存设备状态 req_save_device_data(); } // 设备上线时的状态上报 static void report_device_online_status(void) { e_printf("[report_task] Starting to report all service status\r\n"); fast_report(SVC_ID_SWITCH); fast_report(SVC_ID_BRIGHTNESS); fast_report(SVC_ID_CCT); fast_report(SVC_ID_LIGHT_MODE); fast_report(SVC_ID_FADE_TIME); e_printf("[report_task] Status report completed\r\n"); } // 渐变结束时的状态上报 static void report_fade_complete_status(void) { req_save_device_data(); e_printf("[report_task] Reporting fade complete status\r\n"); fast_report(SVC_ID_LIGHT_MODE); fast_report(SVC_ID_BRIGHTNESS); fast_report(SVC_ID_CCT); e_printf("[report_task] Fade status report completed\r\n"); } // 状态上报任务函数 static void *report_task(const char *arg) { report_func_t report_func = (report_func_t)arg; e_printf("report_task running...\r\n"); while (!(g_device_control.read_done && hf_hilink_main_is_runing())) { // 数据已经正确load并且hilink已经运行才开始上报 e_printf("read_done%d, hilink:%d\r\n", g_device_control.read_done, hf_hilink_main_is_runing()); osal_msleep(50); } if (report_func) { report_func(); } report_task_running = false; e_printf("[report_task] exited\r\n"); return NULL; } // 启动状态上报任务 static void start_report_task(report_func_t report_func) { if (report_task_running) { e_printf("[report_task] Previous task is still running, skip this report\r\n"); return; } if (report_task_handle) { osal_kthread_destroy(report_task_handle, 0); report_task_handle = NULL; } e_printf("start report_task\r\n"); osal_kthread_lock(); report_task_handle = osal_kthread_create((osal_kthread_handler)report_task, (void*)report_func, "ReportStaTask", REPORT_TASK_STACK_SIZE); if (report_task_handle != NULL) { report_task_running = true; // 设置任务运行标志 osal_kthread_set_priority(report_task_handle, REPORT_TASK_PRIO); } osal_kthread_unlock(); } static int device_online = 0; // 修改handle_device_online函数 void handle_device_online(void) { if(device_online) { return; } e_printf("device online!\r\n"); if (!g_device_control.is_networked) { e_printf("设备首次上线,记录配网状态\r\n"); g_device_control.is_networked = true; g_device_control.power_on_cnt = 0; // 重置上电计数 stop_breath_timer(); // 停止呼吸灯 set_light2net_cfg_done(); req_save_device_data(); } // 重置配网状态 g_net_breath_state = NET_CFG_IDLE; g_net_cfg_start_time = 0; // 启动状态上报任务,使用设备上线状态上报函数 start_report_task(report_device_online_status); device_online = 1; } void handle_device_offline(void) { if (!device_online) { return; } device_online = 0; e_printf("device offline!\r\n"); } // 处理设备解绑 void handle_device_unbind(void) { e_printf("设备被解绑,重置配网状态\r\n"); if (g_device_control.is_networked) { g_device_control.is_networked = false; g_device_control.power_on_cnt = 0; // 重置上电计数 stop_spotlight_main_task(); device_control_t tmp = DEFAULT_DEVICE_DATA;//恢复默认 g_device_control = tmp; save_device_data(); } } static void check_net_cfg_power_on_keep_time(void) { if (g_device_control.power_on_cnt <= 0) { return; } if (g_device_control.is_networked) { return; } if (uapi_systick_get_ms() > INIT_NET_CFG_PWOER_ON_KEEP_TIME) { e_printf("power_on keep time is %llums must < %ds, we will reset cnt\r\n", uapi_systick_get_ms(), INIT_NET_CFG_PWOER_ON_KEEP_TIME/1000); g_device_control.power_on_cnt = 0; req_save_device_data(); } } // spotlight主任务相关变量 #define SPOTLIGHT_MAIN_TASK_PRIO 23 #define SPOTLIGHT_MAIN_TASK_STACK_SIZE 0x1000 static osal_task *spotlight_main_task_handle = NULL; static bool spotlight_main_task_running = false; // spotlight主任务函数 static void *spotlight_main_task(const char *arg) { unused(arg); e_printf("[spotlight_main_task] Task started\r\n"); uint32_t current_time = 0; //uapi_systick_get_ms(); while (spotlight_main_task_running) { // 检查配网超时 check_net_cfg_timeout(); check_net_cfg_power_on_keep_time(); osal_msleep(20); } // 停止保存任务 stop_save_task(); e_printf("[spotlight_main_task] Task exited\r\n"); return NULL; } // 启动spotlight主任务 static void start_spotlight_main_task(void) { if (spotlight_main_task_handle != NULL) { e_printf("[start spotlight task] Task already running\r\n"); return; } e_printf("[start spotlight task] Starting task\r\n"); osal_kthread_lock(); spotlight_main_task_handle = osal_kthread_create((osal_kthread_handler)spotlight_main_task, NULL, "SpotlightMain", SPOTLIGHT_MAIN_TASK_STACK_SIZE); if (spotlight_main_task_handle != NULL) { spotlight_main_task_running = true; osal_kthread_set_priority(spotlight_main_task_handle, SPOTLIGHT_MAIN_TASK_PRIO); e_printf("[start spotlight task] Task created successfully\r\n"); } else { e_printf("[start spotlight task] Failed to create task\r\n"); } osal_kthread_unlock(); } // 停止spotlight主任务 static void stop_spotlight_main_task(void) { if (spotlight_main_task_handle == NULL) { return; } spotlight_main_task_running = false; osal_kthread_lock(); osal_kthread_destroy(spotlight_main_task_handle, 0); spotlight_main_task_handle = NULL; osal_kthread_unlock(); e_printf("[stop_spotlight_main_task] Task stopped\r\n"); } // 检查配网超时 static void check_net_cfg_timeout(void) { if (g_net_breath_state != NET_CFG_BREATHING) { return; } uint64_t current_time = uapi_systick_get_ms(); uint64_t elapsed_time = current_time - g_net_cfg_start_time; if (elapsed_time >= NET_CFG_TOTAL_TIMEOUT) { e_printf("[Net Cfg] 配网超过10分钟,退出配网模式\r\n"); g_net_breath_state = NET_CFG_TIMEOUT; } } // 修改spotlight_main函数 int spotlight_main(void) { uapi_systick_init(); read_device_data(); e_printf("uapi_timer_get_max_us:%uus\r\n", uapi_timer_get_max_us()); // 初始化GPIO并将灯关闭 gpio_init(SWITCH_PIN); // 初始化PWM系统 pwm_sys_init(); pwm_init(BRIGHTNESS_PIN, CCT_PIN); // 初始化渐变控制 init_fade_ctx(); // 初始化保存任务 init_save_task(); // 检查配网状态,确定是否需要进入配网状态 handle_network_status(); set_switch(g_device_control.on);//按照当前值更新light start_spotlight_main_task(); return 0; } // 设置渐变时长 int set_smooth_time(uint32_t smooth_time) { e_printf("[set_smooth_time] Setting smooth time: %d s\r\n", smooth_time); if (smooth_time < SMOOTH_TIME_MIN) { e_printf("[set_smooth_time] Smooth time below minimum, adjusted to: %d s\r\n", SMOOTH_TIME_MIN); smooth_time = SMOOTH_TIME_MIN; } if (smooth_time > SMOOTH_TIME_MAX) { e_printf("[set_smooth_time] Smooth time above maximum, adjusted to: %d s\r\n", SMOOTH_TIME_MAX); smooth_time = SMOOTH_TIME_MAX; } g_device_control.fade_time = smooth_time; req_save_device_data(); e_printf("[set_smooth_time] Smooth time setting completed\r\n"); return 0; } // 设置灯光到配网超时状态 static void set_light2breathtimeout(void) { e_printf("[Net cfg] 配网超过1分钟,退出呼吸灯状态\r\n"); // 恢复到自定义模式 g_device_control.brightness_local = BRIGHTNESS_REMOTE2LOCAL(NET_CFG_TIMEOUT_BRIGHTNESS); g_device_control.cct_local = CCT_REMOTE2LOCAL(NET_CFG_TIMEOUT_CCT); calculate_pwm_duty(); update_pwm_output(); } // 设置灯光到配网完成状态 static void set_light2net_cfg_done(void) { g_device_control.elightMode = NET_CFG_DEFAULT_LIGHTMODE; g_device_control.brightness_local = BRIGHTNESS_REMOTE2LOCAL(NET_CFG_DEFAULT_BRIGHTNESS); g_device_control.cct_local = CCT_REMOTE2LOCAL(NET_CFG_DEFAULT_CCT); g_device_control.fade_time = NET_CFG_DEFAULT_FADE_TIME; calculate_pwm_duty(); update_pwm_output(); } // 启动呼吸灯 static void start_breath_timer(void) { g_net_breath_state = NET_CFG_BREATHING; g_net_cfg_start_time = uapi_systick_get_ms(); breath_ctx.is_initial_breath = true; uapi_timer_start(breath_ctx.timer_handle, breath_ctx.update_interval, breath_timer_callback, 0); }