Craig Evans
/
2645_FSM_UpDown_Counter
Sample code from ELEC2645 Week 16 Lab Demonstrates how to implement a simple FSM up/down counter
main.cpp@0:c5278b91719f, 2016-01-07 (annotated)
- Committer:
- eencae
- Date:
- Thu Jan 07 10:00:24 2016 +0000
- Revision:
- 0:c5278b91719f
- Child:
- 1:fb324de02b7f
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
eencae | 0:c5278b91719f | 1 | /* |
eencae | 0:c5278b91719f | 2 | |
eencae | 0:c5278b91719f | 3 | 2645_FSM_UpDown_Counter |
eencae | 0:c5278b91719f | 4 | |
eencae | 0:c5278b91719f | 5 | Sample code from ELEC2645 Week 16 Lab |
eencae | 0:c5278b91719f | 6 | |
eencae | 0:c5278b91719f | 7 | Demonstrates how to implement a simple FSM up/down counter |
eencae | 0:c5278b91719f | 8 | |
eencae | 0:c5278b91719f | 9 | (c) Craig A. Evans, University of Leeds, Jan 2016 |
eencae | 0:c5278b91719f | 10 | |
eencae | 0:c5278b91719f | 11 | */ |
eencae | 0:c5278b91719f | 12 | |
eencae | 0:c5278b91719f | 13 | #include "mbed.h" |
eencae | 0:c5278b91719f | 14 | |
eencae | 0:c5278b91719f | 15 | // pre-processor directives |
eencae | 0:c5278b91719f | 16 | |
eencae | 0:c5278b91719f | 17 | // defines directions as 0/1. Note UPPERCASE |
eencae | 0:c5278b91719f | 18 | #define UP 0 |
eencae | 0:c5278b91719f | 19 | #define DOWN 1 |
eencae | 0:c5278b91719f | 20 | |
eencae | 0:c5278b91719f | 21 | // K64F on-board LEDs |
eencae | 0:c5278b91719f | 22 | DigitalOut r_led(LED_RED); |
eencae | 0:c5278b91719f | 23 | DigitalOut g_led(LED_GREEN); |
eencae | 0:c5278b91719f | 24 | DigitalOut b_led(LED_BLUE); |
eencae | 0:c5278b91719f | 25 | // K64F on-board switches |
eencae | 0:c5278b91719f | 26 | InterruptIn sw2(SW2); |
eencae | 0:c5278b91719f | 27 | InterruptIn sw3(SW3); |
eencae | 0:c5278b91719f | 28 | |
eencae | 0:c5278b91719f | 29 | // LEDs to display counter output |
eencae | 0:c5278b91719f | 30 | // connect up external LEDs to these pins with appropriate current-limiting resistor |
eencae | 0:c5278b91719f | 31 | BusOut output(PTB2,PTB3,PTB10,PTB11); |
eencae | 0:c5278b91719f | 32 | |
eencae | 0:c5278b91719f | 33 | // array of states in the FSM, each element is the output of the counter |
eencae | 0:c5278b91719f | 34 | int fsm[4] = {1,2,4,8}; |
eencae | 0:c5278b91719f | 35 | |
eencae | 0:c5278b91719f | 36 | // flag - must be volatile as changes within ISR |
eencae | 0:c5278b91719f | 37 | // g_ prefix makes it easier to distinguish it as global |
eencae | 0:c5278b91719f | 38 | volatile int g_sw2_flag = 0; |
eencae | 0:c5278b91719f | 39 | |
eencae | 0:c5278b91719f | 40 | // function prototypes |
eencae | 0:c5278b91719f | 41 | // error function hangs flashing an LED |
eencae | 0:c5278b91719f | 42 | void error(); |
eencae | 0:c5278b91719f | 43 | // set-up the on-board LEDs and switches |
eencae | 0:c5278b91719f | 44 | void init_K64F(); |
eencae | 0:c5278b91719f | 45 | // SW2 interrupt service routine |
eencae | 0:c5278b91719f | 46 | void sw2_isr(); |
eencae | 0:c5278b91719f | 47 | |
eencae | 0:c5278b91719f | 48 | int main() |
eencae | 0:c5278b91719f | 49 | { |
eencae | 0:c5278b91719f | 50 | // initialise on-board LED and switches |
eencae | 0:c5278b91719f | 51 | init_K64F(); |
eencae | 0:c5278b91719f | 52 | |
eencae | 0:c5278b91719f | 53 | // SW2 has a pull-up resistor, so the pin will be at 3.3 V by default |
eencae | 0:c5278b91719f | 54 | // and fall to 0 V when pressed. We therefore need to look for a falling edge |
eencae | 0:c5278b91719f | 55 | // on the pin to fire the interrupt |
eencae | 0:c5278b91719f | 56 | sw2.fall(&sw2_isr); |
eencae | 0:c5278b91719f | 57 | |
eencae | 0:c5278b91719f | 58 | // set inital state |
eencae | 0:c5278b91719f | 59 | int state = 0; |
eencae | 0:c5278b91719f | 60 | // set initial direction |
eencae | 0:c5278b91719f | 61 | int direction = UP; |
eencae | 0:c5278b91719f | 62 | |
eencae | 0:c5278b91719f | 63 | while(1) { // loop forever |
eencae | 0:c5278b91719f | 64 | |
eencae | 0:c5278b91719f | 65 | // check if flag i.e. interrupt has occured |
eencae | 0:c5278b91719f | 66 | if (g_sw2_flag) { |
eencae | 0:c5278b91719f | 67 | g_sw2_flag = 0; // if it has, clear the flag |
eencae | 0:c5278b91719f | 68 | |
eencae | 0:c5278b91719f | 69 | // swap direction when button has been pressed |
eencae | 0:c5278b91719f | 70 | // (could just use ! but want this to be explicit to aid understanding) |
eencae | 0:c5278b91719f | 71 | if (direction == UP) { |
eencae | 0:c5278b91719f | 72 | direction = DOWN; |
eencae | 0:c5278b91719f | 73 | } |
eencae | 0:c5278b91719f | 74 | else { |
eencae | 0:c5278b91719f | 75 | direction = UP; |
eencae | 0:c5278b91719f | 76 | } |
eencae | 0:c5278b91719f | 77 | } |
eencae | 0:c5278b91719f | 78 | |
eencae | 0:c5278b91719f | 79 | output = fsm[state]; // output current state |
eencae | 0:c5278b91719f | 80 | |
eencae | 0:c5278b91719f | 81 | // check which state we are in and see which the next state should be next depending on direction |
eencae | 0:c5278b91719f | 82 | switch(state) { |
eencae | 0:c5278b91719f | 83 | case 0: |
eencae | 0:c5278b91719f | 84 | switch(direction) { |
eencae | 0:c5278b91719f | 85 | case UP: |
eencae | 0:c5278b91719f | 86 | state = 1; |
eencae | 0:c5278b91719f | 87 | break; |
eencae | 0:c5278b91719f | 88 | case DOWN: |
eencae | 0:c5278b91719f | 89 | state = 3; |
eencae | 0:c5278b91719f | 90 | break; |
eencae | 0:c5278b91719f | 91 | } |
eencae | 0:c5278b91719f | 92 | break; |
eencae | 0:c5278b91719f | 93 | case 1: |
eencae | 0:c5278b91719f | 94 | switch(direction) { |
eencae | 0:c5278b91719f | 95 | case UP: |
eencae | 0:c5278b91719f | 96 | state = 2; |
eencae | 0:c5278b91719f | 97 | break; |
eencae | 0:c5278b91719f | 98 | case DOWN: |
eencae | 0:c5278b91719f | 99 | state = 0; |
eencae | 0:c5278b91719f | 100 | break; |
eencae | 0:c5278b91719f | 101 | } |
eencae | 0:c5278b91719f | 102 | break; |
eencae | 0:c5278b91719f | 103 | case 2: |
eencae | 0:c5278b91719f | 104 | switch(direction) { |
eencae | 0:c5278b91719f | 105 | case UP: |
eencae | 0:c5278b91719f | 106 | state = 3; |
eencae | 0:c5278b91719f | 107 | break; |
eencae | 0:c5278b91719f | 108 | case DOWN: |
eencae | 0:c5278b91719f | 109 | state = 1; |
eencae | 0:c5278b91719f | 110 | break; |
eencae | 0:c5278b91719f | 111 | } |
eencae | 0:c5278b91719f | 112 | break; |
eencae | 0:c5278b91719f | 113 | case 3: |
eencae | 0:c5278b91719f | 114 | switch(direction) { |
eencae | 0:c5278b91719f | 115 | case UP: |
eencae | 0:c5278b91719f | 116 | state = 0; |
eencae | 0:c5278b91719f | 117 | break; |
eencae | 0:c5278b91719f | 118 | case DOWN: |
eencae | 0:c5278b91719f | 119 | state = 2; |
eencae | 0:c5278b91719f | 120 | break; |
eencae | 0:c5278b91719f | 121 | } |
eencae | 0:c5278b91719f | 122 | break; |
eencae | 0:c5278b91719f | 123 | default: // default case |
eencae | 0:c5278b91719f | 124 | error(); //invalid state - call error routine |
eencae | 0:c5278b91719f | 125 | // or could jump to starting state i.e. state = 0 |
eencae | 0:c5278b91719f | 126 | break; |
eencae | 0:c5278b91719f | 127 | } |
eencae | 0:c5278b91719f | 128 | |
eencae | 0:c5278b91719f | 129 | wait(0.2); // small delay |
eencae | 0:c5278b91719f | 130 | |
eencae | 0:c5278b91719f | 131 | |
eencae | 0:c5278b91719f | 132 | } |
eencae | 0:c5278b91719f | 133 | } |
eencae | 0:c5278b91719f | 134 | |
eencae | 0:c5278b91719f | 135 | void init_K64F() |
eencae | 0:c5278b91719f | 136 | { |
eencae | 0:c5278b91719f | 137 | // on-board LEDs are active-low, so set pin high to turn them off. |
eencae | 0:c5278b91719f | 138 | r_led = 1; |
eencae | 0:c5278b91719f | 139 | g_led = 1; |
eencae | 0:c5278b91719f | 140 | b_led = 1; |
eencae | 0:c5278b91719f | 141 | |
eencae | 0:c5278b91719f | 142 | // since the on-board switches have external pull-ups, we should disable the internal pull-down |
eencae | 0:c5278b91719f | 143 | // resistors that are enabled by default using InterruptIn |
eencae | 0:c5278b91719f | 144 | sw2.mode(PullNone); |
eencae | 0:c5278b91719f | 145 | sw3.mode(PullNone); |
eencae | 0:c5278b91719f | 146 | |
eencae | 0:c5278b91719f | 147 | } |
eencae | 0:c5278b91719f | 148 | |
eencae | 0:c5278b91719f | 149 | void error() |
eencae | 0:c5278b91719f | 150 | { |
eencae | 0:c5278b91719f | 151 | while(1) { // if error, hang while flashing error message |
eencae | 0:c5278b91719f | 152 | r_led = 0; |
eencae | 0:c5278b91719f | 153 | wait(0.2); |
eencae | 0:c5278b91719f | 154 | r_led = 1; |
eencae | 0:c5278b91719f | 155 | wait(0.2); |
eencae | 0:c5278b91719f | 156 | } |
eencae | 0:c5278b91719f | 157 | } |
eencae | 0:c5278b91719f | 158 | |
eencae | 0:c5278b91719f | 159 | // SW2 event-triggered interrupt |
eencae | 0:c5278b91719f | 160 | void sw2_isr() |
eencae | 0:c5278b91719f | 161 | { |
eencae | 0:c5278b91719f | 162 | g_sw2_flag = 1; // set flag in ISR |
eencae | 0:c5278b91719f | 163 | } |