C:\ant buildandtest
C:\me go and get coffee
C:\unit tests fail
// I know this first include isn't very embedded. I need it for Sleeping
#include "windows.h"
#include "stdio.h"
// Declare typedefs for state conditions and actions
typedef unsigned char (*ConditionFunction)(void);
typedef void (*ActionFunction)(void);
// The structure defines an action, a condition and a transition
// If the condition is met, the action is executed and the transition occurs
typedef struct _tagState {
ConditionFunction Condition;
ActionFunction Action;
struct _tagState *nextState;
} StateItem;
// Some sample conditions
unsigned char falseCondition(void)
{ return 0; }
unsigned char trueCondition(void)
{ return 1; }
// Some sample actions
void SomeAction(void)
{ printf ("SomeAction\n"); }
void BootAction (void)
{ printf ("BootAction\n"); }
void NoAction (void)
{ printf ("NoAction\n"); }
// The state machine engine.
// Simplicity is bliss
StateItem* ProcessState(StateItem *si) {
while(1)
{
if(si->Condition() == 0)
{
si++;
}
else
{
si->Action();
return si->nextState;
}
}
}
// Forward declare states so jumping is unhampered
const StateItem OtherState[];
const StateItem BootState[];
/*
* The tables represent states, each line is a state item
* Generally, the last state item performs a state action,
* and jumps back to itself. Preceeding items are generally
* transitions out to other states based on conditions
*/
// Except boot, end all the states with a trueCondition and a jump back to self
const StateItem OtherState[] = {
{&falseCondition, &SomeAction, OtherState},
{&trueCondition, &NoAction, OtherState}
};
const StateItem BootState[] = {
{&falseCondition, &SomeAction, BootState},
{&trueCondition, &BootAction, OtherState}
};
// Main just runs the state machine (no inputs or outputs are processed)
// The 'tick' time is 1 second which is slow for an embedded system
// but good for demonstrations
int main(void)
{
StateItem *StatePtr = BootState;
while (1) {
StatePtr = ProcessState(StatePtr);
Sleep(1000);
}
return 0;
}