Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
State machines are very simple in C if you use function pointers.
/*
http://stackoverflow.com/questions/1371460/state-machines-tutorials/1371654#1371654
State machines are very simple in C if you use function pointers.
Basically you need 2 arrays - one for state function pointers and one for state
transition rules. Every state function returns the code, you lookup state
transition table by state and return code to find the next state and then
just execute it.
*/
int entry_state(void);
int foo_state(void);
int bar_state(void);
int exit_state(void);
/* array and enum below must be in sync! */
int (* state)(void)[] = { entry_state, foo_state, bar_state, exit_state};
enum state_codes { entry, foo, bar, end};
enum ret_codes { ok, fail, repeat};
struct transition {
enum state_codes src_state;
enum ret_codes ret_code;
enum state_codes dst_state;
};
/* transitions from end state aren't needed */
struct transition state_transitions[] = {
{entry, ok, foo},
{entry, fail, end},
{foo, ok, bar},
{foo, fail, end},
{foo, repeat, foo},
{bar, ok, end},
{bar, fail, end},
{bar, repeat, foo}};
#define EXIT_STATE end
#define ENTRY_STATE entry
int main(int argc, char *argv[]) {
enum state_codes cur_state = ENTRY_STATE;
enum ret_codes rc;
int (* state_fun)(void);
for (;;) {
state_fun = state[cur_state];
rc = state_fun();
if (EXIT_STATE == cur_state)
break;
cur_state = lookup_transitions(cur_state, rc);
}
return EXIT_SUCCESS;
}
/*
I don't put lookup_transition() function as it is trivial.
That's the way I do state machines for years.
*/
@hsch0

This comment has been minimized.

Copy link

@hsch0 hsch0 commented Nov 15, 2017

I get an error when I try to compile it:
fsm.c:18:14: error: function cannot return array type 'int []'
int (* state)(void)[] = { entry_state, foo_state, bar_state, exit_state};

@Mrunmoy

This comment has been minimized.

Copy link

@Mrunmoy Mrunmoy commented Jun 9, 2018

I know it's too late to respond but I think it should be defined as
int (* state[])(void) = { entry_state, foo_state, bar_state, exit_state};

@Mrunmoy

This comment has been minimized.

Copy link

@Mrunmoy Mrunmoy commented Jun 9, 2018

good work on example code though 👍

@JimWillette

This comment has been minimized.

Copy link

@JimWillette JimWillette commented Oct 16, 2018

Mrunmoy: That doesn't work either (at least on my compiler, clang).

@ChumKiu

This comment has been minimized.

Copy link

@ChumKiu ChumKiu commented Dec 13, 2018

Nice example, just a think, about the state function pointer array might be more correct express it as

enum ret_codes (* state[])(void) { ... };

due to the nature of the return code.

Concerning the lookup_transition() function here below an example:

enum state_codes lookup_transitions(enum state_codes cur_state, enum ret_codes rc)
{
int8_t i;
int8_t max_items;
enum state_codes next_state;

i=0;
max_items = sizeof(state_transitions)/sizeof(state_transitions[0]);
next_state = fsmError;

// Searching loop
for(i=0; i<max_items; i++)
{
	if ((state_transitions[i].src_state == cur_state) && (state_transitions[i].ret_code == rc))
	{
		next_state = state_transitions[i].dst_state;
		break;
	}
}

// If a correspondence state-ret value is not found the
// returned state is fsmError, this is useful to find some
// errors into the definition of the whole FSM transition
return(next_state);

}

Thank!

@radu022003

This comment has been minimized.

Copy link

@radu022003 radu022003 commented Mar 21, 2019

i have a question regarding the data exchange between the action functions (i.e. entry_state and foo_state) if some data is processed in entry_state and that data is needed in foo_state, than the only way to do this are the global variables, and in my Point of view this is not the optimal way of programming. Please correct me if i missed something or missunderstood. If it is so, what is your aproach of exchange data between these functions, avoiding the global variables?

@adillove

This comment has been minimized.

Copy link

@adillove adillove commented Aug 6, 2020

I have aquestion how ican make position gearangles put it into statemachine aftershutdown back start given thesame position without miss the position or please give me solution if you know this imade the control of camshaft
int pulse=0;
char text[15];
void main() {
TRISD.F0 = 1;
TRISA=0X00;
PORTA=0;
TRISC=0X00;
PORTC=0;
#define SW PORTD.RD0 // RD7 pin is pulse input pin
while(1){
if(SW==1){
while(SW==1);
pulse++;
}
if(pulse>=721) pulse = 0;
if(RD0_bit==1) pulse ++;
if(pulse== pulse <=128){

             portc.f5=0;

             }
             if (pulse>= 129 && pulse <=180){
             porta.f2=1;

             }
             if (pulse>=181&& pulse <=308){
             porta.f2=0;
             portc.f3=0;
             portc.f4=0 ;
              }
             if (pulse>=309 && pulse <=360){
             porta.f2=0;
              portc.f3=1 ;
             portc.f4=0;
             portc.f5=0;

             }if (pulse>=361 && pulse <=488){
             porta.f2=0;
              portc.f3=0 ;
             portc.f4=0;
             portc.f5=0;

             }
            if (pulse>=489 && pulse <=540){
             porta.f2=0;
              portc.f3=0 ;
             portc.f4=1;
             portc.f5=0;

             }
           if (pulse>=541 && pulse <=668){
             porta.f2=0;
              portc.f3=0 ;
             portc.f4=0;
             portc.f5=0;

             }
         if (pulse>=669 && pulse <=720){
             porta.f2=0;
              portc.f3=0;
             portc.f4=0;
             portc.f5=1;

             }

}
}

@nmandery

This comment has been minimized.

Copy link
Owner Author

@nmandery nmandery commented Aug 6, 2020

Hey everybody, I just saw all of your questions regarding this gist for the first time - sorry for being late to reply. I did not author this code, please see the link to the stackoverflow post in the first line. The original author can be asked there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment