blob: 7e69387e82a53d26368773b5d0f1ed492ed3eb82 [file] [log] [blame]
/********************************************************************************************************
* @file app_simple_fsm.c
*
* @brief This is the source file for b85m
*
* @author ROW GROUP
* @date Nov,2022
*
* @par Copyright (c) 2022, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*******************************************************************************************************/
#include "tl_common.h"
#include "app_simple_fsm.h"
/**********************************************************************
* LOCAL DEFINE
*/
//#define APP_FSM_EN_LOG
#ifdef APP_FSM_EN_LOG
#define APP_FSM_LOG_TRACE log_trace
#define APP_FSM_LOG_DEBUG log_debug
#define APP_FSM_LOG_WARN log_warn
#define APP_FSM_LOG_ERROR log_error
#define APP_FSM_ARRAY_LOG_TRACE array_log_trace
#define APP_FSM_ARRAY_LOG_DEBUG array_log_debug
#define APP_FSM_ARRAY_LOG_WARN array_log_warn
#else
#define APP_FSM_LOG_TRACE(...)
#define APP_FSM_LOG_DEBUG(...)
#define APP_FSM_LOG_WARN(...)
#define APP_FSM_LOG_ERROR(...)
#define APP_FSM_ARRAY_LOG_TRACE(...)
#define APP_FSM_ARRAY_LOG_DEBUG(...)
#define APP_FSM_ARRAY_LOG_WARN(...)
#endif
#ifdef APP_FSM_EN_PUSH_TO_FIFO
/* APP VOICE FSM FIFO settings */
#define APP_FSM_BUF_SIZE (8)
#define APP_FSM_BUF_NUM (2)
#endif
/**********************************************************************
* LOCAL TYPES
*/
typedef struct {
u16 eventID;
u16 paraLen;
u8 para[0];
}fsm_event_cache_t;
/**********************************************************************
* LOCAL VARIABLES
*/
#ifdef APP_FSM_EN_PUSH_TO_FIFO
/* FMS FIFO */
_attribute_data_no_init_ u8 s_fsm_fifo_b[APP_FSM_BUF_SIZE * APP_FSM_BUF_NUM] = {0};
_attribute_data_no_init_ app_fifo_t s_fsm_fifo = {
.size = APP_FSM_BUF_SIZE,
.num = APP_FSM_BUF_NUM,
.wptr = 0,
.rptr = 0,
.p = s_fsm_fifo_b};
#endif
/**********************************************************************
* LOCAL FUNCTIONS
*/
inline void app_fsm_stateTrans(app_fsm_t *pFsm,u8 state ){
pFsm->curState = state;
}
static void trigger_event(app_fsm_t *pFsm, u16 eventID, u8 *pBuf, u16 bufLen){
app_fsm_table_t *p_my_table = pFsm->pFsmTable;
if(NULL == p_my_table) return;
u8 my_nextState;
u8 my_curState = pFsm->curState;
u8 my_fsmTabCnt = pFsm->fsmTabCnt;;
app_fsm_eventActFunc_t my_eventFunc = NULL;
u8 flag_hit = 0;
for(u16 i=0; i<my_fsmTabCnt; i++){
if((my_curState == p_my_table[i].curState) && (eventID == p_my_table[i].eventID)){
flag_hit = 1;
my_eventFunc = p_my_table[i].eventFunc;
my_nextState = p_my_table[i].nextState;
break;
}
}
if(flag_hit){
int ret_eventFunc = 0;
if(my_eventFunc){
app_fsm_evnet_t my_event = {eventID, bufLen, pBuf, my_curState, my_nextState};
ret_eventFunc = my_eventFunc(my_event);
}
if(0 == ret_eventFunc){
/* When the return value of the event function is 0, it is converted according to the FSM table. */
app_fsm_stateTrans(pFsm, my_nextState);
}else if(ret_eventFunc < 0){
/* When the return value of the event function is less than 0, the conversion state is refused and the original state is maintained */
}else{
/* When the return value of the event function is greater than 0, it is forced to be set to the state of the return value. */
if(ret_eventFunc <= pFsm->maxState){
app_fsm_stateTrans(pFsm, ret_eventFunc);
}
}
}
}
/**********************************************************************
* GLOBAL FUNCTIONS
*/
void app_fsm_init(app_fsm_t *pFsm, app_fsm_table_t *pFsmTable, u8 fmsTabCnt, u8 initState, u8 maxState){
if((NULL == pFsm) || (NULL == pFsmTable)) return;
pFsm->pFsmTable = pFsmTable;
pFsm->fsmTabCnt = fmsTabCnt;
pFsm->curState = initState;
pFsm->maxState = maxState;
}
void app_fsm_triggerEvent(app_fsm_t *pFsm, u16 eventID, u8 *pBuf, u16 bufLen){
#ifndef APP_FSM_EN_PUSH_TO_FIFO
trigger_event(pFsm, eventID, pBuf, bufLen);
#else
app_fifo_init(&s_fsm_fifo, APP_FSM_BUF_SIZE, APP_FSM_BUF_NUM, s_fsm_fifo_b);
trigger_event(pFsm, eventID, pBuf, bufLen);
/* Check whether FMS events is generated in the callback function */
fsm_event_cache_t *p_my_event_buf = (fsm_event_cache_t *)app_fifo_get(&s_fsm_fifo);
if(NULL == p_my_event_buf){
return;
}
/* Process the events generated in the FSM event callback function sequentially. */
for(u8 i=0; i<pFsm->maxState; i++){
trigger_event(pFsm, p_my_event_buf->eventID, p_my_event_buf->para, p_my_event_buf->paraLen);
app_fifo_pop(&s_fsm_fifo);
p_my_event_buf = (fsm_event_cache_t *)app_fifo_get(&s_fsm_fifo);
if(NULL == p_my_event_buf){
break;
}
}
#endif
}
#ifdef APP_FSM_EN_PUSH_TO_FIFO
void app_fsm_pushEvent(app_fsm_t *pFsm, unsigned short eventID, unsigned char *pBuf, unsigned short bufLen){
if(bufLen > (APP_FSM_BUF_SIZE-sizeof(fsm_event_cache_t))){
APP_FSM_LOG_WARN("bufLen of pBuf passed in is too long");
return;
}
fsm_event_cache_t *p_my_fmsEvent = (fsm_event_cache_t *)app_fifo_wptr(&s_fsm_fifo);
if(NULL == p_my_fmsEvent){
APP_FSM_LOG_WARN("FSM FIFO not enough !!!");
return;
}
p_my_fmsEvent->eventID = eventID;
p_my_fmsEvent->paraLen = 0;
if((NULL == pBuf) || (0 == bufLen)){
}else{
p_my_fmsEvent->paraLen = bufLen;
memcpy(p_my_fmsEvent->para, pBuf, bufLen);
}
app_fifo_next(&s_fsm_fifo);
APP_FSM_ARRAY_LOG_TRACE("FSM EVENT", (u8 *)p_my_fmsEvent, bufLen+sizeof(fsm_event_cache_t));
}
#endif