Craig Evans / Mbed 2 deprecated ELEC2645_FSM_UpDown_Counter

Dependencies:   mbed

main.cpp

Committer:
eencae
Date:
2020-01-24
Revision:
2:2a0738a294df
Parent:
1:fb324de02b7f

File content as of revision 2:2a0738a294df:

/*

2645_FSM_UpDown_Counter

Sample code from ELEC2645

Demonstrates how to implement a simple FSM up/down counter

(c) Craig A. Evans, University of Leeds, Jan 2016
Updated Jan 2020

*/

#include "mbed.h"

// pre-processor directives
// defines directions as 0/1. Note UPPERCASE
#define UP 0
#define DOWN 1

// K64F on-board LEDs
BusOut k64f_leds(LED_RED, LED_GREEN, LED_BLUE);

// Gamepad Button A
InterruptIn buttonA(PTC7);

// LEDs on Gamepad (1 to 3) - active-low 0 = on and 1 = off
// BusOut arguments are LSB first
BusOut output(PTA2,PTC2,PTC3);

// array of states in the FSM, each element is the output of the counter
// set the output in binary to make it easier, 0 is LED on, 1 is LED off
int fsm[3] = {0b011,0b101,0b110};

// flag - must be volatile as changes within ISR
// g_ prefix makes it easier to distinguish it as global
volatile int g_buttonA_flag = 0;


// Button A interrupt service routine
void buttonA_isr();

int main()
{
    k64f_leds = 0b111;  // turn off K64F LEDs

    // Button A is connected between the pin and 3.3 V, we therefore need to turn on the internal pull-down resister
    buttonA.mode(PullUp);
    // Setup interrupt on falling edge
    buttonA.fall(&buttonA_isr);

    // set inital state
    int state = 0;
    // set initial direction
    int direction = UP;

    while(1) {  // loop forever

        // check if flag i.e. interrupt has occured
        if (g_buttonA_flag) {
            g_buttonA_flag = 0;  // if it has, clear the flag

            // swap direction when button has been pressed
            // (could just use ! but want this to be explicit to aid understanding)
            if (direction == UP) {
                direction = DOWN;
            } else {
                direction = UP;
            }
        }

        output = fsm[state];  // output current state

        // check which state we are in and see which the next state should be next depending on direction
        switch(state) {
            case 0:
                switch(direction) {
                    case UP:
                        state = 1;
                        break;
                    case DOWN:
                        state = 2;
                        break;
                }
                break;
            case 1:
                switch(direction) {
                    case UP:
                        state = 2;
                        break;
                    case DOWN:
                        state = 0;
                        break;
                }
                break;
            case 2:
                switch(direction) {
                    case UP:
                        state = 0;
                        break;
                    case DOWN:
                        state = 1;
                        break;
                }
                break;
            default:  // default case
                error("Invalid state!");  //invalid state - call error routine
                // or could jump to starting state i.e. state = 0
                break;
        }

        wait(0.5); // small delay


    }
}

// Button A event-triggered interrupt
void buttonA_isr()
{
    g_buttonA_flag = 1;   // set flag in ISR
}