Code Snippets

Finite State Machine Template

Gabriel Rivas March 28, 20131 comment Coded in C
/*********************************************************************
Finiste State Machine design example

FSM based embedded software design has several advantages:
1. You can translate the systems' requirements into FSM diagramas or
state transition tables.
2. From the FSM diagram or state transition table you can validate if the design
is right or wrong before actually start coding.
3. It makes the code easier to understand
4. You can have traceability from the requirements document to the
code
5. Determinism; you can now exactly what the system is doing at any time
6. Hmmm I don't know, they just look good in C! 

In this code Example it is shown how to implement the following FSM
state transition table into C code. You can use this as a template by 
replacing inputs and outputs sets, set of states by your actual application 
values.

I hope this helps.

Current State	INPUT_0	INPUT_1	INPUT_2	INPUT_3	Next State	OUTPUT_0
DETECT_IN0	    0	    X	    X	    X	    DETECT_IN1	0
	            1	    X	    X	    X	    DETECT_IN0	0
DETECT_IN1	    X	    0	    X	    X	    DETECT_IN2	0
	            X	    1	    X	    X	    DETECT_IN1	0
DETECT_IN2	    X	    X	    0	    X	    DETECT_IN3	0
	            X	    X	    1	    X	    DETECT_IN2	0
DETECT_IN3	    X	    X	    X	    0	    SET_OUTPUT	0
	            X       X	    X	    1	    DETECT_IN3	0
SET_OUTPUT	    X	    X	    X	    X	    DETECT_IN0	1
	            X	    X	    X	    X	    DETECT_IN0	1
 *
 ********************************************************************/
 
#include <stdio.h>

/*Inputs and outputs sets
You can give meaningful names to the IO ports of your microcontroller,
and that will make the code easier to understand and make it consistent
with a FSM diagram or state transition table
*/
#define INPUT_0  PTA0
#define INPUT_1  PTA1
#define INPUT_2  PTA2
#define INPUT_3  PTA3
#define OUTPUT_0 PTB0

/*
The inputs have pull-ups resistors so we can define a condition
to identify when an input has been selected, in this case an
input is selected when its value is 0
*/
#define SELECTED 0x00

/*Set of states
It is more convenient to give meaningful names to the states
and it's better when you can map them to a finite state machine
diagram or state transition table.
*/
typedef enum { DETECT_IN0 = 0x00, 
               DETECT_IN1, 
               DETECT_IN2, 
               DETECT_IN3, 
	       SET_OUTPUT} SM_STATES;

/*We need a state variable to store the next state value as well
and we have to assign an initial state to it
*/
unsigned char state = DETECT_IN0;

int ctr_ms = 500;  /*This finite state machine executes every 500 ms*/

/*wait function*/
static unsigned char wait_ms(void);

void main(void) {
    for(;;) {
        if(wait_ms()) {  /*The state machine is synch to a timer*/
            switch(state) {
                case DETECT_IN0:
                    OUTPUT_0 = 0;
                    if(INPUT_0 == SELECTED) {   
                        state = DETECT_IN1;					
                    }
                    break;
                case DETECT_IN1:
                    if(INPUT_1 == SELECTED) {   
                        state = DETECT_IN2;					
                    }
                    break;		
                case DETECT_IN2:
                    if(INPUT_2 == SELECTED) {   
                        state = DETECT_IN3;					
                    }
                    break;	
                case DETECT_IN3:
                    if(INPUT_3 == SELECTED) {   
                        state = SET_OUTPUT;					
                    }
                    break;	
                case SET_OUTPUT:
                    OUTPUT_0 = 1;
		    state = DETECT_IN0;	
                    break;					
                default:
                /*None of the above*/
                break;                
            }
	}
    } /* loop forever */
  /* please make sure that you never leave main */
}

unsigned char wait_ms(void) {
    unsigned char ctr_flag;
    
    ctr_flag = 0;

	/*Test for timer overflow flag*/
    if(TPM_Get_OVFlag() == 1) {     
        if (ctr_ms == 0) {
            ctr_flag = 1;
         } else {
            ctr_ms--;  
         }
         TPM_Clr_OVFlag();          
     }
     return ctr_flag; 
}