#include "led.h" #include "user_ws2812b.h" #include "define.h" #include "stdarg.h" tmosTaskID led_task_id = INVALID_TASK_ID; static uint32_t alarm_stat = 0; static uint16_t led_task_process_event(uint8_t task_id, uint16_t events); static void prvSet_led_duty(LED_TYPE type); static led_work_s led_work[LED_TYPE_MAX] = { { .idx = DEV_LED, .color = { .red = 0, .green = 0xFF, .blue = 0, }, .workStat = LED_WORK_OFF, .viewStat = LED_VIEW_NULL, .single_flicker_period = 0, .flicker_period = 0, .flicker_onperiod = 0, .flicker_count = 0, .duty_value = 0, .single_on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .single_off_durationTime = 0, //PWM变化结束后持续时间,单位:ms .off_durationTime = 0, //PWM变化结束后持续时间,单位:ms }, { .idx = LED_01, .color = { .red = 0, .green = 0, .blue = 0, }, .workStat = LED_WORK_OFF, .viewStat = LED_VIEW_NULL, .single_flicker_period = 0, .flicker_period = 0, .flicker_onperiod = 0, .flicker_count = 0, .duty_value = 0, .single_on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .single_off_durationTime = 0, //PWM变化结束后持续时间,单位:ms .off_durationTime = 0, //PWM变化结束后持续时间,单位:ms }, { .idx = LED_02, .color = { .red = 0, .green = 0, .blue = 0, }, .workStat = LED_WORK_OFF, .viewStat = LED_VIEW_NULL, .single_flicker_period = 0, .flicker_period = 0, .flicker_onperiod = 0, .flicker_count = 0, .duty_value = 0, .single_on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .single_off_durationTime = 0, //PWM变化结束后持续时间,单位:ms .off_durationTime = 0, //PWM变化结束后持续时间,单位:ms }, { .idx = LED_03, .color = { .red = 0, .green = 0, .blue = 0, }, .workStat = LED_WORK_OFF, .viewStat = LED_VIEW_NULL, .single_flicker_period = 0, .flicker_period = 0, .flicker_onperiod = 0, .flicker_count = 0, .duty_value = 0, .single_on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .single_off_durationTime = 0, //PWM变化结束后持续时间,单位:ms .off_durationTime = 0, //PWM变化结束后持续时间,单位:ms }, { .idx = LED_04, .color = { .red = 0, .green = 0, .blue = 0, }, .workStat = LED_WORK_OFF, .viewStat = LED_VIEW_NULL, .single_flicker_period = 0, .flicker_period = 0, .flicker_onperiod = 0, .flicker_count = 0, .duty_value = 0, .single_on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .single_off_durationTime = 0, //PWM变化结束后持续时间,单位:ms .off_durationTime = 0, //PWM变化结束后持续时间,单位:ms }, { .idx = LED_05, .color = { .red = 0, .green = 0, .blue = 0, }, .workStat = LED_WORK_OFF, .viewStat = LED_VIEW_NULL, .single_flicker_period = 0, .flicker_period = 0, .flicker_onperiod = 0, .flicker_count = 0, .duty_value = 0, .single_on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .on_durationTime = 0, //PWM变化结束后持续时间,单位:ms .single_off_durationTime = 0, //PWM变化结束后持续时间,单位:ms .off_durationTime = 0, //PWM变化结束后持续时间,单位:ms }, }; /******************************************************************************* * @函数名称 prvSet_led_duty * @函数说明 设置指示灯亮度 * @输入参数 type:灯下标 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void prvSet_led_duty(LED_TYPE type) { vUser_ws2812b_set_stat(type, led_work[type].color.red, led_work[type].color.green, led_work[type].color.blue, led_work[type].duty_value); } /******************************************************************************* * @函数名称 led_invert * @函数说明 LED闪烁处理 * @输入参数 led_work:led灯结构体直针 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void led_invert(led_work_s *led_work) { if(led_work->flicker_count > 0) { if(led_work->single_flicker_period == 0) { led_work->single_flicker_period = led_work->flicker_period; led_work->stat = LED_STAT_ON; led_work->duty_value = 100; prvSet_led_duty(led_work->idx); } else if(led_work->single_flicker_period == (led_work->flicker_period - led_work->flicker_onperiod)) { led_work->single_flicker_period--; led_work->stat = LED_STAT_OFF; led_work->duty_value = 0; prvSet_led_duty(led_work->idx); led_work->flicker_count--; } else{ led_work->single_flicker_period--; } } else{ led_work->workStat = LED_WORK_OFF; led_work->duty_value = 0; prvSet_led_duty(led_work->idx); } } /******************************************************************************* * @函数名称 led_heart * @函数说明 LED呼吸灯处理 * @输入参数 led_work:led灯结构体直针 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void led_heart(led_work_s *led_work) { if(led_work->flicker_count > 0) { uint32_t off_period = led_work->flicker_period - led_work->flicker_onperiod; if(led_work->single_flicker_period == 0) { led_work->single_flicker_period = led_work->flicker_period; led_work->duty_value = 0; led_work->single_off_durationTime = led_work->off_durationTime; prvSet_led_duty(led_work->idx); led_work->flicker_count--; } else if(led_work->single_flicker_period == off_period) { led_work->single_flicker_period--; led_work->duty_value = 100; led_work->single_on_durationTime = led_work->on_durationTime; prvSet_led_duty(led_work->idx); } else{ if(led_work->single_flicker_period > off_period) { if(led_work->single_off_durationTime == 0) { led_work->single_flicker_period--; led_work->duty_value = (led_work->flicker_period - led_work->single_flicker_period) * 100 / led_work->flicker_onperiod; prvSet_led_duty(led_work->idx); } else{ led_work->single_off_durationTime--; } } else{ if(led_work->single_on_durationTime == 0) { led_work->single_flicker_period--; led_work->duty_value = led_work->single_flicker_period * 100 / off_period; prvSet_led_duty(led_work->idx); } else{ led_work->single_on_durationTime--; } } } } else{ led_work->workStat = LED_WORK_OFF; } } /******************************************************************************* * @函数名称 led_indication * @函数说明 LED灯处理 * @输入参数 led_work:led灯结构体直针 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void led_indication(led_work_s *led_work) { switch(led_work->workStat) { case LED_WORK_OFF: { break; } case LED_WORK_ON: { break; } case LED_WORK_INVERT: { led_invert(led_work); break; } case LED_WORK_BREATHE: { led_heart(led_work); break; } default:break; } } /******************************************************************************* * @函数名称 led_task * @函数说明 LED任务 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void led_task(void) { for(int i = 0; i < LED_TYPE_MAX; i++) { led_indication(&led_work[i]); } } /******************************************************************************* * @函数名称 led_task * @函数说明 task的event处理回调函数,需要在注册task时候,传进去 * @输入参数 task_id:任务ID events:事件 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static uint16_t led_task_process_event(uint8_t task_id, uint16_t events) { //event 处理 if(events & (1 << LED_QUEUE_TIME)) { led_task(); return (events ^ (1 << LED_QUEUE_TIME)); //异或的方式清除该事件运行标志,并返回未运行的事件标志 } return 0; } /******************************************************************************* * @函数名称 set_led_indication * @函数说明 LED参数设置 * @输入参数 type:LED灯号 color:颜色 workStat:状态 * @输出参数 无 * @返回参数 无 *******************************************************************************/ bool set_led_indication(LED_TYPE type, uint32_t color, LED_WORK_STAT work_stat, ...) { bool stat = false; if(type >= LED_TYPE_MAX) { goto exit; } led_work[type].color.red = (color >> 16) & 0xFF; led_work[type].color.green = (color >> 8) & 0xFF; led_work[type].color.blue = color & 0xFF; if(work_stat == LED_WORK_OFF || work_stat == LED_WORK_ON) { led_work[type].workStat = work_stat; led_work[type].duty_value = (work_stat == LED_WORK_ON) ? 100 : 0; prvSet_led_duty(led_work[type].idx); stat = true; } else if(work_stat == LED_WORK_INVERT || work_stat == LED_WORK_BREATHE) { led_work[type].workStat = work_stat; led_work[type].duty_value = 0; led_work[type].stat = LED_STAT_OFF; va_list ap; //保存所有参数 va_start(ap, work_stat); //第一个参数的位置 led_work[type].flicker_period = va_arg(ap, uint32_t)/LED_INTERVAL; led_work[type].flicker_onperiod = va_arg(ap, uint32_t)/LED_INTERVAL; led_work[type].flicker_count = va_arg(ap, uint32_t); if(led_work[type].flicker_count == 0) { led_work[type].flicker_count = 0x7FFFFFFF; } led_work[type].single_flicker_period = led_work[type].flicker_period; if(work_stat == LED_WORK_BREATHE) { led_work[type].on_durationTime = va_arg(ap, uint32_t) / LED_INTERVAL; led_work[type].off_durationTime = va_arg(ap, uint32_t) / LED_INTERVAL; led_work[type].single_on_durationTime = led_work[type].on_durationTime; led_work[type].single_off_durationTime = led_work[type].off_durationTime; } va_end(ap); for(int i = 1; i < LED_TYPE_MAX; i++) { if(led_work[i].workStat == LED_WORK_INVERT || led_work[i].workStat == LED_WORK_BREATHE) { led_work[i].single_flicker_period = led_work[i].flicker_period; led_work[i].duty_value = 0; } } stat = true; } exit: return stat; } /******************************************************************************* * @函数名称 led_task_init * @函数说明 LED任务初始化 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ void led_task_init(void) { led_task_id = TMOS_ProcessEventRegister(led_task_process_event); PRINT("led_task_id=%d\n", led_task_id); } /******************************************************************************* * @函数名称 led_task_start * @函数说明 LED任务开始 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ void led_task_start(void) { bStatus_t stat = tmos_start_reload_task(led_task_id, (1 << LED_QUEUE_TIME), MS1_TO_SYSTEM_TIME(LED_INTERVAL)); } /******************************************************************************* * @函数名称 vUser_led_set_view_stat * @函数说明 设置LED工作状态 * @输入参数 stat:led工作状态 * @输出参数 无 * @返回参数 无 *******************************************************************************/ void vUser_led_set_view_stat(led_view_stat_e stat) { // PRINT("set led stat:%d,%d\n", idx, stat); switch(stat) { case LED_VIEW_ENTER_OTA:{ set_led_indication(DEV_LED, WS2812B_BLE_RGB, LED_WORK_BREATHE, 3000, 1500, 0, 500, 500); set_led_indication(LED_01, WS2812B_BLE_RGB, LED_WORK_BREATHE, 3000, 1500, 0, 500, 500); set_led_indication(LED_02, WS2812B_BLE_RGB, LED_WORK_BREATHE, 3000, 1500, 0, 500, 500); set_led_indication(LED_03, WS2812B_BLE_RGB, LED_WORK_BREATHE, 3000, 1500, 0, 500, 500); set_led_indication(LED_04, WS2812B_BLE_RGB, LED_WORK_BREATHE, 3000, 1500, 0, 500, 500); set_led_indication(LED_05, WS2812B_BLE_RGB, LED_WORK_BREATHE, 3000, 1500, 0, 500, 500); }break; case LED_VIEW_OTA:{ set_led_indication(DEV_LED, WS2812B_BLE_RGB, LED_WORK_BREATHE, 200, 100, 0, 10, 10); set_led_indication(LED_01, WS2812B_BLE_RGB, LED_WORK_BREATHE, 200, 100, 0, 10, 10); set_led_indication(LED_02, WS2812B_BLE_RGB, LED_WORK_BREATHE, 200, 100, 0, 10, 10); set_led_indication(LED_03, WS2812B_BLE_RGB, LED_WORK_BREATHE, 200, 100, 0, 10, 10); set_led_indication(LED_04, WS2812B_BLE_RGB, LED_WORK_BREATHE, 200, 100, 0, 10, 10); set_led_indication(LED_05, WS2812B_BLE_RGB, LED_WORK_BREATHE, 200, 100, 0, 10, 10); }break; default:break; } }