add a dynamic setting for keyboard scan frequency

The repeat delays of getkey() are adjusted automatically, however a
repeat that is currently going on might be affected.

Also, repeat delays are always approximated as a whole number of
keyboard scans so an increase in scan frequency can impact the speed at
which repeats are emitted.
This commit is contained in:
Lephe 2021-01-31 12:19:39 +01:00
parent 6440527527
commit ee7b4f27b8
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
5 changed files with 93 additions and 20 deletions

View file

@ -64,7 +64,7 @@ void hw_detect(void);
#define HWURAM 6 /* Userspace RAM */ #define HWURAM 6 /* Userspace RAM */
#define HWETMU 7 /* Extra Timer Units */ #define HWETMU 7 /* Extra Timer Units */
#define HWKBD 8 /* Keyboard */ #define HWKBD 8 /* Keyboard */
#define HWKBDSF 9 /* Keyboard Scan Frequency (set iff HWKBD is loaded) */ #define HWKBDSF /* Deprecated: use keysc_scan_frequency() */
#define HWDD 10 /* Display Driver */ #define HWDD 10 /* Display Driver */
/* /*

View file

@ -120,12 +120,28 @@ enum
#define KEYBOARD_QUEUE_SIZE 32 #define KEYBOARD_QUEUE_SIZE 32
#endif #endif
/* Keyboard frequency analysis, must be at least 64 for the keyboard to work, /* Keyboard frequency analysis is a runtime setting since gint 2.4. This macro
and at most 32768 for the extra timer to support it. Better if a power of 2. is preserved for compatibility until gint 3. */
TODO: Add a runtime setting for KEYBOARD_SCAN_FREQUENCY */ #define KEYBOARD_SCAN_FREQUENCY keysc_scan_frequency()
#ifndef KEYBOARD_SCAN_FREQUENCY
#define KEYBOARD_SCAN_FREQUENCY 128 //---
#endif // Scan frequency settings
//---
/* keysc_scan_frequency(): Get the current keyboard scan frequency in Hertz */
int keysc_scan_frequency(void);
/* keysc_scan_frequency_us(): Get keyboard scan delay in microseconds */
uint32_t keysc_scan_frequency_us(void);
/* keysc_set_scan_frequency(): Set the keyboard scan frequency in Hertz
The new frequency must be at least 64 for the keyboard to work reliably, and
at most 32768 for the underlying ETMU to support it. Out-of-range values are
forced to the closest valid value.
@freq New scan frequency, in Hertz */
void keysc_set_scan_frequency(int freq);
//--- //---
// Event-level functions // Event-level functions

View file

@ -5,15 +5,18 @@
#include <gint/keyboard.h> #include <gint/keyboard.h>
#include <gint/gint.h> #include <gint/gint.h>
#include <gint/defs/types.h> #include <gint/defs/types.h>
#include "getkey.h"
#ifdef FX9860G #ifdef FX9860G
#include <gint/drivers/t6k11.h> #include <gint/drivers/t6k11.h>
#endif #endif
/* Delay between a key press and the first repeat, in scan intervals */ /* Delay between a key press and the first repeat, in scan intervals */
static int rep_first = 64; static int rep_first = 51;
/* Delay between subsequent repeats, in scan intervals */ /* Delay between subsequent repeats, in scan intervals */
static int rep_next = 8; static int rep_next = 5;
/* Same in milliseconds (values supplied by the user */
static int rep_first_ms = 400, rep_next_ms = 40;
/* Repeat filter function */ /* Repeat filter function */
static int (*filter_function)(int key, int duration, int count) = NULL; static int (*filter_function)(int key, int duration, int count) = NULL;
@ -132,7 +135,7 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
/* Delay repeat by set amount */ /* Delay repeat by set amount */
if(s > 0) if(s > 0)
{ {
s = (s * KEYBOARD_SCAN_FREQUENCY) / 1000; s = (s * keysc_scan_frequency()) / 1000;
rep_delay += s; rep_delay += s;
break; break;
} }
@ -165,8 +168,11 @@ 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 = (first * KEYBOARD_SCAN_FREQUENCY) / 1000; rep_first_ms = first;
rep_next = (next * KEYBOARD_SCAN_FREQUENCY) / 1000; rep_next_ms = next;
rep_first = (first * keysc_scan_frequency()) / 1000;
rep_next = (next * keysc_scan_frequency()) / 1000;
} }
/* getkey_repeat_filter(): Set the repeat filter function */ /* getkey_repeat_filter(): Set the repeat filter function */
@ -174,3 +180,9 @@ void getkey_repeat_filter(int (*filter)(int key, int duration, int count))
{ {
filter_function = filter; filter_function = filter;
} }
/* Refresh repeat delays after a change in keyboard scan frequency */
void getkey_refresh_delays(void)
{
getkey_repeat(rep_first_ms, rep_next_ms);
}

11
src/keysc/getkey.h Normal file
View file

@ -0,0 +1,11 @@
//---
// gint:keysc:getkey - Internal interface to getkey()
//---
#ifndef GINT_KEYSC_GETKEY
#define GINT_KEYSC_GETKEY
/* Refresh repeat delays after a change in keyboard scan frequency */
void getkey_refresh_delays(void);
#endif /* GINT_KEYSC_GETKEY */

View file

@ -13,8 +13,16 @@
#include <gint/drivers/iokbd.h> #include <gint/drivers/iokbd.h>
#include <gint/hardware.h> #include <gint/hardware.h>
#include "getkey.h"
#include <stdarg.h> #include <stdarg.h>
/* Keyboard scan frequency in Hertz. Start with 128 Hz, this frequency *must
be high* for the keyboard to work! */
static int scan_frequency = 128;
/* Keyboard scanner timer */
static int keysc_tid = -1;
//--- //---
// Keyboard buffer // Keyboard buffer
//--- //---
@ -78,6 +86,38 @@ static int buffer_poll(driver_event_t *ev)
return 0; return 0;
} }
//---
// Keyboard scanning
//---
/* keysc_scan_frequency(): Get the current keyboard scan frequency in Hertz */
int keysc_scan_frequency(void)
{
return scan_frequency;
}
/* keysc_scan_frequency_us(): Get keyboard scan delay in microseconds */
uint32_t keysc_scan_frequency_us(void)
{
int delay = 1000000 / scan_frequency;
if(delay == 0) delay = 1;
return delay;
}
/* keysc_set_scan_frequency(): Set the keyboard scan frequency in Hertz */
void keysc_set_scan_frequency(int freq)
{
if(freq < 64) freq = 64;
if(freq > 32768) freq = 32768;
scan_frequency = freq;
if(keysc_tid < 0) return;
uint32_t TCOR = timer_delay(keysc_tid, keysc_scan_frequency_us(), 0);
timer_reload(keysc_tid, TCOR);
getkey_refresh_delays();
}
/* keysc_frame(): Generate driver events from KEYSC state */ /* keysc_frame(): Generate driver events from KEYSC state */
static void keysc_frame(void) static void keysc_frame(void)
{ {
@ -258,20 +298,14 @@ static int callback(void)
/* init() - setup the support timer */ /* init() - setup the support timer */
static void init(void) static void init(void)
{ {
/* Configure the timer to do 128 keyboard scans per second. This
frequency *must* be high for the KEYSC interface to work! */
int delay = 1000000 / KEYBOARD_SCAN_FREQUENCY;
if(!delay) delay = 1;
/* Set the default repeat times (milliseconds) */ /* Set the default repeat times (milliseconds) */
getkey_repeat(400, 40); getkey_repeat(400, 40);
/* The timer will be stopped when the timer driver is unloaded */ /* The timer will be stopped when the timer driver is unloaded */
int tid = timer_setup(TIMER_ANY, delay, callback); keysc_tid = timer_setup(TIMER_ANY,keysc_scan_frequency_us(),callback);
if(tid >= 0) timer_start(tid); if(keysc_tid >= 0) timer_start(keysc_tid);
gint[HWKBD] = HW_LOADED | (isSH3() ? HWKBD_IO : HWKBD_KSI); gint[HWKBD] = HW_LOADED | (isSH3() ? HWKBD_IO : HWKBD_KSI);
gint[HWKBDSF] = KEYBOARD_SCAN_FREQUENCY;
} }
//--- //---