210 lines
5.9 KiB
C
210 lines
5.9 KiB
C
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <assert.h>
|
||
#include <string.h>
|
||
|
||
#include "FSM_private.h"
|
||
#include "FSM_protected.h"
|
||
#include "FSM_public.h"
|
||
|
||
/*
|
||
protected 函数
|
||
*/
|
||
|
||
void resetBaseFSM(FSM *pFSM)
|
||
{
|
||
if (pFSM->privateVars.fcns.exitActionTable[pFSM->privateVars.curState] != NULL)
|
||
pFSM->privateVars.fcns.exitActionTable[pFSM->privateVars.curState](pFSM->data, pFSM->privateVars.childFSM);
|
||
|
||
pFSM->privateVars.curState = 0;
|
||
}
|
||
|
||
static inline void setNextState(FSM* pFSM){
|
||
int curState = pFSM->privateVars.curState;
|
||
if(curState != 0){
|
||
pFSM->privateVars.nextState = pFSM->privateVars.fcns.selectNextState[curState](pFSM->data, pFSM->signals);
|
||
}
|
||
|
||
if(0 == pFSM->privateVars.numChild)
|
||
return;
|
||
|
||
|
||
for (int i = 0; i < pFSM->privateVars.numChild; i++)
|
||
{
|
||
FSM *cFSM = pFSM->privateVars.childFSM[i];
|
||
setNextState(cFSM);
|
||
}
|
||
}
|
||
|
||
static inline void preload(FSM* pFSM){
|
||
if(pFSM->privateVars.preloader.isReady){
|
||
memcpy(pFSM->data, pFSM->privateVars.preloader.in, pFSM->privateVars.preloader.preloadSize);
|
||
pFSM->privateVars.preloader.isReady = 0;
|
||
}
|
||
}
|
||
|
||
static inline void resetSignals(FSM *pFSM){
|
||
memset(pFSM->signals, 0, pFSM->signalSize);
|
||
}
|
||
|
||
void stepBaseFSM(FSM *pFSM)
|
||
{
|
||
preload(pFSM);
|
||
setNextState(pFSM);
|
||
// pFSM->vtbl.resetSignals(pFSM);
|
||
resetSignals(pFSM);
|
||
|
||
FSMHandler *fcns = &pFSM->privateVars.fcns;
|
||
int curState = pFSM->privateVars.curState;
|
||
void *data = pFSM->data;
|
||
FSM **childFSM = pFSM->privateVars.childFSM;
|
||
int index = pFSM->privateVars.curState * pFSM->privateVars.numState + pFSM->privateVars.nextState;
|
||
int nextState = pFSM->privateVars.nextState;
|
||
|
||
|
||
if(nextState && curState != nextState){ // 状态切换
|
||
if (fcns->transitionTable[index] != NULL) // 有特定的状态转移函数
|
||
{
|
||
if (fcns->exitActionTable[curState] != NULL)
|
||
fcns->exitActionTable[curState](data, childFSM);
|
||
|
||
(*fcns->transitionTable[index])(data);
|
||
|
||
if (fcns->enterActionTable[nextState] != NULL)
|
||
fcns->enterActionTable[nextState](data, childFSM);
|
||
}
|
||
if(fcns->transitionGeneralAction != NULL)
|
||
fcns->transitionGeneralAction(data); // 通用状态转移函数
|
||
pFSM->privateVars.curState = nextState;
|
||
}
|
||
else if(curState == 0){ // 处理刚运行进入的默认状态
|
||
nextState = pFSM->privateVars.defaultState;
|
||
if (fcns->enterActionTable[nextState] != NULL)
|
||
fcns->enterActionTable[nextState](data, childFSM);
|
||
pFSM->privateVars.curState = nextState;
|
||
}
|
||
else // 状态机没动
|
||
{
|
||
if (fcns->duringActionTable[curState] != NULL)
|
||
fcns->duringActionTable[curState](data, childFSM);
|
||
}
|
||
}
|
||
|
||
FSM* newBaseFSM(int numState, int defaultState){
|
||
typedef void (*StateFuncPtr)(void *);
|
||
typedef void (*ChildFSMStepFuncPtr)(FSM **);
|
||
typedef int (*TransitionFuncPtr)(void *, int *);
|
||
typedef int (*SelectNextStateFcnPtr)(void *, void *);
|
||
|
||
FSM *pFSM = calloc(1, sizeof(FSM));
|
||
pFSM->privateVars.numState = numState;
|
||
pFSM->privateVars.defaultState = defaultState;
|
||
pFSM->privateVars.curState = 0;
|
||
pFSM->privateVars.nextState = 0;
|
||
pFSM->privateVars.numChild = 0;
|
||
|
||
pFSM->privateVars.preloader.isReady = 0;
|
||
|
||
pFSM->privateVars.fcns.duringActionTable = calloc(numState, sizeof(StateFuncPtr));
|
||
pFSM->privateVars.fcns.enterActionTable = calloc(numState, sizeof(StateFuncPtr));
|
||
pFSM->privateVars.fcns.exitActionTable = calloc(numState, sizeof(StateFuncPtr));
|
||
|
||
pFSM->privateVars.fcns.selectNextState = calloc(numState, sizeof(SelectNextStateFcnPtr));
|
||
pFSM->privateVars.fcns.transitionTable = calloc(numState * numState, sizeof(TransitionFuncPtr));
|
||
pFSM->privateVars.fcns.transitionGeneralAction = calloc(1, sizeof(StateFuncPtr));
|
||
|
||
pFSM->privateVars.fcns.childFSMStepTable = calloc(numState * numState, sizeof(ChildFSMStepFuncPtr));
|
||
|
||
|
||
|
||
|
||
FSMVtbl vtbl = {
|
||
.reset = resetBaseFSM,
|
||
.step = stepBaseFSM,
|
||
.setupHandler = NULL,
|
||
.initData = NULL,
|
||
.initDataLoader = NULL,
|
||
.initSignals = NULL,
|
||
};
|
||
|
||
pFSM->vtbl = vtbl;
|
||
return pFSM;
|
||
}
|
||
|
||
|
||
void constructFSM(FSM* pFSM){
|
||
assert(pFSM->vtbl.setupHandler);
|
||
assert(pFSM->vtbl.initData);
|
||
assert(pFSM->vtbl.initDataLoader);
|
||
assert(pFSM->vtbl.initSignals);
|
||
|
||
pFSM->vtbl.setupHandler(&pFSM->privateVars.fcns);
|
||
pFSM->vtbl.initData(pFSM);
|
||
pFSM->vtbl.initDataLoader(pFSM);
|
||
pFSM->vtbl.initSignals(pFSM);
|
||
|
||
|
||
/* ---------------------------------- 检查状态表 --------------------------------- */
|
||
for (int i = 1; i < pFSM->privateVars.numState; i++) // 跳过Idle状态,Idle状态只能跳转到默认状态
|
||
{
|
||
if(!pFSM->privateVars.fcns.selectNextState[i]){
|
||
FSM_LOG("每个状态都要有一个状态选择函数!\n");
|
||
assert(0); // 强制退出
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
public 函数
|
||
*/
|
||
int getFSMCurState(FSM *pFSM){
|
||
return pFSM->privateVars.curState;
|
||
}
|
||
int getFSMNextState(FSM *pFSM){
|
||
return pFSM->privateVars.nextState;
|
||
}
|
||
|
||
|
||
void setChildNum(FSM *pFSM, int num){
|
||
pFSM->privateVars.numChild = num;
|
||
pFSM->privateVars.childFSM = (FSM **)calloc(num, sizeof(FSM *));
|
||
}
|
||
|
||
void registerChildFSM(FSM *parent, FSM *child, int index){
|
||
parent->privateVars.childFSM[index] = child;
|
||
}
|
||
|
||
const void *_getData(FSM* pFSM){
|
||
return (const void *)pFSM->data;
|
||
}
|
||
|
||
void *_getSignals(FSM* pFSM){
|
||
return pFSM->signals;
|
||
}
|
||
|
||
|
||
void *_preloadIn(FSM *pFSM){
|
||
return pFSM->privateVars.preloader.in;
|
||
}
|
||
|
||
void _preloaderGetReady(FSM *pFSM){
|
||
if(pFSM->privateVars.preloader.isReady){
|
||
pFSM->privateVars.preloader.isOverflow = 1;
|
||
}
|
||
pFSM->privateVars.preloader.isReady = 1;
|
||
}
|
||
|
||
int _getPreloaderOverFlag(FSM *pFSM){
|
||
return pFSM->privateVars.preloader.isOverflow;
|
||
}
|
||
|
||
void _clearPreloaderOverFlag(FSM *pFSM){
|
||
pFSM->privateVars.preloader.isOverflow = 0;
|
||
}
|
||
|
||
|
||
FSMVtbl *_vptrFSM(FSM* pFSM){
|
||
return &pFSM->vtbl;
|
||
}
|