gint/include/keyboard.h

322 lines
9.4 KiB
C

//---
//
// gint core module: keyboard analyzer
//
// Probably the most difficult hardware interaction. There is very few
// documentation on how the system actually analyzes the keyboard. While
// disassembling syscalls reveals the following procedure (which was
// already documented by SimonLothar), there is nothing about the
// detection problems of the multi-getkey system.
//
//---
#ifndef _KEYBOARD_H
#define _KEYBOARD_H
#include <stdint.h>
#include <rtc.h>
//---
// Keycodes and related.
//---
/*
key_t
The following codes are gint matrix codes. They are not compatible with
the system's. Some keycodes are special event codes; all others are
made of a key identifier and possibly one or more modifiers.
Binary-and a keycode with MOD_CLEAR to remove the modifiers; this will
not work with special event codes.
*/
typedef enum
{
// Special events codes.
KEY_NONE = 0x00,
KEY_NOEVENT = 0xff,
// Key modifiers.
MOD_SHIFT = 0x80,
MOD_ALPHA = 0x100,
MOD_CLEAR = ~(MOD_SHIFT | MOD_ALPHA),
// Key identifiers.
KEY_F1 = 0x69,
KEY_F2 = 0x59,
KEY_F3 = 0x49,
KEY_F4 = 0x39,
KEY_F5 = 0x29,
KEY_F6 = 0x19,
KEY_SHIFT = 0x68,
KEY_OPTN = 0x58,
KEY_VARS = 0x48,
KEY_MENU = 0x38,
KEY_LEFT = 0x28,
KEY_UP = 0x18,
KEY_ALPHA = 0x67,
KEY_SQUARE = 0x57,
KEY_POWER = 0x47,
KEY_EXIT = 0x37,
KEY_DOWN = 0x27,
KEY_RIGHT = 0x17,
KEY_XOT = 0x66,
KEY_LOG = 0x56,
KEY_LN = 0x46,
KEY_SIN = 0x36,
KEY_COS = 0x26,
KEY_TAN = 0x16,
KEY_FRAC = 0x65,
KEY_FD = 0x55,
KEY_LEFTP = 0x45,
KEY_RIGHTP = 0x35,
KEY_COMMA = 0x25,
KEY_ARROW = 0x15,
KEY_7 = 0x64,
KEY_8 = 0x54,
KEY_9 = 0x44,
KEY_DEL = 0x34,
KEY_AC_ON = 0x24,
KEY_4 = 0x63,
KEY_5 = 0x53,
KEY_6 = 0x43,
KEY_MUL = 0x33,
KEY_DIV = 0x23,
KEY_1 = 0x62,
KEY_2 = 0x52,
KEY_3 = 0x42,
KEY_PLUS = 0x32,
KEY_MINUS = 0x22,
KEY_0 = 0x61,
KEY_DOT = 0x51,
KEY_EXP = 0x41,
KEY_NEG = 0x31,
KEY_EXE = 0x21,
} key_t;
//---
// Keyboard configuration.
//---
/*
keyboard_setAnalysisDelay()
Sets the keyboard analysis delay, that is, the delay (in ms) between
two keyboard analyzes. If a key is pressed then released in the lapse
between two analyzes, the program won't notice anything. On the other
hand, if the program spends too much time reading the keyboard, it will
lose a bit of execution power.
The default frequency is about 40 Hz; very few programs will need to
change this setting. Please note that the repeat delays should be
multiples of the analysis delay for better accuracy.
*/
void keyboard_setAnalysisDelay(int analysis_delay_ms);
/*
keyboard_setRepeatRate()
Sets the default repeat rate for key events. The delay before the first
repeat may have a different value (usually longer). The unit for the
argument is ms, but the repeat events themselves may only be fired when
a keyboard analysis is performed; which means that for better accuracy,
these delays should be a multiple of the keyboard period. The keyboard
period may be changed by calling keyboard_setAnalysisDelay().
For instance, delays of (625 ms, 125 ms) will imitate the system's
default setting.
You can disable repetitions by passing 0 as arguments:
- if first = 0, no repetition will ever occur;
- if first != 0 and next = 0, only one repetition will occur.
*/
void keyboard_setRepeatRate(int first, int next);
//---
// Keyboard access.
//---
/*
getkey_opt_t
Options available to customize the behavior of the getkey_opt()
function.
*/
typedef enum
{
getkey_none = 0x00,
// Consider [SHIFT] and [ALPHA] as modifiers. Returns key identifiers
// with MOD_SHIFT and MOD_ALPHA flags instead of returning KEY_SHIFT
// and KEY_ALPHA.
getkey_shift_modifier = 0x01,
getkey_alpha_modifier = 0x02,
// Allow changing the backlight status on [SHIFT] + [OPTN] on
// compatible models.
getkey_manage_backlight = 0x04,
// Allow key repetition. This option does not control the generation of
// repeat events (use keyboard_setRepeatRate() for this) but filters
// them. Please note that modifiers will never be repeated, even when
// pressed continuously.
getkey_repeat_arrow_keys = 0x10,
getkey_repeat_char_keys = 0x20,
getkey_repeat_ctrl_keys = 0x40,
getkey_repeat_func_keys = 0x80,
// Shorthand for the four previous properties.
getkey_repeat_all_keys = 0xf0,
} getkey_option_t;
/*
getkey()
Blocking function with auto-repeat that heeds for the SHIFT and ALPHA
modifiers. In short, this function reproduces the behavior of the
system's GetKey() function. It returns a matrix code, possibly with
modifier bits.
This function does not return until a key is pressed.
*/
int getkey(void);
/*
getkey_opt()
Enhances getkey() with more general functionalities. An OR-combination
of options of type getkey_option_t may be given as first argument.
If delay is non-zero and positive, getkey_opt() will return KEY_NOEVENT
if no event occurs during the given delay. Please note that this
function can only ever return after a keyboard analysis is performed;
the actual delay may exceed the requested time if it's not a multiple
of the keyboard period (which can be changed by calling
keyboard_setAnalysisDelay()).
Like getkey(), returns the pressed key matrix code, possibly with
modifiers depending on the options.
*/
int getkey_opt(getkey_option_t options, int delay_ms);
/*
multigetkey()
Listens the keyboard for simultaneous key hits. This functions fills
the 'keys' array with 'count' keycodes, padding with KEY_NONE values at
the end if less that 'count' keys are detected.
If 'delay_ms' is positive and nothing happens during this delay, this
function returns an array of KEY_NONE. Please note that the delay
detection suffers the same limitation as getkey_opt().
This function suffers from severe limitations and may not be very
convenient to use. For more accuracy, consider using the event system.
WARNING:
Because of hardware limitations, this function generally yields poor
results. Rectangle and column effects make it read unpressed keys as
pressed (see documentation for more information). The more pressed
keys, the more errors.
The results are guaranteed to be exact if two keys or less are pressed.
With three keys or more, column effects (on SH4) and rectangle effects
(on both platforms) mess up the results by making this function think
that some keys, which are actually released, are pressed.
This function is designed to make combinations of one or two arrow keys
with another key as viable as possible. On SH4, this works pretty well
even if combinations like Left + Down + SHIFT trigger ALPHA sometimes.
On SH3, rectangle effects are *always* present, making it impossible to
use Left + Down or Up + Right with any other key in their rows without
having this function return junk.
Any other combination of keys may quite randomly result in variably
incorrect results. Please do not expect multigetkey() to work as an
ideal multi-key analyzer.
*/
void multigetkey(int *keys, int count, int delay_ms);
/*
keyboard_stateBuffer()
Returns the address of the keyboard state array. The keyboard state
consists in 10 bytes, in which every key is represented as a bit.
The returned address is the original buffer address. You should avoid
editing the array. It wouldn't influence the behavior of the keyboard
functions, but the buffer data is very volatile and any data written to
it could be replaced anytime without prior notice.
If the user wishes to do really advanced keyboard management that they
can't achieve it using the library, they can access this buffer.
Updates of this buffer's contents can be detected by watching the
'interrupt_flag' variable defined in internals/keyboard.h. However, the
library will continue firing events so the user needs to catch them and
ignore them.
*/
volatile uint8_t *keyboard_stateBuffer(void);
//---
// Key analysis.
//---
/*
keyid()
Transforms a key identifier and returns a key code that is more
convenient for array subscript that the original matrix codes. The new
codes are laid out the following way:
+0 +1 +2 +3 +4 +5
------------------------------------
+0 | F1 F2 F3 F4 F5 F6
+6 | SHIFT OPTN VARS MENU Left Top
+12 | ALPHA x^2 ^ EXIT Down Right
+18 | X,O,T log ln sin cos tan
+24 | Frac F<>D ( ) , ->
+30 | 7 8 9 DEL AC/ON
+36 | 4 5 6 * /
+42 | 1 2 3 + -
+48 | 0 . x10^ (-) EXE
The returned key code is the sum of the line and column headings. For
instance key_id(KEY_SIN) would be 18 + 3 = 21. Please note that there
are a few holes in the numbering.
This function ignores modifiers and returns -1 on error.
*/
int key_id(int matrix_key);
/*
key_char()
Returns the ASCII character associated with a character key, and 0 for
other keys. This function expects a matrix code and not a key_id()
code, and heeds for the ALPHA modifier.
*/
int key_char(int matrix_key);
/*
key_type_t
Categorizes the keyboard's keys into several types:
- Arrow keys only include the REPLAY pad;
- Function keys only include the F1 .. F6 keys;
- Character keys are those which input characters;
- Control characters are all others.
*/
typedef enum
{
key_type_arrow = 1,
key_type_character = 2,
key_type_control = 4,
key_type_function = 8,
} key_type_t;
/*
key_type()
Returns a key's type. This functions ignores modifiers and expects
matrix codes as argument, not key_id() codes.
*/
key_type_t key_type(int matrix_key);
#endif // _KEYBOARD_H