An example solution for the two switch - flashing LED problem
Fork of Task324Solution by
main.cpp
- Committer:
- noutram
- Date:
- 2019-09-11
- Revision:
- 5:0e52b9b0b1f8
- Parent:
- 3:ba009495c5ef
File content as of revision 5:0e52b9b0b1f8:
#include "mbed.h" //Next state logic for switch debounce void updateSwitchState(int sw, int &swState, Timer &tmr, unsigned short &debouncedSwitchOutput); //Moore outputs for switch debounce void updateSwitchOutputs(int swState, unsigned short &debouncedSwitchOutput); //Mealy machine for timer interval static void updateFlashIntervalFSM(float &interval, unsigned short sw1, unsigned short sw2); DigitalOut red_led(D7); DigitalOut green_led(D5); DigitalIn SW1(D4); DigitalIn SW2(D3); //This is the solution based on the proposed flowchart. //The precise delay required may need adjusting Timer tmr1; Timer tmr2; Timer flashTimer; #define WAITING4PRESS 0 #define WAITING4BOUNCE_RISING 1 #define WAITING4RELEASE 2 #define WAITING4BOUNCE_FALLING 4 #define SWPRESSED 1 #define SWRELEASED 0 int main() { //Initial logging message puts("START"); //Power on check red_led = 1; //Set RED LED to OFF green_led = 1; wait(1.0); //Initial state red_led = 0; //Set RED LED to OFF green_led = 0; //Switch state int sw1State = 0; int sw2State = 0; //Timers tmr1.stop(); tmr1.reset(); tmr2.stop(); tmr2.reset(); flashTimer.stop(); flashTimer.reset(); flashTimer.start(); //Initial logging message puts("Entering state WAITING4PRESS"); //Debounced outputs unsigned short sw1_db = SWRELEASED; unsigned short sw2_db = SWRELEASED; //Timer delay float flashInterval = 1.0f; //Main Polling Loop while (true) { //Poll inputs (without blocking) int sw1 = SW1; int sw2 = SW2; //SWITCH DEBOUNCE FSM updateSwitchState(sw1, sw1State, tmr1, sw1_db); updateSwitchState(sw2, sw2State, tmr2, sw2_db); //Update flashInterval updateFlashIntervalFSM(flashInterval, sw1_db, sw2_db); //LED TIMER DELAY FSM (trivial) if (flashTimer >= flashInterval) { green_led = !green_led; flashTimer.reset(); } } //end while } //Here is an example of a self-contained finite state machine //sw1 and sw2 are debounced, so no need for timers //interval is a Mealy output (keeps the FSM small) static void updateFlashIntervalFSM(float &interval, unsigned short sw1, unsigned short sw2) { //This data type is private to this function enum FI_STATE {NOPRESS, PRESSED}; //This is a static local - it is initilaised ONCE and remembers it's value with each function call static FI_STATE state = NOPRESS; //Simple FSM to update the interval - reduced to 2 states switch (state) { case NOPRESS: if (sw1 && sw2) { state = PRESSED; interval = 1.0; //Mealy output } else if (sw1 & !sw2) { state = PRESSED; interval += ((interval>0.2f) ? -0.1f : 0.0f); } else if (!sw1 & sw2) { state = PRESSED; interval += 0.1f; } break; case PRESSED: //All states lead back to NOPRESS when both are released if (!sw1 && !sw2) { state = NOPRESS; } //If at any time both are pressed, reset the interval else if (sw1 && sw2) { interval = 1.0; //Mealy output } break; default: printf("ERROR"); state = NOPRESS; interval = 1.0; } //End case } //End function // Update the state for a given switch and LED pair // Parameters: // sw is the switch input, 0 for released and 1 for pressed, passed by value // swState is an integer that keeps a record of state, passed by reference (updated by the function) // REMOVED led is of type DigitalOut, connected to a LED // tmr is of type Timer, a reference to unique instance of a timer // This function cannot be called by an ISR void updateSwitchState(int sw, int &swState, Timer &tmr, unsigned short &debouncedSwitchOutput) { //LED switch (swState) { //Waiting for switch to be pressed case WAITING4PRESS: if (sw == 1) { //Output: start timer tmr.reset(); tmr.start(); //Next state swState = WAITING4BOUNCE_RISING; puts("Entering state: WAITING4BOUNCE_RISING"); } break; //Waiting for 50ms to elapse case WAITING4BOUNCE_RISING: if (tmr.read_ms() > 50) { //Outputs: Stop timer tmr.stop(); //Next state swState = WAITING4RELEASE; puts("Entering state: WAITING4RELEASE"); } break; //Waiting for switch to be released case WAITING4RELEASE: if (sw == 0) { tmr.reset(); tmr.start(); //Next state swState = WAITING4BOUNCE_FALLING; puts("Entering state: WAITING4BOUNCE_FALLING"); } break; //Waiting 50ms for switch bounce case WAITING4BOUNCE_FALLING: if (tmr.read_ms() > 50) { //Outputs: Reset timer 1 tmr.stop(); tmr.reset(); //Next state: swState = WAITING4PRESS; puts("Entering state: WAITING4PRESS"); } break; default: //Something has gone very wrong tmr.stop(); tmr.reset(); swState = WAITING4PRESS; puts("ERROR"); break; } //end switch //Moore outputs updateSwitchOutputs(swState, debouncedSwitchOutput); } //end function //Moore Outputs - asserted with each pass. Could be convered easily to Mealy outputs // swState is the state of the switch debounce finite state machine // debouncedSwitchOutput is the Moore output for the state machine void updateSwitchOutputs(int swState, unsigned short &debouncedSwitchOutput) { switch (swState) { //Waiting for switch to be pressed case WAITING4PRESS: debouncedSwitchOutput = SWRELEASED; break; //Waiting for 50ms to elapse case WAITING4BOUNCE_RISING: debouncedSwitchOutput = SWRELEASED; break; //Waiting for switch to be released case WAITING4RELEASE: debouncedSwitchOutput = SWPRESSED; break; //Waiting 50ms for switch bounce case WAITING4BOUNCE_FALLING: debouncedSwitchOutput = SWRELEASED; break; default: //Something has gone very wrong debouncedSwitchOutput = SWRELEASED; printf("ERROR\n\r"); break; } //end switch } //end function