// Simple button/swipe library for FRDM-KL25Z // AI Williams -- The Touch of a Button // Dr.Dobb's Journal // http://www.drdobbs.com/embedded-systems/the-touch-of-a-button/240169431
Simple button/swipe library for FRDM-KL25Z by AI Williams: The Touch of a Button Dr.Dobb's Journal http://www.drdobbs.com/embedded-systems/the-touch-of-a-button/240169431
main.cpp@0:de427e23a099, 2015-11-03 (annotated)
- Committer:
- icserny
- Date:
- Tue Nov 03 12:52:59 2015 +0000
- Revision:
- 0:de427e23a099
First version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
icserny | 0:de427e23a099 | 1 | #include "mbed.h" |
icserny | 0:de427e23a099 | 2 | #include "tsi_sensor.h" |
icserny | 0:de427e23a099 | 3 | |
icserny | 0:de427e23a099 | 4 | // Simple button/swipe library for FRDM-KL25Z |
icserny | 0:de427e23a099 | 5 | // AI Williams -- The Touch of a Button |
icserny | 0:de427e23a099 | 6 | // Dr.Dobb's Journal |
icserny | 0:de427e23a099 | 7 | // http://www.drdobbs.com/embedded-systems/the-touch-of-a-button/240169431 |
icserny | 0:de427e23a099 | 8 | |
icserny | 0:de427e23a099 | 9 | /* This defines will be replaced by PinNames soon */ |
icserny | 0:de427e23a099 | 10 | #if defined (TARGET_KL25Z) || defined (TARGET_KL46Z) |
icserny | 0:de427e23a099 | 11 | #define ELEC0 9 |
icserny | 0:de427e23a099 | 12 | #define ELEC1 10 |
icserny | 0:de427e23a099 | 13 | #elif defined (TARGET_KL05Z) |
icserny | 0:de427e23a099 | 14 | #define ELEC0 9 |
icserny | 0:de427e23a099 | 15 | #define ELEC1 8 |
icserny | 0:de427e23a099 | 16 | #else |
icserny | 0:de427e23a099 | 17 | #error TARGET NOT DEFINED |
icserny | 0:de427e23a099 | 18 | #endif |
icserny | 0:de427e23a099 | 19 | |
icserny | 0:de427e23a099 | 20 | // Define the "zones" considered to be buttons |
icserny | 0:de427e23a099 | 21 | // 4 is about the limit and 3 might be even better |
icserny | 0:de427e23a099 | 22 | // You could also equal space them automatically pretty easily |
icserny | 0:de427e23a099 | 23 | // (e.g., specify 25% and fill in BTNMAX programmatically |
icserny | 0:de427e23a099 | 24 | float BTNMAX[]= {0.25, 0.50, 0.75, 1.00 }; |
icserny | 0:de427e23a099 | 25 | #define SWIPETIME .350 // seconds to wait before sensing a button push or swipe |
icserny | 0:de427e23a099 | 26 | #define SWIPE_R 256 // virtual button code for right swipe |
icserny | 0:de427e23a099 | 27 | #define SWIPE_L 512 // virtual button code for left swipe |
icserny | 0:de427e23a099 | 28 | |
icserny | 0:de427e23a099 | 29 | Serial pc(USBTX, USBRX); // tx, rx for debugging |
icserny | 0:de427e23a099 | 30 | TSIAnalogSlider tsi(ELEC0, ELEC1, 40); // The Analog slider |
icserny | 0:de427e23a099 | 31 | Timeout scan; |
icserny | 0:de427e23a099 | 32 | |
icserny | 0:de427e23a099 | 33 | |
icserny | 0:de427e23a099 | 34 | int candidate=-1; // possible button push (-1 is none) |
icserny | 0:de427e23a099 | 35 | volatile int realbtn=-1; // actual button push (-1 is none) |
icserny | 0:de427e23a099 | 36 | volatile int hold=0; // waiting for button release when 1 |
icserny | 0:de427e23a099 | 37 | |
icserny | 0:de427e23a099 | 38 | // internal function to get raw button state |
icserny | 0:de427e23a099 | 39 | int getrawbtn() |
icserny | 0:de427e23a099 | 40 | { |
icserny | 0:de427e23a099 | 41 | float v=tsi.readPercentage(); // read slider |
icserny | 0:de427e23a099 | 42 | if (v==0.0) return -1; // no button at all |
icserny | 0:de427e23a099 | 43 | for (int i=0;i<sizeof(BTNMAX)/sizeof(BTNMAX[0]);i++) // classify by zone |
icserny | 0:de427e23a099 | 44 | if (v<BTNMAX[i]) return i; |
icserny | 0:de427e23a099 | 45 | return -1; // what? |
icserny | 0:de427e23a099 | 46 | } |
icserny | 0:de427e23a099 | 47 | |
icserny | 0:de427e23a099 | 48 | // This is called by the timeout to |
icserny | 0:de427e23a099 | 49 | // either see there is no swipe |
icserny | 0:de427e23a099 | 50 | // see that there is a swipe |
icserny | 0:de427e23a099 | 51 | // or see that there is a button release |
icserny | 0:de427e23a099 | 52 | void checkbtn(void) |
icserny | 0:de427e23a099 | 53 | { |
icserny | 0:de427e23a099 | 54 | int newbtn=getrawbtn(); |
icserny | 0:de427e23a099 | 55 | if (hold!=0 && newbtn==-1) // wait for key release |
icserny | 0:de427e23a099 | 56 | { |
icserny | 0:de427e23a099 | 57 | hold=0; // released so |
icserny | 0:de427e23a099 | 58 | return; // don't reschedule me |
icserny | 0:de427e23a099 | 59 | } |
icserny | 0:de427e23a099 | 60 | // reschedule us for next swipetime |
icserny | 0:de427e23a099 | 61 | scan.attach(checkbtn,SWIPETIME); |
icserny | 0:de427e23a099 | 62 | if (hold) return; // still waiting for release |
icserny | 0:de427e23a099 | 63 | hold=1; // we will be waiting for release from now on |
icserny | 0:de427e23a099 | 64 | if (newbtn==-1||newbtn==candidate) // if no touch or button is the same, the candidate is the button |
icserny | 0:de427e23a099 | 65 | { |
icserny | 0:de427e23a099 | 66 | realbtn=candidate; |
icserny | 0:de427e23a099 | 67 | return; |
icserny | 0:de427e23a099 | 68 | } |
icserny | 0:de427e23a099 | 69 | // Otherwise we are swiping either left or right |
icserny | 0:de427e23a099 | 70 | if (candidate<newbtn) realbtn=SWIPE_L; else realbtn=SWIPE_R; |
icserny | 0:de427e23a099 | 71 | return; |
icserny | 0:de427e23a099 | 72 | } |
icserny | 0:de427e23a099 | 73 | |
icserny | 0:de427e23a099 | 74 | // This is the main API |
icserny | 0:de427e23a099 | 75 | // Call it to get a button code (0-3 or 256 or 512) |
icserny | 0:de427e23a099 | 76 | // You can block or not (default is to block) |
icserny | 0:de427e23a099 | 77 | int getbtn(bool kwait=true) |
icserny | 0:de427e23a099 | 78 | { |
icserny | 0:de427e23a099 | 79 | while (hold) // if holding, either wait or return |
icserny | 0:de427e23a099 | 80 | { |
icserny | 0:de427e23a099 | 81 | if (!kwait) return -1; |
icserny | 0:de427e23a099 | 82 | } |
icserny | 0:de427e23a099 | 83 | realbtn=-1; // mark that we don't know |
icserny | 0:de427e23a099 | 84 | do |
icserny | 0:de427e23a099 | 85 | { |
icserny | 0:de427e23a099 | 86 | candidate=getrawbtn(); // get a candidate (or return if not waiting) |
icserny | 0:de427e23a099 | 87 | } while (candidate==-1 || !kwait); |
icserny | 0:de427e23a099 | 88 | if (candidate==-1) return -1; |
icserny | 0:de427e23a099 | 89 | scan.attach(checkbtn,SWIPETIME); // schedule the checkbtn routine |
icserny | 0:de427e23a099 | 90 | while (realbtn==-1); // wait for realbtn to get set |
icserny | 0:de427e23a099 | 91 | return realbtn; // return it |
icserny | 0:de427e23a099 | 92 | } |
icserny | 0:de427e23a099 | 93 | |
icserny | 0:de427e23a099 | 94 | // Simple test program |
icserny | 0:de427e23a099 | 95 | int main(void) { |
icserny | 0:de427e23a099 | 96 | |
icserny | 0:de427e23a099 | 97 | while (true) { |
icserny | 0:de427e23a099 | 98 | pc.printf("Button %d\r\n",getbtn()); |
icserny | 0:de427e23a099 | 99 | } |
icserny | 0:de427e23a099 | 100 | } |