zx128: sort out the keyboard driver
authorAlan Cox <alan@linux.intel.com>
Fri, 13 Feb 2015 21:10:24 +0000 (21:10 +0000)
committerAlan Cox <alan@linux.intel.com>
Fri, 13 Feb 2015 21:10:24 +0000 (21:10 +0000)
This adds some of the missing keyboard symbols, arrow key handling etc and
also sorts out the inverted handling bug.

Kernel/platform-zx128/devtty.c
Kernel/platform-zx128/main.c

index 0d81c04..afb7ee4 100644 (file)
@@ -3,6 +3,7 @@
 #include <printf.h>
 #include <stdbool.h>
 #include <devtty.h>
+#include <keycode.h>
 #include <vt.h>
 #include <tty.h>
 
@@ -10,35 +11,34 @@ char tbuf1[TTYSIZ];
 
 /* buffer for port scan procedure */
 uint8_t keybuf[8];
-/* keyboard state on previous execution. Initialized with all 0x1F (everything released) */
-/* FIXME: needs inverting */
-uint8_t keymap[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
+/* 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' }
+       {' ', 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 ,},
-       { '_', ')', '(', '\'', '&' },
-       { '!', '@', '#', '$', '%' },
-       {  0 ,  0 ,  0 , '<', '>' },
-       {  0 ,  0 ,  0 ,  0 ,  0  },
-       {  0,  ':',  0 , '?', '/' } /* 'x' key should actually contain British pound sign here if "big" font is used */
+       {' ', 0 , '.',  ',', '*'},
+       {13 , '=', '+', '-', '^'},
+       {'"', ';', '@', ']', '['},
+       {'_', ')', '(', '\'','&'},
+       {'!', '@', '#', '$', '%'},
+       {'`',  0 ,  0 , '<', '>'},
+       {'~' ,'|', '\\','{', '}'},
+       {0  , ':', KEY_POUND  , '?', '/'}
 };
 
 
@@ -88,18 +88,19 @@ 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
+               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
+               cpl
+               ld(hl), a
+               rrc b
+               inc hl
+               dec e
+               jr nz, read_halfrow
        __endasm;
 }
 
@@ -113,20 +114,23 @@ void tty_pollirq(void)
 
        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;
+               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))
+                                               keysdown--;
+
+                               if ((key & m) && !(keymap[i] & m)) {
+                                       if (!(shiftmask[i] & m))
+                                               keysdown++;
+                                       keybyte = i;
+                                       keybit = n;
+                                       newkey = 1;
+                               }
+                               m >>= 1;
                        }
-                       m >>= 1;
                }
                keymap[i] = keybuf[i];
        }
@@ -135,28 +139,31 @@ void tty_pollirq(void)
                keydecode();
 }
 
+static uint8_t cursor[4] = { KEY_LEFT, KEY_DOWN, KEY_UP, KEY_RIGHT };
+
 static void keydecode(void)
 {
        uint8_t c;
 
-       uint8_t ss = !(keymap[0] & 0x02); /* SYMBOL SHIFT */
-       uint8_t cs = !(keymap[7] & 0x01); /* CAPS SHIFT */
+       uint8_t ss = keymap[0] & 0x02;  /* SYMBOL SHIFT */
+       uint8_t cs = keymap[7] & 0x01;  /* CAPS SHIFT */
 
-       if (ss)
-       {
+       if (ss) {
                c = shiftkeyboard[keybyte][keybit];
-       }
-       else {
+       } else {
                c = keyboard[keybyte][keybit];
-               if (cs)
-               {
+               if (cs) {
                        if (c >= 'a' && c <= 'z')
                                c -= 'a' - 'A';
-                       else if (c == '0') /* CS + 0 is backspace) */
+                       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 (c != 0)
                tty_inproc(1, c);
@@ -165,4 +172,3 @@ static void keydecode(void)
 
 /* This is used by the vt asm code, but needs to live in the kernel */
 uint16_t cursorpos;
-
index b6a4cb2..bd4ffcb 100644 (file)
@@ -17,10 +17,9 @@ void pagemap_init(void)
    for the polled ports */
 void platform_idle(void)
 {
-  /* We don't want an idle poll and IRQ driven tty poll at the same moment */
-  irqflags_t irq = di();
-  tty_pollirq(); 
-  irqrestore(irq);
+ __asm
+  halt
+ __endasm;
 }
 
 void platform_interrupt(void)