diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e5aa0f..85100f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Develop +- Add detection of the first button state to be inactive before debouncing can even start + ## v1.1.0 - Add `lwbtn_keepalive_get_period` function diff --git a/examples/test.c b/examples/test.c index 6e72913..d160835 100644 --- a/examples/test.c +++ b/examples/test.c @@ -46,29 +46,26 @@ static volatile uint32_t time_current; static volatile uint8_t is_pressed = 0, is_click = 0; /* Set button state -> used for test purposes */ -#define BTN_STATE(_state_, _duration_) \ - { .state = (_state_), .duration = (_duration_) } +#define BTN_STATE(_state_, _duration_) {.state = (_state_), .duration = (_duration_)} -#define BTN_PRINT(text_to_print) \ - { .text = (text_to_print) } +#define BTN_PRINT(text_to_print) {.text = (text_to_print)} /* On-Press event */ -#define BTN_EVENT_ONPRESS() \ - { .evt = LWBTN_EVT_ONPRESS } +#define BTN_EVENT_ONPRESS() {.evt = LWBTN_EVT_ONPRESS} /* On-Release event */ -#define BTN_EVENT_ONRELEASE() \ - { .evt = LWBTN_EVT_ONRELEASE } +#define BTN_EVENT_ONRELEASE() {.evt = LWBTN_EVT_ONRELEASE} /* On-Click event */ -#define BTN_EVENT_ONCLICK(_conseq_clicks_) \ - { .evt = LWBTN_EVT_ONCLICK, .conseq_clicks = (_conseq_clicks_) } +#define BTN_EVENT_ONCLICK(_conseq_clicks_) {.evt = LWBTN_EVT_ONCLICK, .conseq_clicks = (_conseq_clicks_)} /* On-Click event */ -#define BTN_EVENT_KEEPALIVE(_keepalive_cnt_) \ - { .evt = LWBTN_EVT_KEEPALIVE, .keepalive_cnt = (_keepalive_cnt_) } +#define BTN_EVENT_KEEPALIVE(_keepalive_cnt_) {.evt = LWBTN_EVT_KEEPALIVE, .keepalive_cnt = (_keepalive_cnt_)} /* * Simulate click event */ static btn_test_time_t test_sequence[] = { + /* Button state must start with 0 */ + BTN_STATE(0, 1), + #if TEST1 /* * Test 1: diff --git a/lwbtn/src/lwbtn/lwbtn.c b/lwbtn/src/lwbtn/lwbtn.c index 5a61d74..82e60c4 100644 --- a/lwbtn/src/lwbtn/lwbtn.c +++ b/lwbtn/src/lwbtn/lwbtn.c @@ -42,6 +42,8 @@ #define LWBTN_FLAG_MANUAL_STATE \ ((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 */ #if LWBTN_CFG_TIME_DEBOUNCE_PRESS_DYNAMIC #define LWBTN_TIME_DEBOUNCE_PRESS_GET_MIN(btn) (uint32_t)((btn)->time_debounce) @@ -111,6 +113,20 @@ prv_process_btn(lwbtn_t* lwobj, lwbtn_btn_t* btn, uint32_t mstime) { /* Get button state */ new_state = LWBTN_BTN_GET_STATE(lwobj, btn); + /* + * First state must be "inactive" one, before + * any further button state is being processed. + * + * This is to prevent initial detected state on hardware errors, + * or when button is kept pressed after the system/lib reset + */ + if (!(btn->flags & LWBTN_FLAG_FIRST_INACTIVE_RCVD)) { + if (new_state) { + return; + } + btn->flags |= LWBTN_FLAG_FIRST_INACTIVE_RCVD; + } + /* Button state has just changed */ if (new_state != btn->old_state) { btn->time_state_change = mstime;