From 64d7f584885dd43d5b3a4893beb84165c7244ec6 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sat, 29 Oct 2016 21:47:02 +0200 Subject: [PATCH] Add CRT9128 video terminal driver CRT9028/CRT9128 from Standard Microsystems Corporation. Signed-off-by: Tormod Volden --- Kernel/dev/crt9128.c | 167 +++++++++++++++++++++++++++++++++++++++++++ Kernel/dev/crt9128.h | 35 +++++++++ 2 files changed, 202 insertions(+) create mode 100644 Kernel/dev/crt9128.c create mode 100644 Kernel/dev/crt9128.h diff --git a/Kernel/dev/crt9128.c b/Kernel/dev/crt9128.c new file mode 100644 index 00000000..ea2ecdf9 --- /dev/null +++ b/Kernel/dev/crt9128.c @@ -0,0 +1,167 @@ +/* SMC CRT9128 Video Terminal Logic Controller driver */ +/* 2016-10-29 Tormod Volden */ + +#include +#include "crt9128.h" +#include + +/* constants for now, otherwise must be shadowed */ +static const uint8_t tosadd_tim = 0; /* CRT9128_TOSADD_TIM for 50 Hz */ +static const uint8_t curhi_sle = 0; /* non-scrolling status line enable */ + +/* these are mask-programmed in the chip */ +static const uint8_t data_row_length = 80; +static const uint8_t display_lines = 24; +static const uint8_t vram_lines = 25; + +/* keep track of current scan-out offset */ +static uint8_t vram_start_line; +/* shadow register */ +static uint8_t attdat; + +static uint8_t crt9128_read_char(void) +{ + *((volatile uint8_t *)CRT9128_ADDRESS_REG) = CRT9128_REG_CHARACTER; + *((volatile uint8_t *)CRT9128_DATA_REG); + while (!crt9128_done()); + return *((volatile uint8_t *)CRT9128_DATA_REG); +} + +static void crt9128_write_reg(uint8_t reg, uint8_t value) +{ + *((volatile uint8_t *)CRT9128_ADDRESS_REG) = reg; + *((volatile uint8_t *)CRT9128_DATA_REG) = value; +} + +static void crt9128_fill(uint16_t end_addr, uint8_t character) +{ + crt9128_write_reg(CRT9128_REG_FILADD, end_addr >> 4); + while (!crt9128_done()); + crt9128_write_reg(CRT9128_REG_CHARACTER, character); +} + +static void crt9128_set_cursor_address(uint16_t addr) +{ + while (!crt9128_done()); + crt9128_write_reg(CRT9128_REG_CURLO, addr & 0xff); + crt9128_write_reg(CRT9128_REG_CURHI, addr >> 8 | curhi_sle); +} + +/* the scan-out offset register is used for fast scrolling */ +static void crt9128_set_tos_line(uint8_t vram_line) +{ + crt9128_write_reg(CRT9128_REG_TOSADD, tosadd_tim | vram_line * (data_row_length >> 4)); +} + +void crt9128_init(void) +{ + vram_start_line = 0; + attdat = CRT9128_ATTDAT_TAG_REVERSE_VIDEO | CRT9128_ATTDAT_SCREEN; + + crt9128_write_reg(CRT9128_REG_CHIP_RESET, 0); + crt9128_write_reg(CRT9128_REG_MODE_REGISTER, 0); + crt9128_write_reg(CRT9128_REG_ATTDAT, attdat); + crt9128_set_tos_line(vram_start_line); + clear_lines(0, display_lines); +} + +/* return cursor address as a bonus */ +static uint16_t crt9128_set_cursor(uint8_t newy, uint8_t newx) +{ + uint8_t vram_line; + uint16_t cur_addr; + + vram_line = vram_start_line + newy; + if (vram_line >= vram_lines) + vram_line -= vram_lines; + cur_addr = vram_line * data_row_length + newx; + crt9128_set_cursor_address(cur_addr); + return cur_addr; +} + +static void crt9128_blank_hidden_line(void) +{ + uint16_t start_addr; + uint16_t end_addr; + + end_addr = vram_start_line * data_row_length; + if (end_addr == 0) + start_addr = (vram_lines - 1) * data_row_length; + else + start_addr = end_addr - data_row_length; + crt9128_set_cursor_address(start_addr); + crt9128_fill(end_addr, ' '); +} + +/* interface to Kernel/vt.c VT52 emulation */ + +void clear_across(int8_t y, int8_t x, int16_t num) +{ + uint16_t end_addr; + + end_addr = crt9128_set_cursor(y, x) + (num & 0xff); + crt9128_fill(end_addr, ' '); +} + +/* also sets cursor to first cleared line */ +void clear_lines(int8_t y, int8_t num) +{ + uint16_t end_addr; + + end_addr = crt9128_set_cursor(y, 0) + num * data_row_length; + if (end_addr >= vram_lines * data_row_length) + end_addr -= vram_lines * data_row_length; + crt9128_fill(end_addr, ' '); +} + +void scroll_up(void) +{ + crt9128_blank_hidden_line(); + if (vram_start_line == vram_lines - 1) + vram_start_line = 0; + else + vram_start_line++; + crt9128_set_tos_line(vram_start_line); +} + +void scroll_down(void) +{ + crt9128_blank_hidden_line(); + if (vram_start_line == 0) + vram_start_line = vram_lines - 1; + else + vram_start_line--; + crt9128_set_tos_line(vram_start_line); +} + +void plot_char(int8_t y, int8_t x, uint16_t c) +{ + crt9128_set_cursor(y, x); + crt9128_write_reg(CRT9128_REG_CHARACTER, c & 0x7f); +} + +void cursor_off(void) +{ + attdat |= CRT9128_ATTDAT_CURSOR_SUPRESS; + crt9128_write_reg(CRT9128_REG_ATTDAT, attdat); +} + +void cursor_on(int8_t newy, int8_t newx) +{ + crt9128_set_cursor(newy, newx); + + attdat &= ~CRT9128_ATTDAT_CURSOR_SUPRESS; + crt9128_write_reg(CRT9128_REG_ATTDAT, attdat); +} + +void vtattr_notify(void) +{} + +void video_cmd(uint8_t *ptr) +{} + +void video_read(uint8_t *ptr) +{} + +void video_write(uint8_t *ptr) +{} diff --git a/Kernel/dev/crt9128.h b/Kernel/dev/crt9128.h new file mode 100644 index 00000000..9c3c6b26 --- /dev/null +++ b/Kernel/dev/crt9128.h @@ -0,0 +1,35 @@ +/* SMC CRT9128 Video Terminal Logic Controller driver */ +/* 2016-10-29 Tormod Volden */ + +/* CRT9128_BASE defined in platform config.h */ +#define CRT9128_DATA_REG CRT9128_BASE /* read/write */ +#define CRT9128_ADDRESS_REG (CRT9128_BASE+1) /* write only */ +#define CRT9128_STATUS_REG CRT9128_ADDRESS_REG /* read only */ + +#define CRT9128_REG_CHIP_RESET 0x6 +#define CRT9128_REG_TOSADD 0x8 +#define CRT9128_REG_CURLO 0x9 +#define CRT9128_REG_CURHI 0xa +#define CRT9128_REG_FILADD 0xb +#define CRT9128_REG_ATTDAT 0xc +#define CRT9128_REG_CHARACTER 0xd +#define CRT9128_REG_MODE_REGISTER 0xe + +#define CRT9128_STATUS_DONE (1<<7) +#define CRT9128_TOSADD_TIM (1<<7) +#define CRT9128_CURHI_SLE (1<<7) +#define CRT9128_ATTDAT_MODE_SELECT (1<<7) +#define CRT9128_ATTDAT_CURSOR_SUPRESS (1<<6) +#define CRT9128_ATTDAT_CURSOR_DISPLAY (1<<5) +#define CRT9128_ATTDAT_SCREEN (1<<4) +#define CRT9128_ATTDAT_TAG_CHAR_SUPRESS (1<<3) +#define CRT9128_ATTDAT_TAG_INTENSITYs (1<<2) +#define CRT9128_ATTDAT_TAG_UNDERLINE (1<<1) +#define CRT9128_ATTDAT_TAG_REVERSE_VIDEO (1<<0) +#define CRT9128_MODE_AUTO_INCREMENT (1<<7) + +#define crt9128_status() (*(volatile uint8_t *)CRT9128_STATUS_REG) +#define crt9128_done() (crt9128_status() & CRT9128_STATUS_DONE) + +void crt9128_init(void); + -- 2.34.1