After some help as have some code which works but trying to fully understand a small section which uses a lookup table as part of a state machine. The state machine I understand and have been using for a tutorial I am writing found here http://coder-tronics.com/state-machine-tutorial-pt1 Instead of using more switch case statements inside the UponExit, UponEnter and ActionWhileInState, someone suggested using this method which I like but don't fully understand.
Now the part I am unsure about is these lines to do with the typedef and lookup table
typedef void (* const voidFunc)(void);
voidFunc UponEnter[S_MAX] = {hEnter_OFF, hEnter_ON, hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] = {hExit_OFF, hExit_ON, hExit_PROCESS};
I looked up typedef and lookup tables and have a basic understanding, but was hoping someone could give a brief walk through of how this works in this case?
The full part of code this relates to is below for completeness.
enum states { S_OFF, S_ON, S_PROCESS, S_MAX };
enum events { E_OFF, E_ON, E_START, E_MAX};
typedef void (* const voidFunc)(void);
void hEnter_OFF(void); void hEnter_ON(void); void hEnter_PROCESS(void);
void hInState_OFF(void); void hInState_ON(void); void hInState_PROCESS(void);
void hExit_OFF(void); void hExit_ON(void); void hExit_PROCESS(void);
voidFunc UponEnter[S_MAX] = {hEnter_OFF, hEnter_ON, hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] = {hExit_OFF, hExit_ON, hExit_PROCESS};
enum states StateMachine(enum events event, enum states Current_State)
{
int Next_State = Current_State;
switch ( Current_State )
{
case S_OFF:
switch (event )
{
// A transition to the next state will occur here
case E_ON:
Next_State = S_ON;
break;
default: // Default case placed here to avoid Eclipse warnings as Eclipse expects
break; //to handle all enumerated values
}
break;
case S_ON:
switch (event )
{
// A transition to the next state will occur here
case E_OFF:
Next_State = S_OFF;
break;
case E_START:
Next_State = S_PROCESS;
break;
default: // Default case placed here to avoid Eclipse warnings as Eclipse expects
break; //to handle all enumerated values
}
break;
case S_PROCESS:
switch (event )
{
// A transition to the next state will occur here
case E_OFF:
Next_State = S_OFF;
break;
default: // Default case placed here to avoid Eclipse warnings as Eclipse expects
break; //to handle all enumerated values
}
break;
// The program should never arrive here
default:
break;
}
if (Next_State != Current_State)
{
// Function call for Upon Exit function, it can be omitted but allows extra functionality
UponExit[Current_State]();
// Function call for Upon Enter function, it can be omitted but allows extra functionality
if (Next_State != S_MAX) UponEnter[Next_State]();
}
else // I think ActionWhileInState should only be called when NOT doing a transition!
{
if ( event != E_MAX) ActionWhileInState[Current_State]();
}
return Next_State;
}
Thanks,
Ant
typedef void (* const voidFunc)(void);
is a typedef for a function pointer (for a pointer to a function expecting no parameters and not returning anything to be exact). So your arrays
voidFunc UponEnter[S_MAX] = {hEnter_OFF, hEnter_ON, hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] = {hExit_OFF, hExit_ON, hExit_PROCESS};
Each hold three different function pointers, one for each state. So a line like
UponExit[Current_State]();
calls the function the pointer UponExit[Current_State] points to which is hExit_OFF if Current_State is 0, hExit_ON if Current_State is 1 or hExit_PROCESS if Current_State is 2.
You could also write the line like that:
(*UponExit[Current_State])();
What looks more complicated but makes clear that UponExit[Current_State] is a function pointer that is "dereferenced" to a call to the function it points to.
Edit:
You have an enum for your states:
enum states { S_OFF, S_ON, S_PROCESS, S_MAX };
Thus, S_OFF == 0, S_ON == 1, S_PROCESS == 2 and S_MAX == 3 (look here)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With