Craig Evans
/
ELEC2645_UpDown_Counter_Transition_Table_2021
Up Down counter using a transition table
main.cpp@1:1e34d5c96ecf, 2020-12-10 (annotated)
- Committer:
- eencae
- Date:
- Thu Dec 10 14:22:22 2020 +0000
- Revision:
- 1:1e34d5c96ecf
- Parent:
- 0:7c0953072ecb
Initial Commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
eencae | 0:7c0953072ecb | 1 | /* |
eencae | 0:7c0953072ecb | 2 | |
eencae | 0:7c0953072ecb | 3 | 2645_FSM_UpDown_Counter |
eencae | 0:7c0953072ecb | 4 | |
eencae | 0:7c0953072ecb | 5 | Sample code from ELEC2645 |
eencae | 0:7c0953072ecb | 6 | |
eencae | 0:7c0953072ecb | 7 | Demonstrates how to implement a simple FSM up/down counter |
eencae | 0:7c0953072ecb | 8 | |
eencae | 0:7c0953072ecb | 9 | (c) Craig A. Evans, University of Leeds, Jan 2016 |
eencae | 0:7c0953072ecb | 10 | Updated Jan 2020 |
eencae | 0:7c0953072ecb | 11 | Updated Dec 2020 |
eencae | 0:7c0953072ecb | 12 | |
eencae | 0:7c0953072ecb | 13 | */ |
eencae | 0:7c0953072ecb | 14 | |
eencae | 0:7c0953072ecb | 15 | #include "mbed.h" |
eencae | 0:7c0953072ecb | 16 | #include "platform/mbed_thread.h" |
eencae | 0:7c0953072ecb | 17 | |
eencae | 0:7c0953072ecb | 18 | // defines directions as 0/1. Note UPPERCASE |
eencae | 0:7c0953072ecb | 19 | #define UP 0 |
eencae | 0:7c0953072ecb | 20 | #define DOWN 1 |
eencae | 0:7c0953072ecb | 21 | |
eencae | 0:7c0953072ecb | 22 | // create a bus for writing to the output (LEDs) at once |
eencae | 0:7c0953072ecb | 23 | BusOut output(LED4,LED3,LED2,LED1); |
eencae | 0:7c0953072ecb | 24 | // Button A on board |
eencae | 0:7c0953072ecb | 25 | InterruptIn buttonA(p29); |
eencae | 0:7c0953072ecb | 26 | |
eencae | 1:1e34d5c96ecf | 27 | // struct for state |
eencae | 1:1e34d5c96ecf | 28 | struct State { |
eencae | 1:1e34d5c96ecf | 29 | int output; // output value for current state |
eencae | 1:1e34d5c96ecf | 30 | int time; // wait time for state (ms) |
eencae | 1:1e34d5c96ecf | 31 | int next_state[2]; // next state (depending on direction 0 - UP, 1 - DOWN) |
eencae | 1:1e34d5c96ecf | 32 | }; |
eencae | 1:1e34d5c96ecf | 33 | |
eencae | 1:1e34d5c96ecf | 34 | // array of states in the FSM, each element is the output of the counter, wait time, next state(s) |
eencae | 1:1e34d5c96ecf | 35 | State g_fsm[4] = { |
eencae | 1:1e34d5c96ecf | 36 | {0b0001,500,{1,3}}, |
eencae | 1:1e34d5c96ecf | 37 | {0b0010,500,{2,0}}, |
eencae | 1:1e34d5c96ecf | 38 | {0b0100,500,{3,1}}, |
eencae | 1:1e34d5c96ecf | 39 | {0b1000,500,{0,2}}, |
eencae | 1:1e34d5c96ecf | 40 | }; |
eencae | 0:7c0953072ecb | 41 | |
eencae | 0:7c0953072ecb | 42 | // flag - must be volatile as changes within ISR |
eencae | 0:7c0953072ecb | 43 | // g_ prefix makes it easier to distinguish it as global |
eencae | 0:7c0953072ecb | 44 | volatile int g_buttonA_flag = 0; |
eencae | 0:7c0953072ecb | 45 | |
eencae | 0:7c0953072ecb | 46 | // Button A interrupt service routine |
eencae | 0:7c0953072ecb | 47 | void buttonA_isr(); |
eencae | 0:7c0953072ecb | 48 | |
eencae | 0:7c0953072ecb | 49 | int main() |
eencae | 0:7c0953072ecb | 50 | { |
eencae | 0:7c0953072ecb | 51 | // Button A has a pull-down resistor, so the pin will be at 0 V by default |
eencae | 0:7c0953072ecb | 52 | // and rise to 3.3 V when pressed. We therefore need to look for a rising edge |
eencae | 0:7c0953072ecb | 53 | // on the pin to fire the interrupt |
eencae | 0:7c0953072ecb | 54 | buttonA.rise(&buttonA_isr); |
eencae | 0:7c0953072ecb | 55 | // since Button A has an external pull-down, we should disable to internal pull-down |
eencae | 0:7c0953072ecb | 56 | // resistor that is enabled by default using InterruptIn |
eencae | 0:7c0953072ecb | 57 | buttonA.mode(PullNone); |
eencae | 1:1e34d5c96ecf | 58 | |
eencae | 0:7c0953072ecb | 59 | // set inital state |
eencae | 0:7c0953072ecb | 60 | int state = 0; |
eencae | 0:7c0953072ecb | 61 | // set initial direction |
eencae | 0:7c0953072ecb | 62 | int direction = UP; |
eencae | 0:7c0953072ecb | 63 | |
eencae | 0:7c0953072ecb | 64 | while(1) { // loop forever |
eencae | 0:7c0953072ecb | 65 | |
eencae | 0:7c0953072ecb | 66 | // check if flag i.e. interrupt has occured |
eencae | 0:7c0953072ecb | 67 | if (g_buttonA_flag) { |
eencae | 0:7c0953072ecb | 68 | g_buttonA_flag = 0; // if it has, clear the flag |
eencae | 0:7c0953072ecb | 69 | // swap direction when button has been pressed |
eencae | 1:1e34d5c96ecf | 70 | direction = ! direction; |
eencae | 0:7c0953072ecb | 71 | } |
eencae | 0:7c0953072ecb | 72 | |
eencae | 1:1e34d5c96ecf | 73 | // set output of current state (use dot syntax to access struct members) |
eencae | 1:1e34d5c96ecf | 74 | output = g_fsm[state].output; |
eencae | 1:1e34d5c96ecf | 75 | // implement required delay |
eencae | 1:1e34d5c96ecf | 76 | thread_sleep_for(g_fsm[state].time); |
eencae | 1:1e34d5c96ecf | 77 | // set the next state depending on direction |
eencae | 1:1e34d5c96ecf | 78 | state = g_fsm[state].next_state[direction]; |
eencae | 0:7c0953072ecb | 79 | |
eencae | 0:7c0953072ecb | 80 | } |
eencae | 0:7c0953072ecb | 81 | } |
eencae | 0:7c0953072ecb | 82 | |
eencae | 0:7c0953072ecb | 83 | // Button A event-triggered interrupt |
eencae | 0:7c0953072ecb | 84 | void buttonA_isr() |
eencae | 0:7c0953072ecb | 85 | { |
eencae | 0:7c0953072ecb | 86 | g_buttonA_flag = 1; // set flag in ISR |
eencae | 0:7c0953072ecb | 87 | } |