diff --git a/README.md b/README.md index 562872b..4fa063f 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ int main() } } -void BTN1_SINGLE_CLICK_Handler() +void BTN1_PRESSED_Handler() { //do something.. } diff --git a/button.c b/button.c index 380f4e5..5bc79db 100644 --- a/button.c +++ b/button.c @@ -2,14 +2,15 @@ * Copyright (c) 2016 Zibin Zheng * All rights reserved */ - + #include "button.h" #define TICKS_INTERVAL 5 //ms +#define EVENT_CB(ev) if(handle->cb[ev]){handle->cb[ev](handle)} //According to your need to modify the constants. const uint8_t kDebounceTicks = 3; //MAX 8 -const uint16_t kClickTicks = (400/TICKS_INTERVAL); +const uint16_t kShortTicks = (350/TICKS_INTERVAL); const uint16_t kLongTicks = (1000/TICKS_INTERVAL); //button handle list head. @@ -37,19 +38,19 @@ void button_init(struct Button* handle, uint8_t(*pin_level)(), uint8_t active_le * @param cb: callback function. * @retval None */ -void button_attach(struct Button* handle, BtnEvent event, CallBackFunc cb) +void button_attach(struct Button* handle, PressEvent event, CallBackFunc cb) { handle->cb[event] = cb; } /** - * @brief Inquire the button is pressed. + * @brief Inquire the button event happen. * @param handle: the button handle strcut. - * @retval 0 not press, 1 pressed. + * @retval button event. */ -int button_is_pressed(struct Button* handle) +PressEvent get_button_event(const struct Button* handle) { - return ((handle->button_level == handle->active_level) ? 1:0); + return (handle->event); } /** @@ -79,55 +80,80 @@ void button_handler(struct Button* handle) /*-----------------State machine-------------------*/ switch (handle->state) { case 0: - if(handle->button_level == handle->active_level) { //start press - if(handle->cb[CLICK]) handle->cb[CLICK](); - + if(handle->button_level == handle->active_level) { //start press down + handle->event = (uint8_t)PRESS_DOWN; + EVENT_CB(PRESS_DOWN); handle->ticks = 0; + handle->repeat = 1; handle->state = 1; } break; case 1: - if(handle->button_level != handle->active_level) { //released + if(handle->button_level != handle->active_level) { //released press up + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP); + handle->ticks = 0; handle->state = 2; } else if(handle->ticks > kLongTicks) { - if(handle->cb[LONG_RRESS_START]) handle->cb[LONG_RRESS_START](); - + handle->event = (uint8_t)LONG_RRESS_START; + EVENT_CB(LONG_RRESS_START); handle->state = 5; } break; case 2: - if(handle->ticks > kClickTicks) { //released - //press event - if(handle->cb[PRESSED]) handle->cb[PRESSED](); //press event - - handle->state = 0; //reset - - } else if(handle->button_level == handle->active_level) { //press again - if(handle->cb[CLICK]) handle->cb[CLICK](); + if(handle->button_level == handle->active_level) { //press down again + handle->event = (uint8_t)PRESS_DOWN; + EVENT_CB(PRESS_DOWN); + handle->repeat++; + if(handle->repeat == 2) { + handle->event = (uint8_t)DOUBLE_CLICK; + EVENT_CB(DOUBLE_CLICK); // repeat hit + } else { + handle->event = (uint8_t)PRESS_REPEAT; + } + + EVENT_CB(PRESS_REPEAT); // repeat hit + handle->ticks = 0; handle->state = 3; + } else if(handle->ticks > kShortTicks) { + if(handle->repeat == 1) { + handle->event = (uint8_t)SINGLE_CLICK; + EVENT_CB(SINGLE_CLICK); + } + handle->state = 0; + handle->event = (uint8_t)NONE_PRESS; } - break; - - case 3: //repeat press pressing - if(handle->button_level != handle->active_level) { //double releasd - //double click event - if(handle->cb[DOUBLE_CLICK]) handle->cb[DOUBLE_CLICK](); + break; - handle->state = 0; + case 3: + if(handle->button_level != handle->active_level) { //released press up + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP); + if(handle->ticks < kShortTicks) { + handle->ticks = 0; + handle->state = 2; //repeat press + } else { + handle->state = 0; + handle->event = (uint8_t)NONE_PRESS; + } } + break; case 5: if(handle->button_level == handle->active_level) { //continue hold trigger - if(handle->cb[LONG_PRESS_HOLD]) handle->cb[LONG_PRESS_HOLD](); + handle->event = (uint8_t)LONG_PRESS_HOLD; + EVENT_CB(LONG_PRESS_HOLD); } else { //releasd - if(handle->cb[LONG_PRESS_STOP]) handle->cb[LONG_PRESS_STOP](); + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP) handle->state = 0; //reset + handle->event = (uint8_t)NONE_PRESS; } break; } diff --git a/button.h b/button.h index 321efcb..5bfb78d 100644 --- a/button.h +++ b/button.h @@ -9,26 +9,30 @@ #include "stdint.h" #include "string.h" -typedef void (*CallBackFunc)(void); +typedef void (*BtnCallback)(const struct Button* btn); typedef enum { - CLICK = 0, - PRESSED, + PRESS_DOWN = 0, + PRESS_UP, + PRESS_REPEAT, + SINGLE_CLICK, DOUBLE_CLICK, LONG_RRESS_START, LONG_PRESS_HOLD, - LONG_PRESS_STOP, - number_of_event -}BtnEvent; + number_of_event, + NONE_PRESS +}PressEvent; struct Button { uint16_t ticks; + uint8_t repeat : 4; + uint8_t event : 4; uint8_t state : 3; uint8_t debounce_cnt : 3; uint8_t active_level : 1; uint8_t button_level : 1; uint8_t (*hal_button_Level)(void); - CallBackFunc cb[number_of_event]; + BtnCallback cb[number_of_event]; struct Button* next; }; @@ -37,8 +41,8 @@ extern "C" { #endif void button_init(struct Button* handle, uint8_t(*pin_level)(), uint8_t active_level); -void button_attach(struct Button* handle, BtnEvent event, CallBackFunc cb); -int button_is_pressed(struct Button* handle); +void button_attach(struct Button* handle, PressEvent event, CallBackFunc cb); +PressEvent get_button_event(const struct Button* handle); int button_start(struct Button* btn); void button_stop(struct Button* btn); void button_ticks(void);