freeRTOS操作系统机器人实现
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

341 lines
8.3 KiB

/******************************************************************************
版权所有 (C), 2018-2099, Radkil_Std
******************************************************************************
文 件 名 : led.c
版 本 号 : 初稿
作 者 : Radkil
生成日期 : 2022年12月2日
最近修改 :
功能描述 : io输出相关模块管理
修改历史 :
1.日 期 : 2022年12月2日
作 者 : Radkil
修改内容 : 创建文件
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "led.h"
#include "rd_thread.h"
#include "rd_time.h"
/*----------------------------------------------*
* 外部变量说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 内部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 全局变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
static rd_slist_t g_sLedListHead = RD_SLIST_OBJECT_INIT(g_sLedListHead); //led对象的链表头结点
static rd_mutex_t g_fpLedCtrl = RD_MUTEX_INITIALIZER; //led控制模块互斥锁
/*----------------------------------------------*
* 常量定义 *
*----------------------------------------------*/
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
static void cbk_LedDefaultCompeleteCallback(rd_led_t *_ptLed)
{
log_i("Led[%p] is compelete!", _ptLed);
}
static int rd_LedGetLightArr(rd_led_t *_ptLed, const char *light_mode)
{
int iRet = RD_SUCCESS;
if(NULL == _ptLed || NULL == _ptLed->m_pCbkCtrl)
{
return RD_INVALUE;
}
const char *ptr = light_mode;
while (*ptr)
{
if (*ptr == ',')
{
_ptLed->m_iArrNum++;
}
ptr++;
}
if (*(ptr - 1) != ',')
{
_ptLed->m_iArrNum++;
}
if (_ptLed->m_iArrNum == 0)
{
iRet = RD_FAILURE;
goto END;
}
uint32_t *piLightArr = RD_MALLOC(_ptLed->m_iArrNum * sizeof(uint32_t));
if (piLightArr == NULL)
{
iRet = RD_FAILURE;
goto END;
}
RD_MEMSET(piLightArr, 0, _ptLed->m_iArrNum * sizeof(int));
ptr = light_mode;
int i = 0;
for (i = 0; i < _ptLed->m_iArrNum; i++)
{
piLightArr[i] = (uint32_t)atoi(ptr);
ptr = strchr(ptr, ',');
if (ptr)
ptr++;
}
_ptLed->m_piLightArr = piLightArr;
END:
return iRet;
}
int rd_LedStart(rd_led_t *_ptLed)
{
int iRet = RD_SUCCESS;
Rd_MutexLock(&g_fpLedCtrl, __func__, NULL);
if(NULL == _ptLed)
{
goto END;
return RD_INVALUE;
}
if (_ptLed->m_iActive)
{
iRet = RD_FAILURE;
goto END;
}
if ((_ptLed->m_piLightArr == NULL) || (_ptLed->m_iArrNum == 0))
{
iRet = RD_FAILURE;
goto END;
}
_ptLed->m_iArrIndex = 0;
_ptLed->m_iLoopCnt = _ptLed->m_iLoopInit;
_ptLed->m_iTimeout = Rd_GetTime();
rd_slist_append(&g_sLedListHead, &(_ptLed->m_tSlist));
_ptLed->m_iActive = 1;
END:
Rd_MutexUnlock(&g_fpLedCtrl, __func__, NULL);
return iRet;
}
int rd_LedStop(rd_led_t *_ptLed)
{
int iRet = RD_SUCCESS;
Rd_MutexLock(&g_fpLedCtrl, __func__, NULL);
if(NULL == _ptLed)
{
goto END;
return RD_INVALUE;
}
if (!_ptLed->m_iActive)
{
iRet = RD_FAILURE;
goto END;
}
rd_slist_remove(&g_sLedListHead, &(_ptLed->m_tSlist));
_ptLed->m_tSlist.next = NULL;
_ptLed->m_iActive = 0;
END:
Rd_MutexUnlock(&g_fpLedCtrl, __func__, NULL);
return iRet;
}
void rd_LedOn(rd_led_t *_ptLed)
{
if(NULL != _ptLed && NULL != _ptLed->m_pCbkCtrl)
{
_ptLed->m_pCbkCtrl(_ptLed->m_pLed_t, _ptLed->m_iActiveLogic);
}
}
void rd_LedOff(rd_led_t *_ptLed)
{
if(NULL != _ptLed && NULL != _ptLed->m_pCbkCtrl)
{
_ptLed->m_pCbkCtrl(_ptLed->m_pLed_t, !_ptLed->m_iActiveLogic);
}
}
rd_led_t *rd_LedCreate(int active_logic, const char *light_mode, uint8_t loop_cnt, void (*_pCbkCtrl)(l_led_t *pLed, int _iState), l_led_t *pLed_t)
{
rd_led_t *_ptLed = (rd_led_t *)RD_MALLOC(sizeof(rd_led_t));
if(NULL == _ptLed || NULL == _pCbkCtrl)
{
return NULL;
}
_ptLed->m_iActive = 0;
_ptLed->m_pLed_t = pLed_t;
_ptLed->m_pCbkCtrl = _pCbkCtrl;
_ptLed->m_iActiveLogic = active_logic;
_ptLed->m_piLightArr = NULL;
_ptLed->m_iArrNum = 0;
_ptLed->m_iArrIndex = 0;
if (light_mode)
{
if (rd_LedGetLightArr(_ptLed, light_mode) != RD_SUCCESS)
{
RD_FREE(_ptLed);
return NULL;
}
}
_ptLed->m_iLoopInit = loop_cnt;
_ptLed->m_iLoopCnt = _ptLed->m_iLoopInit;
_ptLed->m_iTimeout = Rd_GetTime();
_ptLed->m_pCompelete = cbk_LedDefaultCompeleteCallback;
rd_slist_init(&(_ptLed->m_tSlist));
_ptLed->m_pCbkCtrl(pLed_t, !active_logic);
return _ptLed;
}
int rd_LedDelete(rd_led_t *_ptLed)
{
if(NULL == _ptLed)
{
return RD_INVALUE;
}
Rd_MutexLock(&g_fpLedCtrl, __func__, NULL);
rd_slist_remove(&g_sLedListHead, &(_ptLed->m_tSlist));
_ptLed->m_tSlist.next = NULL;
Rd_MutexUnlock(&g_fpLedCtrl, __func__, NULL);
if (_ptLed->m_piLightArr)
{
RD_FREE((int *)_ptLed->m_piLightArr);
_ptLed->m_piLightArr = NULL;
}
RD_FREE(_ptLed);
return RD_SUCCESS;
}
int rd_LedDynamicChangeLightMode(rd_led_t *_ptLed, const char *light_mode, uint8_t loop_cnt)
{
int iRet = RD_SUCCESS;
Rd_MutexLock(&g_fpLedCtrl, __func__, NULL);
if(NULL == _ptLed)
{
goto END;
return RD_INVALUE;
}
if (light_mode)
{
if (_ptLed->m_piLightArr)
{
RD_FREE((int *)_ptLed->m_piLightArr);
_ptLed->m_piLightArr = NULL;
}
_ptLed->m_iArrNum = 0;
if (rd_LedGetLightArr(_ptLed, light_mode) != RD_SUCCESS)
{
rd_LedStop(_ptLed);
iRet = RD_FAILURE;
goto END;
}
}
_ptLed->m_iLoopInit = loop_cnt;
_ptLed->m_iArrIndex = 0;
_ptLed->m_iLoopCnt = _ptLed->m_iLoopInit;
_ptLed->m_iTimeout = Rd_GetTime();
END:
Rd_MutexUnlock(&g_fpLedCtrl, __func__, NULL);
return iRet;
}
void rd_LedProcess(void)
{
rd_slist_t *pNode;
rd_slist_t *pN;
rd_slist_for_each(pNode, pN, &g_sLedListHead)
{
rd_led_t *pLed = rd_slist_entry(pNode, rd_led_t, m_tSlist);
if (pLed->m_iLoopCnt == 0)
{
rd_LedStop(pLed);
if (pLed->m_pCompelete)
{
pLed->m_pCompelete(pLed);
}
pNode = &g_sLedListHead;
continue;
}
Rd_MutexLock(&g_fpLedCtrl, __func__, NULL);
REPEAT:
if (pLed->m_iArrIndex < pLed->m_iArrNum && NULL != pLed->m_piLightArr)
{
if (pLed->m_piLightArr[pLed->m_iArrIndex] == 0)
{
pLed->m_iArrIndex++;
goto REPEAT;
}
if (Rd_GetTime() - pLed->m_iTimeout >= pLed->m_piLightArr[pLed->m_iArrIndex])
{
if (pLed->m_iArrIndex % 2)
{
rd_LedOff(pLed);
}
else
{
rd_LedOn(pLed);
}
pLed->m_iTimeout = Rd_GetTime();
pLed->m_iArrIndex++;
}
}
else
{
pLed->m_iArrIndex = 0;
if (pLed->m_iLoopCnt > 0)
{
pLed->m_iLoopCnt--;
}
}
Rd_MutexUnlock(&g_fpLedCtrl, __func__, NULL);
}
}