From 00ce337473ac8e926d8df26bbc086366405d181f Mon Sep 17 00:00:00 2001 From: arcmer Date: Fri, 22 Nov 2024 01:07:51 +0000 Subject: [PATCH] new file --- cot_led2 | 941 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 941 insertions(+) create mode 100644 cot_led2 diff --git a/cot_led2 b/cot_led2 new file mode 100644 index 0000000..b8fbaa4 --- /dev/null +++ b/cot_led2 @@ -0,0 +1,941 @@ +/** + ********************************************************************************************************************** + * @file cot_led.c + * @brief 该文件提供LED灯控制功能 + * @author const_zpc any question please send mail to const_zpc@163.com + * @version V1.0.0 + * @date 2023-11-05 + * + ********************************************************************************************************************** + * 源码路径:https://gitee.com/cot_package/cot_led.git 具体问题及建议可在该网址填写 Issue + * + * + ********************************************************************************************************************** + */ + +/* Includes ----------------------------------------------------------------------------------------------------------*/ +#include "cot_led.h" +#include +#include + +// 呼吸灯软件模拟PWM频率(HZ) +#define BREATHE_PWM_RATE 120 + +/* Private typedef ---------------------------------------------------------------------------------------------------*/ +/* Private define ----------------------------------------------------------------------------------------------------*/ + +//#define BREATHE_PWM_PERIOD (1000 / BREATHE_PWM_RATE) //定时周期1ms +#define BREATHE_PWM_PERIOD (8000 / BREATHE_PWM_RATE) //定时周期125us + +/* Private macro -----------------------------------------------------------------------------------------------------*/ + +#define TIME_MAX_VAL (uint32_t)0xffff +#define TIME_ADD(tic, time) (TIME_MAX_VAL - (tic) < (time) ? ((tic) = 0xffff) : (tic += time)) +#define LED_ABS(a) ((a) > 0 ? (a) : -(a)) + +#define FILL_STATE_BITS(state, sbit, ebit) {int bit; for (bit = (sbit); bit < (ebit); bit++) (state)[bit / 8] |= (0x01 << (bit % 8));} +#define SET_STATE_BITS(state, bit) {(state)[bit / 8] |= (0x01 << (bit % 8));} + +/* Private variables -------------------------------------------------------------------------------------------------*/ + +static cotLedCfg_t *sg_pLedTable = NULL; +static size_t sg_ledNum = 0; + +/* Private function prototypes ---------------------------------------------------------------------------------------*/ +/* Private function --------------------------------------------------------------------------------------------------*/ + +/** + * @brief 按键初始化 + * + * @param[in] pCfgTable 指示灯数组表指针 + * @param[in] num 指示灯数组元素数目 + * @return 0,成功; -1,失败 + */ +int cotLed_Init(cotLedCfg_t pCfgTable[], size_t num) +{ + uint8_t led; + + sg_pLedTable = pCfgTable; + sg_ledNum = num; + + for (led = 0; led < num; led++) + { + memset(&sg_pLedTable[led].proc, 0, sizeof(cotLedProc_t)); + } + + return 0; +} + +/** + * @brief 设置LED的亮灭状态 + * + * @param[in] led 指定指示灯 + * @param[in] state 亮灭状态 + * @return 0,成功; -1,失败 + */ +int cotLed_SetState(led_t led, cotLedState_e state) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum) + { + return -1; + } + + sg_pLedTable[led].proc.interval = 100; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.data.state[0] = (state == COT_LED_ON ? 0x01 : 0x00); + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 1; + sg_pLedTable[led].proc.count = 0; + sg_pLedTable[led].proc.isSetCount = 0; + sg_pLedTable[led].proc.defState = 0; + sg_pLedTable[led].proc.isPwm = 0; + return 0; +} + +/** + * @brief 设置LED的亮灭状态及持续时间 + * + * @attention 时间应为控制任务调度周期的倍数 + * @param[in] led 指定指示灯 + * @param[in] state 亮灭状态 + * @param[in] time 持续时间, 单位毫秒 + * @return 0,成功; -1,失败 + */ +int cotLed_SetStateWithTime(led_t led, cotLedState_e state, uint16_t time) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum) + { + return -1; + } + + sg_pLedTable[led].proc.interval = time; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.data.state[0] = (state == COT_LED_ON ? 0x01 : 0x00); + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 1; + sg_pLedTable[led].proc.count = 1; + sg_pLedTable[led].proc.isSetCount = 1; + sg_pLedTable[led].proc.defState = (state == COT_LED_ON ? 0 : 1); + sg_pLedTable[led].proc.isPwm = 0; + + return 0; +} + +/** + * @brief 点亮LED + * + * @param[in] led 指定指示灯 + * @return 0,成功; -1,失败 + */ +int cotLed_ON(led_t led) +{ + return cotLed_SetState(led, COT_LED_ON); +} + +/** + * @brief 熄灭LED + * + * @param[in] led 指定指示灯 + * @return 0,成功; -1,失败 + */ +int cotLed_OFF(led_t led) +{ + return cotLed_SetState(led, COT_LED_OFF); +} + +/** + * @brief 翻转指定LED亮灭状态 + * + * @param led 指定指示灯 + * @return 0,成功; -1,失败 + */ +int cotLed_Toggle(led_t led) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum) + { + return -1; + } + + sg_pLedTable[led].proc.interval = 100; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.data.state[0] = sg_pLedTable[led].proc.data.state[0] == 0 ? 0x01 : 0x00; + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 1; + sg_pLedTable[led].proc.count = 0; + sg_pLedTable[led].proc.isSetCount = 0; + sg_pLedTable[led].proc.defState = 0; + sg_pLedTable[led].proc.isPwm = 0; + + return 0; +} + +/** + * @brief 设置LED为闪烁状态 + * + * @attention 时间应为控制任务调度周期的倍数 + * @param[in] led 指定指示灯 + * @param[in] time 闪烁亮灭间隔时间, 单位毫秒 + * @return 0,成功; -1,失败 + */ +int cotLed_Twinkle(led_t led, uint16_t time) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum) + { + return -1; + } + + sg_pLedTable[led].proc.interval = time; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.data.state[0] = 0x01; + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 2; + sg_pLedTable[led].proc.count = 0; + sg_pLedTable[led].proc.isSetCount = 0; + sg_pLedTable[led].proc.defState = 0; + sg_pLedTable[led].proc.isPwm = 0; + + return 0; +} + +/** + * @brief 设置LED为闪烁状态及次数, 最后次数完成后的亮灭状态 + * + * @note 一亮一灭为一次闪烁 + * @attention 时间应为控制任务调度周期的倍数 + * @param[in] led 指定指示灯 + * @param[in] time 闪烁亮灭间隔时间, 单位毫秒 + * @param[in] count 闪烁次数 + * @param[in] defState 闪烁次数完成后的亮灭状态 + * @return 0,成功; -1,失败 + */ +int cotLed_TwinkleWithCount(led_t led, uint16_t time, uint8_t count, cotLedState_e defState) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum) + { + return -1; + } + + sg_pLedTable[led].proc.interval = time; + sg_pLedTable[led].proc.tic = 0; + // 根据默认状态最后一次闪烁时状态设置相反状态达到较好的闪烁效果 + sg_pLedTable[led].proc.data.state[0] = defState == COT_LED_ON ? 0x01 : 0x02; + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 2; + sg_pLedTable[led].proc.count = count; + sg_pLedTable[led].proc.isSetCount = 1; + sg_pLedTable[led].proc.defState = defState == COT_LED_ON ? 1 : 0; + sg_pLedTable[led].proc.isPwm = 0; + + return 0; +} + +/** + * @brief 为多个LED设置为跑马灯 + * + * @note + * @param[in] led LED组 + * @param[in] ledNum LED数目 + * @param[in] time LED亮时间 + * @return 0,成功; -1,失败 + */ +int cotLed_Marquee(led_t led[], uint8_t ledNum, int32_t time) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + + for (uint8_t i = 0; i < ledNum; i++) + { + if (led[i] < sg_ledNum) + { + memset(sg_pLedTable[led[i]].proc.data.state, 0, LED_STATE_BYTE_NUM); + + sg_pLedTable[led[i]].proc.interval = time; + sg_pLedTable[led[i]].proc.tic = 0; + SET_STATE_BITS(sg_pLedTable[led[i]].proc.data.state, i); + sg_pLedTable[led[i]].proc.offset = 0; + sg_pLedTable[led[i]].proc.validBits = ledNum; + sg_pLedTable[led[i]].proc.count = 0; + sg_pLedTable[led[i]].proc.isSetCount = 0; + sg_pLedTable[led[i]].proc.defState = 0; + sg_pLedTable[led[i]].proc.isPwm = 0; + } + } + + return 0; +} + +/** + * @brief 为多个LED设置为跑马灯及次数, 最后次数完成后的亮灭状态 + * + * @note + * @param[in] led LED组 + * @param[in] ledNum LED数目 + * @param[in] time LED亮时间 + * @param[in] count 跑马灯次数 + * @param[in] defState 跑马灯次数完成后的亮灭状态 + * @return 0,成功; -1,失败 + */ +int cotLed_MarqueeWithCount(led_t led[], uint8_t ledNum, int32_t time, uint8_t count, cotLedState_e defState) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + + for (uint8_t i = 0; i < ledNum; i++) + { + if (led[i] < sg_ledNum) + { + memset(sg_pLedTable[led[i]].proc.data.state, 0, LED_STATE_BYTE_NUM); + + sg_pLedTable[led[i]].proc.interval = time; + sg_pLedTable[led[i]].proc.tic = 0; + SET_STATE_BITS(sg_pLedTable[led[i]].proc.data.state, i); + sg_pLedTable[led[i]].proc.offset = 0; + sg_pLedTable[led[i]].proc.validBits = ledNum; + sg_pLedTable[led[i]].proc.count = count; + sg_pLedTable[led[i]].proc.isSetCount = 1; + sg_pLedTable[led[i]].proc.defState = defState == COT_LED_ON ? 1 : 0; + sg_pLedTable[led[i]].proc.isPwm = 0; + } + } + + return 0; +} + +/** + * @brief 为多个LED设置为流水灯 + * + * @note + * @param[in] led LED组 + * @param[in] ledNum LED数目 + * @param[in] time LED亮时间 + * @return 0,成功; -1,失败 + */ +int cotLed_Waterfall(led_t led[], uint8_t ledNum, int32_t time) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + + for (uint8_t i = 0; i < ledNum; i++) + { + if (led[i] < sg_ledNum) + { + memset(sg_pLedTable[led[i]].proc.data.state, 0, LED_STATE_BYTE_NUM); + + sg_pLedTable[led[i]].proc.interval = time; + sg_pLedTable[led[i]].proc.tic = 0; + FILL_STATE_BITS(sg_pLedTable[led[i]].proc.data.state, i, ledNum); + sg_pLedTable[led[i]].proc.offset = 0; + sg_pLedTable[led[i]].proc.validBits = ledNum + 1; + sg_pLedTable[led[i]].proc.count = 0; + sg_pLedTable[led[i]].proc.isSetCount = 0; + sg_pLedTable[led[i]].proc.defState = 0; + sg_pLedTable[led[i]].proc.isPwm = 0; + } + } + + return 0; +} + +/** + * @brief 为多个LED设置为流水灯及次数, 最后次数完成后的亮灭状态 + * + * @note + * @param[in] led LED组 + * @param[in] ledNum LED数目 + * @param[in] time LED亮时间 + * @param[in] count 流水灯次数 + * @param[in] defState 流水灯次数完成后的亮灭状态 + * @return 0,成功; -1,失败 + */ +int cotLed_WaterfallWithCount(led_t led[], uint8_t ledNum, int32_t time, uint8_t count, cotLedState_e defState) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + + for (uint8_t i = 0; i < ledNum; i++) + { + if (led[i] < sg_ledNum) + { + memset(sg_pLedTable[led[i]].proc.data.state, 0, LED_STATE_BYTE_NUM); + + sg_pLedTable[led[i]].proc.interval = time; + sg_pLedTable[led[i]].proc.tic = 0; + FILL_STATE_BITS(sg_pLedTable[led[i]].proc.data.state, i, ledNum); + sg_pLedTable[led[i]].proc.offset = 0; + sg_pLedTable[led[i]].proc.validBits = ledNum + 1; + sg_pLedTable[led[i]].proc.count = count; + sg_pLedTable[led[i]].proc.isSetCount = 1; + sg_pLedTable[led[i]].proc.defState = defState == COT_LED_ON ? 1 : 0; + sg_pLedTable[led[i]].proc.isPwm = 0; + } + } + + return 0; +} + +/** + * @brief 设置指定LED为呼吸灯模式 + * + * @attention LED控制任务必须为1ms周期 + * @param[in] led 指定指示灯 + * @param[in] period 呼吸周期,即多久完成一次呼吸;单位毫秒 + * @param[in] silence 静默时间,即闭气时间;单位毫秒 + * @return 0,成功; -1,失败 + */ +int cotLed_Breathe(led_t led, uint16_t period, uint16_t silence) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + + if (led < sg_ledNum) + { + sg_pLedTable[led].proc.interval = period / 2 / BREATHE_PWM_PERIOD; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.data.state[0] = 0; // 根据默认状态最后一次闪烁时状态设置相反状态达到较好的闪烁效果 + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 2; + sg_pLedTable[led].proc.count = 0; + sg_pLedTable[led].proc.isSetCount = 0; + sg_pLedTable[led].proc.defState = 0; + sg_pLedTable[led].proc.isPwm = 1; + sg_pLedTable[led].proc.silenceTic = 0; + sg_pLedTable[led].proc.silence = silence; + sg_pLedTable[led].proc.breatheScaleDiff = 0; + sg_pLedTable[led].proc.data.pwm.onTime = 0; + sg_pLedTable[led].proc.data.pwm.tic = 0; + sg_pLedTable[led].proc.pwmDir = 1; + } + + return 0; +} + +/** + * @brief 设置指定LED为呼吸灯模式及次数, 最后次数完成后的亮灭状态 + * + * @attention LED控制任务必须为1ms周期 + * @param[in] led 指定指示灯 + * @param[in] period 呼吸周期,即多久完成一次呼吸;单位毫秒 + * @param[in] count 次数 + * @param[in] defState 次数完成后的亮灭状态 + * @return 0,成功; -1,失败 + */ +int cotLed_BreatheWithCount(led_t led, uint16_t period, uint8_t count, cotLedState_e defState) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + + if (led < sg_ledNum) + { + sg_pLedTable[led].proc.interval = period / 2 / BREATHE_PWM_PERIOD; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.data.state[0] = 0; // 根据默认状态最后一次闪烁时状态设置相反状态达到较好的闪烁效果 + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 2; + sg_pLedTable[led].proc.count = count; + sg_pLedTable[led].proc.isSetCount = 1; + sg_pLedTable[led].proc.defState = defState == COT_LED_ON ? 1 : 0; + sg_pLedTable[led].proc.isPwm = 1; + sg_pLedTable[led].proc.data.pwm.onTime = 0; + sg_pLedTable[led].proc.data.pwm.tic = 0; + sg_pLedTable[led].proc.pwmDir = 1; + } + + return 0; +} + +/** + * @brief 设置指定LED为呼吸灯模式及开始点 + * + * @attention LED控制任务必须为1ms周期 + * @param[in] led 指定指示灯 + * @param[in] period 呼吸周期,即多久完成一次呼吸;单位毫秒 + * @param[in] silence 静默时间,即闭气时间;单位毫秒 + * @param[in] breatheScaleDiff 呼吸时间刻度值差 + * @return 0,成功; -1,失败 + */ +int cotLed_BreatheWithStart(led_t led, uint16_t period, uint16_t silence, uint16_t breatheScaleDiff) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + if (breatheScaleDiff >= (period + silence)) //判断指定开始点是否正常 + { + return -1; + } + + if (led < sg_ledNum) + { + sg_pLedTable[led].proc.interval = period / 2 / BREATHE_PWM_PERIOD; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.data.state[0] = 0; // 根据默认状态最后一次闪烁时状态设置相反状态达到较好的闪烁效果 + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 2; + sg_pLedTable[led].proc.count = 0; + sg_pLedTable[led].proc.isSetCount = 0; + sg_pLedTable[led].proc.defState = COT_LED_ON ? 1 : 0; + sg_pLedTable[led].proc.isPwm = 1; + sg_pLedTable[led].proc.silenceTic = 0; + sg_pLedTable[led].proc.silence = silence; + sg_pLedTable[led].proc.breatheScaleDiff = breatheScaleDiff; + if(breatheScaleDiff <= period/2) + { + sg_pLedTable[led].proc.data.pwm.onTime = (uint32_t)breatheScaleDiff*BREATHE_PWM_PERIOD/((uint32_t)period/2); + sg_pLedTable[led].proc.pwmDir = 1; + } + else if(breatheScaleDiff <= period) + { + sg_pLedTable[led].proc.data.pwm.onTime = ((uint32_t)period - breatheScaleDiff)*BREATHE_PWM_PERIOD/((uint32_t)period/2); + sg_pLedTable[led].proc.pwmDir = 0; + } + else + { + sg_pLedTable[led].proc.data.pwm.onTime = 0; + sg_pLedTable[led].proc.pwmDir = 2; + } + sg_pLedTable[led].proc.data.pwm.tic = 0; + } + + return 0; +} + +/** + * @brief 设置指定LED为常亮模式及亮度 + * + * @attention LED控制任务必须为1ms周期 + * @param[in] led 指定指示灯 + * @param[in] share 份额,单位等分数之一份,与刷新率有关 + * @return 0,成功; -1,失败 + */ +int cotLed_OnWithShare(led_t led, uint16_t share) +{ + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + if (share >= BREATHE_PWM_PERIOD) //限制最大份额 + { + share = BREATHE_PWM_PERIOD; +// return -1; + } + + if (led < sg_ledNum) + { + sg_pLedTable[led].proc.interval = 100; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.data.state[0] = 0; // 根据默认状态最后一次闪烁时状态设置相反状态达到较好的闪烁效果 + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = 2; + sg_pLedTable[led].proc.count = 0; + sg_pLedTable[led].proc.isSetCount = 0; + sg_pLedTable[led].proc.defState = COT_LED_ON ? 1 : 0; + sg_pLedTable[led].proc.isPwm = 1; + sg_pLedTable[led].proc.silenceTic = 0; + sg_pLedTable[led].proc.silence = 1; + sg_pLedTable[led].proc.breatheScaleDiff = 0; + sg_pLedTable[led].proc.data.pwm.onTime = share; + sg_pLedTable[led].proc.pwmDir = 3;//恒定 + sg_pLedTable[led].proc.data.pwm.tic = 0; + } + + return 0; +} + +/** + * @brief 设置LED的自定义状态 + * + * @attention 时间应为控制任务调度周期的倍数 + * @param[in] led 指定指示灯 + * @param[in] ... 亮灭时间参数: + * > 0, 亮的持续时间 + * < 0, 灭的持续时间 + * = 0, 可变参数设置结束 + * @return 0,成功; -1,失败 + */ +int cotLed_Custom(led_t led, ...) +{ + uint8_t bits; + uint8_t offset = 0; + uint8_t validBits = 0; + va_list timeList; + int32_t time; + uint16_t interval = 0xffff; + + if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum) + { + return -1; + } + + va_start(timeList, led); + + do + { + time = va_arg(timeList, int32_t); + + if (time != 0 && LED_ABS(time) < interval) + { + interval = (uint16_t)LED_ABS(time); + } + } while (time != 0); + + va_end(timeList); + + validBits = 0; + offset = 0; + memset(sg_pLedTable[led].proc.data.state, 0, sizeof(sg_pLedTable[led].proc.data.state)); + + va_start(timeList, led); + + do + { + time = va_arg(timeList, int32_t); + + if (LED_ABS(time) != 0) + { + bits = (uint16_t)LED_ABS(time) / interval; + + if (time > 0) + { + for (int i = 0; i < bits; i++) + { + sg_pLedTable[led].proc.data.state[offset / 8] |= 0x01 << (offset % 8); + offset++; + } + } + else + { + for (int i = 0; i < bits; i++) + { + sg_pLedTable[led].proc.data.state[offset / 8] |= 0x00 << (offset % 8); + offset++; + } + } + + validBits += bits; + } + } while (time != 0); + + va_end(timeList); + sg_pLedTable[led].proc.interval = interval; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = validBits; + sg_pLedTable[led].proc.count = 0; + sg_pLedTable[led].proc.isSetCount = 0; + sg_pLedTable[led].proc.defState = 0; + sg_pLedTable[led].proc.isPwm = 0; + + return 0; +} + + +/** + * @brief 设置LED的自定义状态及次数, 最后次数完成后的亮灭状态 + * + * @attention 时间应为控制任务调度周期的倍数 + * @param[in] led 指定指示灯 + * @param[in] count 自定义状态次数,0表示无次数限制 + * @param[in] defState 自定义状态次数完成后的亮灭状态 + * @param[in] ... 亮灭时间参数: + * > 0, 亮的持续时间 + * < 0, 灭的持续时间 + * = 0, 可变参数设置结束 + * @return 0,成功; -1,失败 + */ +int cotLed_CustomWithCount(led_t led, uint8_t count, cotLedState_e defState, ...) +{ + uint8_t bits; + uint8_t offset = 0; + uint8_t validBits = 0; + va_list timeList; + int32_t time; + uint16_t interval = 0xffff; + + if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum) + { + return -1; + } + + va_start(timeList, defState); + + do + { + time = va_arg(timeList, int32_t); + + if (time != 0 && LED_ABS(time) < interval) + { + interval = (uint16_t)LED_ABS(time); + } + } while (time != 0); + + va_end(timeList); + + validBits = 0; + offset = 0; + memset(sg_pLedTable[led].proc.data.state, 0, sizeof(sg_pLedTable[led].proc.data.state)); + + va_start(timeList, defState); + + do + { + time = va_arg(timeList, int32_t); + + if (LED_ABS(time) != 0) + { + bits = (uint16_t)LED_ABS(time) / interval; + + if (time > 0) + { + for (int i = 0; i < bits; i++) + { + sg_pLedTable[led].proc.data.state[offset / 8] |= 0x01 << (offset % 8); + offset++; + } + } + else + { + for (int i = 0; i < bits; i++) + { + sg_pLedTable[led].proc.data.state[offset / 8] |= 0x00 << (offset % 8); + offset++; + } + } + + validBits += bits; + } + } while (time != 0); + + va_end(timeList); + sg_pLedTable[led].proc.interval = interval; + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.offset = 0; + sg_pLedTable[led].proc.validBits = validBits; + sg_pLedTable[led].proc.count = count; + sg_pLedTable[led].proc.isSetCount = count == 0 ? 0 : 1; + sg_pLedTable[led].proc.defState = defState == COT_LED_ON ? 1 : 0; + sg_pLedTable[led].proc.isPwm = 0; + + return 0; +} + +/** + * @brief 设置指定三色LED为呼吸灯模式 + * + * @attention LED控制任务必须为1ms周期 + * @param[in] ledRgb 指定指示灯 + * @param[in] colorRgb 指定颜色 + * @param[in] period 呼吸周期,即多久完成一次呼吸;单位毫秒 + * @param[in] silence 静默时间,即闭气时间;单位毫秒 + * @return 0,成功; -1,失败 + */ +int cotLed_RgbBreathe(ledRgb_t *ledRgb, colorRgb_t *colorRgb, uint16_t period, uint16_t silence) +{ + color_t color_judge; + if (sg_pLedTable == NULL || sg_ledNum == 0 || ledRgb == NULL || colorRgb == NULL)// || colorRgb != COLOR_RGB_TYPE_NULL || colorRgb < COLOR_RGB_TYPE_MAX_NUM) + { + return -1; + } + color_judge = *((color_t *)colorRgb); + if((color_judge == 0) || (color_judge >= COLOR_NUM_MAX_NUM)) //判断颜色是否超出范围 + { + return -1; + } + + if(colorRgb->red == 1) + cotLed_Breathe(ledRgb->red, period, silence); + else + cotLed_SetState(ledRgb->red, COT_LED_OFF); + if(colorRgb->green == 1) + cotLed_Breathe(ledRgb->green, period, silence); + else + cotLed_SetState(ledRgb->green, COT_LED_OFF); + if(colorRgb->blue == 1) + cotLed_Breathe(ledRgb->blue, period, silence); + else + cotLed_SetState(ledRgb->blue, COT_LED_OFF); + + return 0; +} + + +static cotLedState_e ReadPwmLedState(cotLedProc_t *pLed) +{ + cotLedState_e eLedState; + + if (pLed->data.pwm.tic < pLed->data.pwm.onTime) + { + eLedState = COT_LED_ON; + } + else + { + eLedState = COT_LED_OFF; + } + + if (pLed->data.pwm.tic >= BREATHE_PWM_PERIOD) + { + pLed->data.pwm.tic = 0; + } + + return eLedState; +} + +static void CtrlPwmLedState(cotLedProc_t *pLed) +{ + if (pLed->tic > pLed->interval) + { +// pLed->tic = 0; + + if (1 == pLed->pwmDir) //递增 + { + pLed->data.pwm.onTime++; + + if (pLed->data.pwm.onTime >= BREATHE_PWM_PERIOD) + { + pLed->pwmDir = 0; + } + } + else if (0 == pLed->pwmDir) //递减 + { + pLed->data.pwm.onTime--; + + if (pLed->data.pwm.onTime == 0) + { + pLed->pwmDir = 2; +// pLed->silence = (8*20 / pLed->interval)?(8*20 / pLed->interval):1; //至少1个,防止溢出 +// pLed->silence = (SILENCE_TIC / pLed->interval)?(SILENCE_TIC / pLed->interval):1; //至少1个,防止溢出 + pLed->silenceTic = 0; + } + } + else if (2 == pLed->pwmDir) //保持 + { + pLed->silenceTic += pLed->tic; + + if (pLed->silenceTic >= pLed->silence) + { + pLed->pwmDir = 1; + +// if (pLed->count > 0) +// { +// pLed->count--; +// } + } + } + else //恒定,专为调光常亮 + { + //此时占空比一直保持不变 + } + pLed->tic = 0; + } +} + +/** + * @brief LED控制周期任务 + * + * @param[in] sysTime 系统运行时间, 单位毫秒 + * @return 0,成功; -1,失败 + */ +int cotLed_Ctrl(uint32_t sysTime) +{ + uint16_t led; + static uint32_t s_sysTimeBak = 0; + + if (sg_pLedTable == NULL || sg_ledNum == 0) + { + return -1; + } + + if (s_sysTimeBak == 0) + { + s_sysTimeBak = sysTime; + } + + for (led = 0; led < sg_ledNum; led++) + { + TIME_ADD(sg_pLedTable[led].proc.tic, (sysTime - s_sysTimeBak)); + + if (sg_pLedTable[led].proc.isSetCount) + { + if (sg_pLedTable[led].proc.count == 0) + { + sg_pLedTable[led].proc.curState = sg_pLedTable[led].proc.defState ? COT_LED_ON : COT_LED_OFF; + } + else + { + if (sg_pLedTable[led].proc.isPwm) + { + sg_pLedTable[led].proc.curState = ReadPwmLedState(&sg_pLedTable[led].proc); + } + else + { + sg_pLedTable[led].proc.curState = (cotLedState_e)((sg_pLedTable[led].proc.data.state[sg_pLedTable[led].proc.offset / 8] >> (sg_pLedTable[led].proc.offset % 8)) & 0X01); + } + } + } + else + { + if (sg_pLedTable[led].proc.isPwm) + { + sg_pLedTable[led].proc.curState = ReadPwmLedState(&sg_pLedTable[led].proc); + } + else + { + sg_pLedTable[led].proc.curState = (cotLedState_e)((sg_pLedTable[led].proc.data.state[sg_pLedTable[led].proc.offset / 8] >> (sg_pLedTable[led].proc.offset % 8)) & 0X01); + } + } + + if (sg_pLedTable[led].proc.isPwm) + { + TIME_ADD(sg_pLedTable[led].proc.data.pwm.tic, (sysTime - s_sysTimeBak)); + TIME_ADD(sg_pLedTable[led].proc.breatheTic, (sysTime - s_sysTimeBak));//计算一个呼吸周期 + if (sg_pLedTable[led].proc.breatheTic >= (BREATHE_TIC + SILENCE_TIC)) + { + sg_pLedTable[led].proc.breatheTic = 0; + if (sg_pLedTable[led].proc.count > 0) + { + sg_pLedTable[led].proc.count--; + } + } + + CtrlPwmLedState(&sg_pLedTable[led].proc); + } + else + { + if (sg_pLedTable[led].proc.tic >= sg_pLedTable[led].proc.interval) + { + sg_pLedTable[led].proc.tic = 0; + sg_pLedTable[led].proc.offset++; + + if (sg_pLedTable[led].proc.offset >= sg_pLedTable[led].proc.validBits) + { + sg_pLedTable[led].proc.offset = 0; + + if (sg_pLedTable[led].proc.count > 0) + { + sg_pLedTable[led].proc.count--; + } + } + } + } + } + + for (led = 0; led < sg_ledNum; led++) + { + sg_pLedTable[led].pfnLedCtrl(sg_pLedTable[led].proc.curState ? COT_LED_ON : COT_LED_OFF); + } + + s_sysTimeBak = sysTime; + + return 0; +} -- Gitee