Skip to content

Instantly share code, notes, and snippets.

@dheeptuck
Created June 19, 2019 18:20
Show Gist options
  • Save dheeptuck/b9c2d6e32d87f5fc67ecf8edb9adcf77 to your computer and use it in GitHub Desktop.
Save dheeptuck/b9c2d6e32d87f5fc67ecf8edb9adcf77 to your computer and use it in GitHub Desktop.
#include "stdio.h"
typedef void (*ptStateFunc)(void);
/// Define all events
typedef enum eEvent {
EVT_NO_EVENT,
EVT_BUTTON_PRESSED,
EVT_BEAN_CRUSHED,
EVT_MILK_HEATED,
EVT_WATER_MIXED,
EVT_DISPENSED,
EVT_NO_BEAN,
EVT_NO_MILK,
EVT_NO_WATER
} eEvent;
/// Define all states
void stateIdle(void);
void stateCrushBean(void);
void stateHeatMilk(void);
void stateMixWater(void);
void stateDispenseCofee(void);
void stateError(void);
/// Define a row of STM
typedef struct stStmRow {
ptStateFunc pSrcState;
eEvent eEvt;
ptStateFunc pDestState;
} stStmRow;
void stateIdle(void)
{
if(bIsStateFirstEntry)
{
/// Do stuff for first entry(state initialization stuff)
}
if(bIsStateAboutToExit)
{
/// Handle exit(i.e free up resources)
}
}
void stateCrushBean(void)
{
if(bIsStateFirstEntry)
{
/// Do stuff for first entry(state initialization stuff)
/// TurnHeaterOn();
}
if(bIsStateAboutToExit)
{
/// Handle exit(i.e free up resources)
/// TurnHeaterOff();
}
}
void stateHeatMilk(void)
{
}
void stateMixWater(void)
{
}
void stateDispenseCofee(void)
{
}
void stateError(void)
{
}
static eEvent eCurrentEvent = EVT_NO_EVENT;
static ptStateFunc stCurrentState = stateIdle;
/// Used to flag first entry to a state
static bool bIsStateFirstEntry = false;
/// Used to flag an imminent exit from the state
static bool bIsStateAboutToExit = false;
stStmRow stStm[] = {
{stateIdle , EVT_BUTTON_PRESSED, stateCrushBean },
{stateCrushBean, EVT_BEAN_CRUSHED , stateHeatMilk },
{stateCrushBean, EVT_NO_BEAN , stateError },
{stateHeatMilk , EVT_MILK_HEATED , stateMixWater },
{stateHeatMilk , EVT_NO_MILK , stateError },
{stateMixWater , EVT_WATER_MIXED , stateDispenseCofee},
{stateMixWater , EVT_NO_WATER , stateError }
};
void StateMachineHandler()
{
int idx = 0;
if(EVT_NO_EVENT != eCurrentEvent)
{
for(;idx < sizeof(stStm)/sizeof(stStmRow); idx++)
{
if( (stStm[idx].pSrcState == stCurrentState) &&
(stStm[idx].eEvt == eCurrentEvent))
{
/// Clear event
eCurrentEvent = EVT_NO_EVENT;
/// Notify the state that the exit is imminent;
bIsStateAboutToExit = true;
stCurrentState();
/// Move to new state
stCurrentState = stStm[idx].pDestState;
/// Flag that this is the first entry to the state
bIsStateFirstEntry = true;
}
}
}
if(NULL != stCurrentState)
{
/// Run the state
stCurrentState();
/// Unfllag first entry
bIsStateFirstEntry = false;
}
}
int main()
{
while(true)
{
StateMachineHandler();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment