State machines are commonly used to implement decision making algorithms. State machines are used in applications where distinguishable states exist. A finite state machine (FSM) is based on the idea that a given system has a finite number of states.

Dependencies:   mbed

Fork of FRDM-K64F_FSM by Nikolaos Maliganis

main.cpp

Committer:
mnikolaos
Date:
2014-08-07
Revision:
0:17539d6d4289

File content as of revision 0:17539d6d4289:

#include "mbed.h"
 
Serial pc(USBTX, USBRX);
 
DigitalOut gpo1(D1);
DigitalOut gpo2(D2);
DigitalOut gpo3(D3);
DigitalOut ledB(LED_BLUE);
DigitalOut ledG(LED_GREEN);
DigitalOut ledR(LED_RED);

Ticker tick;
 
typedef struct EventTag {
    uint16_t sig;                                    /* signal of the event */
} Event;

struct StateTableTag;                                /* forward declaration */

typedef void (*Tran)(struct StateTableTag *me, Event const *e);

typedef struct StateTableTag {
    uint8_t state;                              /* the current active state */
    uint8_t *st_desc;                           /* the current active state Name Descriprion */
    Tran const *state_table;                    /* the State-Table */
    uint8_t n_states;                           /* number of states */
    uint8_t n_signals;                          /* number of signals */
    Tran initial;                               /* the initial transition */
} StateTable;

void StTbl_ctor(StateTable *me,
                    Tran const *table, 
                    uint8_t n_states, 
                    uint8_t n_signals,
                    Tran initial);
                    
void StTbl_init(StateTable *me);
void StTbl_dispatch(StateTable *me, Event const *e);
void StTbl_empty(StateTable *me, Event const *e);

/* macro for taking a state transition inside a transition function */
#define TRAN(target_)  (((StateTable *)me)->state = (uint8_t)(target_)) 
 
 void StTbl_ctor(StateTable *me,
Tran const *table, uint8_t n_states, uint8_t n_signals,
Tran initial)
{
    me->state_table = table;
    me->n_states    = n_states;
    me->n_signals   = n_signals;
    me->initial     = initial;
}

void StTbl_init(StateTable *me) {
    me->state = me->n_states;
    (*me->initial)(me, (Event *)0);      
}

void StTbl_dispatch(StateTable *me, Event const *e) {
    Tran t;

    t = me->state_table[me->state*me->n_signals + e->sig];
    (*t)(me, e);                         
}

void StTbl_empty(StateTable *me, Event const *e) {
    (void)me;
    (void)e; 
}
 
 typedef struct Tag {               /*  FSM */
    StateTable super;               /* derive from the StateTable structure */
    uint8_t timeout;                /* number of seconds till exp */
    uint8_t defuse;                 /* secret defuse code to disarm */
    uint8_t code;                   /* currently entered code to disarm  */
} FSM1;
 
 
 enum FSMSignals {                          /* all signals for the Bomb FSM */
    GO_SIG,
    OUT_SIG,
    TICK_SIG,
    ERR_SIG,
    CONF_SIG,
    TRANADM_SIG,

    MAX_SIG                                        /* the number of signals */
};
 
 enum FSMStates {
    SETTING_FSM_STATE,           /* Setting for FSM */
    READY_FSM_STATE,             /* Unassigned and Ready to be configured from PC */
    ASSIGNED_FSM_STATE,          /* Assigned to a user. None could use it apart from him.*/
    LOCKED_FSM_STATE,            /* Locked by user*/
    ERROR_STATE,                /* Error state. Only logging communication*/
    
    MAX_STATE
};
  
 typedef struct TickEvtTag {
    Event super;                         /* derive from the Event structure */
    uint8_t fine_time;                           /* the fine 1/10 s counter */
} TickEvt;

 
static void FSM_initial (FSM1 *me, Event const *e)
{
     (void)e;
     
    pc.printf("State --> Initial\n");
    TRAN(SETTING_FSM_STATE);
 }

static void FSM_setting_GO    (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Setting - GO Event was caught\n");
    TRAN(READY_FSM_STATE);
}

static void FSM_setting_OUT   (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Setting - OUT Event was caught\n");
}

static void FSM_setting_ERR   (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Setting - ERR Event was caught\n");
    TRAN(ERROR_STATE);
}

static void FSM_setting_TRAN  (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Setting - TRAN ADMIN Event was caught\n");
}

static void FSM_ready_GO      (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Ready - GO Event was caught\n");
    TRAN(ASSIGNED_FSM_STATE);
}

static void FSM_ready_OUT     (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Ready - OUT Event was caught\n");
}

static void FSM_ready_TICK    (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Ready - TICK Event was caught\n");
}

static void FSM_ready_ERR     (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Ready - ERR Event was caught\n");
    TRAN(ERROR_STATE);
    
}

static void FSM_ready_CONF    (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Ready - CONF Event was caught\n");
    TRAN(SETTING_FSM_STATE); 
    
}

static void FSM_ready_TRAN    (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Ready - TRAN ADMIN Event was caught\n");
}

static void FSM_assigned_GO   (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Assigned - GO Event was caught\n");
    TRAN(LOCKED_FSM_STATE);
}

static void FSM_assigned_OUT  (FSM1 *me, Event const *e)
{
    (void)e;    
    pc.printf("State --> Assigned - OUT Event was caught\n");
    TRAN(READY_FSM_STATE);
}

static void FSM_assigned_TICK (FSM1 *me, Event const *e)
{
    (void)e;    
    pc.printf("State --> Assigned - TICK Event was caught\n");

}

static void FSM_assigned_ERR  (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Assigned - ERR Event was caught\n");
    TRAN(ERROR_STATE);
    
}

static void FSM_assigned_CONF (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Assigned - CONF Event was caught\n");
    TRAN(SETTING_FSM_STATE);
    
}

static void FSM_assigned_TRAN (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Assigned - TRAN ADMIN Event was caught\n");
    
}

static void FSM_locked_GO     (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Locked - GO Event was caught\n");
    
}

static void FSM_locked_OUT    (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Locked - OUT Event was caught\n");
    TRAN(ASSIGNED_FSM_STATE);

}

static void FSM_locked_TICK   (FSM1 *me, Event const *e)
{
    (void)e;    
    pc.printf("State --> Locked - TICK Event was caught\n");

}

static void FSM_locked_ERR    (FSM1 *me, Event const *e)
{
    (void)e;    
    pc.printf("State --> Locked - ERR Event was caught\n");
    TRAN(ERROR_STATE);

}

static void FSM_locked_CONF   (FSM1 *me, Event const *e)
{
    (void)e;
    pc.printf("State --> Locked - CONF Event was caught\n");
    TRAN(SETTING_FSM_STATE);
    
}

static void FSM_locked_TRAN   (FSM1 *me, Event const *e)
{
    (void)e;    
    pc.printf("State --> Locked - TRAN ADMIN Event was caught\n");
    
}
 
 
void FSM_ctor(FSM1 *me, uint8_t defuse) {

     static const Tran fsm_state_table[MAX_STATE][MAX_SIG] =
    {
        {(Tran)&FSM_setting_GO,  (Tran)&FSM_setting_OUT,  &StTbl_empty, (Tran)&FSM_setting_ERR, &StTbl_empty, (Tran)&FSM_setting_TRAN },
        {(Tran)&FSM_ready_GO,    (Tran)&FSM_ready_OUT,    (Tran)&FSM_ready_TICK, (Tran)&FSM_ready_ERR, (Tran)&FSM_ready_CONF, (Tran)&FSM_ready_TRAN },
        {(Tran)&FSM_assigned_GO, (Tran)&FSM_assigned_OUT, (Tran)&FSM_assigned_TICK, (Tran)&FSM_assigned_ERR, (Tran)&FSM_assigned_CONF, (Tran)&FSM_assigned_TRAN },
        {(Tran)&FSM_locked_GO,   (Tran)&FSM_locked_OUT,   (Tran)&FSM_locked_TICK, (Tran)&FSM_locked_ERR, (Tran)&FSM_locked_CONF, (Tran)&FSM_locked_TRAN }
    };
    
    StTbl_ctor(&me->super, &fsm_state_table[0][0], MAX_STATE, MAX_SIG, (Tran)&FSM_initial);
    
    me->defuse = defuse;
}

bool _t1_OVRFL = false;
 // ISR Timer per 1sec
 void ISR(void) {
    _t1_OVRFL = true;
}

char cmd;
bool _pc_GTCMD = false;
// ISR when Gets command
void Serial_ISR(void) {
    _pc_GTCMD = true;
    cmd = pc.getc(); //Gets the command
}

int main()
{

    pc.baud(9600);
    pc.attach(&Serial_ISR);
    tick.attach(&ISR, 1.0);

    static FSM1 _frdm_fsm;
    static Event const go_evt     = { GO_SIG   };
    static Event const out_evt    = { OUT_SIG };
    static Event const err_evt    = { ERR_SIG };
    static Event const conf_evt   = { CONF_SIG };
    static TickEvt tick_evt       = { TICK_SIG, 0};

    FSM_ctor(&_frdm_fsm, 0xFF);
    
    StTbl_init((StateTable *)&_frdm_fsm);
    
    pc.printf("Frdm K64F FSM App\r\n");
    Event const *e = (Event *)0;
       
    while (true) {
        
        pc.printf("Running\r\n\n");
        gpo1 = !gpo1; // toggle pin
        ledB = !ledB; // toggle led
        wait(0.2f);
        
        if(_t1_OVRFL)
        {
            _t1_OVRFL = false;
                StTbl_dispatch((StateTable *)&_frdm_fsm, (Event *)&tick_evt);
        }
        
        switch (cmd) 
        {
            case 'G': {
                pc.printf(" Go received \n");
                e = &go_evt;
                break;
            }
            case 'O': {
                pc.printf(" Out Received \n");
                e = &out_evt;
                break;
            }
            case 'E': {
                pc.printf(" Error Received \n");
                e = &err_evt;
                break;
            }
            case 'C': {
                pc.printf(" Config Received \n");
                e = &conf_evt;
                break;
            }
        }
        if(_pc_GTCMD)
        {
            _pc_GTCMD = false;
            if (e != (Event *)0)
            {
               StTbl_dispatch((StateTable *)&_frdm_fsm, e);
            }
        }
        
    }
}