#define MODE_EXTEND_CMD 0x40
+#define V99xx_VRAM_PAGE_SIZE 0x4000
+
/* vram access flags */
#define REG_VRAM_ADDR_MASK 1
#define REG_VRAM_WRITE_FLAG 0x40
#undef CONFIG_SINGLETASK
/* Video terminal, not a serial tty */
#define CONFIG_VT
+#define CONFIG_VT_MULTI
/* 16K banking so use the helper */
#define CONFIG_BANK16
#define MAX_MAPS 255
#define VT_RIGHT 79
#define VT_BOTTOM 23
+/* MODE TEXT2 supports up to 16 VT's */
+#define MAX_VT 4
+
#define TICKSPERSEC 60 /* default value, it will be upated on device_init */
#define PROGBASE 0x0000 /* also data base */
#define PROGLOAD 0x0100
#define CMDLINE NULL /* Location of root dev name */
/* Device parameters */
-#define NUM_DEV_TTY 2
+#define NUM_DEV_TTY 5
+#define TTYSIZ 64
#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */
#define NBUFS 10 /* Number of block buffers */
#define NMOUNTS 4 /* Number of mounts at a time */
#undef DEBUG /* UNdefine to delete debug code sequences */
+extern void set_active_vt(uint8_t curtty);
+extern void set_visible_vt(uint8_t curtty);
+
__sfr __at 0x2F tty_debug2;
__sfr __at 0xAA kbd_row_set;
__sfr __at 0xA9 kbd_row_read;
char tbuf1[TTYSIZ];
char tbuf2[TTYSIZ];
+char tbuf3[TTYSIZ];
+char tbuf4[TTYSIZ];
+char tbuf5[TTYSIZ];
+uint8_t curtty;
+uint8_t inputtty;
+static struct vt_switch ttysave[5];
struct vt_repeat keyrepeat;
uint8_t vtattr_cap;
static uint8_t kbd_timer;
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},
+ {tbuf4, tbuf4, tbuf4, TTYSIZ, 0, TTYSIZ / 2},
+ {tbuf5, tbuf5, tbuf5, TTYSIZ, 0, TTYSIZ / 2},
};
uint8_t keyboard[11][8];
uint8_t shiftkeyboard[11][8];
-/* tty1 is the screen tty2 is the debug port */
+/* tty1 to tty4 is the screen tty5 is the debug port */
/* Output for the system console (kprintf etc) */
void kputchar(char c)
{
/* Debug port for bringup */
if (c == '\n')
- tty_putc(2, '\r');
- tty_putc(2, c);
+ tty_putc(5, '\r');
+ tty_putc(5, c);
}
-/* Both console and debug port are always ready */
+/* All tty are always ready */
ttyready_t tty_writeready(uint8_t minor)
{
minor;
+ // tty are ready to write
return TTY_READY_NOW;
}
-void tty_putc(uint8_t minor, unsigned char c)
+void vtexchange()
{
- minor;
+ vt_save(&ttysave[curtty]);
+ cursor_off();
+ set_visible_vt(inputtty);
+ cursor_on(ttysave[inputtty].cursory, ttysave[inputtty].cursorx);
+}
- vtoutput(&c, 1);
- tty_debug2 = c;
+void tty_putc(uint8_t minor, unsigned char c)
+{
+ irqflags_t irq;
+ if (minor == 5)
+ tty_debug2 = c;
+ else {
+ irq = di();
+ if (curtty != minor -1) {
+ vt_save(&ttysave[curtty]);
+ curtty = minor - 1;
+ vt_load(&ttysave[curtty]);
+ set_active_vt(curtty);
+ }
+ vtoutput(&c, 1);
+ irqrestore(irq);
+ }
}
int tty_carrier(uint8_t minor)
minor;
/* setup termios to use msx keys */
- ttydata[1].termios.c_cc[VERASE] = KEY_BS;
- ttydata[1].termios.c_cc[VSTOP] = KEY_STOP;
- ttydata[1].termios.c_cc[VSTART] = KEY_STOP;
+ ttydata[minor].termios.c_cc[VERASE] = KEY_BS;
+ ttydata[minor].termios.c_cc[VSTOP] = KEY_STOP;
+ ttydata[minor].termios.c_cc[VSTART] = KEY_STOP;
}
uint8_t keymap[11];
return;
}
- if (keymap[6] & 3 ) /* shift or control */
+ if (keymap[6] & 3 ) { /* shift or control */
c = shiftkeyboard[keybyte][keybit];
- else
+ /* VT switcher */
+ if (c == KEY_F1 || c == KEY_F2 || c == KEY_F3 || c == KEY_F4) {
+ if (inputtty != c - KEY_F1) {
+ inputtty = c - KEY_F1;
+ vtexchange(); /* Exchange the video and backing buffer */
+ }
+ return;
+ }
+ } else
c = keyboard[keybyte][keybit];
if (keymap[6] & 2) { /* control */
/* TODO: function keys (F1-F10), graph, code */
- vt_inproc(1, c);
+ vt_inproc(inputtty +1, c);
}
void update_keyboard()
/* This is used by the vt asm code, but needs to live in the kernel */
uint16_t cursorpos;
-
#include <kernel.h>
#include <vt.h>
#include <v99xx.h>
+#include <printf.h>
-/* TODO: extend to support multiple VT (or scrollable history)
- * possible to keep up to 31 pages in VRAM */
#define VT_BASE 0x0000
#define VT_BASE_FONT 0x1000
#define VT_BASE_BLINK 0x800
#define VT_BUFSIZE 80
+#define VT_OFFSET 0x2000
extern void *fontdata_6x8;
static uint8_t vt_buff[VT_BUFSIZE];
static uint16_t cur_blink_addr = 0;
+static uint16_t vt_offset;
void vdpinit()
{
+ uint8_t i;
+
v99xx_set_mode(MODE_TEXT2);
v99xx_set_color(15, 4);
v99xx_copy_to_vram(VT_BASE_FONT + 32*8, (uint8_t *)&fontdata_6x8, 768);
v99xx_set_blink_color(15, 8);
v99xx_set_blink_period(4, 4);
+
+ /* clean vram for all vt's */
+ for (i = 0; i < MAX_VT; i++) {
+ v99xx_set_vram_page(i/2);
+ v99xx_memset_vram(VT_BASE + i * VT_OFFSET, ' ', VT_HEIGHT * VT_WIDTH);
+ v99xx_memset_vram(VT_BASE_BLINK + i * VT_OFFSET, 0,
+ VT_HEIGHT * VT_WIDTH / 8);
+ }
+ vt_offset = 0;
}
void clear_lines(int8_t y, int8_t ct)
{
uint16_t addr;
- addr = VT_BASE + y * VT_WIDTH;
+ addr = VT_BASE + vt_offset + y * VT_WIDTH;
+ v99xx_set_vram_page(addr / V99xx_VRAM_PAGE_SIZE);
v99xx_memset_vram(addr, ' ', ct * VT_WIDTH);
}
{
uint16_t addr;
- addr = VT_BASE + y * VT_WIDTH + x;
+ addr = VT_BASE + vt_offset + y * VT_WIDTH + x;
+ v99xx_set_vram_page(addr / V99xx_VRAM_PAGE_SIZE);
v99xx_memset_vram(addr, ' ', l);
}
void cursor_off(void)
{
+ v99xx_set_vram_page(cur_blink_addr / V99xx_VRAM_PAGE_SIZE);
v99xx_write_vram(cur_blink_addr, 0);
}
uint16_t blink_addr;
uint8_t bit;
- blink_addr = VT_BASE_BLINK + y * 10 + (x >> 3);
+ blink_addr = VT_BASE_BLINK + vt_offset + y * 10 + (x >> 3);
bit = 7 - (x & 0x7);
-
+ v99xx_set_vram_page(blink_addr / V99xx_VRAM_PAGE_SIZE);
v99xx_write_vram(blink_addr, 1 << bit);
cur_blink_addr = blink_addr;
}
void memcpy_vram(uint16_t dst, uint16_t src, uint16_t size)
{
uint16_t i;
-
+ v99xx_set_vram_page(dst / V99xx_VRAM_PAGE_SIZE);
for (i = 0; i < size; i += VT_BUFSIZE) {
v99xx_copy_from_vram(vt_buff, src + i, VT_BUFSIZE);
v99xx_copy_to_vram(dst + i, vt_buff, VT_BUFSIZE);
- }
+}
}
void scroll_up(void)
{
- memcpy_vram(VT_BASE, VT_WIDTH, VT_WIDTH * VT_BOTTOM);
+ memcpy_vram(VT_BASE + vt_offset , VT_WIDTH + vt_offset, VT_WIDTH * VT_BOTTOM);
}
void scroll_down(void)
{
- memcpy_vram(VT_WIDTH, VT_BASE, VT_WIDTH * VT_BOTTOM);
+ memcpy_vram(VT_WIDTH + vt_offset , VT_BASE + vt_offset , VT_WIDTH * VT_BOTTOM);
}
void plot_char(int8_t y, int8_t x, uint16_t c)
{
uint16_t addr;
-
- addr = VT_BASE + y * VT_WIDTH + x;
+ addr = VT_BASE + vt_offset + y * VT_WIDTH + x;
+ v99xx_set_vram_page(addr / V99xx_VRAM_PAGE_SIZE);
v99xx_write_vram(addr, c);
}
void vtattr_notify(void)
{
}
+
+void set_active_vt(uint8_t vt)
+{
+ vt_offset = vt * VT_OFFSET;
+}
+
+void set_visible_vt(uint8_t vt)
+{
+ uint8_t val;
+ uint16_t offset = vt * VT_OFFSET;
+
+ val = (uint8_t)(((VT_BASE + offset & 0xF800) >> 10) | 0x03);
+ v99xx_write_reg(V99xx_REG_PTRN_LAYOUT_BASE, val);
+
+ val = (uint8_t)(((VT_BASE_BLINK + offset & 0x3F00) >> 6) | 0x07);
+ v99xx_write_reg(V99xx_REG_COLOR_BASE_H, val);
+
+ val = (uint8_t)(((VT_BASE_BLINK + offset & 0xC000) >> 14) & 0x07);
+ v99xx_write_reg(V99xx_REG_COLOR_BASE_L, val);
+}