zx128: keyboard support for tty
authorAlexander Tsidaev <a.tsidaev@gmail.com>
Mon, 10 Nov 2014 13:40:08 +0000 (18:40 +0500)
committerAlexander Tsidaev <a.tsidaev@gmail.com>
Mon, 10 Nov 2014 13:40:08 +0000 (18:40 +0500)
Kernel/platform-zx128/devtty.c
Kernel/platform-zx128/devtty.h

index 79f2300..c2d7713 100644 (file)
@@ -8,6 +8,41 @@
 
 char tbuf1[TTYSIZ];
 
+/* buffer for port scan procedure */
+uint8_t keybuf[8];
+/* keyboard state on previous execution. Initialized with all 0x1F (everything released) */
+uint8_t keymap[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
+
+static uint8_t keybyte, keybit;
+static uint8_t newkey;
+static int keysdown = 0;
+
+static 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 */
+static uint8_t keyboard_ss[8][5] = {
+       { ' ',  0,  '.', ',', '*' },
+       {  13, '=', '+', '-', '^',},
+       { '"', ';',  0 ,  0 ,  0 ,},
+       { '_', ')', '(', '\'', '&' },
+       { '!', '@', '#', '$', '%' },
+       {  0 ,  0 ,  0 , '<', '>' },
+       {  0 ,  0 ,  0 ,  0 ,  0  },
+       {  0,  ':',  0 , '?', '/' } /* 'x' key should actually contain British pound sign here if "big" font is used */
+};
+
+
+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},
        {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2},
@@ -47,15 +82,86 @@ void tty_setup(uint8_t minor)
        minor;
 }
 
+void update_keyboard(void)
+{
+       /* We need this assembler code because SDCC __sfr cannot handle 16-bit addresses. And because it is much faster, of course  */
+       /* TODO: make it naked? */
+       __asm
+       ld hl, #_keybuf
+       ld c, #0xFE
+       ld b, #0x7f
+       ld e, #8        ; 8 keyboard ports, 7FFE, BFFE, DFFE and so on
+read_halfrow:
+       in a, (c)
+;      and #0
+       ld (hl), a
+       rrc b
+       inc hl
+       dec e
+       jr nz, read_halfrow
+       __endasm;
+}
+
 void tty_pollirq(void)
 {
+       int i;
+
+       update_keyboard();
+
+       newkey = 0;
+
+       for (i = 0; i < 8; i++) {
+               int n;
+               uint8_t m = 0x10;
+               for (n = 4; n >= 0; n--) {
+                       if ((keybuf[i] & m) && !(keymap[i] & m))
+                               if (!shiftmask[i] & m)
+                                       keysdown--;
+
+                       if (!(keybuf[i] & m) && (keymap[i] & m)) {
+                               if (!(shiftmask[i] & m))
+                                   keysdown++;
+                               keybyte = i;
+                               keybit = n;
+                               newkey = 1;
+                       }
+                       m >>= 1;
+               }
+               keymap[i] = keybuf[i];
+       }
 
+       if (keysdown < 3 && newkey)
+               keydecode();
 }
 
-void tty_interrupt(void)
+static void keydecode(void)
 {
+       uint8_t c;
+
+       uint8_t ss = !(keymap[0] & 0x02); /* SYMBOL SHIFT */
+       uint8_t cs = !(keymap[7] & 0x01); /* CAPS SHIFT */
+
+       if (ss)
+       {
+               c = keyboard_ss[keybyte][keybit];
+       }
+       else {
+               c = keyboard[keybyte][keybit];
+               if (cs)
+               {
+                       if (c >= 'a' && c <= 'z')
+                               c -= 'a' - 'A';
+                       else if (c == '0') /* CS + 0 is backspace) */
+                               c = 0x08;
+               }
+       }
+       
+
+       if (c != 0)
+               tty_inproc(1, c);
 }
 
+
 /* This is used by the vt asm code, but needs to live in the kernel */
 uint16_t cursorpos;
 
index de0eaf7..f96542f 100644 (file)
@@ -2,5 +2,6 @@
 #define __DEVTTY_DOT_H__
 
 void tty_pollirq(void);
+static void keydecode(void);
 
 #endif