2024-01-23 20:05:30 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <assert.h>
|
2024-01-30 15:11:15 +08:00
|
|
|
#include <string.h>
|
2024-01-23 20:05:30 +08:00
|
|
|
|
|
|
|
#include "FSM_private.h"
|
|
|
|
#include "FSM_protected.h"
|
|
|
|
#include "FSM_public.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
protected 函数
|
|
|
|
*/
|
|
|
|
|
|
|
|
void resetBaseFSM(FSM *pFSM)
|
|
|
|
{
|
2024-01-29 20:32:07 +08:00
|
|
|
|
2024-01-23 20:05:30 +08:00
|
|
|
if (pFSM->privateVars.fcns.exitActionTable[pFSM->privateVars.curState] != NULL)
|
2024-01-30 15:11:15 +08:00
|
|
|
pFSM->privateVars.fcns.exitActionTable[pFSM->privateVars.curState](pFSM->data, pFSM->privateVars.childFSM);
|
2024-01-23 20:05:30 +08:00
|
|
|
|
|
|
|
pFSM->privateVars.curState = 0;
|
|
|
|
}
|
2024-01-30 15:11:15 +08:00
|
|
|
|
|
|
|
static inline void setEvent(FSM* pFSM){
|
|
|
|
assert(pFSM->vtbl.selectEvent);
|
2024-04-19 15:58:28 +08:00
|
|
|
pFSM->privateVars.curEvent = pFSM->vtbl.selectEvent(pFSM->data, pFSM->signals);
|
2024-01-30 15:11:15 +08:00
|
|
|
|
|
|
|
if(0 == pFSM->privateVars.numChild){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < pFSM->privateVars.numChild; i++)
|
|
|
|
{
|
|
|
|
FSM *cFSM = pFSM->privateVars.childFSM[i];
|
|
|
|
setEvent(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;
|
|
|
|
}
|
|
|
|
}
|
2024-01-30 19:38:48 +08:00
|
|
|
|
2024-01-23 20:05:30 +08:00
|
|
|
|
|
|
|
void stepBaseFSM(FSM *pFSM)
|
|
|
|
{
|
2024-01-30 15:11:15 +08:00
|
|
|
preload(pFSM);
|
|
|
|
setEvent(pFSM);
|
2024-04-19 16:11:24 +08:00
|
|
|
pFSM->vtbl.resetSignals(pFSM);
|
2024-01-30 15:11:15 +08:00
|
|
|
|
2024-01-30 15:44:19 +08:00
|
|
|
FSMHandler *fcns = &pFSM->privateVars.fcns;
|
2024-01-29 20:32:07 +08:00
|
|
|
int curState = pFSM->privateVars.curState;
|
|
|
|
void *data = pFSM->data;
|
2024-01-30 15:44:19 +08:00
|
|
|
FSM **childFSM = pFSM->privateVars.childFSM;
|
|
|
|
int index = pFSM->privateVars.curState * pFSM->privateVars.numEvent + pFSM->privateVars.curEvent;
|
|
|
|
int nextState;
|
|
|
|
|
2024-01-30 20:35:05 +08:00
|
|
|
if(fcns->delayedEvent){
|
|
|
|
fcns->transitionDelayTable[fcns->delayedEvent](data);
|
|
|
|
fcns->delayedEvent = 0;
|
|
|
|
}
|
|
|
|
|
2024-01-29 20:32:07 +08:00
|
|
|
if (fcns->transitionTable[index] != NULL)
|
2024-01-23 20:05:30 +08:00
|
|
|
{
|
2024-01-29 20:32:07 +08:00
|
|
|
if (fcns->exitActionTable[curState] != NULL)
|
2024-01-30 15:11:15 +08:00
|
|
|
fcns->exitActionTable[curState](data, childFSM);
|
2024-01-29 20:32:07 +08:00
|
|
|
|
2024-01-30 20:35:05 +08:00
|
|
|
nextState = (*fcns->transitionTable[index])(data, curState, &fcns->delayedEvent);
|
2024-01-23 20:05:30 +08:00
|
|
|
|
2024-01-29 20:32:07 +08:00
|
|
|
if (fcns->enterActionTable[nextState] != NULL)
|
2024-01-30 15:11:15 +08:00
|
|
|
fcns->enterActionTable[nextState](data, childFSM);
|
2024-01-23 20:05:30 +08:00
|
|
|
|
2024-01-29 20:32:07 +08:00
|
|
|
pFSM->privateVars.curState = nextState;
|
2024-01-23 20:05:30 +08:00
|
|
|
}
|
2024-01-29 20:32:07 +08:00
|
|
|
else if(curState == 0){
|
|
|
|
nextState = pFSM->privateVars.defaultState;
|
|
|
|
if (fcns->enterActionTable[nextState] != NULL)
|
2024-01-30 15:11:15 +08:00
|
|
|
fcns->enterActionTable[nextState](data, childFSM);
|
2024-01-29 20:32:07 +08:00
|
|
|
pFSM->privateVars.curState = nextState;
|
2024-01-23 20:05:30 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-01-29 20:32:07 +08:00
|
|
|
if (fcns->duringActionTable[curState] != NULL)
|
2024-01-30 15:11:15 +08:00
|
|
|
fcns->duringActionTable[curState](data, childFSM);
|
2024-01-23 20:05:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FSM* newBaseFSM(int numState, int numEvent, int defaultState){
|
2024-01-29 20:32:07 +08:00
|
|
|
typedef void (*StateFuncPtr)(void *data);
|
|
|
|
typedef void (*ChildFSMStepFuncPtr)(FSM **cFSM);
|
|
|
|
typedef int (*TransitionFuncPtr)(void *data, int currentState);
|
2024-01-23 20:05:30 +08:00
|
|
|
|
|
|
|
FSM *pFSM = calloc(1, sizeof(FSM));
|
|
|
|
pFSM->privateVars.curEvent = 0;
|
|
|
|
pFSM->privateVars.curState = 0;
|
|
|
|
pFSM->privateVars.numEvent = numEvent;
|
|
|
|
pFSM->privateVars.defaultState = defaultState;
|
|
|
|
pFSM->privateVars.numChild = 0;
|
|
|
|
|
2024-01-30 15:11:15 +08:00
|
|
|
pFSM->privateVars.preloader.isReady = 0;
|
|
|
|
|
2024-01-23 20:05:30 +08:00
|
|
|
pFSM->privateVars.fcns.duringActionTable = calloc(numState, sizeof(StateFuncPtr));
|
|
|
|
pFSM->privateVars.fcns.enterActionTable = calloc(numState, sizeof(StateFuncPtr));
|
|
|
|
pFSM->privateVars.fcns.exitActionTable = calloc(numState, sizeof(StateFuncPtr));
|
2024-01-29 20:32:07 +08:00
|
|
|
|
2024-01-23 20:05:30 +08:00
|
|
|
pFSM->privateVars.fcns.transitionTable = calloc(numState * numEvent, sizeof(TransitionFuncPtr));
|
2024-01-29 20:32:07 +08:00
|
|
|
pFSM->privateVars.fcns.childFSMStepTable = calloc(numState * numEvent, sizeof(ChildFSMStepFuncPtr));
|
2024-01-30 20:35:05 +08:00
|
|
|
pFSM->privateVars.fcns.transitionDelayTable = calloc(numEvent, sizeof(StateFuncPtr));
|
2024-01-23 20:05:30 +08:00
|
|
|
|
|
|
|
FSMVtbl vtbl = {
|
|
|
|
.reset = resetBaseFSM,
|
|
|
|
.step = stepBaseFSM,
|
|
|
|
.selectEvent = NULL,
|
|
|
|
.setupHandler = NULL,
|
|
|
|
.initData = NULL,
|
2024-01-30 20:35:05 +08:00
|
|
|
.initDataLoader = NULL,
|
2024-04-19 15:58:28 +08:00
|
|
|
.initSignals = NULL,
|
2024-01-23 20:05:30 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
pFSM->vtbl = vtbl;
|
|
|
|
return pFSM;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void constructFSM(FSM* pFSM){
|
|
|
|
assert(pFSM->vtbl.setupHandler);
|
|
|
|
assert(pFSM->vtbl.initData);
|
2024-01-30 20:35:05 +08:00
|
|
|
assert(pFSM->vtbl.initDataLoader);
|
2024-04-19 15:58:28 +08:00
|
|
|
assert(pFSM->vtbl.initSignals);
|
2024-01-23 20:05:30 +08:00
|
|
|
|
|
|
|
pFSM->vtbl.setupHandler(&pFSM->privateVars.fcns);
|
|
|
|
pFSM->vtbl.initData(pFSM);
|
2024-01-30 20:35:05 +08:00
|
|
|
pFSM->vtbl.initDataLoader(pFSM);
|
2024-04-19 15:58:28 +08:00
|
|
|
pFSM->vtbl.initSignals(pFSM);
|
2024-01-23 20:05:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
public 函数
|
|
|
|
*/
|
|
|
|
int getFSMCurState(FSM *pFSM){
|
|
|
|
return pFSM->privateVars.curState;
|
|
|
|
}
|
|
|
|
int getFSMCurEvent(FSM *pFSM){
|
|
|
|
return pFSM->privateVars.curEvent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-04-19 13:07:09 +08:00
|
|
|
const void *_getData(FSM* pFSM){
|
2024-01-30 15:11:15 +08:00
|
|
|
return (const void *)pFSM->data;
|
|
|
|
}
|
|
|
|
|
2024-04-19 15:58:28 +08:00
|
|
|
void *_getSignals(FSM* pFSM){
|
|
|
|
return pFSM->signals;
|
|
|
|
}
|
|
|
|
|
2024-04-19 13:07:09 +08:00
|
|
|
|
2024-01-30 23:00:38 +08:00
|
|
|
void *_preloadIn(FSM *pFSM){
|
2024-01-30 15:11:15 +08:00
|
|
|
return pFSM->privateVars.preloader.in;
|
|
|
|
}
|
|
|
|
|
2024-01-30 23:07:08 +08:00
|
|
|
void _preloaderGetReady(FSM *pFSM){
|
2024-04-19 13:07:09 +08:00
|
|
|
if(pFSM->privateVars.preloader.isReady){
|
|
|
|
pFSM->privateVars.preloader.isOverflow = 1;
|
|
|
|
}
|
2024-01-30 15:11:15 +08:00
|
|
|
pFSM->privateVars.preloader.isReady = 1;
|
2024-01-23 20:05:30 +08:00
|
|
|
}
|
|
|
|
|
2024-04-19 13:07:09 +08:00
|
|
|
int _getPreloaderOverFlag(FSM *pFSM){
|
|
|
|
return pFSM->privateVars.preloader.isOverflow;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _clearPreloaderOverFlag(FSM *pFSM){
|
|
|
|
pFSM->privateVars.preloader.isOverflow = 0;
|
|
|
|
}
|
|
|
|
|
2024-01-30 15:11:15 +08:00
|
|
|
|
2024-01-30 23:00:38 +08:00
|
|
|
FSMVtbl *_vptrFSM(FSM* pFSM){
|
2024-01-23 20:05:30 +08:00
|
|
|
return &pFSM->vtbl;
|
|
|
|
}
|