BLE_TYQ_BJQ_CH32V303/packages/agile_led-1.1.1/agile_led.c

630 lines
16 KiB
C
Raw Normal View History

2024-12-01 13:49:43 +08:00
/*
* @Author : stark1898y 1658608470@qq.com
* @Date : 2024-07-04 16:13:57
* @LastEditors : stark1898y 1658608470@qq.com
* @LastEditTime : 2024-09-04 12:03:39
* @FilePath : \JT-DT-YD4N02A_RTT_MRS\packages\agile_led-1.1.1\agile_led.c
* @Description :
*
* Copyright (c) 2024 by yzy, All Rights Reserved.
*/
/**
* @file agile_led.c
* @brief Agile Led
* @author (2544047213@qq.com)
* @version 1.1.1
* @date 2021-12-28
*
@verbatim
使
使 PKG_AGILE_LED_USING_THREAD_AUTO_INIT:
1. agile_led_env_init
2. 线 agile_led_process
- agile_led_create / agile_led_init /
- agile_led_start
- agile_led_dynamic_change_light_mode / agile_led_static_change_light_mode
- agile_led_set_compelete_callback
- 使 agile_led_stop
- agile_led_on / agile_led_off / agile_led_toggle
@endverbatim
*
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Ma Longwei.
* All rights reserved.</center></h2>
*
*/
#include <agile_led.h>
#include <stdlib.h>
#include <string.h>
#define PKG_AGILE_LED_USING_THREAD_AUTO_INIT
/** @defgroup RT_Thread_DBG_Configuration RT-Thread DBG Configuration
* @{
*/
/** @name RT-Thread DBG 功能配置
* @{
*/
#define DBG_ENABLE
#define DBG_COLOR
#define DBG_SECTION_NAME "agile_led"
#ifdef PKG_AGILE_LED_DEBUG
#define DBG_LEVEL DBG_LOG
#else
#define DBG_LEVEL DBG_INFO
#endif
#include <rtdbg.h>
/**
* @}
*/
/**
* @}
*/
#ifdef PKG_AGILE_LED_USING_THREAD_AUTO_INIT
/** @defgroup AGILE_LED_Thread_Auto_Init Agile Led Thread Auto Init
* @{
*/
/** @defgroup AGILE_LED_Thread_Auto_Init_Configuration Agile Led Thread Auto Init Configuration
* @{
*/
/** @name Agile Led 自动初始化线程配置
* @{
*/
#ifndef PKG_AGILE_LED_THREAD_STACK_SIZE
#define PKG_AGILE_LED_THREAD_STACK_SIZE 512 /**< Agile Led 线程堆栈大小 */
#endif
#ifndef PKG_AGILE_LED_THREAD_PRIORITY
#define PKG_AGILE_LED_THREAD_PRIORITY RT_THREAD_PRIORITY_MAX - 4 /**< Agile Led 线程优先级 */
#endif
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* PKG_AGILE_LED_USING_THREAD_AUTO_INIT */
/** @defgroup AGILE_LED_Private_Variables Agile Led Private Variables
* @{
*/
ALIGN(RT_ALIGN_SIZE)
static rt_slist_t _slist_head = RT_SLIST_OBJECT_INIT(_slist_head); /**< Agile Led 链表头节点 */
static struct rt_mutex _mtx; /**< Agile Led 互斥锁 */
static uint8_t _is_init = 0; /**< Agile Led 初始化完成标志 */
#ifdef PKG_AGILE_LED_USING_THREAD_AUTO_INIT
static struct rt_thread _thread; /**< Agile Led 线程控制块 */
static uint8_t _thread_stack[PKG_AGILE_LED_THREAD_STACK_SIZE]; /**< Agile Led 线程堆栈 */
#endif
/**
* @}
*/
/** @defgroup AGILE_LED_Private_Functions Agile Led Private Functions
* @{
*/
/**
* @brief Agile Led
* @param led Agile Led
*/
static void agile_led_default_compelete_callback(agile_led_t *led)
{
RT_ASSERT(led);
LOG_D("led pin:%d compeleted.", led->pin);
}
#ifdef RT_USING_HEAP
/**
* @brief Agile Led light_arr arr_num
* @param led Agile Led
* @param light_mode
@verbatim
:
"100,200,100,200"
@endverbatim
* @return RT_EOK:; !=RT_EOK:
*/
static int agile_led_get_light_arr(agile_led_t *led, const char *light_mode)
{
RT_ASSERT(led);
RT_ASSERT(led->type == AGILE_LED_TYPE_DYNAMIC);
RT_ASSERT(led->light_arr == RT_NULL);
RT_ASSERT(led->arr_num == 0);
const char *ptr = light_mode;
while (*ptr) {
if (*ptr == ',')
led->arr_num++;
ptr++;
}
if (*(ptr - 1) != ',')
led->arr_num++;
if (led->arr_num == 0)
return -RT_ERROR;
uint32_t *light_arr = rt_malloc(led->arr_num * sizeof(uint32_t));
if (light_arr == RT_NULL)
return -RT_ENOMEM;
rt_memset(light_arr, 0, led->arr_num * sizeof(uint32_t));
ptr = light_mode;
for (uint32_t i = 0; i < led->arr_num; i++) {
light_arr[i] = atoi(ptr);
ptr = strchr(ptr, ',');
if (ptr)
ptr++;
}
led->light_arr = light_arr;
return RT_EOK;
}
#endif /* RT_USING_HEAP */
/**
* @}
*/
/** @defgroup AGILE_LED_Exported_Functions Agile Led Exported Functions
* @{
*/
#ifdef RT_USING_HEAP
/**
* @brief Agile Led
* @param pin led
* @param active_logic led (PIN_HIGH/PIN_LOW)
* @param light_mode
@verbatim
:
"100,200,100,200"
@endverbatim
* @param loop_cnt ()
* @return !=RT_NULL:Agile Led ; RT_NULL:
*/
agile_led_t *agile_led_create(uint32_t pin, uint32_t active_logic, const char *light_mode, int32_t loop_cnt)
{
if (!_is_init) {
LOG_E("Please call agile_led_env_init first.");
return RT_NULL;
}
agile_led_t *led = (agile_led_t *)rt_malloc(sizeof(agile_led_t));
if (led == RT_NULL)
return RT_NULL;
led->type = AGILE_LED_TYPE_DYNAMIC;
led->active = 0;
led->pin = pin;
led->active_logic = active_logic;
led->light_arr = RT_NULL;
led->arr_num = 0;
led->arr_index = 0;
if (light_mode) {
if (agile_led_get_light_arr(led, light_mode) != RT_EOK) {
rt_free(led);
return RT_NULL;
}
}
led->loop_init = loop_cnt;
led->loop_cnt = led->loop_init;
led->tick_timeout = rt_tick_get();
led->compelete = agile_led_default_compelete_callback;
rt_slist_init(&(led->slist));
rt_pin_mode(pin, PIN_MODE_OUTPUT);
rt_pin_write(pin, !active_logic);
return led;
}
/**
* @brief Agile Led
* @param led Agile Led
* @return RT_EOK:
*/
int agile_led_delete(agile_led_t *led)
{
RT_ASSERT(led);
RT_ASSERT(led->type == AGILE_LED_TYPE_DYNAMIC);
rt_mutex_take(&_mtx, RT_WAITING_FOREVER);
rt_slist_remove(&_slist_head, &(led->slist));
led->slist.next = RT_NULL;
rt_mutex_release(&_mtx);
if (led->light_arr) {
rt_free((uint32_t *)led->light_arr);
led->light_arr = RT_NULL;
}
rt_free(led);
return RT_EOK;
}
/**
* @brief Agile Led
* @note Agile Led 使 agile_led_create
* @param led Agile Led
* @param light_mode
@verbatim
:
"100,200,100,200"
@endverbatim
* @param loop_cnt ()
* @return RT_EOK:; !=RT_EOK:
*/
int agile_led_dynamic_change_light_mode(agile_led_t *led, const char *light_mode, int32_t loop_cnt)
{
RT_ASSERT(led);
RT_ASSERT(led->type == AGILE_LED_TYPE_DYNAMIC);
rt_mutex_take(&_mtx, RT_WAITING_FOREVER);
if (light_mode) {
if (led->light_arr) {
rt_free((uint32_t *)led->light_arr);
led->light_arr = RT_NULL;
}
led->arr_num = 0;
if (agile_led_get_light_arr(led, light_mode) != RT_EOK) {
agile_led_stop(led);
rt_mutex_release(&_mtx);
return -RT_ERROR;
}
}
led->loop_init = loop_cnt;
led->arr_index = 0;
led->loop_cnt = led->loop_init;
led->tick_timeout = rt_tick_get();
rt_mutex_release(&_mtx);
return RT_EOK;
}
/**
* @brief Agile Led
* @note API agile_led_dynamic_change_light_mode
* @param led Agile Led
* @param light_mode
@verbatim
:
"100,200,100,200"
@endverbatim
* @param loop_cnt ()
* @return RT_EOK:; !=RT_EOK:
*/
int agile_led_set_light_mode(agile_led_t *led, const char *light_mode, int32_t loop_cnt)
{
return agile_led_dynamic_change_light_mode(led, light_mode, loop_cnt);
}
#endif /* RT_USING_HEAP */
/**
* @brief Agile Led
* @param led Agile Led
* @param pin led
* @param active_logic led (PIN_HIGH/PIN_LOW)
* @param light_array
@verbatim
:
[100, 200, 100, 200]
@endverbatim
* @param array_size
* @param loop_cnt ()
* @return RT_EOK:; !=RT_EOK:
*/
int agile_led_init(agile_led_t *led, uint32_t pin, uint32_t active_logic, const uint32_t *light_array, int array_size, int32_t loop_cnt)
{
RT_ASSERT(led);
if (!_is_init) {
LOG_E("Please call agile_led_env_init first.");
return -RT_ERROR;
}
led->type = AGILE_LED_TYPE_STATIC;
led->active = 0;
led->pin = pin;
led->active_logic = active_logic;
led->light_arr = light_array;
led->arr_num = array_size;
led->arr_index = 0;
led->loop_init = loop_cnt;
led->loop_cnt = led->loop_init;
led->tick_timeout = rt_tick_get();
led->compelete = agile_led_default_compelete_callback;
rt_slist_init(&(led->slist));
rt_pin_mode(pin, PIN_MODE_OUTPUT);
rt_pin_write(pin, !active_logic);
return RT_EOK;
}
/**
* @brief Agile Led
* @note Agile Led
* @param led Agile Led
* @param light_array
@verbatim
:
[100, 200, 100, 200]
@endverbatim
* @param array_size
* @param loop_cnt ()
* @return RT_EOK:
*/
int agile_led_static_change_light_mode(agile_led_t *led, const uint32_t *light_array, int array_size, int32_t loop_cnt)
{
RT_ASSERT(led);
RT_ASSERT(led->type == AGILE_LED_TYPE_STATIC);
rt_mutex_take(&_mtx, RT_WAITING_FOREVER);
led->light_arr = light_array;
led->arr_num = array_size;
led->arr_index = 0;
led->loop_init = loop_cnt;
led->loop_cnt = led->loop_init;
led->tick_timeout = rt_tick_get();
rt_mutex_release(&_mtx);
return RT_EOK;
}
/**
* @brief Agile Led ,
* @param led Agile Led
* @return RT_EOK:; !=RT_OK:
*/
int agile_led_start(agile_led_t *led)
{
RT_ASSERT(led);
rt_mutex_take(&_mtx, RT_WAITING_FOREVER);
if (led->active) {
rt_mutex_release(&_mtx);
return -RT_ERROR;
}
if ((led->light_arr == RT_NULL) || (led->arr_num == 0)) {
rt_mutex_release(&_mtx);
return -RT_ERROR;
}
led->arr_index = 0;
led->loop_cnt = led->loop_init;
led->tick_timeout = rt_tick_get();
rt_slist_append(&_slist_head, &(led->slist));
led->active = 1;
rt_mutex_release(&_mtx);
return RT_EOK;
}
/**
* @brief Agile Led
* @param led Agile Led
* @return RT_EOK:
*/
int agile_led_stop(agile_led_t *led)
{
RT_ASSERT(led);
rt_mutex_take(&_mtx, RT_WAITING_FOREVER);
if (!led->active) {
rt_mutex_release(&_mtx);
return RT_EOK;
}
rt_slist_remove(&_slist_head, &(led->slist));
led->slist.next = RT_NULL;
led->active = 0;
rt_mutex_release(&_mtx);
return RT_EOK;
}
/**
* @brief Agile Led
* @param led Agile Led
* @param compelete
* @return RT_EOK:
*/
int agile_led_set_compelete_callback(agile_led_t *led, void (*compelete)(agile_led_t *led))
{
RT_ASSERT(led);
rt_mutex_take(&_mtx, RT_WAITING_FOREVER);
led->compelete = compelete;
rt_mutex_release(&_mtx);
return RT_EOK;
}
/**
* @brief Agile Led
* @param led Agile Led
*/
void agile_led_toggle(agile_led_t *led)
{
RT_ASSERT(led);
rt_pin_write(led->pin, !rt_pin_read(led->pin));
}
/**
* @brief Agile Led
* @param led Agile Led
*/
void agile_led_on(agile_led_t *led)
{
RT_ASSERT(led);
rt_pin_write(led->pin, led->active_logic);
}
/**
* @brief Agile Led
* @param led Agile Led
*/
void agile_led_off(agile_led_t *led)
{
RT_ASSERT(led);
rt_pin_write(led->pin, !led->active_logic);
}
/**
* @brief Agile Led
* @note 使 PKG_AGILE_LED_USING_THREAD_AUTO_INIT, 线 5ms
* 线 while (1) {}
*/
void agile_led_process(void)
{
rt_slist_t *node;
rt_mutex_take(&_mtx, RT_WAITING_FOREVER);
rt_slist_for_each(node, &_slist_head)
{
agile_led_t *led = rt_slist_entry(node, agile_led_t, slist);
if (led->loop_cnt == 0) {
agile_led_stop(led);
if (led->compelete) {
led->compelete(led);
}
node = &_slist_head;
continue;
}
__repeat:
if ((rt_tick_get() - led->tick_timeout) < (RT_TICK_MAX / 2)) {
if (led->arr_index < led->arr_num) {
if (led->light_arr[led->arr_index] == 0) {
led->arr_index++;
goto __repeat;
}
if (led->arr_index % 2) {
agile_led_off(led);
} else {
agile_led_on(led);
}
led->tick_timeout = rt_tick_get() + rt_tick_from_millisecond(led->light_arr[led->arr_index]);
led->arr_index++;
} else {
led->arr_index = 0;
if (led->loop_cnt > 0)
led->loop_cnt--;
}
}
}
rt_mutex_release(&_mtx);
}
/**
* @brief Agile Led
* @note 使 API
* 使 PKG_AGILE_LED_USING_THREAD_AUTO_INIT,
*/
void agile_led_env_init(void)
{
if (_is_init)
return;
rt_mutex_init(&_mtx, "led_mtx", RT_IPC_FLAG_FIFO);
_is_init = 1;
}
/**
* @}
*/
#ifdef PKG_AGILE_LED_USING_THREAD_AUTO_INIT
/** @addtogroup AGILE_LED_Thread_Auto_Init
* @{
*/
/** @defgroup AGILE_LED_Thread_Auto_Init_Functions Agile Led Thread Auto Init Functions
* @{
*/
/**
* @brief Agile Led 线
* @param parameter 线
*/
static void agile_led_auto_thread_entry(void *parameter)
{
while (1) {
agile_led_process();
rt_thread_mdelay(5);
}
}
/**
* @brief Agile Led 线
* @return RT_EOK:
*/
static int agile_led_auto_thread_init(void)
{
agile_led_env_init();
rt_thread_init(&_thread,
"agled",
agile_led_auto_thread_entry,
RT_NULL,
&_thread_stack[0],
sizeof(_thread_stack),
PKG_AGILE_LED_THREAD_PRIORITY,
100);
rt_thread_startup(&_thread);
return RT_EOK;
}
INIT_PREV_EXPORT(agile_led_auto_thread_init);
/**
* @}
*/
/**
* @}
*/
#endif /* PKG_AGILE_LED_USING_THREAD_AUTO_INIT */