Up Down counter using a transition table

Committer:
eencae
Date:
Thu Dec 10 13:42:11 2020 +0000
Revision:
0:7c0953072ecb
Child:
1:1e34d5c96ecf
Initial Commit

Who changed what in which revision?

UserRevisionLine numberNew 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 }