keyboard: finalize getkey()

This commit is contained in:
lephe 2019-07-16 18:23:21 -04:00
parent 2d7a6f154e
commit 8dbdd32adb
3 changed files with 38 additions and 30 deletions

View file

@ -93,12 +93,12 @@ enum
/* pollevent() - poll the next keyboard event /* pollevent() - poll the next keyboard event
This function returns the next yet-unpolled event from the keyboard buffer. This function returns the next yet-unpolled event from the keyboard buffer.
If no event is available, it returns a dummy event with type = KEYEV_NONE. If no event is available, it returns a dummy event with type = KEYEV_NONE.
This event has always mod = 0, shift = 0, alpha = 0. */ This function always returns events with mod=0. */
key_event_t pollevent(void); key_event_t pollevent(void);
/* waitevent() - wait for the next keyboard event /* waitevent() - wait for the next keyboard event
This function works as pollevent() but waits if no event is available. When This function works as pollevent() but waits if no event is available. When
timeout = NULL, it waits indefinitely. Otherwise, it waits until *timeout timeout=NULL, it waits indefinitely. Otherwise, it waits until *timeout
becomes non-zero. It is particularly suitable to set *timeout to 1 using a becomes non-zero. It is particularly suitable to set *timeout to 1 using a
timer with [timer_timeout] as callback. See <gint/timer.h>. */ timer with [timer_timeout] as callback. See <gint/timer.h>. */
key_event_t waitevent(volatile int *timeout); key_event_t waitevent(volatile int *timeout);
@ -123,18 +123,18 @@ key_event_t getkey(void);
/* The following are the option bits for getkey_opt(). */ /* The following are the option bits for getkey_opt(). */
enum { enum {
/* Enable modifiers keys */ /* Enable modifiers keys */
GETKEY_MOD_SHIFT = 0x01, GETKEY_MOD_SHIFT = 0x01,
GETKEY_MOD_ALPHA = 0x02, GETKEY_MOD_ALPHA = 0x02,
/* SHIFT + OPTN toggles backlight (requires GETKEY_MOD_SHIFT) */ /* SHIFT + OPTN toggles backlight (requires GETKEY_MOD_SHIFT) */
GETKEY_BACKLIGHT = 0x04, GETKEY_BACKLIGHT = 0x04,
/* MENU triggers a task switch and displays the main menu */ /* MENU triggers a task switch and displays the main menu */
GETKEY_MENU = 0x08, GETKEY_MENU = 0x08,
/* Repeat arrow keys, or even all keys */ /* Repeat arrow keys, or even all keys */
GETKEY_REP_ARROWS = 0x10, GETKEY_REP_ARROWS = 0x10,
GETKEY_REP_ALL = 0x20, GETKEY_REP_ALL = 0x20,
/* Default settings of getkey() */ /* Default settings of getkey() */
GETKEY_DEFAULT = 0x1f, GETKEY_DEFAULT = 0x1f,
}; };
/* getkey_opt() - enhanced getkey() /* getkey_opt() - enhanced getkey()
@ -148,7 +148,7 @@ enum {
pointer [timeout]. If it's NULL, getkey_opt() waits indefinitely. Otherwise, pointer [timeout]. If it's NULL, getkey_opt() waits indefinitely. Otherwise,
it waits until *timeout becomes non-zero. It's up to you to change the it waits until *timeout becomes non-zero. It's up to you to change the
value whenever you want to interrupt the call; using a timer with value whenever you want to interrupt the call; using a timer with
[timer_timeout] as callback is suitable. [timer_timeout] as callback is suitable. See <gint/timer.h>.
@options An or-combination of values from the GETKEY_* enumeration @options An or-combination of values from the GETKEY_* enumeration
@timeout Optional pointer to a timeout value @timeout Optional pointer to a timeout value
@ -166,8 +166,8 @@ key_event_t getkey_opt(int options, volatile int *timeout);
rounded to the closest feasible delays to ensure that repetitions are rounded to the closest feasible delays to ensure that repetitions are
perfectly regular, rather than approximating the requested frequency. perfectly regular, rather than approximating the requested frequency.
The system default is (625 ms, 25 ms). With the 128 Hz setting, this default The system default is (500 ms, 125 ms). With the 128 Hz setting, this
will be approximated at (625 ms, 23.4375 ms). default is reached exactly without approximation.
@first Delay between key press and first repeat (no more than one hour) @first Delay between key press and first repeat (no more than one hour)
@next Delay between subsequent repeats (no more than one hour) */ @next Delay between subsequent repeats (no more than one hour) */

View file

@ -9,13 +9,10 @@
#include <gint/drivers/t6k11.h> #include <gint/drivers/t6k11.h>
#endif #endif
/* Atom for counting time in getkey() is 32768 Hz, 1ull << ATOM is a second */ /* Delay between a key press and the first repeat, in scan intervals */
#define ATOM 15 static int rep_first = 64;
/* Delay between subsequent repeats, in scan intervals */
/* Delay between a key press and the first repeat, in 1/32768 seconds */ static int rep_next = 16;
static uint64_t rep_first;
/* Delay between subsequent repeats, in 1/32768 seconds */
static uint64_t rep_next;
/* getkey() - wait for a pressed key */ /* getkey() - wait for a pressed key */
key_event_t getkey(void) key_event_t getkey(void)
@ -30,11 +27,11 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
int shift = 0, alpha = 0, key = 0; int shift = 0, alpha = 0, key = 0;
/* Last pressed key (only this key may be repeated) */ /* Last pressed key (only this key may be repeated) */
int rep_key = 0; static int rep_key = 0;
/* Number of repeats already emitted */ /* Number of repeats already emitted */
int rep_count = 0; static int rep_count = 0;
/* Time elapsed since last repeat emission (in atoms) */ /* Scan intervals elapsed since last repeat */
uint64_t rep_time = 0; static int rep_time = 0;
while(1) switch((ev = waitevent(timeout)).type) while(1) switch((ev = waitevent(timeout)).type)
{ {
@ -89,10 +86,16 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
/* Return new events when a key is held (maybe) */ /* Return new events when a key is held (maybe) */
case KEYEV_HOLD: case KEYEV_HOLD:
if(ev.key != rep_key) break; if(ev.key != rep_key) break;
rep_time += (1ull << ATOM) / KEYBOARD_SCAN_FREQUENCY;
/* Check that this key can be repeated */
int arrow = (rep_key == KEY_LEFT || rep_key == KEY_RIGHT ||
rep_key == KEY_UP || rep_key == KEY_DOWN);
if(!(opt & GETKEY_REP_ALL) && !(opt & GETKEY_REP_ARROWS &&
arrow)) break;
/* If the key is key pressed long enough, create a new event */ /* If the key is key pressed long enough, create a new event */
if(rep_time < (rep_count ? rep_next : rep_first)) break; if(++rep_time < (rep_count ? rep_next : rep_first)) break;
ev.mod = 1; ev.mod = 1;
ev.shift = shift; ev.shift = shift;
@ -113,6 +116,6 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
/* getkey_repeat() - set repeat delays for getkey() */ /* getkey_repeat() - set repeat delays for getkey() */
void getkey_repeat(int first, int next) void getkey_repeat(int first, int next)
{ {
rep_first = ((uint64_t)first << ATOM) / 1000; rep_first = (first * KEYBOARD_SCAN_FREQUENCY) / 1000;
rep_next = ((uint64_t)next << ATOM) / 1000; rep_next = (next * KEYBOARD_SCAN_FREQUENCY) / 1000;
} }

View file

@ -148,12 +148,14 @@ key_event_t waitevent(volatile int *timeout)
{ {
key_event_t none = { .type = KEYEV_NONE }; key_event_t none = { .type = KEYEV_NONE };
do { while(1)
{
key_event_t ev = pollevent(); key_event_t ev = pollevent();
if(ev.type != KEYEV_NONE) return ev; if(ev.type != KEYEV_NONE) return ev;
sleep();
} while(!(timeout && *timeout)); if(timeout && *timeout) break;
sleep();
}
return none; return none;
} }
@ -181,6 +183,9 @@ static void init(void)
int delay = 32768 / KEYBOARD_SCAN_FREQUENCY; int delay = 32768 / KEYBOARD_SCAN_FREQUENCY;
if(!delay) delay = 1; if(!delay) delay = 1;
/* Set the default repeat times (milliseconds) */
getkey_repeat(500, 125);
timer_setup(tid, delay, 0, callback, NULL); timer_setup(tid, delay, 0, callback, NULL);
timer_start(tid); timer_start(tid);