Implementation of a button class and test program

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Button.hpp Source File

Button.hpp

00001 /**
00002 * copyright (c) 2018, James Flynn
00003 * SPDX-License-Identifier: MIT
00004 */
00005 
00006 /**
00007 *   @file   button.hpp
00008 *   @brief  A small BUTTON class for detecting & debouncing button preesses
00009 *
00010 *   @author James Flynn
00011 *
00012 *   @date   24-Aug-2018
00013 */
00014 
00015 #include "mbed.h"
00016 
00017 #define BUTTON_DEBOUNCE           20     //specify the number of msec to debounce
00018 
00019 class Button {
00020     protected:
00021         InterruptIn user_button;
00022         void (*br_cb)(int);    //button release callback
00023         void (*bp_cb)(void);   //button press callback
00024 
00025         Thread      *button_thread;
00026         void        button_monitor_task(void);
00027         EventQueue  button_queue;
00028         uint64_t    bp_time, bp_duration;  //button press start time and button press duration
00029         int         button_pressed;        //counts the number of times the button has been pressed
00030 
00031         void button_press_handler(void) {
00032             if( (rtos::Kernel::get_ms_count() - bp_time) < BUTTON_DEBOUNCE)
00033                 return;
00034             bp_time = rtos::Kernel::get_ms_count();
00035             if( bp_cb )
00036                 bp_cb();
00037         }
00038 
00039         void button_release_handler(void) {
00040             uint64_t tmp = rtos::Kernel::get_ms_count() - bp_time;
00041             if( tmp > BUTTON_DEBOUNCE ) {
00042                 bp_duration = tmp;
00043                 button_pressed++;
00044                 if( br_cb )
00045                   br_cb(bp_duration);
00046                 }
00047         }
00048 
00049     public:
00050         enum State { ActiveHigh = 0, ActiveLow };
00051 
00052         Button(PinName p, State s, void (*cb)(int)=NULL) : 
00053             user_button(p),
00054             br_cb(cb),
00055             bp_cb(NULL),
00056             bp_time(0),
00057             bp_duration(0),
00058             button_pressed(0)
00059             {
00060             // The user button is setup for the edge to generate an interrupt. 
00061             // The release is caught an event queue callback
00062             button_thread=new Thread(osPriorityNormal,256,NULL,"button_thread");
00063             button_thread->start(callback(&button_queue, &EventQueue::dispatch_forever));
00064             if( s == ActiveHigh ) {
00065                 user_button.rise( Callback<void()>(this, &Button::button_press_handler) ); 
00066                 user_button.fall( button_queue.event( Callback<void()>(this, &Button::button_release_handler)));
00067                 }
00068             else{
00069                 user_button.fall( Callback<void()>(this, &Button::button_press_handler) );
00070                 user_button.rise(button_queue.event(Callback<void()>(this, &Button::button_release_handler)));
00071                 }
00072             }
00073 
00074         ~Button() {
00075             button_thread->terminate();
00076             delete button_thread;
00077             }
00078 
00079         // will return the number of times the button has been pressed (if it was pressed > 1 time before checked)
00080         // and returns the duration of the last button press in duration
00081         int chkButton_press(int *duration) {
00082             int bp = button_pressed;
00083         
00084             if( button_pressed ) {
00085                 *duration = bp_duration;
00086                 bp_duration = 0;
00087                 button_pressed = 0;
00088                 }
00089             return bp;
00090             }
00091             
00092         //allows the user to set a callback for a button press in
00093         void setButton_press_cb( void (*buttonpresscb)(void) ) {
00094             bp_cb = buttonpresscb;
00095             }
00096 };
00097