+/*
+ * The MicroBee has a console interface which we map as tty1. It's a
+ * rather normal 6845 setup but with options to do character based high
+ * res with 8x16 patterns, two colours per pattern.
+ *
+ * The input side on the other hand is a bit different. The TC has a
+ * rather normal sane interface but the older machines wire the keyboard
+ * through some of the address scanning of the 6845 and the light pen
+ * input so that the raster scan does a (slow) keyboard scan. Sucky but
+ * cheap.
+ *
+ * The serial ports are wired to a pair of PIO controllers not to an
+ * actual UART although there are interrupting on the edges. We don't
+ * support those for now. Some machines had add in Z8530 based
+ * interfaces at 0x68/0x69: we need to look at those some day.
+ */
+
#include <kernel.h>
#include <kdata.h>
#include <printf.h>
#include <devtty.h>
#include <stdarg.h>
-char tbuf1[TTYSIZ];
-char tbuf2[TTYSIZ];
+static char tbuf1[TTYSIZ];
uint8_t vtattr_cap;
-__sfr __at 0xE8 tr1865_ctrl;
-__sfr __at 0xE9 tr1865_baud;
-__sfr __at 0xEA tr1865_status;
-__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}
};
/* Write to system console */
}
#if 0
-static uint8_t keymap[8];
-static uint8_t keyin[8];
-static uint8_t keybyte, keybit;
-static uint8_t newkey;
-static int keysdown = 0;
static uint8_t shiftmask[8] = {
0, 0, 0, 0, 0, 0, 0, 7
};
}
}
-static 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', '[', '\\', ']', '^', '_'},
- {'0', '1', '2', '3', '4', '5', '6', '7'},
- {'8', '9', ':', ';', ',', '-', '.', '/'},
- {13, 12, 3, 0 /*up */ , 0 /*down */ , 8 /* left */ , 0 /*right */ ,
- ' '},
- {0, 0, 0, 0, 0xF1, 0xF2, 0xF3, 0}
+#endif
+
+static uint8_t keymap[15];
+static uint8_t keyin[15];
+static uint8_t keybyte, keybit;
+static uint8_t newkey;
+static int keysdown = 0;
+
+/* These are not completely correct for the TC yet */
+static uint8_t keyboard_tc[15][8] = {
+ /* 0x */
+ { KEY_F1, KEY_ESC, KEY_TAB, KEY_STOP, 0, '0','.',' ' },
+ { KEY_F2, '1', 'q', 'a', 0, 0/*Capslock*/, CTRL('M'), KEY_INSERT },
+ /* 1x */
+ { KEY_F3, '2', 'w', 's', '+', '2', '3', 'z' },
+ { KEY_F4, '3', 'e', 'd', '-', '5', '6', 'x' },
+ /* 2x */
+ { KEY_F5, '4', 'r', 'f', '*', '8', '9', 'c' },
+ { KEY_F6, '5', 't', 'g', '7', '1', '4', 'v' },
+ /* 3x */
+ { KEY_F7, '6', 'y', 'h', '/', KEY_DOWN, KEY_RIGHT, 'b' },
+ { KEY_F8, '7', 'u', 'j', 0 , KEY_LEFT, 0 , 'n' },
+ /* 4x */
+ { KEY_F9, '8', 'i', 'k', 0 , 0 , KEY_UP, 'm' },
+ { KEY_F10, '9', 'o', 'l', 0, KEY_BS, KEY_ENTER, ',' },
+ /* 5x */
+ { KEY_F11, '0', 'p', ';', KEY_DEL, '`', '\\', '.' },
+ { KEY_F12, '-', '[', '\'', 0, '=', ']', '/' },
+ /* 60 shift 67 ctrl 70 alt */
};
-static uint8_t shiftkeyboard[8][10] = {
- {'@', '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', '{', '|', '}', '^', '_'},
- {'0', '!', '"', '#', '$', '%', '&', '\''},
- {'(', ')', '*', '+', '<', '=', '>', '?'},
- {13, 12, 3, 0 /*up */ , 0 /*down */ , 8 /* left */ , 0 /*right */ ,
- ' '},
- {0, 0, 0, 0, 0xF1, 0xF2, 0xF3, 0}
+static uint8_t shift_keyboard_tc[15][8] = {
+ /* 0x */
+ { KEY_F1, KEY_ESC, KEY_TAB, KEY_STOP, 0, '0','.',' ' },
+ { KEY_F2, '!', 'Q', 'A', 0, 0/*Capslock*/, CTRL('M'), KEY_INSERT },
+ /* 1x */
+ { KEY_F3, '@', 'W', 'S', '+', '2', '3', 'z' },
+ { KEY_F4, '#', 'E', 'D', '-', '5', '6', 'x' },
+ /* 2x */
+ { KEY_F5, '$', 'R', 'F', '*', '8', '9', 'c' },
+ { KEY_F6, '%', 'T', 'G', '7', '1', '4', 'v' },
+ /* 3x */
+ { KEY_F7, '^', 'Y', 'H', '/', KEY_DOWN, KEY_RIGHT, 'b' },
+ { KEY_F8, '&', 'U', 'J', 0 , KEY_LEFT, 0 , 'n' },
+ /* 4x */
+ { KEY_F9, '*', 'I', 'K', 0 , 0 , KEY_UP, 'm' },
+ { KEY_F10, '(', 'O', 'L', 0, KEY_BS, KEY_ENTER, '<' },
+ /* 5x */
+ { KEY_F11, ')', 'P', ':', KEY_DEL, '"', '|', '>' },
+ { KEY_F12, '_', '{', '\'', 0, '+', '}', '?' },
+ /* 60 shift 67 ctrl 70 alt */
};
+
static uint8_t capslock = 0;
-static void keydecode(void)
+static void keydecode_tc(void)
{
uint8_t c;
- if (keybyte == 7 && keybit == 3) {
+ if (keybyte == 1 && keybit == 5) {
capslock = 1 - capslock;
return;
}
- if (keymap[7] & 3) /* shift */
- c = shiftkeyboard[keybyte][keybit];
+ /* TODO: ALT */
+ if (keymap[6] & 0x80) /* shift */
+ c = shift_keyboard_tc[keybyte][keybit];
else
- c = keyboard[keybyte][keybit];
+ c = keyboard_tc[keybyte][keybit];
- /* The keyboard lacks some rather important symbols so remap them
- with control */
- if (keymap[7] & 4) { /* control */
+ if (keymap[7] & 0x80) { /* control */
if (c > 31 && c < 127)
c &= 31;
- if (keymap[7] & 3) {
- if (c == '(')
- c = '{';
- if (c == ')')
- c = '}';
- if (c == '-')
- c = '_';
- if (c == '/')
- c = '``';
- if (c == '<')
- c = '^';
- } else {
- if (c == '(')
- c = '[';
- if (c == ')')
- c = ']';
- if (c == '-')
- c = '|';
- }
}
if (capslock && c >= 'a' && c <= 'z')
c -= 'a' - 'A';
tty_inproc(1, c);
}
+#if 0
void kbd_interrupt(void)
{
newkey = 0;
}
#endif
+
+__sfr __at 0x02 tc256_kstat;
+__sfr __at 0x18 tc256_kcode;
+
+/* In order to make most of the code follow the same logic as the scan
+ keyboad we basically fake a scan keyboard using the keycodes we get */
+static void keymap_down(uint8_t c)
+{
+ keybyte = c >> 3;
+ keybit = c & 7;
+ if (keybyte < 15) {
+ keymap[keybyte] |= keybit;
+ keysdown++;
+ newkey = 1;
+ }
+}
+
+static void keymap_up(uint8_t c)
+{
+ if (keybyte < 15) {
+ keymap[c >> 3] &= ~(c & 7);
+ keysdown--;
+ }
+}
+
+/* 256TC */
+void kbd_interrupt(void)
+{
+ uint8_t x = tc256_kstat;
+ if (x & 1) {
+ x = tc256_kcode;
+ if (x & 0x80)
+ keymap_down(x & 0x7F);
+ else
+ keymap_up(x & 0x7F);
+ if (keysdown < 3)
+ keydecode_tc();
+ }
+}
.globl fd_nmi_handler
.globl null_handler
+ .globl _ubee_model
+
.globl s__COMMONMEM
.globl l__COMMONMEM
call map_kernel
jp to_reboot
+;
+; Sit in common and play with th banks to see what we have
+;
+size_ram:
+ ; We could have < 128, 128 or various extensions up to 512K or
+ ; so.
+ ld ix,#0x80 ; safe scribble
+ ld c,#0x01
+ ld de,#page_codes
+ ld (ix),#0 ; clear in bank 0 low
+ ld hl,#32
+scan_ram:
+ add hl,hl
+ ld a,(de) ; try entry in table
+ or a
+ jr z,scan_done ; finished
+ inc de
+ out (0x50),a ; select proposed bank
+ ld (ix),c ; write to it
+ ld a,#4
+ out (0x50),a ; back to bank 0
+ ld a,(ix) ; read it back
+ cp c ; did it mess with bank 0L ?
+ jr nz, scan_ram
+
+; We found our first mismatch HL is our memory size
+; info if at least 128K is present (or 64 if not)
+scan_done:
+ ret
+
+page_codes:
+ ; Detect a standard or premium 128K system
+ .byte 0x06 ; write 1 to bank 1L 0x80
+ ; Detect a system with a 256K expansion mod
+ .byte 0x44 ; write 1 to bank 2L 0x80
+ ; Detect a system with a 512K expansion mod
+ .byte 0x84 ; write 1 to bank 4L 0x80
+ ; We don't handle the modern ubee premium plus emulated thing
+ .byte 0x00 ; and done
+
; -----------------------------------------------------------------------------
; KERNEL MEMORY BANK (below 0xE800, only accessible when the kernel is mapped)
; -----------------------------------------------------------------------------
.area _CODE
-; These two must be below 32K and not use the stack until they hit ROM space
+; These two must be below 32K and not use the stack until they hit ROM
+; space.
+;
+; Not sure we can do this for most cases because not everyone has all that
+; ROM
;
to_monitor:
xor a ; 0 or 1 to keep low 32K right ? */
.db 0x1a, 0x19, 0x05, 0x1B, 0x37, 0x58, 0x50, 0x6B
init_early:
-
; load the 6845 parameters
ld hl, #_ctc6845
- ld bc, #0x100C
+ ld bc, #0x0F0C
ctcloop: out (c), b ; register
ld a, (hl)
out (0x0D), a ; data
inc hl
dec b
- jp po, ctcloop ; check V not C
+ jp p, ctcloop
; ensure the CTC clock is right
ld a, #0
in a, (9) ; manual says in but double check
ret
init_hardware:
- ; set system RAM size
- ld hl, #128 ; FIXME according to platform
+ ld a,(_ubee_model)
+ cp #2 ; 256TC
+ ld hl,#256 ; 256TC has 256K
+ call nz, size_ram
+is_tc:
ld (_ramsize), hl
- ld hl, #(128-64) ; 64K for kernel
+ ld de,#64 ; 64K for kernel
+ or a
+ sbc hl,de
ld (_procmem), hl
; set up interrupt vectors for the kernel (also sets up common memory in page 0x000F which is unused)
; set up the RTC driven periodic timer. The PIA should already
; have been configured for us
;
+ ; FIXME: RTC is an option - use vblank instead (pio bit 7)
+ ;
ld a, #0x0A ; PIR timer
out (0x04), a
ld a, #0x1001 ; 64 ints/second
out (0x50), a
pop af
ret
-
map_process:
ld a, h
or l