Jim Flynn
/
button_class_and_test
Implementation of a button class and test program
Button.hpp@1:c668e9604e63, 2018-09-07 (annotated)
- Committer:
- JMF
- Date:
- Fri Sep 07 20:54:25 2018 +0000
- Revision:
- 1:c668e9604e63
- Parent:
- 0:377a50b631cf
Added a destructor to the class.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JMF | 1:c668e9604e63 | 1 | /** |
JMF | 1:c668e9604e63 | 2 | * copyright (c) 2018, James Flynn |
JMF | 1:c668e9604e63 | 3 | * SPDX-License-Identifier: MIT |
JMF | 1:c668e9604e63 | 4 | */ |
JMF | 1:c668e9604e63 | 5 | |
JMF | 1:c668e9604e63 | 6 | /** |
JMF | 1:c668e9604e63 | 7 | * @file button.hpp |
JMF | 1:c668e9604e63 | 8 | * @brief A small BUTTON class for detecting & debouncing button preesses |
JMF | 1:c668e9604e63 | 9 | * |
JMF | 1:c668e9604e63 | 10 | * @author James Flynn |
JMF | 1:c668e9604e63 | 11 | * |
JMF | 1:c668e9604e63 | 12 | * @date 24-Aug-2018 |
JMF | 1:c668e9604e63 | 13 | */ |
JMF | 0:377a50b631cf | 14 | |
JMF | 0:377a50b631cf | 15 | #include "mbed.h" |
JMF | 0:377a50b631cf | 16 | |
JMF | 1:c668e9604e63 | 17 | #define BUTTON_DEBOUNCE 20 //specify the number of msec to debounce |
JMF | 0:377a50b631cf | 18 | |
JMF | 0:377a50b631cf | 19 | class Button { |
JMF | 0:377a50b631cf | 20 | protected: |
JMF | 0:377a50b631cf | 21 | InterruptIn user_button; |
JMF | 1:c668e9604e63 | 22 | void (*br_cb)(int); //button release callback |
JMF | 1:c668e9604e63 | 23 | void (*bp_cb)(void); //button press callback |
JMF | 0:377a50b631cf | 24 | |
JMF | 1:c668e9604e63 | 25 | Thread *button_thread; |
JMF | 0:377a50b631cf | 26 | void button_monitor_task(void); |
JMF | 0:377a50b631cf | 27 | EventQueue button_queue; |
JMF | 1:c668e9604e63 | 28 | uint64_t bp_time, bp_duration; //button press start time and button press duration |
JMF | 1:c668e9604e63 | 29 | int button_pressed; //counts the number of times the button has been pressed |
JMF | 0:377a50b631cf | 30 | |
JMF | 0:377a50b631cf | 31 | void button_press_handler(void) { |
JMF | 0:377a50b631cf | 32 | if( (rtos::Kernel::get_ms_count() - bp_time) < BUTTON_DEBOUNCE) |
JMF | 0:377a50b631cf | 33 | return; |
JMF | 0:377a50b631cf | 34 | bp_time = rtos::Kernel::get_ms_count(); |
JMF | 0:377a50b631cf | 35 | if( bp_cb ) |
JMF | 0:377a50b631cf | 36 | bp_cb(); |
JMF | 0:377a50b631cf | 37 | } |
JMF | 0:377a50b631cf | 38 | |
JMF | 0:377a50b631cf | 39 | void button_release_handler(void) { |
JMF | 0:377a50b631cf | 40 | uint64_t tmp = rtos::Kernel::get_ms_count() - bp_time; |
JMF | 0:377a50b631cf | 41 | if( tmp > BUTTON_DEBOUNCE ) { |
JMF | 0:377a50b631cf | 42 | bp_duration = tmp; |
JMF | 0:377a50b631cf | 43 | button_pressed++; |
JMF | 0:377a50b631cf | 44 | if( br_cb ) |
JMF | 0:377a50b631cf | 45 | br_cb(bp_duration); |
JMF | 0:377a50b631cf | 46 | } |
JMF | 0:377a50b631cf | 47 | } |
JMF | 0:377a50b631cf | 48 | |
JMF | 0:377a50b631cf | 49 | public: |
JMF | 0:377a50b631cf | 50 | enum State { ActiveHigh = 0, ActiveLow }; |
JMF | 0:377a50b631cf | 51 | |
JMF | 0:377a50b631cf | 52 | Button(PinName p, State s, void (*cb)(int)=NULL) : |
JMF | 0:377a50b631cf | 53 | user_button(p), |
JMF | 0:377a50b631cf | 54 | br_cb(cb), |
JMF | 0:377a50b631cf | 55 | bp_cb(NULL), |
JMF | 0:377a50b631cf | 56 | bp_time(0), |
JMF | 0:377a50b631cf | 57 | bp_duration(0), |
JMF | 0:377a50b631cf | 58 | button_pressed(0) |
JMF | 0:377a50b631cf | 59 | { |
JMF | 1:c668e9604e63 | 60 | // The user button is setup for the edge to generate an interrupt. |
JMF | 1:c668e9604e63 | 61 | // The release is caught an event queue callback |
JMF | 1:c668e9604e63 | 62 | button_thread=new Thread(osPriorityNormal,256,NULL,"button_thread"); |
JMF | 1:c668e9604e63 | 63 | button_thread->start(callback(&button_queue, &EventQueue::dispatch_forever)); |
JMF | 0:377a50b631cf | 64 | if( s == ActiveHigh ) { |
JMF | 0:377a50b631cf | 65 | user_button.rise( Callback<void()>(this, &Button::button_press_handler) ); |
JMF | 0:377a50b631cf | 66 | user_button.fall( button_queue.event( Callback<void()>(this, &Button::button_release_handler))); |
JMF | 0:377a50b631cf | 67 | } |
JMF | 0:377a50b631cf | 68 | else{ |
JMF | 0:377a50b631cf | 69 | user_button.fall( Callback<void()>(this, &Button::button_press_handler) ); |
JMF | 0:377a50b631cf | 70 | user_button.rise(button_queue.event(Callback<void()>(this, &Button::button_release_handler))); |
JMF | 0:377a50b631cf | 71 | } |
JMF | 0:377a50b631cf | 72 | } |
JMF | 0:377a50b631cf | 73 | |
JMF | 1:c668e9604e63 | 74 | ~Button() { |
JMF | 1:c668e9604e63 | 75 | button_thread->terminate(); |
JMF | 1:c668e9604e63 | 76 | delete button_thread; |
JMF | 1:c668e9604e63 | 77 | } |
JMF | 1:c668e9604e63 | 78 | |
JMF | 1:c668e9604e63 | 79 | // will return the number of times the button has been pressed (if it was pressed > 1 time before checked) |
JMF | 1:c668e9604e63 | 80 | // and returns the duration of the last button press in duration |
JMF | 0:377a50b631cf | 81 | int chkButton_press(int *duration) { |
JMF | 0:377a50b631cf | 82 | int bp = button_pressed; |
JMF | 0:377a50b631cf | 83 | |
JMF | 0:377a50b631cf | 84 | if( button_pressed ) { |
JMF | 0:377a50b631cf | 85 | *duration = bp_duration; |
JMF | 0:377a50b631cf | 86 | bp_duration = 0; |
JMF | 0:377a50b631cf | 87 | button_pressed = 0; |
JMF | 0:377a50b631cf | 88 | } |
JMF | 0:377a50b631cf | 89 | return bp; |
JMF | 0:377a50b631cf | 90 | } |
JMF | 0:377a50b631cf | 91 | |
JMF | 1:c668e9604e63 | 92 | //allows the user to set a callback for a button press in |
JMF | 0:377a50b631cf | 93 | void setButton_press_cb( void (*buttonpresscb)(void) ) { |
JMF | 0:377a50b631cf | 94 | bp_cb = buttonpresscb; |
JMF | 0:377a50b631cf | 95 | } |
JMF | 0:377a50b631cf | 96 | }; |
JMF | 1:c668e9604e63 | 97 |