Up Down counter using a transition table

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002 
00003 2645_FSM_UpDown_Counter
00004 
00005 Sample code from ELEC2645
00006 
00007 Demonstrates how to implement a simple FSM up/down counter
00008 
00009 (c) Craig A. Evans, University of Leeds, Jan 2016
00010 Updated Jan 2020
00011 Updated Dec 2020
00012 
00013 */
00014 
00015 #include "mbed.h"
00016 #include "platform/mbed_thread.h"
00017 
00018 // defines directions as 0/1. Note UPPERCASE
00019 #define UP 0
00020 #define DOWN 1
00021 
00022 // create a bus for writing to the output (LEDs) at once
00023 BusOut output(LED4,LED3,LED2,LED1);
00024 // Button A on board
00025 InterruptIn buttonA(p29);
00026 
00027 // struct for state
00028 struct State {
00029     int output;  // output value for current state
00030     int time;  // wait time for state (ms)
00031     int next_state[2]; // next state (depending on direction 0 - UP, 1 - DOWN)
00032 };
00033 
00034 // array of states in the FSM, each element is the output of the counter, wait time, next state(s)
00035 State g_fsm[4] = {
00036     {0b0001,500,{1,3}},
00037     {0b0010,500,{2,0}},
00038     {0b0100,500,{3,1}},
00039     {0b1000,500,{0,2}},
00040 };
00041 
00042 // flag - must be volatile as changes within ISR
00043 // g_ prefix makes it easier to distinguish it as global
00044 volatile int g_buttonA_flag = 0;
00045 
00046 // Button A interrupt service routine
00047 void buttonA_isr();
00048 
00049 int main()
00050 {
00051     // Button A has a pull-down resistor, so the pin will be at 0 V by default
00052     // and rise to 3.3 V when pressed. We therefore need to look for a rising edge
00053     // on the pin to fire the interrupt
00054     buttonA.rise(&buttonA_isr);
00055     // since Button A has an external pull-down, we should disable to internal pull-down
00056     // resistor that is enabled by default using InterruptIn
00057     buttonA.mode(PullNone);
00058 
00059     // set inital state
00060     int state = 0;
00061     // set initial direction
00062     int direction = UP;
00063 
00064     while(1) {  // loop forever
00065 
00066         // check if flag i.e. interrupt has occured
00067         if (g_buttonA_flag) {
00068             g_buttonA_flag = 0;  // if it has, clear the flag
00069             // swap direction when button has been pressed
00070             direction = ! direction;
00071         }
00072 
00073         // set output of current state (use dot syntax to access struct members)
00074         output = g_fsm[state].output;
00075         // implement required delay
00076         thread_sleep_for(g_fsm[state].time);
00077         // set the next state depending on direction
00078         state = g_fsm[state].next_state[direction];
00079 
00080     }
00081 }
00082 
00083 // Button A event-triggered interrupt
00084 void buttonA_isr()
00085 {
00086     g_buttonA_flag = 1;   // set flag in ISR
00087 }