ubee: first sketch out of light pen keyboard support
authorAlan Cox <alan@linux.intel.com>
Tue, 17 Apr 2018 22:13:07 +0000 (23:13 +0100)
committerAlan Cox <alan@linux.intel.com>
Tue, 17 Apr 2018 22:13:07 +0000 (23:13 +0100)
Kernel/platform-ubee/README
Kernel/platform-ubee/config.h
Kernel/platform-ubee/devtty.c
Kernel/platform-ubee/devtty.h
Kernel/platform-ubee/floppy.s
Kernel/platform-ubee/main.c
Kernel/platform-ubee/ubee.s

index 3326738..741b4f5 100644 (file)
@@ -5,7 +5,7 @@ First 64K
        0000-00FF               Vectors
        0100-01FF               Free
        0200-wherever           Kernel
-       DB00                    Discard
+       DB00                    Discard (need to fix to reclaim buffers here)
        E400                    Common
        F000                    Video
 
@@ -33,16 +33,8 @@ Done so far:
 - Basic initialization and setup, video and machine type probing
 - Sketch of various drivers
 - Basic floppy driver code
-
-To Do:
-- Floppy - media detect/sectors per track etc
 - Try mounting a file system on floppy
-- Debug TC keyboard code: shift/ctrl are busted - do we need repeat ?
-- Hard disk driver debug
-- Bank the video
 - Get init loading, load and test userspace
-- IDE driver (note the ubee512 emulator ide appears to be very busted as
-  on 5.8.0)
 - How to tell wd1010 system from 2793 from both with 0x58 switch
        -       Select 0x58 = 0
                See if track register writes to values
@@ -70,19 +62,28 @@ To Do:
        *Never write 0x41 while probing as it's precomp on the WD. 0x45
        however is either cyl_high or track_w so safe
 
+
+To Do:
+- Floppy - media detect/sectors per track etc/ hard skew
+- Debug TC keyboard code: shift/ctrl are busted - do we need repeat ?
+- Hard disk driver debug
+- Bank the video
+- IDE driver (note the ubee512 emulator ide appears to be very busted as
+  on 5.8.0)
 - If we have wd1002-5 and fd wtf do we put IDE in major/minors ?
+- Non TC keyboard (lightpen keyboard)
 
 Longer Term
 - Support attributes, colour, RAM based fonts (load the ROM one into RAM
   customised for bold/italic ?)
 - Hardware 6x45 scrolling
 - Do delayed video output via a buffer off vblank event for non premium
-- Non TC keyboard (lightpen keyboard)
 - Proper support for Z80 PIO interfaces
 - Z8530 SCC
 - Graphics not just vt interfaces
 - Maybe eventually switch to soft interrupt model and support soft serial
   interrupts (ick)
+- Buffer reclaim of discard memory
 
 
 Notes:
index ef89ade..62b6e34 100644 (file)
@@ -56,7 +56,7 @@
 #define NUM_DEV_TTY 1
 #define TTYDEV   BOOT_TTY /* Device used by kernel for messages, panics */
 #define SWAPDEV  (256)   /* Device for swapping (1st hd). */
-#define NBUFS    10       /* Number of block buffers */
+#define NBUFS           /* Number of block buffers */
 #define NMOUNTS         4        /* Number of mounts at a time */
 
 
index 3cf7a71..c3cefc5 100644 (file)
@@ -69,47 +69,6 @@ int tty_carrier(uint8_t minor)
        return 1;
 }
 
-#if 0
-static uint8_t shiftmask[8] = {
-       0, 0, 0, 0, 0, 0, 0, 7
-};
-
-static void keyproc(void)
-{
-       int i;
-       uint8_t key;
-
-       for (i = 0; i < 8; i++) {
-               /* Set one of A0 to A7, and read the byte we get back.
-                  Invert that to get a mask of pressed buttons */
-               keyin[i] = *(uint8_t *) (0xF400 | (1 << i));
-               key = keyin[i] ^ keymap[i];
-               if (key) {
-                       int n;
-                       int m = 1;
-                       for (n = 0; n < 8; n++) {
-                               if ((key & m) && (keymap[i] & m)) {
-                                       if (!(shiftmask[i] & m))
-                                               keysdown--;
-                               }
-                               if ((key & m) && !(keymap[i] & m)) {
-                                       if (!(shiftmask[i] & m)) {
-                                               keysdown++;
-                                               newkey = 1;
-                                               keybyte = i;
-                                               keybit = n;
-                                       }
-                               }
-                               m += m;
-
-                       }
-               }
-               keymap[i] = keyin[i];
-       }
-}
-
-#endif
-
 static uint8_t keymap[15];
 static uint8_t keyin[15];
 static uint8_t keybyte, keybit;
@@ -188,17 +147,6 @@ static void keydecode_tc(void)
        tty_inproc(1, c);
 }
 
-#if 0
-void kbd_interrupt(void)
-{
-       newkey = 0;
-       keyproc();
-       if (keysdown < 3 && newkey)
-               keydecode();
-}
-
-#endif
-
 __sfr __at 0x02        tc256_kstat;
 __sfr __at 0x18 tc256_kcode;
 
@@ -235,3 +183,73 @@ void kbd_interrupt(void)
        if (keysdown < 3 && newkey)
                keydecode_tc();
 }
+
+static const uint8_t xlate[64] = {
+       '@',
+       'a','b','c','d','e','f','g','h',
+       'i','j','k','l','m','n','o','p',
+       'q','r','s','t','u','v','w','x',
+       'y','z',
+       '[','\\',']',
+       '^', KEY_DEL,
+       '0','1','2','3','4','5','6','7','8','9',
+       ':',';',',','-','.','/',
+       KEY_ESC, KEY_BS, KEY_TAB,
+       KEY_PGDOWN, KEY_ENTER, 0/*CAPSLOCK*/, KEY_STOP,
+       ' ', KEY_UP, 0/*Control*/, KEY_DOWN,
+       KEY_LEFT, 0 /* Unused */, 0 /* Unused */, KEY_RIGHT, 0/*Shift*/
+};
+
+static const uint8_t xlate_shift[64] = {
+       '@',
+       'A','B','C','D','E','F','G','H',
+       'I','J','K','L','M','N','O','P',
+       'Q','R','S','T','U','V','W','X',
+       'Y','Z',
+       '{','|','}',
+       '~', KEY_DEL,
+       /* We map _ to shift-0 */
+       '_','!','"','#','$','%','&','\'','(',')',
+       '*','+','<','=','>','?',
+       KEY_ESC, KEY_BS, KEY_TAB,
+       KEY_PGDOWN, KEY_ENTER, 0/*CAPSLOCK*/, KEY_STOP,
+       ' ', KEY_UP, 0/*Control*/, KEY_DOWN,
+       KEY_LEFT, 0 /* Unused */, 0 /* Unused */, KEY_RIGHT, 0/*Shift*/
+};
+
+/*
+ *     Poll the non-TC keyboard: Need to add autorepeat once it works.
+ *
+ *     On the asm side the scan needs fixing to skip ctrl, as we don't want
+ *     to report ctrl as it'll hide down/left/right !
+ */
+
+uint8_t lpen_kbd_last = 0xFF;
+static uint8_t capslock;
+
+void lpen_kbd_poll(void)
+{
+       uint8_t k = kbscan();
+       /* Don't want shift/ctrl */
+       if (k != 0xFF && xlate[k]) {
+               lpen_kbd_last = k;
+               return;
+       }
+       /* Key up ? */
+       if (lpen_kbd_last == 0xFF)
+               return;
+       if (lpen_kbd_last == 53) {      /* Caps lock */
+               capslock ^= 1;
+               return;
+       }
+       if (kbtest(63))
+               k = xlate_shift[k];
+       else
+               k = xlate[k];
+       if (capslock && (k >= 'a' && k <= 'z'))
+               k -= 32;
+       if (k >= 64 && k <= 127 && kbtest(57))
+               k &= 31;
+       tty_inproc(1, k);
+       lpen_kbd_last = 0xFF;
+}
index 300ecd6..a010a72 100644 (file)
@@ -3,6 +3,8 @@
 
 extern void tty_interrupt(void);
 extern void kbd_interrupt(void);
-extern int trstty_close(uint8_t minor);
+extern void lpen_kbd_poll(void);
 
+extern uint8_t kbscan(void);
+extern uint8_t kbtest(uint16_t code);
 #endif
index 26f3bc4..c4e209d 100644 (file)
@@ -1,5 +1,5 @@
 ;
-;      Core floppy routines for the TRS80 1791 FDC
+;      Core floppy routines for the Microbee 2791 FDC
 ;      Based on the 6809 code
 ;
 ;      FIXME: double sided media
index e9bff50..b9d0457 100644 (file)
@@ -11,7 +11,14 @@ uint16_t ramtop = PROGTOP;
    for the polled ports */
 void platform_idle(void)
 {
-       __asm halt __endasm;
+       if (ubee_model == UBEE_256TC)
+               __asm halt __endasm;
+       else {
+               /* Try to make the keyboard suck as little as possible */
+               irqflags_t irq = di();
+               lpen_kbd_poll();
+               irqrestore(irq);
+       }
 }
 
 void do_beep(void)
@@ -43,8 +50,7 @@ void platform_interrupt(void)
        static uint8_t icount;
        uint8_t r = pia0b;
        /* TODO: printer interrupt */
-       /* Need to check if TC */
-       if (r & 0x02)
+       if (ubee_model == UBEE_256TC && (r & 0x02))
                kbd_interrupt();
        if (r & 0x80) {
                cmos_reg = 0x0C;
@@ -57,6 +63,8 @@ void platform_interrupt(void)
                                icount = 0;
                        }
                }
+               if (ubee_model != UBEE_256TC)
+                       lpen_kbd_poll();
        }
 }
 
index ef0230d..b605c39 100644 (file)
@@ -49,7 +49,7 @@
             .include "../kernel.def"
 
 ; -----------------------------------------------------------------------------
-; COMMON MEMORY BANK (0xE800 upwards)
+; COMMON MEMORY BANK (kept even when we task switch)
 ; -----------------------------------------------------------------------------
             .area _COMMONMEM
 
@@ -68,7 +68,7 @@ _platform_reboot:
            jp to_reboot
 
 ;
-;      Sit in common and play with th banks to see what we have
+;      Sit in common and play with the banks to see what we have
 ;
 size_ram:
            ; We could have < 128, 128 or various extensions up to 512K or
@@ -194,8 +194,7 @@ not_t256:
            ; set up the RTC driven periodic timer. The PIA should already
            ; have been configured for us
            ;
-           ; we don't necessarily have one in which case we have a
-           ; (arguably far more useful) vblank timer. In which case this
+           ; we don't necessarily have one. In which case this
            ; routine will pee into the void and do no harm whatsoever
            ;
            ld bc,#0x0A04
@@ -310,7 +309,7 @@ _program_vectors:
             ld hl, #interrupt_handler
             ld (0x0039), hl
 
-            ; set restart vector for UZI system calls
+            ; set restart vector for FUZIX system calls
             ld (0x0030), a   ;  (rst 30h is unix function call vector)
             ld hl, #unix_syscall_entry
             ld (0x0031), hl
@@ -378,29 +377,151 @@ outchar:
 ;      Swap helpers
 ;
 _hd_xfer_in:
-          pop de
-          pop hl
-          push hl
-          push de
-          ld a, (_hd_page)
-          or a
-          call nz, map_process_a
-          ld bc, #0x40                 ; 512 bytes from 0x40
-          inir
-          inir
-          call map_kernel
-          ret
+           pop de
+           pop hl
+           push hl
+           push de
+           ld a, (_hd_page)
+           or a
+           call nz, map_process_a
+           ld bc, #0x40                        ; 512 bytes from 0x40
+           inir
+           inir
+           call map_kernel
+           ret
 
 _hd_xfer_out:
-          pop de
-          pop hl
-          push hl
-          push de
-          ld a, (_hd_page)
-          or a
-          call nz, map_process_a
-          ld bc, #0x40                 ; 512 bytes to 0x40
-          otir
-          otir
-          call map_kernel
-          ret
+           pop de
+           pop hl
+           push hl
+           push de
+           ld a, (_hd_page)
+           or a
+           call nz, map_process_a
+           ld bc, #0x40                        ; 512 bytes to 0x40
+           otir
+           otir
+           call map_kernel
+           ret
+
+;
+;      Ubee Keyboard. Except for the TC the Ubee pulls this crazy (or neat
+;      depending how you look at it) trick of demuxing a keyboard with the
+;      lightpen input.
+;
+;      See the Ubee technical manual for more information on scanning.
+;
+           .area _CODE
+
+           .globl _kbscan
+           .globl _kbtest
+           .globl _lpen_kbd_last
+;
+_kbscan:
+           ; FIXME set right register ??? or do we always put it right
+           ; irq handling versus video setup !
+           in a,(0x0C)
+           bit 6,a             ; No light pen signal - no key
+           jr z, nokey         ; Fast path exit
+            ld a, (_lpen_kbd_last)     ; Rather than the slow scan try and
+            cp #255            ; test if we are holding down the same key
+            jr z, notlast      ; assuming one was held down
+            call ispressed     ; see if the key is held down (usual case)
+           ld a, (_lpen_kbd_last)
+                               ; if so return the last key
+           bit 0,l             ; b = 1 if we found it
+            jr nz, key_return
+notlast:
+           ld l,#57            ; Scan the keys in two banks, the first 57
+           ld de,#0x0000
+           call scanner
+           ld a,#57
+           jr nz, gotkey
+            ld l,#5
+           ld de,#0x03A0       ; and if that fails the last 5 oddities
+           call scanner        ; in order to handle shift etc
+            ld a,#63
+gotkey:
+           sub b
+           jr key_return
+nokey:
+           ld a,#255
+key_return:
+           ld l,a
+           ret
+
+_kbtest:
+           pop hl
+           pop de
+           push de
+           push hl
+           ld a,e
+;
+;      Check if key is currently pressed
+;      Split the key by matrix position and use our scanner
+;
+ispressed:
+           rrca
+           rrca
+           rrca
+           rrca
+           ld e,a
+           and #0x0F
+           ld d,a
+            ld a,e
+            and #0xF0
+            ld e,a
+            ld l,#1
+
+;
+;      Test for keys
+;
+;      On entry L is the number of keys to test
+;      DE is the address to scan
+;
+;      Returns L holding the count of keys until we found a hit
+;
+scanner:
+           ld a,#1
+           out (0x0b),a                ; character ROM so we can scan
+           ld bc,#0x130c               ; for convenience
+           ld h,#31                    ; port numbers used in the loop
+           ld a,#16                    ; select lpen high
+            out (c),a
+            in a,(0x0d)                        ; clear status
+sethigh:    ld a,#18                   ; update register high
+            out (c),a
+            ld a,d
+            out (0x0d),a               ; load passed address
+            ld a,e
+            push de                    ; save working address
+            ld d,#16
+setlow:     out (c),b                  ; set the low byte from the passed address
+           out (0x0d),a
+            out (c),h                  ; dummy read to reset
+            out (0x0d),a
+strobe:     in e,(c)                   ; spin for a strobe
+            jp p, strobe
+            in e,(c)
+            bit 6,e                    ; did we get a strobe ?
+            jr nz,scanner_done
+            dec l                      ; next key to test
+            jr z,scanner_done          ; are we done ?
+            add a,d
+            jp nz,setlow               ; next inner scan
+            pop de
+            ld e,a
+            inc d
+            jp sethigh                 ; next outer scan
+           ;
+           ;   L holds the count remaining and thus computes the keycode
+           ;   0 means 'we found nothing'
+           ;
+scanner_done:
+           pop de                      ; recover position we are at
+            ld a,#16                   ; lpen reset
+            out (0x0c),a
+            in a,(0x0d)                        ; VDU reset
+            xor a
+            out (0x0b),a
+           ret