diff --git a/examples/test.c b/examples/test.c index 2c385f5..4a57756 100644 --- a/examples/test.c +++ b/examples/test.c @@ -1,5 +1,6 @@ #include #include +#include "lwbtn/lwbtn.h" #include "test.h" #if defined(WIN32) #include "windows.h" diff --git a/lwbtn/src/include/lwbtn/lwbtn.h b/lwbtn/src/include/lwbtn/lwbtn.h index 3049f44..1a1718f 100644 --- a/lwbtn/src/include/lwbtn/lwbtn.h +++ b/lwbtn/src/include/lwbtn/lwbtn.h @@ -112,7 +112,7 @@ typedef struct lwbtn_btn { uint8_t curr_state; /*!< Current button state to be processed. It is used to keep track when application manually sets the button state */ #endif /* LWBTN_CFG_GET_STATE_MODE != LWBTN_GET_STATE_MODE_CALLBACK || __DOXYGEN__ */ - uint8_t old_state; /*!< Old button state - `1` means active, `0` means inactive */ + uint8_t last_state; /*!< Last button state - `1` means active, `0` means inactive */ lwbtn_time_t time_change; /*!< Time in ms when button state got changed last time after valid debounce */ lwbtn_time_t time_state_change; /*!< Time in ms when button state got changed last time */ @@ -174,6 +174,7 @@ uint8_t lwbtn_process_ex(lwbtn_t* lwobj, lwbtn_time_t mstime); uint8_t lwbtn_process_btn_ex(lwbtn_t* lwobj, lwbtn_btn_t* btn, lwbtn_time_t mstime); uint8_t lwbtn_set_btn_state(lwbtn_btn_t* btn, uint8_t state); uint8_t lwbtn_is_btn_active(const lwbtn_btn_t* btn); +uint8_t lwbtn_reset(lwbtn_t* lwobj, lwbtn_btn_t* btn); /** * \brief Initialize LwBTN library with buttons on default button group diff --git a/lwbtn/src/lwbtn/lwbtn.c b/lwbtn/src/lwbtn/lwbtn.c index 85f96dd..ee5b648 100644 --- a/lwbtn/src/lwbtn/lwbtn.c +++ b/lwbtn/src/lwbtn/lwbtn.c @@ -43,7 +43,8 @@ ((uint16_t)0x0002) /*!< Flag indicates that user wants to manually set button state. Do not call "get_state" function */ #define LWBTN_FLAG_FIRST_INACTIVE_RCVD \ - ((uint16_t)0x0004) /*!< We are waiting for first inactive state before we continue further */ + ((uint16_t)0x0004) /*!< We are waiting for first inactive state before we continue further */ +#define LWBTN_FLAG_RESET ((uint16_t)0x0008) /*!< Reset called on the button */ #if LWBTN_CFG_TIME_DEBOUNCE_PRESS_DYNAMIC #define LWBTN_TIME_DEBOUNCE_PRESS_GET_MIN(btn) ((lwbtn_time_t)((btn)->time_debounce)) @@ -122,16 +123,36 @@ prv_process_btn(lwbtn_t* lwobj, lwbtn_btn_t* btn, lwbtn_time_t mstime) { * * When user uses manual state set (no callback system), * it is up to user to first call "set state" function and set state to inactive + * + * This features is also used for "button reset" */ if (!(btn->flags & LWBTN_FLAG_FIRST_INACTIVE_RCVD)) { if (new_state) { return; } - btn->flags |= LWBTN_FLAG_FIRST_INACTIVE_RCVD; + + /* Reset all states */ + btn->last_state = 0; + btn->flags = LWBTN_FLAG_FIRST_INACTIVE_RCVD; } +#if 0 + /* + * When the button is pressed, user can manually + * reset the button + */ + if ((btn->flags) & LWBTN_FLAG_RESET) { + btn->last_state = 0; /* Disable the state */ + btn->flags &= LWBTN_FLAG_RESET; /* Keep reset, delete others */ + if (new_state) { + return; + } + btn->flags &= ~LWBTN_FLAG_RESET; /* Start over */ + } +#endif + /* Button state has just changed */ - if (new_state != btn->old_state) { + if (new_state != btn->last_state) { btn->time_state_change = mstime; } @@ -295,7 +316,7 @@ prv_process_btn(lwbtn_t* lwobj, lwbtn_btn_t* btn, lwbtn_time_t mstime) { } } - btn->old_state = new_state; + btn->last_state = new_state; } /** @@ -430,3 +451,39 @@ uint8_t lwbtn_is_btn_active(const lwbtn_btn_t* btn) { return btn != NULL && (btn->flags & LWBTN_FLAG_ONPRESS_SENT); } + +/** + * \brief Reset button[s] state to default + * + * When reset is called, if button is pressed (active) + * no further events will be called up until we receive + * the new valid press action. + * + * A typical use case would be when application needs to react + * on a long press (several keep alive events). + * A reaction may change the eg. screen view where new screen (menu screen) + * performs some other activity on button hold event. + * + * Resetting the button state before switching the internal application state, + * forces the user to re-press the button to restart the action for the new + * hold activity. + * + * \note If button is reset during active time, there will be no further events + * for this button sent to the application, up until a new valid on-press is detected + * + * \param lwobj: Object to reset buttons. Set to non-NULL to reset + * all buttons in an object + * \param btn: Button object to reset. Optional parameter. + * When non-NULL, button is reset + * \return `1` on success, `0` otherwise + */ +uint8_t +lwbtn_reset(lwbtn_t* lwobj, lwbtn_btn_t* btn) { + for (size_t idx = 0; idx < (lwobj != NULL ? lwobj->btns_cnt : 0); ++idx) { + lwobj->btns[idx].flags &= ~LWBTN_FLAG_FIRST_INACTIVE_RCVD; + } + if (btn != NULL) { + btn->flags &= ~LWBTN_FLAG_FIRST_INACTIVE_RCVD; + } + return 1; +}