From: Alan Cox Date: Mon, 26 Nov 2018 13:22:41 +0000 (+0000) Subject: zxdiv: split out keyboard driver into dev/zx/ X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=43f1f2b7190489e62df5d96d89e3774ca9e661d6;p=FUZIX.git zxdiv: split out keyboard driver into dev/zx/ The clones mostly use the same keyboard mechanics so make it available to any other future ports --- diff --git a/Kernel/dev/zx/zxkeyboard.c b/Kernel/dev/zx/zxkeyboard.c new file mode 100644 index 00000000..7b44551f --- /dev/null +++ b/Kernel/dev/zx/zxkeyboard.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* buffer for port scan procedure */ +uint8_t keybuf[8]; +/* Previous state */ +uint8_t keymap[8]; + +struct vt_repeat keyrepeat; +static uint8_t kbd_timer; + +static uint8_t keybyte, keybit; +static uint8_t newkey; +static int keysdown = 0; + +uint8_t keyboard[8][5] = { + {' ', 0 , 'm', 'n', 'b'}, + {13 , 'l', 'k', 'j', 'h'}, + {'p', 'o', 'i', 'u', 'y'}, + {'0', '9', '8', '7', '6'}, + {'1', '2', '3', '4', '5'}, + {'q', 'w', 'e', 'r', 't'}, + {'a', 's', 'd', 'f', 'g'}, + {0 , 'z', 'x', 'c', 'v'} +}; + +/* SYMBOL SHIFT MODE */ +uint8_t shiftkeyboard[8][5] = { + {' ', 0 , '.', ',', '*'}, + {13 , '=', '+', '-', '^'}, + {'"', ';', '@', ']', '['}, + {'_', ')', '(', '\'','&'}, + {'!', '@', '#', '$', '%'}, + {'`', 0 , 0 , '<', '>'}, + {'~' ,'|', '\\','{', '}'}, + {0 , ':', KEY_POUND , '?', '/'} +}; + + +static uint8_t shiftmask[8] = { 0x02, 0, 0, 0, 0, 0, 0, 0x01 }; + +static uint8_t update_keyboard(void) __naked +{ + /* + * This is run 50 time a second so we do it in asm and also return + * 0 if nothing changed. That allows us to avoid the main tty + * processing on most interrupt events which saves us a lot of + * clocks. + */ + __asm + ld hl,#_keybuf + ld c, #0xFE + ld b, #0x7f + ld de, #8 ; 8 keyboard ports, 7FFE, BFFE, DFFE and so on + ; D to 0 for no change found + read_halfrow: + in a, (c) + cpl + cp (hl) + jr z,nochange + inc d ; there 8 ports so we cannot overflow + ld (hl), a + nochange: + rrc b + inc hl + dec e + jr nz, read_halfrow + ld l,d + ret + __endasm; +} + +static uint8_t cursor[4] = { KEY_LEFT, KEY_DOWN, KEY_UP, KEY_RIGHT }; + +static void keydecode(void) +{ + uint8_t m = 0; + uint8_t c; + + uint8_t ss = keymap[0] & 0x02; /* SYMBOL SHIFT */ + uint8_t cs = keymap[7] & 0x01; /* CAPS SHIFT */ + + if (ss && !cs) { + m = KEYPRESS_SHIFT; + c = shiftkeyboard[keybyte][keybit]; + } else { + c = keyboard[keybyte][keybit]; + if (cs && !ss) { + if (c >= 'a' && c <= 'z') + c -= 'a' - 'A'; + else if (c == '0') /* CS + 0 is backspace) */ + c = 0x08; + else if (c == ' ') + c = KEY_STOP; /* ^C map for BREAK */ + else if (c >= '5' && c <= '8') + c = cursor[c - '5']; + } + } + if (ss && cs) { + m |= KEYPRESS_CTRL; + c &= 31; + } + if (c) { + switch (keyboard_grab) { + case 0: + vt_inproc(1, c); + break; + case 1: + if (!input_match_meta(c)) { + vt_inproc(1, c); + break; + } + /* Fall through */ + case 2: + queue_input(KEYPRESS_DOWN); + queue_input(c); + break; + case 3: + /* Queue an event giving the base key (unshifted) + and the state of shift/ctrl/alt */ + queue_input(KEYPRESS_DOWN | m); + queue_input(keyboard[keybyte][keybit]); + break; + } + } +} + + +void tty_pollirq(void) +{ + int i; + + newkey = 0; + + /* Nothing changed - no processing required */ + if (!update_keyboard()) + return; + + for (i = 0; i < 8; i++) { + int n; + uint8_t key = keybuf[i] ^ keymap[i]; + if (key) { + uint8_t m = 0x10; + for (n = 4; n >= 0; n--) { + if ((key & m) && (keymap[i] & m)) + if (!(shiftmask[i] & m)) { + if (keyboard_grab == 3) { + queue_input(KEYPRESS_UP); + queue_input(keyboard[i][n]); + } + keysdown--; + } + + if ((key & m) && !(keymap[i] & m)) { + if (!(shiftmask[i] & m)) { + keysdown++; + newkey = 1; + keybyte = i; + keybit = n; + } + } + m >>= 1; + } + } + keymap[i] = keybuf[i]; + } + if (keysdown && keysdown < 3) { + if (newkey) { + keydecode(); + kbd_timer = keyrepeat.first; + } else if (! --kbd_timer) { + keydecode(); + kbd_timer = keyrepeat.continual; + } + } + +} diff --git a/Kernel/platform-zxdiv/Makefile b/Kernel/platform-zxdiv/Makefile index 578fe860..87289914 100644 --- a/Kernel/platform-zxdiv/Makefile +++ b/Kernel/platform-zxdiv/Makefile @@ -2,7 +2,7 @@ CSRCS = devtty.c devices.c main.c bank128.c devinput.c CDSRCS = discard.c DSRCS = ../dev/devide.c ../dev/devsd.c ../dev/blkdev.c DDSRCS = ../dev/devide_discard.c ../dev/devsd_discard.c ../dev/mbr.c -DZSRCS = ../dev/zx/divide.c ../dev/zx/divmmc.c +DZSRCS = ../dev/zx/divide.c ../dev/zx/divmmc.c ../dev/zx/zxkeyboard.c DDZSRCS = ASRCS = crt0.s zx128.s zxvideo.s ASRCS += tricks.s commonmem.s loader-divide.s diff --git a/Kernel/platform-zxdiv/devtty.c b/Kernel/platform-zxdiv/devtty.c index aba7c2e8..e3bfabb7 100644 --- a/Kernel/platform-zxdiv/devtty.c +++ b/Kernel/platform-zxdiv/devtty.c @@ -15,8 +15,6 @@ char tbuf1[TTYSIZ]; uint8_t vtattr_cap = VTA_INVERSE|VTA_FLASH|VTA_UNDERLINE; uint8_t vtborder; uint8_t curattr = 7; -struct vt_repeat keyrepeat; -static uint8_t kbd_timer; static tcflag_t console_mask[4] = { _ISYS, @@ -30,40 +28,6 @@ tcflag_t *termios_mask[NUM_DEV_TTY + 1] = { console_mask }; -/* buffer for port scan procedure */ -uint8_t keybuf[8]; -/* Previous state */ -uint8_t keymap[8]; - -static uint8_t keybyte, keybit; -static uint8_t newkey; -static int keysdown = 0; - -uint8_t keyboard[8][5] = { - {' ', 0 , 'm', 'n', 'b'}, - {13 , 'l', 'k', 'j', 'h'}, - {'p', 'o', 'i', 'u', 'y'}, - {'0', '9', '8', '7', '6'}, - {'1', '2', '3', '4', '5'}, - {'q', 'w', 'e', 'r', 't'}, - {'a', 's', 'd', 'f', 'g'}, - {0 , 'z', 'x', 'c', 'v'} -}; - -/* SYMBOL SHIFT MODE */ -uint8_t shiftkeyboard[8][5] = { - {' ', 0 , '.', ',', '*'}, - {13 , '=', '+', '-', '^'}, - {'"', ';', '@', ']', '['}, - {'_', ')', '(', '\'','&'}, - {'!', '@', '#', '$', '%'}, - {'`', 0 , 0 , '<', '>'}, - {'~' ,'|', '\\','{', '}'}, - {0 , ':', KEY_POUND , '?', '/'} -}; - - -static uint8_t shiftmask[8] = { 0x02, 0, 0, 0, 0, 0, 0, 0x01 }; struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */ {NULL, NULL, NULL, 0, 0, 0}, @@ -113,142 +77,6 @@ void tty_data_consumed(uint8_t minor) { } -static uint8_t update_keyboard(void) __naked -{ - /* - * This is run 50 time a second so we do it in asm and also return - * 0 if nothing changed. That allows us to avoid the main tty - * processing on most interrupt events which saves us a lot of - * clocks. - */ - __asm - ld hl,#_keybuf - ld c, #0xFE - ld b, #0x7f - ld de, #8 ; 8 keyboard ports, 7FFE, BFFE, DFFE and so on - ; D to 0 for no change found - read_halfrow: - in a, (c) - cpl - cp (hl) - jr z,nochange - inc d ; there 8 ports so we cannot overflow - ld (hl), a - nochange: - rrc b - inc hl - dec e - jr nz, read_halfrow - ld l,d - ret - __endasm; -} - -void tty_pollirq(void) -{ - int i; - - newkey = 0; - - /* Nothing changed - no processing required */ - if (!update_keyboard()) - return; - - for (i = 0; i < 8; i++) { - int n; - uint8_t key = keybuf[i] ^ keymap[i]; - if (key) { - uint8_t m = 0x10; - for (n = 4; n >= 0; n--) { - if ((key & m) && (keymap[i] & m)) - if (!(shiftmask[i] & m)) { - if (keyboard_grab == 3) { - queue_input(KEYPRESS_UP); - queue_input(keyboard[i][n]); - } - keysdown--; - } - - if ((key & m) && !(keymap[i] & m)) { - if (!(shiftmask[i] & m)) { - keysdown++; - newkey = 1; - keybyte = i; - keybit = n; - } - } - m >>= 1; - } - } - keymap[i] = keybuf[i]; - } - if (keysdown && keysdown < 3) { - if (newkey) { - keydecode(); - kbd_timer = keyrepeat.first; - } else if (! --kbd_timer) { - keydecode(); - kbd_timer = keyrepeat.continual; - } - } - -} - -static uint8_t cursor[4] = { KEY_LEFT, KEY_DOWN, KEY_UP, KEY_RIGHT }; - -static void keydecode(void) -{ - uint8_t m = 0; - uint8_t c; - - uint8_t ss = keymap[0] & 0x02; /* SYMBOL SHIFT */ - uint8_t cs = keymap[7] & 0x01; /* CAPS SHIFT */ - - if (ss && !cs) { - m = KEYPRESS_SHIFT; - c = shiftkeyboard[keybyte][keybit]; - } else { - c = keyboard[keybyte][keybit]; - if (cs && !ss) { - if (c >= 'a' && c <= 'z') - c -= 'a' - 'A'; - else if (c == '0') /* CS + 0 is backspace) */ - c = 0x08; - else if (c == ' ') - c = KEY_STOP; /* ^C map for BREAK */ - else if (c >= '5' && c <= '8') - c = cursor[c - '5']; - } - } - if (ss && cs) { - m |= KEYPRESS_CTRL; - c &= 31; - } - if (c) { - switch (keyboard_grab) { - case 0: - vt_inproc(1, c); - break; - case 1: - if (!input_match_meta(c)) { - vt_inproc(1, c); - break; - } - /* Fall through */ - case 2: - queue_input(KEYPRESS_DOWN); - queue_input(c); - break; - case 3: - /* Queue an event giving the base key (unshifted) - and the state of shift/ctrl/alt */ - queue_input(KEYPRESS_DOWN | m); - queue_input(keyboard[keybyte][keybit]); - break; - } - } -} - /* This is used by the vt asm code, but needs to live in the kernel */ uint16_t cursorpos; diff --git a/Kernel/platform-zxdiv/fuzix.lnk b/Kernel/platform-zxdiv/fuzix.lnk index 4e65d77e..cbb26f80 100644 --- a/Kernel/platform-zxdiv/fuzix.lnk +++ b/Kernel/platform-zxdiv/fuzix.lnk @@ -56,4 +56,5 @@ platform-zxdiv/divmmc.rel platform-zxdiv/mbr.rel platform-zxdiv/blkdev.rel platform-zxdiv/devinput.rel +platform-zxdiv/zxkeyboard.rel -e