From: Alan Cox Date: Sun, 1 Jul 2018 23:58:12 +0000 (+0100) Subject: trs80m1: sort out the keyboard X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=1adb4ac0df5b738202e1a46fd3307a61d6608f62;p=FUZIX.git trs80m1: sort out the keyboard We now correctly implement the Model I and III keyboards including allowing the use of downarrow for control and various extra control/control-shift combos for characters that are otherwise missing. While we are at it put back the framework for console flipping although this depends at the moment on a key you can't press ! --- diff --git a/Kernel/platform-trs80m1/Makefile b/Kernel/platform-trs80m1/Makefile index f8517220..301b199d 100644 --- a/Kernel/platform-trs80m1/Makefile +++ b/Kernel/platform-trs80m1/Makefile @@ -3,7 +3,7 @@ CSRCS = devlpr.c devtty.c devfd.c devfd3.c devhd.c devgfx.c CSRCS += devices.c main.c DISCARD_CSRCS = discard.c devhd_discard.c -ASRCS = trs80.s trs80-bank.s crt0.s +ASRCS = trs80.s trs80-bank.s crt0.s vtswap.s ASRCS += tricks.s commonmem.s floppy.s floppy3.s COBJS = $(CSRCS:.c=.rel) diff --git a/Kernel/platform-trs80m1/README b/Kernel/platform-trs80m1/README index 2628a468..a865242b 100644 --- a/Kernel/platform-trs80m1/README +++ b/Kernel/platform-trs80m1/README @@ -9,8 +9,9 @@ Emulator Bugs: PC -= 2". FUZIX doesn't do any overlapped LDIR tricks so shouldn't be affected. - The interrupt flags are misemulated. A patch for this is in the - Fuzix tree and is needed to run Fuzix. + The interrupt flags are misemulated and RETI is also wrong. + + Use the xtrs in the EtchedPixels github User Space: The TRS80 Model I/III have ROM in the low 16K. At the moment our @@ -24,14 +25,20 @@ Requirements: Floppy drive or Hard drive (strongly recommend the latter) Optional: - Lower case modification (or will be) + Lower case modification To Do: - Keyboard mappings for keys not present on Model 1 Other banked expansions Hires card - Stringy floppy + Stringy floppy (Model 1 looks easy but needs ROM image) Orchestra + Graphics hooks (both hires and also describe 64x16 lo-res pixel blocks) + Look at RTS/CTS flow control + - Needs tty sleeping support + - Needs to deal with model 1 case where it's polled so we need + to check the flow control on timer ticks if needed + Fast block copy routines for uget/uput + Hint based pre-fetching uget Memory Map: 0000-3FFF Various fixed model 1 functionality diff --git a/Kernel/platform-trs80m1/config.h b/Kernel/platform-trs80m1/config.h index 776e9651..dcadfd14 100644 --- a/Kernel/platform-trs80m1/config.h +++ b/Kernel/platform-trs80m1/config.h @@ -14,6 +14,7 @@ #define CONFIG_VT /* Simple character addressed device */ #define CONFIG_VT_SIMPLE +#define CONFIG_VT_MULTI /* Banked memory set up */ #define CONFIG_BANK_FIXED @@ -53,7 +54,7 @@ #define CMDLINE NULL /* Location of root dev name */ /* Device parameters */ -#define NUM_DEV_TTY 2 +#define NUM_DEV_TTY 3 #define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ #define SWAPDEV (swap_dev) /* Device for swapping (dynamic). */ #define NBUFS 5 /* Number of block buffers - keep in sync with asm! */ diff --git a/Kernel/platform-trs80m1/devtty.c b/Kernel/platform-trs80m1/devtty.c index 2bbe9d39..ff36b45f 100644 --- a/Kernel/platform-trs80m1/devtty.c +++ b/Kernel/platform-trs80m1/devtty.c @@ -7,11 +7,18 @@ #include #include -char tbuf1[TTYSIZ]; -char tbuf2[TTYSIZ]; +static char tbuf1[TTYSIZ]; +static char tbuf2[TTYSIZ]; +static char tbuf3[TTYSIZ]; +static uint8_t curtty; /* output side */ +static uint8_t inputtty; /* input side */ +static struct vt_switch ttysave[2]; +static uint8_t vtbackbuf[VT_WIDTH * VT_HEIGHT]; struct vt_repeat keyrepeat; +uint8_t *vtbase[2] = { 0xF800, vtbackbuf }; + __sfr __at 0xE8 tr1865_ctrl; __sfr __at 0xE9 tr1865_baud; __sfr __at 0xEA tr1865_status; @@ -20,7 +27,8 @@ __sfr __at 0xEB tr1865_rxtx; 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 }, - { tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ/2 } + { tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ/2 }, + { tbuf3, tbuf3, tbuf3, TTYSIZ, 0, TTYSIZ/2 } }; /* Write to system console */ @@ -36,6 +44,7 @@ ttyready_t tty_writeready(uint8_t minor) uint8_t reg; if (minor != 2) return TTY_READY_NOW; + /* TODO: check model status & 0x80 for CTS flow control if appropriate */ reg = tr1865_status; return (reg & 0x40) ? TTY_READY_NOW : TTY_READY_SOON; } @@ -49,6 +58,27 @@ static void vtflush(void) vtq = vtbuf; } +static void vtexchange(void) +{ + /* Swap the pointers over: TRS80 video we switch by copying not + flipping hardware pointers */ + uint8_t *v = vtbase[0]; + vtbase[0] = vtbase[1]; + vtbase[1] = v; + /* The cursor x/y for current tty are stale in the save area + so save them */ + vt_save(&ttysave[curtty]); + + /* Before we flip the memory */ + cursor_off(); + + vtswap(); + + /* Cursor back */ + if (!ttysave[inputtty].cursorhide) + cursor_on(ttysave[inputtty].cursory, ttysave[inputtty].cursorx); +} + void tty_putc(uint8_t minor, unsigned char c) { irqflags_t irq; @@ -56,7 +86,20 @@ void tty_putc(uint8_t minor, unsigned char c) tr1865_rxtx = c; else { irq = di(); - if (vtq == vtbuf + sizeof(vtbuf)) + if (curtty != minor -1) { + /* Kill the cursor as we are changing the memory buffers. If + we don't do this the next cursor_off will hit the wrong + buffer */ + vtflush(); + cursor_off(); + vt_save(&ttysave[curtty]); + curtty = minor - 1; + vt_load(&ttysave[curtty]); + /* Fix up the cursor */ + if (!ttysave[curtty].cursorhide) + cursor_on(ttysave[curtty].cursory, ttysave[curtty].cursorx); + } + else if (vtq == vtbuf + sizeof(vtbuf)) vtflush(); *vtq++ = c; irqrestore(irq); @@ -68,7 +111,7 @@ void tty_interrupt(void) uint8_t reg = tr1865_status; if (reg & 0x80) { reg = tr1865_rxtx; - tty_inproc(2, reg); + tty_inproc(3, reg); } } @@ -85,37 +128,37 @@ void tty_setup(uint8_t minor) { uint8_t baud; uint8_t ctrl; - if (minor != 2) + if (minor != 3) return; - baud = ttydata[2].termios.c_cflag & CBAUD; + baud = ttydata[3].termios.c_cflag & CBAUD; if (baud > B19200) { - ttydata[2].termios.c_cflag &= ~CBAUD; - ttydata[2].termios.c_cflag |= B19200; + ttydata[3].termios.c_cflag &= ~CBAUD; + ttydata[3].termios.c_cflag |= B19200; baud = B19200; } baud = trsbaud[baud]; tr1865_baud = baud | (baud << 4); - ctrl = 3; - if (ttydata[2].termios.c_cflag & PARENB) { - if (ttydata[2].termios.c_cflag & PARODD) + ctrl = 3; /* DTR|RTS */ + if (ttydata[3].termios.c_cflag & PARENB) { + if (ttydata[3].termios.c_cflag & PARODD) ctrl |= 0x80; } else ctrl |= 0x8; /* No parity */ - ctrl |= trssize[(ttydata[2].termios.c_cflag & CSIZE) >> 4]; + ctrl |= trssize[(ttydata[3].termios.c_cflag & CSIZE) >> 4]; tr1865_ctrl = ctrl; } int trstty_close(uint8_t minor) { - if (minor == 2 && ttydata[2].users == 0) - tr1865_ctrl = 0; /* Drop carrier */ + if (minor == 3 && ttydata[3].users == 0) + tr1865_ctrl = 0; /* Drop carrier and rts */ return tty_close(minor); } int tty_carrier(uint8_t minor) { - if (minor != 2) + if (minor != 3) return 1; if (tr1865_ctrl & 0x80) return 1; @@ -174,22 +217,25 @@ uint8_t keyboard[8][8] = { {'@', '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', '[', '\\', ']', '^', '_' }, + {'x', 'y', 'z', 0, 0, 0, 0, 0 }, {'0', '1', '2', '3', '4', '5', '6', '7' }, {'8', '9', ':', ';', ',', '-', '.', '/' }, - { KEY_ENTER, KEY_CLEAR, KEY_STOP, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, ' '}, - { 0, 0, 0, 0, KEY_F1, KEY_F2, KEY_F3, 0 } + { KEY_ENTER, KEY_CLEAR, KEY_STOP, KEY_UP, 0/*KEY_DOWN*/, KEY_LEFT, KEY_RIGHT, ' '}, + /* The Model 1 only has bit 0 of this for its shift key. The Model 3 + has bit 2 for right shift. Some add-ons used bit 4 for control, + other things borrowed the down arrow */ + { 0, 0, 0, 0, 0, 0, 0, 0 } }; uint8_t shiftkeyboard[8][8] = { {'@', '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', '{', '|', '}', '^', '_' }, + {'X', 'Y', 'Z', 0, 0, 0, 0, 0 }, {'0', '!', '"', '#', '$', '%', '&', '\'' }, {'(', ')', '*', '+', '<', '=', '>', '?' }, - { KEY_ENTER, KEY_CLEAR, KEY_STOP, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, ' '}, - { 0, 0, 0, 0, KEY_F1, KEY_F2, KEY_F3, 0 } + { KEY_ENTER, KEY_CLEAR, KEY_STOP, KEY_UP, 0/*KEY_DOWN*/, KEY_LEFT, KEY_RIGHT, ' '}, + { 0, 0, 0, 0, 0, 0, 0, 0 } }; static uint8_t capslock = 0; @@ -204,14 +250,23 @@ static void keydecode(void) return; } - if (keymap[7] & 3) { /* shift */ + /* Only the model 3 has right shift (2) */ + if (keymap[7] & 3) { /* shift (left/right) */ c = shiftkeyboard[keybyte][keybit]; + /* VT switcher */ + if (c == KEY_F1 || c == KEY_F2) { + if (inputtty != c - KEY_F1) { + inputtty = c - KEY_F1; + vtexchange(); /* Exchange the video and backing buffer */ + } + return; + } } else c = keyboard[keybyte][keybit]; /* The keyboard lacks some rather important symbols so remap them - with control */ - if (keymap[7] & 4) { /* control */ + with control (down arrow)*/ + if ((keymap[6] | keymap[7]) & 16) { /* control */ if (keymap[7] & 3) { /* shift */ if (c == '(') c = '{'; @@ -224,9 +279,9 @@ static void keydecode(void) if (c == '<') c = '^'; } else { - if (c == '(') + if (c == '8'/*'('*/) c = '['; - else if (c == ')') + else if (c == '9'/*')'*/) c = ']'; else if (c == '-') c = '|'; diff --git a/Kernel/platform-trs80m1/devtty.h b/Kernel/platform-trs80m1/devtty.h index 12714e4d..1d4bc755 100644 --- a/Kernel/platform-trs80m1/devtty.h +++ b/Kernel/platform-trs80m1/devtty.h @@ -6,6 +6,9 @@ extern void kbd_interrupt(void); extern int trstty_close(uint8_t minor); extern void vtbuf_init(void); +/* And from the asm helper */ +extern void vtswap(void); + #define KEY_ROWS 8 #define KEY_COLS 8 extern uint8_t keymap[8]; @@ -13,5 +16,4 @@ extern uint8_t keyboard[8][8]; extern uint8_t shiftkeyboard[8][8]; extern uint8_t *vtbase[2]; -extern uint8_t curtty; #endif diff --git a/Kernel/platform-trs80m1/fuzix.lnk b/Kernel/platform-trs80m1/fuzix.lnk index 666b038d..43db9d7c 100644 --- a/Kernel/platform-trs80m1/fuzix.lnk +++ b/Kernel/platform-trs80m1/fuzix.lnk @@ -46,5 +46,6 @@ vt.rel devsys.rel platform-trs80m1/devlpr.rel platform-trs80m1/devtty.rel +platform-trs80m1/vtswap.rel platform-trs80m1/discard.rel -e diff --git a/Kernel/platform-trs80m1/vtswap.s b/Kernel/platform-trs80m1/vtswap.s new file mode 100644 index 00000000..1ab78b0d --- /dev/null +++ b/Kernel/platform-trs80m1/vtswap.s @@ -0,0 +1,32 @@ +; +; Do this in assembler so we can keep the vtbackbuf banked +; + .module vtswap + + .area _CODE2 + + .globl _vtswap + .globl _vtbackbuf + +_vtbackbuf: + .ds 1024 + +_vtswap: + ld hl, #0xf800 + ld de, #_vtbackbuf + ld bc, #1024 ; 64 * 16 + exchit: + push bc + ld a, (de) ; Could be optimised but its only 1K + ld c, (hl) ; Probably worth doing eventuallly + ex de, hl + ld (hl), c + ld (de), a + inc hl + inc de + pop bc + dec bc + ld a, b + or c + jr nz, exchit + ret