Extracted abstract Finite State Machine (from DMC2280 motor driver)
r2272 | dcl | 2008-01-15 12:27:25 +1100 (Tue, 15 Jan 2008) | 2 lines
This commit is contained in:
93
site_ansto/fsm.c
Normal file
93
site_ansto/fsm.c
Normal file
@@ -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 : "<unknown>",
|
||||
self->state_name ? self->state_name(self->myState) : "<unknown>",
|
||||
self->mySubState,
|
||||
self->event_name ? self->event_name(event, text, sizeof(text)) : "<unknown>");
|
||||
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("<TIMEOUT>", 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 : "<unknown>",
|
||||
self->state_name ? self->state_name(self->myState) : "<unknown>",
|
||||
self->mySubState,
|
||||
self->state_name ? self->state_name(func) : "<unknown>");
|
||||
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 : "<unknown>",
|
||||
self->state_name ? self->state_name(self->myState) : "<unknown>",
|
||||
self->mySubState,
|
||||
self->event_name ? self->event_name(event, text, sizeof(text)) : "<unknown>");
|
||||
SICSLogWrite(line, eError);
|
||||
}
|
||||
|
||||
62
site_ansto/fsm.h
Normal file
62
site_ansto/fsm.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef FINITESTATEMACHINE
|
||||
#define FINITESTATEMACHINE
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <sics.h>
|
||||
#include <asyncqueue.h>
|
||||
|
||||
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 */
|
||||
Reference in New Issue
Block a user