switch to the new vt emulator (untested)

This commit is contained in:
Jeff Epler 2024-10-07 10:59:53 -05:00
parent c7d87d4cf9
commit e430750beb
5 changed files with 49 additions and 187 deletions

View file

@ -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)

View file

@ -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);

202
chargen.c
View file

@ -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<FB_WIDTH_CHAR / 2; i++) {
chardata32[(FB_HEIGHT_CHAR-1) * FB_WIDTH_CHAR / 2 + i] = mask;
}
}
void increase_y() {
cy = (cy + 1);
if (cy == FB_HEIGHT_CHAR) {
scroll_terminal();
cy = FB_HEIGHT_CHAR - 1;
}
}
int writefn(void *cookie, const char *data, int n) {
uint16_t *chardata = cookie;
for(; n; data++, n--) {
switch(*data) {
case '\r':
cx = 0;
break;
case '\n':
increase_y();
break;
default:
if(*data >= 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<CHAR_Y; j++) {
scan_convert(&chardata32[FB_WIDTH_CHAR * row / 2],
scan_convert(chardata,
&chargen[256 * j], frameno & 0x20 ? base_shade : base_shade + 4);
}
}
@ -213,147 +157,43 @@ void __not_in_flash_func(core1_entry)() {
#define BG_ATTR(x) ((x) << 11)
#define FG_ATTR(x) ((x) << 8)
int saved_attr;
void show_cursor() {
int xx = cx == FB_WIDTH_CHAR ? FB_WIDTH_CHAR - 1 : cx;
saved_attr = readattr(xx, cy);
setattr(xx, cy, saved_attr ^ BG_ATTR(7));
}
void hide_cursor() {
int xx = cx == FB_WIDTH_CHAR ? FB_WIDTH_CHAR - 1 : cx;
setattr(xx, cy, saved_attr);
}
#define MAKE_ATTR(fg, bg) ((fg) ^ (((bg) * 9) & 073))
esc_state vt_st;
void invert_screen() {
for(size_t i=0; i<count_of(chardata32); i++) { chardata32[i] ^= 0x18001800; }
}
void clear_eol(int ps) {
size_t start = cx + cy * FB_WIDTH_CHAR, end = (cx+1) * FB_WIDTH_CHAR;
if(ps == 1) { end = start+1; }
if(ps > 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; i<count_of(st->esc_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;

12
hl-vt100/vt_dump.py Normal file
View file

@ -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)

2
run-gdb.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/sh
exec gdb-multiarch --eval-command "target extended-remote :3333" build/cr100.elf "$@"