diff --git a/openrtx/include/core/input.h b/openrtx/include/core/input.h index 0474544b..edfb7619 100644 --- a/openrtx/include/core/input.h +++ b/openrtx/include/core/input.h @@ -20,12 +20,49 @@ #ifndef INPUT_H #define INPUT_H +#include #include #include +/** + * Time interval in milliseconds after which a keypress is considered a long-press + */ +static const uint16_t input_longPressTimeout = 700; + +/** + * 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, + _padding : 2; + }; + + uint32_t value; +} +kbd_msg_t; + + +/** + * Scan all the keyboard buttons to detect possible keypresses filling a + * keyboard event data structure. The function returns true if a keyboard event + * has been detected. + * + * @param msg: keyboard event message to be filled. + * @return true if a keyboard event has been detected, false otherwise. + */ +bool input_scanKeyboard(kbd_msg_t *msg); + /** * This function returns true if at least one number is pressed on the * keyboard. + * * @param msg: the keyboard queue message * @return true if at least a number is pressed on the keyboard */ @@ -34,6 +71,7 @@ bool input_isNumberPressed(kbd_msg_t msg); /** * This function returns the smallest number that is pressed on the keyboard, * 0 if none is pressed. + * * @param msg: the keyboard queue message * @return the smalled pressed number on the keyboard */ diff --git a/openrtx/include/interfaces/keyboard.h b/openrtx/include/interfaces/keyboard.h index 167a7666..8112f22d 100644 --- a/openrtx/include/interfaces/keyboard.h +++ b/openrtx/include/interfaces/keyboard.h @@ -30,70 +30,47 @@ */ enum key { - KEY_0 = (1 << 0), /* Keypad digit "0" */ - KEY_1 = (1 << 1), /* Keypad digit "1" */ - KEY_2 = (1 << 2), /* Keypad digit "2" */ - KEY_3 = (1 << 3), /* Keypad digit "3" */ - KEY_4 = (1 << 4), /* Keypad digit "4" */ - KEY_5 = (1 << 5), /* Keypad digit "5" */ - KEY_6 = (1 << 6), /* Keypad digit "6" */ - KEY_7 = (1 << 7), /* Keypad digit "7" */ - KEY_8 = (1 << 8), /* Keypad digit "8" */ - KEY_9 = (1 << 9), /* Keypad digit "9" */ - KEY_STAR = (1 << 10), /* Keypad digit "*" */ - KEY_HASH = (1 << 11), /* Keypad digit "#" */ - KEY_ENTER = (1 << 12), /* Keypad green button/enter */ - KEY_ESC = (1 << 13), /* Keypad red button/esc */ - KEY_UP = (1 << 14), /* Keypad upward arrow */ - KEY_DOWN = (1 << 15), /* Keypad downward arrow */ - KEY_LEFT = (1 << 16), /* Keypad leftward arrow */ - KEY_RIGHT = (1 << 17), /* Keypad rightward arrow */ - KEY_MONI = (1 << 18), /* Monitor button */ - KEY_F1 = (1 << 19), /* Function button */ - KEY_F2 = (1 << 20), /* Function button (device specific) */ - KEY_F3 = (1 << 21), /* Function button (device specific) */ - KEY_F4 = (1 << 22), /* Function button (device specific) */ - KEY_F5 = (1 << 23), /* Function button (device specific) */ - KEY_F6 = (1 << 24), /* Function button (device specific) */ - KEY_F7 = (1 << 25), /* Function button (device specific) */ - KEY_F8 = (1 << 26), /* Function button (device specific) */ - KNOB_LEFT = (1 << 27), /* Knob rotated counter clockwise */ - KNOB_RIGHT = (1 << 28), /* Knob rotated clockwise */ + KEY_0 = (1 << 0), /* Keypad digit "0" */ + KEY_1 = (1 << 1), /* Keypad digit "1" */ + KEY_2 = (1 << 2), /* Keypad digit "2" */ + KEY_3 = (1 << 3), /* Keypad digit "3" */ + KEY_4 = (1 << 4), /* Keypad digit "4" */ + KEY_5 = (1 << 5), /* Keypad digit "5" */ + KEY_6 = (1 << 6), /* Keypad digit "6" */ + KEY_7 = (1 << 7), /* Keypad digit "7" */ + KEY_8 = (1 << 8), /* Keypad digit "8" */ + KEY_9 = (1 << 9), /* Keypad digit "9" */ + KEY_STAR = (1 << 10), /* Keypad digit "*" */ + KEY_HASH = (1 << 11), /* Keypad digit "#" */ + KEY_ENTER = (1 << 12), /* Keypad green button/enter */ + KEY_ESC = (1 << 13), /* Keypad red button/esc */ + KEY_UP = (1 << 14), /* Keypad upward arrow */ + KEY_DOWN = (1 << 15), /* Keypad downward arrow */ + KEY_LEFT = (1 << 16), /* Keypad leftward arrow */ + KEY_RIGHT = (1 << 17), /* Keypad rightward arrow */ + KEY_MONI = (1 << 18), /* Monitor button */ + KEY_F1 = (1 << 19), /* Function button */ + KEY_F2 = (1 << 20), /* Function button (device specific) */ + KEY_F3 = (1 << 21), /* Function button (device specific) */ + KEY_F4 = (1 << 22), /* Function button (device specific) */ + KEY_F5 = (1 << 23), /* Function button (device specific) */ + KEY_F6 = (1 << 24), /* Function button (device specific) */ + KEY_F7 = (1 << 25), /* Function button (device specific) */ + KEY_F8 = (1 << 26), /* Function button (device specific) */ + KNOB_LEFT = (1 << 27), /* Knob rotated counter clockwise */ + KNOB_RIGHT = (1 << 28), /* Knob rotated clockwise */ }; /** * 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 uint16_t kbd_long_interval = TICK_FREQ * 0.7; +#define KBD_NUM_KEYS 29 /** * Mask for the numeric keys in a key map * Numeric keys: bit0->bit11 = 0xFFF */ -static const uint32_t kbd_num_mask = 0xFFF; - -/** - * 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, - _padding : 2; - }; - - uint32_t value; -} kbd_msg_t; +#define KBD_NUM_MASK 0x0FFF /** * We encode the status of all the keys with a uint32_t value diff --git a/openrtx/src/core/input.c b/openrtx/src/core/input.c index 50b93cc7..4eba314f 100644 --- a/openrtx/src/core/input.c +++ b/openrtx/src/core/input.c @@ -17,20 +17,80 @@ * along with this program; if not, see * ***************************************************************************/ -#include +#include #include #include #include +static long long keyTs[KBD_NUM_KEYS]; // Timestamp of each keypress +static uint32_t longPressSent; // Flags to manage long-press events +static keyboard_t prevKeys = 0; // Previous keyboard status + +bool input_scanKeyboard(kbd_msg_t *msg) +{ + msg->value = 0; + bool kbd_event = false; + + keyboard_t keys = kbd_getKeys(); + long long now = getTick(); + + // The key status has changed + if(keys != prevKeys) + { + // Find newly pressed keys + keyboard_t newKeys = (keys ^ prevKeys) & keys; + + // Save timestamp + for(uint8_t k = 0; k < KBD_NUM_KEYS; k++) + { + keyboard_t mask = 1 << k; + if((newKeys & mask) != 0) + { + keyTs[k] = now; + longPressSent &= ~mask; + } + } + + // New keyboard event + msg->keys = keys; + kbd_event = true; + } + // Some key is kept pressed + else if(keys != 0) + { + // Check for saved timestamp to trigger long-presses + for(uint8_t k = 0; k < KBD_NUM_KEYS; k++) + { + keyboard_t mask = 1 << k; + + // The key is pressed and its long-press timer is over + if(((keys & mask) != 0) && + ((longPressSent & mask) == 0) && + ((now - keyTs[k]) >= input_longPressTimeout)) + { + msg->long_press = 1; + msg->keys = keys; + kbd_event = true; + longPressSent |= mask; + } + } + } + + prevKeys = keys; + + return kbd_event; +} + bool input_isNumberPressed(kbd_msg_t msg) { - return msg.keys & kbd_num_mask; + return msg.keys & KBD_NUM_MASK; } uint8_t input_getPressedNumber(kbd_msg_t msg) { - uint32_t masked_input = msg.keys & kbd_num_mask; + uint32_t masked_input = msg.keys & KBD_NUM_MASK; if (masked_input == 0) return 0; - return __builtin_ctz(msg.keys & kbd_num_mask); + + return __builtin_ctz(msg.keys & KBD_NUM_MASK); } diff --git a/openrtx/src/core/threads.c b/openrtx/src/core/threads.c index c72e9a78..e8ea9e3f 100644 --- a/openrtx/src/core/threads.c +++ b/openrtx/src/core/threads.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #ifdef HAS_GPS #include #include @@ -144,69 +144,16 @@ void *kbd_task(void *arg) // Initialize keyboard driver kbd_init(); - // Allocate timestamp array - long long key_ts[kbd_num_keys]; - long long now; - - // Allocate bool array to send only one long-press event - bool long_press_sent[kbd_num_keys]; - - // Variable for saving previous and current keyboard status - keyboard_t prev_keys = 0; - keyboard_t keys = 0; - bool long_press = false; - bool send_event = false; - while(1) { - // Reset flags and get current time - long_press = false; - send_event = false; - // Lock display mutex and read keyboard status + kbd_msg_t msg; + pthread_mutex_lock(&display_mutex); - keys = kbd_getKeys(); + bool event = input_scanKeyboard(&msg); pthread_mutex_unlock(&display_mutex); - now = getTick(); - // The key status has changed - if(keys != prev_keys) + + if(event) { - for(uint8_t k=0; k < kbd_num_keys; k++) - { - // Key has been pressed - if(!(prev_keys & (1 << k)) && (keys & (1 << k))) - { - // Save timestamp - key_ts[k] = now; - send_event = true; - long_press_sent[k] = false; - } - // Key has been released - else if((prev_keys & (1 << k)) && !(keys & (1 << k))) - { - send_event = true; - } - } - } - // Some key is kept pressed - else if(keys != 0) - { - // Check for saved timestamp to trigger long-presses - for(uint8_t k=0; k < kbd_num_keys; k++) - { - // The key is pressed and its long-press timer is over - if(keys & (1 << k) && !long_press_sent[k] && (now - key_ts[k]) >= kbd_long_interval) - { - long_press = true; - send_event = true; - long_press_sent[k] = 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 event; event.type = EVENT_KBD; @@ -214,8 +161,6 @@ void *kbd_task(void *arg) // Send keyboard status in queue (void) queue_post(&ui_queue, event.value); } - // Save current keyboard state as previous - prev_keys = keys; // Read keyboard state at 40Hz sleepFor(0u, 25u); diff --git a/openrtx/src/ui/ui.c b/openrtx/src/ui/ui.c index 4eb4f858..51f4ebe6 100644 --- a/openrtx/src/ui/ui.c +++ b/openrtx/src/ui/ui.c @@ -886,7 +886,7 @@ void _ui_textInputKeypad(char *buf, uint8_t max_len, kbd_msg_t msg, bool callsig if(ui_state.last_keypress != 0) { // Same key pressed and timeout not expired: cycle over chars of current key - if((ui_state.input_number == num_key) && ((now - ui_state.last_keypress) < kbd_long_interval)) + if((ui_state.input_number == num_key) && ((now - ui_state.last_keypress) < input_longPressTimeout)) { ui_state.input_set = (ui_state.input_set + 1) % num_symbols; }