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
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.
This event has always mod = 0, shift = 0, alpha = 0. */
This function always returns events with mod=0. */
key_event_t pollevent(void);
/* waitevent() - wait for the next keyboard event
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
timer with [timer_timeout] as callback. See <gint/timer.h>. */
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(). */
enum {
/* Enable modifiers keys */
GETKEY_MOD_SHIFT = 0x01,
GETKEY_MOD_ALPHA = 0x02,
GETKEY_MOD_SHIFT = 0x01,
GETKEY_MOD_ALPHA = 0x02,
/* SHIFT + OPTN toggles backlight (requires GETKEY_MOD_SHIFT) */
GETKEY_BACKLIGHT = 0x04,
GETKEY_BACKLIGHT = 0x04,
/* MENU triggers a task switch and displays the main menu */
GETKEY_MENU = 0x08,
GETKEY_MENU = 0x08,
/* Repeat arrow keys, or even all keys */
GETKEY_REP_ARROWS = 0x10,
GETKEY_REP_ALL = 0x20,
GETKEY_REP_ARROWS = 0x10,
GETKEY_REP_ALL = 0x20,
/* Default settings of getkey() */
GETKEY_DEFAULT = 0x1f,
GETKEY_DEFAULT = 0x1f,
};
/* getkey_opt() - enhanced getkey()
@ -148,7 +148,7 @@ enum {
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
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
@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
perfectly regular, rather than approximating the requested frequency.
The system default is (625 ms, 25 ms). With the 128 Hz setting, this default
will be approximated at (625 ms, 23.4375 ms).
The system default is (500 ms, 125 ms). With the 128 Hz setting, this
default is reached exactly without approximation.
@first Delay between key press and first repeat (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>
#endif
/* Atom for counting time in getkey() is 32768 Hz, 1ull << ATOM is a second */
#define ATOM 15
/* Delay between a key press and the first repeat, in 1/32768 seconds */
static uint64_t rep_first;
/* Delay between subsequent repeats, in 1/32768 seconds */
static uint64_t rep_next;
/* Delay between a key press and the first repeat, in scan intervals */
static int rep_first = 64;
/* Delay between subsequent repeats, in scan intervals */
static int rep_next = 16;
/* getkey() - wait for a pressed key */
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;
/* Last pressed key (only this key may be repeated) */
int rep_key = 0;
static int rep_key = 0;
/* Number of repeats already emitted */
int rep_count = 0;
/* Time elapsed since last repeat emission (in atoms) */
uint64_t rep_time = 0;
static int rep_count = 0;
/* Scan intervals elapsed since last repeat */
static int rep_time = 0;
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) */
case KEYEV_HOLD:
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(rep_time < (rep_count ? rep_next : rep_first)) break;
if(++rep_time < (rep_count ? rep_next : rep_first)) break;
ev.mod = 1;
ev.shift = shift;
@ -113,6 +116,6 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
/* getkey_repeat() - set repeat delays for getkey() */
void getkey_repeat(int first, int next)
{
rep_first = ((uint64_t)first << ATOM) / 1000;
rep_next = ((uint64_t)next << ATOM) / 1000;
rep_first = (first * KEYBOARD_SCAN_FREQUENCY) / 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 };
do {
while(1)
{
key_event_t ev = pollevent();
if(ev.type != KEYEV_NONE) return ev;
sleep();
} while(!(timeout && *timeout));
if(timeout && *timeout) break;
sleep();
}
return none;
}
@ -181,6 +183,9 @@ static void init(void)
int delay = 32768 / KEYBOARD_SCAN_FREQUENCY;
if(!delay) delay = 1;
/* Set the default repeat times (milliseconds) */
getkey_repeat(500, 125);
timer_setup(tid, delay, 0, callback, NULL);
timer_start(tid);