keysc: add support for the CP-400 key layout

This commit is contained in:
Lephe 2024-05-25 18:01:15 +02:00
parent e3105701d9
commit 4a2b60b785
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
2 changed files with 77 additions and 22 deletions

View file

@ -79,6 +79,14 @@ enum {
KEY_HELP = 0x20, /* fx-9860G Slim: 0x75 */ KEY_HELP = 0x20, /* fx-9860G Slim: 0x75 */
KEY_LIGHT = 0x10, /* fx-9860G Slim: 0x76 */ KEY_LIGHT = 0x10, /* fx-9860G Slim: 0x76 */
/* Key codes for the CP-400 */
KEY_KBD = 0xa1,
KEY_X = 0xa2,
KEY_Y = 0xa3,
KEY_Z = 0xa4,
KEY_EQUALS = 0xa5,
KEY_CLEAR = KEY_ACON,
/* Key aliases (handle with care =D) */ /* Key aliases (handle with care =D) */
KEY_X2 = KEY_SQUARE, KEY_X2 = KEY_SQUARE,
KEY_CARET = KEY_POWER, KEY_CARET = KEY_POWER,

View file

@ -2,6 +2,7 @@
// gint:keydev - Generic input handling on keyboard devices // gint:keydev - Generic input handling on keyboard devices
//--- //---
#include <gint/config.h>
#include <gint/keyboard.h> #include <gint/keyboard.h>
#include <gint/cpu.h> #include <gint/cpu.h>
#include <gint/drivers/keydev.h> #include <gint/drivers/keydev.h>
@ -11,6 +12,50 @@
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#if GINT_HW_CP
static uint8_t const CP_translation_table[] = {
KEY_SHIFT, KEY_DIV, KEY_MUL, KEY_MINUS, KEY_PLUS, KEY_EXE,
KEY_DEL, KEY_POWER, KEY_9, KEY_6, KEY_3, KEY_EXP,
KEY_RIGHT, KEY_LEFT, KEY_Z, 0, 0, 0,
KEY_UP, KEY_DOWN, KEY_8, KEY_5, KEY_2, KEY_DOT,
KEY_KBD, KEY_Y, KEY_7, KEY_4, KEY_1, KEY_0,
KEY_EQUALS, KEY_X, KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_NEG,
};
static int keymatrix_to_keycode(int row, int col)
{
if(row == 0 && col == 1)
return KEY_CLEAR;
return CP_translation_table[6 * (row-1) + (7-col)];
}
static void keycode_to_keymatrix(int keycode, int *row, int *col)
{
if(keycode == KEY_CLEAR) {
*row = 0;
*col = 1;
return;
}
for(int i = 0; i < (int)sizeof(CP_translation_table); i++) {
if(CP_translation_table[i] == keycode) {
*row = i / 6 + 1;
*col = 7 - (i % 6);
return;
}
}
*row = 0;
*col = 0;
}
#else
static GINLINE int keymatrix_to_keycode(int row, int col)
{
return (row << 4) + (7 - col);
}
static GINLINE void keycode_to_keymatrix(int keycode, int *row, int *col)
{
*row = keycode >> 4;
*col = 7 - (keycode & 7);
}
#endif
void keydev_init(keydev_t *d) void keydev_init(keydev_t *d)
{ {
memset(d, 0, sizeof *d); memset(d, 0, sizeof *d);
@ -78,16 +123,14 @@ void keydev_process_state(keydev_t *d, uint8_t scan[12])
: d->state_now[row] & ~scan[row]; : d->state_now[row] & ~scan[row];
if(!diff) continue; if(!diff) continue;
ev.key = (row << 4); for(int mask = 0x80, col = 7; mask; mask >>= 1, col--)
for(int mask = 0x80; mask != 0; mask >>= 1)
{ {
ev.key = keymatrix_to_keycode(row, col);
/* Update state only if the push succeeds */ /* Update state only if the push succeeds */
if((diff & mask) && keydev_queue_push(d, ev)) if((diff & mask) && keydev_queue_push(d, ev))
d->state_now[row] = mode d->state_now[row] = mode
? d->state_now[row] | mask ? d->state_now[row] | mask
: d->state_now[row] & ~mask; : d->state_now[row] & ~mask;
ev.key++;
} }
} }
@ -145,9 +188,9 @@ void keydev_tick(keydev_t *d, uint us)
/* Disable repeat if the repeating key was released */ /* Disable repeat if the repeating key was released */
if(d->rep_key != 0) if(d->rep_key != 0)
{ {
int row = (d->rep_key >> 4); int row, col;
int col = 0x80 >> (d->rep_key & 0x7); keycode_to_keymatrix(d->rep_key, &row, &col);
if(!(d->state_now[row] & col)) if(!(d->state_now[row] & (1 << col)))
{ {
d->rep_key = 0; d->rep_key = 0;
d->rep_count = -1; d->rep_count = -1;
@ -189,13 +232,14 @@ key_event_t keydev_unqueue_event(keydev_t *d)
return ev; return ev;
/* Update the event state accordingly */ /* Update the event state accordingly */
int row = (ev.key >> 4); int row, col;
int col = 0x80 >> (ev.key & 0x7); keycode_to_keymatrix(ev.key, &row, &col);
int mask = 1 << col;
if(ev.type == KEYEV_DOWN) if(ev.type == KEYEV_DOWN)
{ {
d->state_queue[row] |= col; d->state_queue[row] |= mask;
d->state_flips[row] ^= col; d->state_flips[row] ^= mask;
/* Mark this key as the currently repeating one */ /* Mark this key as the currently repeating one */
if(d->rep_key == 0 && can_repeat(d, ev.key)) if(d->rep_key == 0 && can_repeat(d, ev.key))
{ {
@ -207,8 +251,8 @@ key_event_t keydev_unqueue_event(keydev_t *d)
} }
else if(ev.type == KEYEV_UP) else if(ev.type == KEYEV_UP)
{ {
d->state_queue[row] &= ~col; d->state_queue[row] &= ~mask;
d->state_flips[row] ^= col; d->state_flips[row] ^= mask;
} }
return ev; return ev;
@ -219,28 +263,31 @@ key_event_t _WEAK_keydev_unqueue_event(keydev_t *d);
/* keydev_keydown(): Check if a key is down according to generated events */ /* keydev_keydown(): Check if a key is down according to generated events */
bool keydev_keydown(keydev_t *d, int key) bool keydev_keydown(keydev_t *d, int key)
{ {
int row = (key >> 4); int row, col;
int col = 0x80 >> (key & 0x7); keycode_to_keymatrix(key, &row, &col);
int mask = 1 << col;
return (d->state_queue[row] & col) != 0; return (d->state_queue[row] & mask) != 0;
} }
__attribute__((alias("keydev_keydown"))) __attribute__((alias("keydev_keydown")))
bool _WEAK_keydev_keydown(keydev_t *d, int key); bool _WEAK_keydev_keydown(keydev_t *d, int key);
bool keydev_keypressed(keydev_t *d, int key) bool keydev_keypressed(keydev_t *d, int key)
{ {
int row = (key >> 4); int row, col;
int col = 0x80 >> (key & 0x7); keycode_to_keymatrix(key, &row, &col);
int mask = 1 << col;
return (d->state_queue[row] & col) && (d->state_flips[row] & col); return (d->state_queue[row] & mask) && (d->state_flips[row] & mask);
} }
bool keydev_keyreleased(keydev_t *d, int key) bool keydev_keyreleased(keydev_t *d, int key)
{ {
int row = (key >> 4); int row, col;
int col = 0x80 >> (key & 0x7); keycode_to_keymatrix(key, &row, &col);
int mask = 1 << col;
return !(d->state_queue[row] & col) && (d->state_flips[row] & col); return !(d->state_queue[row] & mask) && (d->state_flips[row] & mask);
} }
void keydev_clear_flips(keydev_t *d) void keydev_clear_flips(keydev_t *d)