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
Signed by: Lephenixnoir
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 HWETMU 7 /* Extra Timer Units */
#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 */
/*

View File

@ -120,12 +120,28 @@ enum
#define KEYBOARD_QUEUE_SIZE 32
#endif
/* Keyboard frequency analysis, must be at least 64 for the keyboard to work,
and at most 32768 for the extra timer to support it. Better if a power of 2.
TODO: Add a runtime setting for KEYBOARD_SCAN_FREQUENCY */
#ifndef KEYBOARD_SCAN_FREQUENCY
#define KEYBOARD_SCAN_FREQUENCY 128
#endif
/* Keyboard frequency analysis is a runtime setting since gint 2.4. This macro
is preserved for compatibility until gint 3. */
#define KEYBOARD_SCAN_FREQUENCY keysc_scan_frequency()
//---
// 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

View File

@ -5,15 +5,18 @@
#include <gint/keyboard.h>
#include <gint/gint.h>
#include <gint/defs/types.h>
#include "getkey.h"
#ifdef FX9860G
#include <gint/drivers/t6k11.h>
#endif
/* 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 */
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 */
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 */
if(s > 0)
{
s = (s * KEYBOARD_SCAN_FREQUENCY) / 1000;
s = (s * keysc_scan_frequency()) / 1000;
rep_delay += s;
break;
}
@ -165,8 +168,11 @@ 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 = (first * KEYBOARD_SCAN_FREQUENCY) / 1000;
rep_next = (next * KEYBOARD_SCAN_FREQUENCY) / 1000;
rep_first_ms = first;
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 */
@ -174,3 +180,9 @@ void getkey_repeat_filter(int (*filter)(int key, int duration, int count))
{
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/hardware.h>
#include "getkey.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
//---
@ -78,6 +86,38 @@ static int buffer_poll(driver_event_t *ev)
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 */
static void keysc_frame(void)
{
@ -258,20 +298,14 @@ static int callback(void)
/* init() - setup the support timer */
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) */
getkey_repeat(400, 40);
/* The timer will be stopped when the timer driver is unloaded */
int tid = timer_setup(TIMER_ANY, delay, callback);
if(tid >= 0) timer_start(tid);
keysc_tid = timer_setup(TIMER_ANY,keysc_scan_frequency_us(),callback);
if(keysc_tid >= 0) timer_start(keysc_tid);
gint[HWKBD] = HW_LOADED | (isSH3() ? HWKBD_IO : HWKBD_KSI);
gint[HWKBDSF] = KEYBOARD_SCAN_FREQUENCY;
}
//---