Craig Evans
/
ELEC2645_UpDown_Counter_2021
Up Down Counter using FSM
main.cpp@0:7c0953072ecb, 2020-12-10 (annotated)
- Committer:
- eencae
- Date:
- Thu Dec 10 13:42:11 2020 +0000
- Revision:
- 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 | 0:7c0953072ecb | 27 | // array of states in the FSM, each element is the output of the counter |
eencae | 0:7c0953072ecb | 28 | // set the output in binary to make it easier, 1 is LED on, 0 is LED off |
eencae | 0:7c0953072ecb | 29 | int g_fsm[4] = {0b0001,0b0010,0b0100,0b1000}; |
eencae | 0:7c0953072ecb | 30 | |
eencae | 0:7c0953072ecb | 31 | // flag - must be volatile as changes within ISR |
eencae | 0:7c0953072ecb | 32 | // g_ prefix makes it easier to distinguish it as global |
eencae | 0:7c0953072ecb | 33 | volatile int g_buttonA_flag = 0; |
eencae | 0:7c0953072ecb | 34 | |
eencae | 0:7c0953072ecb | 35 | // Button A interrupt service routine |
eencae | 0:7c0953072ecb | 36 | void buttonA_isr(); |
eencae | 0:7c0953072ecb | 37 | |
eencae | 0:7c0953072ecb | 38 | int main() |
eencae | 0:7c0953072ecb | 39 | { |
eencae | 0:7c0953072ecb | 40 | // Button A has a pull-down resistor, so the pin will be at 0 V by default |
eencae | 0:7c0953072ecb | 41 | // and rise to 3.3 V when pressed. We therefore need to look for a rising edge |
eencae | 0:7c0953072ecb | 42 | // on the pin to fire the interrupt |
eencae | 0:7c0953072ecb | 43 | buttonA.rise(&buttonA_isr); |
eencae | 0:7c0953072ecb | 44 | // since Button A has an external pull-down, we should disable to internal pull-down |
eencae | 0:7c0953072ecb | 45 | // resistor that is enabled by default using InterruptIn |
eencae | 0:7c0953072ecb | 46 | buttonA.mode(PullNone); |
eencae | 0:7c0953072ecb | 47 | |
eencae | 0:7c0953072ecb | 48 | // set inital state |
eencae | 0:7c0953072ecb | 49 | int state = 0; |
eencae | 0:7c0953072ecb | 50 | // set initial direction |
eencae | 0:7c0953072ecb | 51 | int direction = UP; |
eencae | 0:7c0953072ecb | 52 | |
eencae | 0:7c0953072ecb | 53 | while(1) { // loop forever |
eencae | 0:7c0953072ecb | 54 | |
eencae | 0:7c0953072ecb | 55 | // check if flag i.e. interrupt has occured |
eencae | 0:7c0953072ecb | 56 | if (g_buttonA_flag) { |
eencae | 0:7c0953072ecb | 57 | g_buttonA_flag = 0; // if it has, clear the flag |
eencae | 0:7c0953072ecb | 58 | |
eencae | 0:7c0953072ecb | 59 | // swap direction when button has been pressed |
eencae | 0:7c0953072ecb | 60 | // (could just use ! but want this to be explicit to aid understanding) |
eencae | 0:7c0953072ecb | 61 | if (direction == UP) { |
eencae | 0:7c0953072ecb | 62 | direction = DOWN; |
eencae | 0:7c0953072ecb | 63 | } else { |
eencae | 0:7c0953072ecb | 64 | direction = UP; |
eencae | 0:7c0953072ecb | 65 | } |
eencae | 0:7c0953072ecb | 66 | } |
eencae | 0:7c0953072ecb | 67 | |
eencae | 0:7c0953072ecb | 68 | output = g_fsm[state]; // output current state |
eencae | 0:7c0953072ecb | 69 | |
eencae | 0:7c0953072ecb | 70 | // check which state we are in and see which the next state should be next depending on direction |
eencae | 0:7c0953072ecb | 71 | switch(state) { |
eencae | 0:7c0953072ecb | 72 | case 0: |
eencae | 0:7c0953072ecb | 73 | switch(direction) { |
eencae | 0:7c0953072ecb | 74 | case UP: |
eencae | 0:7c0953072ecb | 75 | state = 1; |
eencae | 0:7c0953072ecb | 76 | break; |
eencae | 0:7c0953072ecb | 77 | case DOWN: |
eencae | 0:7c0953072ecb | 78 | state = 3; |
eencae | 0:7c0953072ecb | 79 | break; |
eencae | 0:7c0953072ecb | 80 | } |
eencae | 0:7c0953072ecb | 81 | break; |
eencae | 0:7c0953072ecb | 82 | case 1: |
eencae | 0:7c0953072ecb | 83 | switch(direction) { |
eencae | 0:7c0953072ecb | 84 | case UP: |
eencae | 0:7c0953072ecb | 85 | state = 2; |
eencae | 0:7c0953072ecb | 86 | break; |
eencae | 0:7c0953072ecb | 87 | case DOWN: |
eencae | 0:7c0953072ecb | 88 | state = 0; |
eencae | 0:7c0953072ecb | 89 | break; |
eencae | 0:7c0953072ecb | 90 | } |
eencae | 0:7c0953072ecb | 91 | break; |
eencae | 0:7c0953072ecb | 92 | case 2: |
eencae | 0:7c0953072ecb | 93 | switch(direction) { |
eencae | 0:7c0953072ecb | 94 | case UP: |
eencae | 0:7c0953072ecb | 95 | state = 3; |
eencae | 0:7c0953072ecb | 96 | break; |
eencae | 0:7c0953072ecb | 97 | case DOWN: |
eencae | 0:7c0953072ecb | 98 | state = 1; |
eencae | 0:7c0953072ecb | 99 | break; |
eencae | 0:7c0953072ecb | 100 | } |
eencae | 0:7c0953072ecb | 101 | break; |
eencae | 0:7c0953072ecb | 102 | case 3: |
eencae | 0:7c0953072ecb | 103 | switch(direction) { |
eencae | 0:7c0953072ecb | 104 | case UP: |
eencae | 0:7c0953072ecb | 105 | state = 0; |
eencae | 0:7c0953072ecb | 106 | break; |
eencae | 0:7c0953072ecb | 107 | case DOWN: |
eencae | 0:7c0953072ecb | 108 | state = 2; |
eencae | 0:7c0953072ecb | 109 | break; |
eencae | 0:7c0953072ecb | 110 | } |
eencae | 0:7c0953072ecb | 111 | break; |
eencae | 0:7c0953072ecb | 112 | default: // default case |
eencae | 0:7c0953072ecb | 113 | error("Invalid state!"); //invalid state - call error routine |
eencae | 0:7c0953072ecb | 114 | state = 0; |
eencae | 0:7c0953072ecb | 115 | break; |
eencae | 0:7c0953072ecb | 116 | } |
eencae | 0:7c0953072ecb | 117 | |
eencae | 0:7c0953072ecb | 118 | thread_sleep_for(500); |
eencae | 0:7c0953072ecb | 119 | } |
eencae | 0:7c0953072ecb | 120 | } |
eencae | 0:7c0953072ecb | 121 | |
eencae | 0:7c0953072ecb | 122 | // Button A event-triggered interrupt |
eencae | 0:7c0953072ecb | 123 | void buttonA_isr() |
eencae | 0:7c0953072ecb | 124 | { |
eencae | 0:7c0953072ecb | 125 | g_buttonA_flag = 1; // set flag in ISR |
eencae | 0:7c0953072ecb | 126 | } |