1267 lines
42 KiB
C
1267 lines
42 KiB
C
#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);
|
||
}
|
||
|