Theo Ekelmans
/
14_Key_Poller_debounce_DEMO
14 Key poller with debouncing DEMO
main.cpp
- Committer:
- ekelmans
- Date:
- 2012-01-07
- Revision:
- 0:acabda48796c
- Child:
- 1:6ee2362ce0fd
File content as of revision 0:acabda48796c:
/* ----------------------------------------------------------------------- 14 Key poller and debounce demo by Theo Ekelmans, Version 1.0 ----------------------------------------------------------------------- In this demo, banks A, C and D are push buttons, bank B are toggle switches that have a LED inside The timer used for SampleInterval is set to 10 ms (sample time) 2 * SampleInterval = 20ms for good quality switches, 80ms for high CPU load or really crappy switches :) led3 on the MBED Config your USB COM port terminal session as a VT100 terminal :) Notes: 1: The SampleCnt is 32 bit, that means every 2^32 times 10ms SampleInterval it will trigger an overflow on the long vars, thats why @ 4000000000 the TimerOverflowRecover resets all counters. During in that brief moment (2 miliseconds every 25 days or so), the debounce is not reliable ;) 2: The USB COM port / VT100 terminal session hangs somtimes when you are bashing buttons like a madman, the LCD however is rock solid. */ #include "mbed.h" #include "DigitalIn.h" //--- Defines #define ON 1 #define OFF 0 //ASCII commands for the VT100 terminal #define LF 10 #define CLS 12 #define CR 13 #define BS 8 #define ESC 27 //Serial LCD - Matrix Orbital LK204 command codes #define CMD 254 #define CurPos 71 //follow up by COL ROW Serial lcd(p9, p10); // tx, rx //Debounce vars int DebounceThreshold = 3; // 2 * SampleInterval = 20ms for good quality switches, 80ms for high CPU load or really crappy switches :) float SampleInterval = 0.01; // The timer for debouncing interval: 10 ms sample time unsigned long PollCount1 = 0; unsigned long PollCount2 = 0; unsigned long KillBeepAt = 0; char strCmd [100] = ""; //Debounce vars unsigned long SampleCnt = 0; unsigned long DebounceActivationCounter = 0; unsigned long LastSampleA1 = 0; unsigned long LastSampleA2 = 0; unsigned long LastSampleA3 = 0; unsigned long LastSampleA4 = 0; unsigned long LastSampleB1 = 0; unsigned long LastSampleB2 = 0; unsigned long LastSampleB3 = 0; unsigned long LastSampleB4 = 0; unsigned long LastSampleC1 = 0; unsigned long LastSampleC2 = 0; unsigned long LastSampleC3 = 0; unsigned long LastSampleC4 = 0; unsigned long LastSampleD1 = 0; unsigned long LastSampleD2 = 0; bool LastButtonA1 = false; bool LastButtonA2 = false; bool LastButtonA3 = false; bool LastButtonA4 = false; bool LastButtonB1 = false; bool LastButtonB2 = false; bool LastButtonB3 = false; bool LastButtonB4 = false; bool LastButtonC1 = false; bool LastButtonC2 = false; bool LastButtonC3 = false; bool LastButtonC4 = false; bool LastButtonD1 = false; bool LastButtonD2 = false; // The switch mapping DigitalIn buttonA1(p11); DigitalIn buttonA2(p12); DigitalIn buttonA3(p13); DigitalIn buttonA4(p14); DigitalIn buttonB1(p15); DigitalIn buttonB2(p16); DigitalIn buttonB3(p17); DigitalIn buttonB4(p18); DigitalIn buttonC1(p21); DigitalIn buttonC2(p22); DigitalIn buttonC3(p23); DigitalIn buttonC4(p24); DigitalIn buttonD1(p28); DigitalIn buttonD2(p27); //Bank B Leds DigitalOut ledH1(p5); DigitalOut ledH2(p6); DigitalOut ledH3(p7); DigitalOut ledH4(p8); //MBED leds DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); //Timer that starts the polling event Ticker DebounceTimer; //Beeper port DigitalOut Beep(p29); // Config your USB COM port terminal session as a VT100 terminal :) Serial usbUART ( USBTX, USBRX ); // Kill tha beep.... void KillBeep() {Beep = OFF; } // beepTimer.detach();} //------------------------------------------------------------------------------------------------------- //This is where you put your payload; //------------------------------------------------------------------------------------------------------- void PayLoadPressed(char msg[] ) { lcd.printf("%c%c%c%cA%i%i%i%iB%i%i%i%iC%i%i%i%iD%i%i\r\n@ %ld, %ld bounces\r\nKey + %s @ %ld\r\n ", CMD, CurPos, 1, 1,buttonA1.read(),buttonA2.read(),buttonA3.read(),buttonA4.read(),buttonB1.read(),buttonB2.read(),buttonB3.read(),buttonB4.read(),buttonC1.read(),buttonC2.read(),buttonC3.read(),buttonC4.read(),buttonD1.read(),buttonD2.read(), PollCount2, DebounceActivationCounter, msg, SampleCnt);}; void PayLoadRelease(char msg[] ) { lcd.printf("%c%c%c%cA%i%i%i%iB%i%i%i%iC%i%i%i%iD%i%i\r\n@ %ld, %ld bounces\r\nKey - %s @ %ld\r\n ", CMD, CurPos, 1, 1,buttonA1.read(),buttonA2.read(),buttonA3.read(),buttonA4.read(),buttonB1.read(),buttonB2.read(),buttonB3.read(),buttonB4.read(),buttonC1.read(),buttonC2.read(),buttonC3.read(),buttonC4.read(),buttonD1.read(),buttonD2.read(), PollCount2, DebounceActivationCounter, msg, SampleCnt);}; //------------------------------------------------------------------------------------------------------- //This routine is only needed for the demo and can be removed for runtime //------------------------------------------------------------------------------------------------------- void DeboucnceActive(char msg[], unsigned long l, unsigned long c) { lcd.printf("%c%c%c%cA%i%i%i%iB%i%i%i%iC%i%i%i%iD%i%i\r\n@ %ld, %ld bounces\r\nKey - %s @ %ld\r\n%s bounced %ld x ", CMD, CurPos, 1, 1, buttonA1.read(),buttonA2.read(),buttonA3.read(),buttonA4.read(),buttonB1.read(),buttonB2.read(),buttonB3.read(),buttonB4.read(),buttonC1.read(),buttonC2.read(),buttonC3.read(),buttonC4.read(),buttonD1.read(),buttonD2.read(), PollCount2, DebounceActivationCounter, msg, SampleCnt, msg, (c - l)); DebounceActivationCounter ++; led3 = !led3; //Blink on debounce Beep = ON; KillBeepAt = SampleCnt + 50; //Kill Beep in 500 Ms }; //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Wait at least <DebounceThreshold> samples Toggle status Payload Save debounce counter Debounce active //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- void keyPressedA1 ( void ) {if ((LastSampleA1 + DebounceThreshold) < SampleCnt) {LastButtonA1 = buttonA1; PayLoadPressed("F"); LastSampleA1 = SampleCnt;} else {DeboucnceActive("F", LastSampleA1, SampleCnt);};}; void keyReleasedA1( void ) {if ((LastSampleA1 + DebounceThreshold) < SampleCnt) {LastButtonA1 = buttonA1; /*no key up event*/ LastSampleA1 = SampleCnt;} else {/*no key up debounce needed either*/ ;};}; void keyPressedA2 ( void ) {if ((LastSampleA2 + DebounceThreshold) < SampleCnt) {LastButtonA2 = buttonA2; PayLoadPressed("G"); LastSampleA2 = SampleCnt;} else {DeboucnceActive("G", LastSampleA2, SampleCnt);};}; void keyReleasedA2( void ) {if ((LastSampleA2 + DebounceThreshold) < SampleCnt) {LastButtonA2 = buttonA2; LastSampleA2 = SampleCnt;} else { ;};}; void keyPressedA3 ( void ) {if ((LastSampleA3 + DebounceThreshold) < SampleCnt) {LastButtonA3 = buttonA3; PayLoadPressed("H"); LastSampleA3 = SampleCnt;} else {DeboucnceActive("H", LastSampleA3, SampleCnt);};}; void keyReleasedA3( void ) {if ((LastSampleA3 + DebounceThreshold) < SampleCnt) {LastButtonA3 = buttonA3; LastSampleA3 = SampleCnt;} else { ;};}; void keyPressedA4 ( void ) {if ((LastSampleA4 + DebounceThreshold) < SampleCnt) {LastButtonA4 = buttonA4; PayLoadPressed("I"); LastSampleA4 = SampleCnt;} else {DeboucnceActive("I", LastSampleA4, SampleCnt);};}; void keyReleasedA4( void ) {if ((LastSampleA4 + DebounceThreshold) < SampleCnt) {LastButtonA4 = buttonA4; LastSampleA4 = SampleCnt;} else { ;};}; //Toggle switches need a payload on the pressed and release event, and debouncing on both void keyPressedB1 ( void ) {if ((LastSampleB1 + DebounceThreshold) < SampleCnt) {LastButtonB1 = buttonB1; PayLoadPressed("A"); LastSampleB1 = SampleCnt;} else {DeboucnceActive("A", LastSampleB1, SampleCnt);};}; void keyReleasedB1( void ) {if ((LastSampleB1 + DebounceThreshold) < SampleCnt) {LastButtonB1 = buttonB1; PayLoadRelease("a"); LastSampleB1 = SampleCnt;} else {DeboucnceActive("a", LastSampleB1, SampleCnt);};}; void keyPressedB2 ( void ) {if ((LastSampleB2 + DebounceThreshold) < SampleCnt) {LastButtonB2 = buttonB2; PayLoadPressed("B"); LastSampleB2 = SampleCnt;} else {DeboucnceActive("B", LastSampleB2, SampleCnt);};}; void keyReleasedB2( void ) {if ((LastSampleB2 + DebounceThreshold) < SampleCnt) {LastButtonB2 = buttonB2; PayLoadRelease("b"); LastSampleB2 = SampleCnt;} else {DeboucnceActive("b", LastSampleB2, SampleCnt);};}; void keyPressedB3 ( void ) {if ((LastSampleB3 + DebounceThreshold) < SampleCnt) {LastButtonB3 = buttonB3; PayLoadPressed("C"); LastSampleB3 = SampleCnt;} else {DeboucnceActive("C", LastSampleB3, SampleCnt);};}; void keyReleasedB3( void ) {if ((LastSampleB3 + DebounceThreshold) < SampleCnt) {LastButtonB3 = buttonB3; PayLoadRelease("c"); LastSampleB3 = SampleCnt;} else {DeboucnceActive("c", LastSampleB3, SampleCnt);};}; void keyPressedB4 ( void ) {if ((LastSampleB4 + DebounceThreshold) < SampleCnt) {LastButtonB4 = buttonB4; PayLoadPressed("D"); LastSampleB4 = SampleCnt;} else {DeboucnceActive("D", LastSampleB4, SampleCnt);};}; void keyReleasedB4( void ) {if ((LastSampleB4 + DebounceThreshold) < SampleCnt) {LastButtonB4 = buttonB4; PayLoadRelease("d"); LastSampleB4 = SampleCnt;} else {DeboucnceActive("d", LastSampleB4, SampleCnt);};}; //Push button switches only need a payload and debouncing on the pressed event, and you can ignore the release event (C4 left on for demo purposes) void keyPressedC1 ( void ) {if ((LastSampleC1 + DebounceThreshold) < SampleCnt) {LastButtonC1 = buttonC1; PayLoadPressed("L"); LastSampleC1 = SampleCnt;} else {DeboucnceActive("L", LastSampleC1, SampleCnt);};}; void keyReleasedC1( void ) {if ((LastSampleC1 + DebounceThreshold) < SampleCnt) {LastButtonC1 = buttonC1; /*no key up event*/ LastSampleC1 = SampleCnt;} else {/*no key up debounce needed either*/ ;};}; void keyPressedC2 ( void ) {if ((LastSampleC2 + DebounceThreshold) < SampleCnt) {LastButtonC2 = buttonC2; PayLoadPressed("M"); LastSampleC2 = SampleCnt;} else {DeboucnceActive("M", LastSampleC2, SampleCnt);};}; void keyReleasedC2( void ) {if ((LastSampleC2 + DebounceThreshold) < SampleCnt) {LastButtonC2 = buttonC2; LastSampleC2 = SampleCnt;} else { ;};}; void keyPressedC3 ( void ) {if ((LastSampleC3 + DebounceThreshold) < SampleCnt) {LastButtonC3 = buttonC3; PayLoadPressed("N"); LastSampleC3 = SampleCnt;} else {DeboucnceActive("N", LastSampleC3, SampleCnt);};}; void keyReleasedC3( void ) {if ((LastSampleC3 + DebounceThreshold) < SampleCnt) {LastButtonC3 = buttonC3; LastSampleC3 = SampleCnt;} else { ;};}; void keyPressedC4 ( void ) {if ((LastSampleC4 + DebounceThreshold) < SampleCnt) {LastButtonC4 = buttonC4; PayLoadPressed("O"); LastSampleC4 = SampleCnt;} else {DeboucnceActive("O", LastSampleC4, SampleCnt);};}; void keyReleasedC4( void ) {if ((LastSampleC4 + DebounceThreshold) < SampleCnt) {LastButtonC4 = buttonC4; PayLoadRelease("o"); LastSampleC4 = SampleCnt;} else {DeboucnceActive("o", LastSampleC4, SampleCnt);};}; //Push button switches only need a payload and debouncing on the pressed event, and you can ignore the release event (C4 left on for demo purposes) void keyPressedD1 ( void ) {if ((LastSampleD1 + DebounceThreshold) < SampleCnt) {LastButtonD1 = buttonD1; PayLoadPressed("Q"); LastSampleD1 = SampleCnt;} else {DeboucnceActive("Q", LastSampleD1, SampleCnt);};}; void keyReleasedD1( void ) {if ((LastSampleD1 + DebounceThreshold) < SampleCnt) {LastButtonD1 = buttonD1; /*no key up event*/ LastSampleD1 = SampleCnt;} else {/*no key up debounce needed either*/ ;};}; void keyPressedD2 ( void ) {if ((LastSampleD2 + DebounceThreshold) < SampleCnt) {LastButtonD2 = buttonD2; PayLoadPressed("P"); LastSampleD2 = SampleCnt;} else {DeboucnceActive("P", LastSampleD2, SampleCnt);};}; void keyReleasedD2( void ) {if ((LastSampleD2 + DebounceThreshold) < SampleCnt) {LastButtonD2 = buttonD2; PayLoadRelease("p"); LastSampleD2 = SampleCnt;} else {DeboucnceActive("P", LastSampleD2, SampleCnt);};}; //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------- //INIT of the buttons, since toggle switches can be ON at startup //------------------------------------------------------------------------------------------------------- void InitButtons(void) { if (buttonA1){LastButtonA1 = true;} else {LastButtonA1 = false;}; if (buttonA2){LastButtonA2 = true;} else {LastButtonA2 = false;}; if (buttonA3){LastButtonA3 = true;} else {LastButtonA3 = false;}; if (buttonA4){LastButtonA4 = true;} else {LastButtonA4 = false;}; if (buttonB1){LastButtonB1 = true;} else {LastButtonB1 = false;}; if (buttonB2){LastButtonB2 = true;} else {LastButtonB2 = false;}; if (buttonB3){LastButtonB3 = true;} else {LastButtonB3 = false;}; if (buttonB4){LastButtonB4 = true;} else {LastButtonB4 = false;}; if (buttonC1){LastButtonC1 = true;} else {LastButtonC1 = false;}; if (buttonC2){LastButtonC2 = true;} else {LastButtonC2 = false;}; if (buttonC3){LastButtonC3 = true;} else {LastButtonC3 = false;}; if (buttonC4){LastButtonC4 = true;} else {LastButtonC4 = false;}; if (buttonD1){LastButtonD1 = true;} else {LastButtonD1 = false;}; if (buttonD2){LastButtonD2 = true;} else {LastButtonD2 = false;}; // Update bank B Leds (Toggle switches) ledH1 = buttonB1.read(); ledH2 = buttonB2.read(); ledH3 = buttonB3.read(); ledH4 = buttonB4.read(); } void TimerOverflowRecover (void) { //Reset all counters PollCount2 = 0; PollCount1 = 0; SampleCnt = 0; LastSampleA1 = 0; LastSampleA2 = 0; LastSampleA3 = 0; LastSampleA4 = 0; LastSampleB1 = 0; LastSampleB2 = 0; LastSampleB3 = 0; LastSampleB4 = 0; LastSampleC1 = 0; LastSampleC2 = 0; LastSampleC3 = 0; LastSampleC4 = 0; LastSampleD1 = 0; LastSampleD2 = 0; } //------------------------------------------------------------------------------------------------------- //The key detection routine //------------------------------------------------------------------------------------------------------- void DebounceTick() { // XOR only traps 01 and 10 0->1 = pressed 1->0 = released if (buttonA1 ^ LastButtonA1) {if (buttonA1){keyPressedA1();} else {keyReleasedA1();};}; if (buttonA2 ^ LastButtonA2) {if (buttonA2){keyPressedA2();} else {keyReleasedA2();};}; if (buttonA3 ^ LastButtonA3) {if (buttonA3){keyPressedA3();} else {keyReleasedA3();};}; if (buttonA4 ^ LastButtonA4) {if (buttonA4){keyPressedA4();} else {keyReleasedA4();};}; if (buttonB1 ^ LastButtonB1) {if (buttonB1){keyPressedB1();} else {keyReleasedB1();};}; if (buttonB2 ^ LastButtonB2) {if (buttonB2){keyPressedB2();} else {keyReleasedB2();};}; if (buttonB3 ^ LastButtonB3) {if (buttonB3){keyPressedB3();} else {keyReleasedB3();};}; if (buttonB4 ^ LastButtonB4) {if (buttonB4){keyPressedB4();} else {keyReleasedB4();};}; if (buttonC1 ^ LastButtonC1) {if (buttonC1){keyPressedC1();} else {keyReleasedC1();};}; if (buttonC2 ^ LastButtonC2) {if (buttonC2){keyPressedC2();} else {keyReleasedC2();};}; if (buttonC3 ^ LastButtonC3) {if (buttonC3){keyPressedC3();} else {keyReleasedC3();};}; if (buttonC4 ^ LastButtonC4) {if (buttonC4){keyPressedC4();} else {keyReleasedC4();};}; if (buttonD1 ^ LastButtonD1) {if (buttonD1){keyPressedD1();} else {keyReleasedD1();};}; if (buttonD2 ^ LastButtonD2) {if (buttonD2){keyPressedD2();} else {keyReleasedD2();};}; // Update bank B Leds (Toggle switches) ledH1 = buttonB1.read(); ledH2 = buttonB2.read(); ledH3 = buttonB3.read(); ledH4 = buttonB4.read(); SampleCnt ++; //Kill Beep if (SampleCnt > KillBeepAt) {Beep = OFF;} //Overflow protection if (SampleCnt >= 4000000000) {TimerOverflowRecover();}; } //------------------------------------------------------------------------------------------------------- // Main loop //------------------------------------------------------------------------------------------------------- int main() { //Init Serial LCD lcd.baud(115200); lcd.printf("%c", CLS); //Init USB COM port for VT100 usbUART.baud(115200); //VT100 clear screen (ESC[2J) , move cursor (ESC[1;1H) to Row 1, Col 1 usbUART.printf("%c[2J%c[1;1H", ESC , ESC ); InitButtons(); // The timer for debouncing interval: 10 ms sample time DebounceTimer.attach(&DebounceTick, SampleInterval); //Sound a beep for 500 Ms Beep = ON; KillBeepAt = SampleCnt + 50; PollCount1 = 0; while (1) { PollCount1 ++; //Update terminal every 500000'th pass if ( PollCount1 % 500000 == 0 ) { PollCount1 = 0; PollCount2 ++; //Send to VT100 terminal emulator on the PC USB COM port //And because i think scrolling screens are annoying, i added cursor control codes below //VT100 move cursor (ESC[1;1H) to Row 1, Col 1 usbUART.printf("%c[1;1H", ESC ); usbUART.printf("A%i%i%i%i ",buttonA1.read(),buttonA2.read(),buttonA3.read(),buttonA4.read()); usbUART.printf("B%i%i%i%i ",buttonB1.read(),buttonB2.read(),buttonB3.read(),buttonB4.read()); usbUART.printf("C%i%i%i%i ",buttonC1.read(),buttonC2.read(),buttonC3.read(),buttonC4.read()); usbUART.printf("D%i%i @ %ld, %ld bounces",buttonD1.read(),buttonD2.read(), PollCount2, DebounceActivationCounter); } } }