From: Alan Cox Date: Tue, 17 Apr 2018 22:13:07 +0000 (+0100) Subject: ubee: first sketch out of light pen keyboard support X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=0a8f4ff9b8e8dbe9280f19059c2d5ff445af5fdb;p=FUZIX.git ubee: first sketch out of light pen keyboard support --- diff --git a/Kernel/platform-ubee/README b/Kernel/platform-ubee/README index 33267382..741b4f54 100644 --- a/Kernel/platform-ubee/README +++ b/Kernel/platform-ubee/README @@ -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: diff --git a/Kernel/platform-ubee/config.h b/Kernel/platform-ubee/config.h index ef89ade7..62b6e341 100644 --- a/Kernel/platform-ubee/config.h +++ b/Kernel/platform-ubee/config.h @@ -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 7 /* Number of block buffers */ #define NMOUNTS 4 /* Number of mounts at a time */ diff --git a/Kernel/platform-ubee/devtty.c b/Kernel/platform-ubee/devtty.c index 3cf7a712..c3cefc53 100644 --- a/Kernel/platform-ubee/devtty.c +++ b/Kernel/platform-ubee/devtty.c @@ -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; +} diff --git a/Kernel/platform-ubee/devtty.h b/Kernel/platform-ubee/devtty.h index 300ecd62..a010a725 100644 --- a/Kernel/platform-ubee/devtty.h +++ b/Kernel/platform-ubee/devtty.h @@ -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 diff --git a/Kernel/platform-ubee/floppy.s b/Kernel/platform-ubee/floppy.s index 26f3bc4c..c4e209dc 100644 --- a/Kernel/platform-ubee/floppy.s +++ b/Kernel/platform-ubee/floppy.s @@ -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 diff --git a/Kernel/platform-ubee/main.c b/Kernel/platform-ubee/main.c index e9bff507..b9d04571 100644 --- a/Kernel/platform-ubee/main.c +++ b/Kernel/platform-ubee/main.c @@ -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(); } } diff --git a/Kernel/platform-ubee/ubee.s b/Kernel/platform-ubee/ubee.s index ef0230d4..b605c394 100644 --- a/Kernel/platform-ubee/ubee.s +++ b/Kernel/platform-ubee/ubee.s @@ -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