From ebdcc7be0ba0d4d2f0a08f8af28766e3429ada2b Mon Sep 17 00:00:00 2001 From: Douglas Clowes Date: Tue, 15 Jan 2008 12:27:25 +1100 Subject: [PATCH] Extracted abstract Finite State Machine (from DMC2280 motor driver) r2272 | dcl | 2008-01-15 12:27:25 +1100 (Tue, 15 Jan 2008) | 2 lines --- site_ansto/fsm.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ site_ansto/fsm.h | 62 ++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 site_ansto/fsm.c create mode 100644 site_ansto/fsm.h diff --git a/site_ansto/fsm.c b/site_ansto/fsm.c new file mode 100644 index 00000000..1a85760c --- /dev/null +++ b/site_ansto/fsm.c @@ -0,0 +1,93 @@ +#include "fsm.h" + +static void report_event(pStateMachine self, pEvtEvent event) { + char line[132]; + char text[132]; + snprintf(line, sizeof(line), "StateMachine=%s, State=%s(%d), event=%s", + self->name ? self->name : "", + self->state_name ? self->state_name(self->myState) : "", + self->mySubState, + self->event_name ? self->event_name(event, text, sizeof(text)) : ""); + SICSLogWrite(line, eStatus); +} + +static void handle_event(pStateMachine self, pEvtEvent event) { + if (self->debug) + report_event(self, event); + if (self->myState) + self->myState(self, event); +} + +int fsm_msg_callback(pAsyncTxn pCmd) +{ + pStateMachine self = (pStateMachine) pCmd->cntx; + EvtEvent event; + + if (pCmd->txn_status == ATX_TIMEOUT) { + if (self->debug) { + SICSLogWrite(pCmd->out_buf, eStatus); + SICSLogWrite("", eStatus); + } + event.event_type = eTimeoutEvent; + event.event.msg.cmd = pCmd; + } + else { + if (self->debug) { + SICSLogWrite(pCmd->out_buf, eStatus); + SICSLogWrite(pCmd->inp_buf, eStatus); + } + event.event_type = eMessageEvent; + event.event.msg.cmd = pCmd; + } + handle_event(self, &event); + return 0; +} + +int fsm_tmr_callback(void* ctx, int mode) +{ + pStateMachine self = (pStateMachine) ctx; + EvtEvent event; + event.event_type = eTimerEvent; + handle_event(self, &event); + return 0; +} + +int fsm_cmd_execute(pStateMachine self, const void* cmd) { + EvtEvent event; + event.event_type = eCommandEvent; + event.event.cmd.cmd_text = cmd; + handle_event(self, &event); + return 0; +} + +void fsm_change_state(pStateMachine self, StateFunc func) { + if (self->debug) { + char line[132]; + snprintf(line, sizeof(line), "StateMachine=%s, OldState=%s(%d), NewState=%s", + self->name ? self->name : "", + self->state_name ? self->state_name(self->myState) : "", + self->mySubState, + self->state_name ? self->state_name(func) : ""); + if (self->debug) + SICSLogWrite(line, eStatus); + } + self->myPrevState = self->myState; + self->myState = func; + self->mySubState = 0; + EvtEvent evt; + evt.event_type = eStateEvent; + if (self->myState) + self->myState(self, &evt); +} + +void fsm_unhandled_event(pStateMachine self, pEvtEvent event) { + char line[132]; + char text[132]; + snprintf(line, sizeof(line), "StateMachine=%s, State=%s(%d), unhandled event=%s", + self->name ? self->name : "", + self->state_name ? self->state_name(self->myState) : "", + self->mySubState, + self->event_name ? self->event_name(event, text, sizeof(text)) : ""); + SICSLogWrite(line, eError); +} + diff --git a/site_ansto/fsm.h b/site_ansto/fsm.h new file mode 100644 index 00000000..e4f9c070 --- /dev/null +++ b/site_ansto/fsm.h @@ -0,0 +1,62 @@ +#ifndef FINITESTATEMACHINE +#define FINITESTATEMACHINE + +#include +#include +#include +#include + +typedef struct statemachine_s StateMachine, *pStateMachine; +typedef struct EvtEvent_s EvtEvent, *pEvtEvent; +typedef void (*StateFunc)(pStateMachine self, pEvtEvent event); + +enum eventtype { + eStateEvent, + eTimerEvent, + eMessageEvent, + eCommandEvent, + eTimeoutEvent +}; + +typedef struct EvtState_s { } EvtState; +typedef struct EvtTimer_s { } EvtTimer; + +typedef struct EvtMessage_s { + pAsyncTxn cmd; +} EvtMessage; + +typedef struct EvtCommand_s { + const void* cmd_text; +} EvtCommand; + +typedef struct EvtTimeout_s { } EvtTimeout; + +struct EvtEvent_s { + enum eventtype event_type; + union { + EvtState sta; + EvtTimer tmr; + EvtMessage msg; + EvtCommand cmd; + EvtTimeout tmo; + } event; +}; + +struct statemachine_s { + void* context; + char* name; + bool debug; + StateFunc myState; + int mySubState; + StateFunc myPrevState; + const char* (*state_name)(StateFunc func); + const char* (*event_name)(pEvtEvent event, char* text, int length); +}; + +int fsm_msg_callback(pAsyncTxn pCmd); +int fsm_tmr_callback(void* ctx, int mode); +int fsm_cmd_execute(pStateMachine self, const void* cmd); + +void fsm_change_state(pStateMachine self, StateFunc func); +void fsm_unhandled_event(pStateMachine self, pEvtEvent event); +#endif /* FINITESTATEMACHINE */