diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e4d339..e097a0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,15 @@ pico_sdk_init() project(pico-cr100) -add_executable(cr100 chargen.c vt.c keyboard.c) +add_executable(cr100 + chargen.c + vt.c + keyboard.c + hl-vt100/src/lw_terminal_parser.c + hl-vt100/src/lw_terminal_vt100.c + ) + +target_include_directories(cr100 PRIVATE hl-vt100/src) pico_enable_stdio_usb(cr100 1) diff --git a/atkbd.pio b/atkbd.pio index 980100f..35c9d81 100644 --- a/atkbd.pio +++ b/atkbd.pio @@ -44,8 +44,8 @@ send_bit: % c-sdk { #include "hardware/clocks.h" -void atkbd_program_init(PIO pio, int sm, int base_pin) { - pio_sm_config c = vga_660x400_70_program_get_default_config(offset); +void atkbd_program_init(PIO pio, int sm, int offset, int base_pin) { + pio_sm_config c = atkbd_program_get_default_config(offset); sm_config_set_in_pins(&c, base_pin); sm_config_set_in_shift(&c, 1, 1, 10); @@ -57,14 +57,14 @@ void atkbd_program_init(PIO pio, int sm, int base_pin) { sm_config_set_jmp_pin(&c, base_pin + 1); - sm_config_set_clkdiv(&c, clock_get_hz(clk_sys() / 8000000); // 8 MHz + sm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / 8000000); // 8 MHz // Set this pin's GPIO function (connect PIO to the pad) pio_gpio_init(pio, base_pin); pio_gpio_init(pio, base_pin+1); - // make sure the pins are outputs - pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false); + // make sure the pins are initially inputs + pio_sm_set_consecutive_pindirs(pio, sm, base_pin, 2, false); // Load our configuration, and jump to the start of the program pio_sm_init(pio, sm, offset, &c); diff --git a/chargen.c b/chargen.c index 94f81a7..dde017c 100644 --- a/chargen.c +++ b/chargen.c @@ -11,7 +11,7 @@ #include "vga_660x477_60.pio.h" -#include "vt.h" +#include "lw_terminal_vt100.h" int pixels_sm; @@ -26,6 +26,8 @@ int pixels_sm; #define CHAR_Y (9) #define FB_HEIGHT_PIXEL (FB_HEIGHT_CHAR * CHAR_Y) +struct lw_terminal_vt100 *vt100; + void __not_in_flash_func(scan_convert)(const uint32_t * restrict cptr32, const uint16_t * restrict cgptr, const uint16_t * restrict shade) { #define READ_CHARDATA \ (ch = *cptr32++) @@ -83,67 +85,8 @@ uint16_t chargen[256*CHAR_Y] = { int cx, cy, attr = 0x300; _Static_assert(FB_WIDTH_CHAR % 6 == 0); -uint32_t chardata32[FB_WIDTH_CHAR * FB_HEIGHT_CHAR / 2]; - -int readchar(int cx, int cy) { - uint16_t *chardata = (void*)chardata32; - int i = cx + cy * FB_WIDTH_CHAR; - return chardata[i] & 0xff; -} -int readattr(int cx, int cy) { - uint16_t *chardata = (void*)chardata32; - int i = cx + cy * FB_WIDTH_CHAR; - return chardata[i] & 0xff00; -} - -void setchar(int cx, int cy, int ch) { - uint16_t *chardata = (void*)chardata32; - int i = cx + cy * FB_WIDTH_CHAR; - chardata[i] = (chardata[i] & 0xff00) | ch; -} -void setattr(int cx, int cy, int attr) { - uint16_t *chardata = (void*)chardata32; - int i = cx + cy * FB_WIDTH_CHAR; - chardata[i] = (chardata[i] & 0xff) | attr; -} - -void scroll_terminal() { - - memmove(chardata32, chardata32 + FB_WIDTH_CHAR / 2, FB_WIDTH_CHAR * (FB_HEIGHT_CHAR - 1) * 2); - uint32_t mask = attr | (attr << 16); - for(size_t i=0; i= 32) { - if(cx == FB_WIDTH_CHAR) { - cx = 0; - increase_y(); - } - chardata[cx + cy * FB_WIDTH_CHAR] = *data | attr; - cx ++; - } - } - } return n; } @@ -153,7 +96,7 @@ int scrnprintf(const char *fmt, ...) { va_start(ap, fmt); int n = vasprintf(&ptr, fmt, ap); va_end(ap); - writefn((void*)chardata32, ptr, n); + lw_terminal_vt100_read_buf(vt100, ptr, n); free(ptr); return n; } @@ -199,8 +142,9 @@ void __not_in_flash_func(core1_entry)() { while(true) { for(int row = 0; row < FB_HEIGHT_CHAR; row++) { + uint32_t *chardata = (uint32_t*)lw_terminal_vt100_getline(vt100, row); for(int j=0; j 0) { start = cy * FB_WIDTH_CHAR; } - uint16_t *chardata = (void*)chardata32; - for(size_t i = start; i< end; i++) { chardata[i] = 32 | attr; } -} - -void clear_screen(int ps) { - size_t start = cx + cy * FB_WIDTH_CHAR, end = FB_HEIGHT_CHAR * FB_WIDTH_CHAR; - if(ps == 1) { end = start+1; } - if(ps > 0) { start = 0; } - uint16_t *chardata = (void*)chardata32; - for(size_t i = start; i< end; i++) { chardata[i] = 32 | attr; } -} - -void cursor_left() { - if(cx > 0) cx -= 1; -} - -void cursor_position(esc_state *st) { - // param 1 is row (cy), 1-bsaed - if(st->esc_param[1] > 0 && st->esc_param[1] < FB_WIDTH_CHAR) { - cx = st->esc_param[1] - 1; - } - // param 1 is column (cx), 1-bsaed - if(st->esc_param[0] > 0 && st->esc_param[0] < FB_HEIGHT_CHAR) { - cy = st->esc_param[0] - 1; - } -} +#define MAKE_ATTR(fg, bg) (((fg) ^ (((bg) * 9) & 073)) << 8) int map_one(int i) { return (i > 0) + (i > 6); } -void char_attr(esc_state *st) { - int new_fg = 2; - int new_bg = 0; - - for(int i= 0; iesc_param); i++) { - int p = st->esc_param[i]; - if (30 <= p && p <= 37) new_fg = map_one(p - 30); - if (90 <= p && p <= 97) new_fg = map_one(p - 90); - if (40 <= p && p <= 47) new_fg = map_one(p - 40); - if (100 <= p && p <= 107) new_fg = map_one(p - 100); +lw_cell_t char_attr(void *user_data, const struct lw_parsed_attr *attr) { + int fg = map_one(attr->fg); + int bg = map_one(attr->bg); + if(attr->bold) fg = 3; + if(attr->blink) fg ^= 4; + if(attr->inverse) { + return MAKE_ATTR(bg, fg); } - attr = MAKE_ATTR(new_fg, new_bg) << 8; + return MAKE_ATTR(fg, bg); } + int main() { #if !STANDALONE set_sys_clock_khz(vga_660x477_60_sys_clock_khz, false); stdio_init_all(); #endif + vt100 = lw_terminal_vt100_init(NULL, NULL, char_attr, FB_WIDTH_CHAR, FB_HEIGHT_CHAR); + multicore_launch_core1(core1_entry); + scrnprintf( "(line 0)\r\n" "CR100 terminal demo...\r\n" ); - for(int bg = 0; bg < 8; bg++) { - for(int fg = 0; fg < 8; fg++) { - attr = MAKE_ATTR(fg, bg) << 8; - scrnprintf(" %o%o ", bg, fg); - attr = 0x300; - scrnprintf(" "); - } - scrnprintf("\r\n"); - } - - multicore_launch_core1(core1_entry); - keyboard_setup(); - - attr = 0x300; - show_cursor(); while (true) { int c = getchar(); if (c == EOF) { continue; } - - vt_action action = vt_process_code(&vt_st, c); - - if (action == NO_OUTPUT) { continue; } - - hide_cursor(); - switch(action) { - case NO_OUTPUT: - __builtin_unreachable(); - - case PRINTABLE: - scrnprintf("%c", c); - if(0 && c == '\r') - scrnprintf("\n"); - break; - - case BELL: - invert_screen(); - sleep_ms(100); - invert_screen(); - break; - - case CLEAR_EOL: - clear_eol(vt_st.esc_param[0]); - break; - - case CLEAR_SCREEN: - clear_screen(vt_st.esc_param[0]); - break; - - case CURSOR_LEFT: - cursor_left(); - break; - - case CURSOR_POSITION: - cursor_position(&vt_st); - break; - - case CHAR_ATTR: - char_attr(&vt_st); - break; - } - show_cursor(); + char cc = c; + lw_terminal_vt100_read_buf(vt100, &cc, 1); } return 0; diff --git a/hl-vt100/vt_dump.py b/hl-vt100/vt_dump.py new file mode 100644 index 0000000..b60e41b --- /dev/null +++ b/hl-vt100/vt_dump.py @@ -0,0 +1,12 @@ +import hl_vt100 +import sys + +vt100 = hl_vt100.vt100_headless() +vt100.fork(sys.argv[1], sys.argv[1:]) +vt100.main_loop() +print(*vt100.getlines(), sep="\n") + +print() +for a in vt100.getattrlines()[:8]: + s = " ".join(f"{c >> 8:02x}" for c in a[:20]) + print(s) diff --git a/run-gdb.sh b/run-gdb.sh new file mode 100755 index 0000000..ec4f12d --- /dev/null +++ b/run-gdb.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec gdb-multiarch --eval-command "target extended-remote :3333" build/cr100.elf "$@"