From 970f3553c40a49cc7364b43fed68412b8b44c9fb Mon Sep 17 00:00:00 2001 From: Federico Amedeo Izzo Date: Mon, 14 Dec 2020 15:06:11 +0100 Subject: [PATCH] kbd_task refactoring, add long-press detection logic --- openrtx/include/event.h | 4 +-- openrtx/include/interfaces/keyboard.h | 33 ++++++++++++++++-- openrtx/src/threads.c | 50 ++++++++++++++++++++++----- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/openrtx/include/event.h b/openrtx/include/event.h index cdfa76c7..b681d14d 100644 --- a/openrtx/include/event.h +++ b/openrtx/include/event.h @@ -44,8 +44,8 @@ typedef union { struct { - uint32_t type : 3, - payload : 29; + uint32_t type : 2, + payload : 30; }; void *value; diff --git a/openrtx/include/interfaces/keyboard.h b/openrtx/include/interfaces/keyboard.h index f00ccbd0..6d145f18 100644 --- a/openrtx/include/interfaces/keyboard.h +++ b/openrtx/include/interfaces/keyboard.h @@ -27,7 +27,7 @@ * The following enum provides a set of flags to be used to check which buttons * are pressed by bit-masking the uint32_t value returned by kbd_getKeys(). */ -enum keys +enum key { KEY_0 = (1 << 0), /* Keypad digit "0" */ KEY_1 = (1 << 1), /* Keypad digit "1" */ @@ -61,9 +61,36 @@ enum keys }; /** - * The status of the keyboard keys is provided as an uint32_t. + * Number of supported keys + */ +static const uint8_t kbd_num_keys = 29; + +/** + * Time interval in ticks after which a keypress is considered a long-press + */ +static const uint8_t kbd_long_interval = 29; + +/** + * Structure that represents a keyboard event payload + * The maximum size of an event payload is 30 bits + * For a keyboard event we use 1 bit to signal a short or long press + * And the remaining 29 bits to communicate currently pressed keys. + */ +typedef union +{ + struct + { + uint32_t long_press : 1, + keys : 29; + }; + + uint32_t value; +} kbd_msg_t; + +/** + * We encode the status of all the keys with a uint32_t value * To check which buttons are pressed one can bit-mask the - * uint32_t value keyboard_t with one of the values defined in keys. + * keys value with one of the enum values defined in key. * Example: * keyboard_t keys = kbd_getKeys(); * if(keys & KEY_ENTER) do_stuff(); diff --git a/openrtx/src/threads.c b/openrtx/src/threads.c index 7a4a2458..6b6e6bad 100644 --- a/openrtx/src/threads.c +++ b/openrtx/src/threads.c @@ -128,20 +128,54 @@ static void kbd_task(void *arg) // Initialize keyboard driver kbd_init(); + // Allocate timestamp array + OS_TICK key_ts[kbd_num_keys]; + OS_TICK now; + + // Variable for saving previous and current keyboard status + keyboard_t prev_keys = 0; + keyboard_t keys = 0; + while(1) { - keyboard_t keys = kbd_getKeys(); - // Check if some key is pressed - if(keys != 0) + // Get currently pressed keys + keys = kbd_getKeys(); + // Compare with previous keyboard status + if(keys != prev_keys) { + bool long_press = false; + bool send_event = false; + now = OSTimeGet(&os_err); + for(uint8_t k=0; k < kbd_num_keys; k++) + { + // Key has been pressed + if(!(prev_keys & k) && (keys & k)) + { + // Save timestamp + key_ts[k] = now; + } + // Key has been released + else if((prev_keys & k) && !(keys & k)) + { + send_event = true; + // Check timestamp + if((now - key_ts[k]) >= kbd_long_interval) + long_press = true; + } + } + if(send_event) + { + kbd_msg_t msg; + msg.long_press = long_press; + msg.keys = keys; // Send event_t as void * message to use with OSQPost - event_t kbd_msg; - kbd_msg.type = EVENT_KBD; - kbd_msg.payload = keys; - + event_t event; + event.type = EVENT_KBD; + event.payload = msg.value; // Send keyboard status in queue - OSQPost(&ui_queue, (void *)kbd_msg.value, sizeof(event_t), + OSQPost(&ui_queue, (void *)event.value, sizeof(event_t), OS_OPT_POST_FIFO + OS_OPT_POST_NO_SCHED, &os_err); + } } // Read keyboard state at 5Hz OSTimeDlyHMSM(0u, 0u, 0u, 200u, OS_OPT_TIME_HMSM_STRICT, &os_err);