diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..39f9642 --- /dev/null +++ b/.clang-format @@ -0,0 +1 @@ +IndentWidth: 4 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..8531669 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò +# +# SPDX-License-Identifier: Unlicense + +# CIRCUITPY-CHANGE: CircuitPython-specific. + +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace +- repo: https://github.com/codespell-project/codespell + rev: v2.2.4 + hooks: + - id: codespell + args: [-w] + exclude: | + (?x)^( + hl-vt100 + ) +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v14.0.6 + hooks: + - id: clang-format + exclude: 5x9.h +- repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.6.2 + hooks: + # Run the linter. + - id: ruff + args: [ --fix ] + # Run the formatter. + - id: ruff-format diff --git a/atkbd.pio b/atkbd.pio index b3cd139..a15750a 100644 --- a/atkbd.pio +++ b/atkbd.pio @@ -15,7 +15,7 @@ start: ; keyboard has signaled start condition set x 9 ; will receive 10 bits (data + parity + stop) wait 1 pin 1 ; wait for clock pin to go high (discard start bit) - + receive_bit: wait 0 pin 1 in pins 1 @@ -35,7 +35,7 @@ send_bit: out pins 1 wait 1 pin 1 jmp x-- send_bit - + set pindirs 0 ; pins back to input mode wait 0 pin 0 wait 1 pin 0 ; wait for keyboard ACK @@ -78,4 +78,3 @@ void atkbd_program_init(PIO pio, int sm, int offset, int base_pin) { } %} - diff --git a/chargen.c b/chargen.c index e6a8a50..6e560db 100644 --- a/chargen.c +++ b/chargen.c @@ -1,20 +1,24 @@ #define _GNU_SOURCE +#include #include +#include +#include +#include -#include "pinout.h" -#include "keyboard.h" #include "chargen.h" +#include "keyboard.h" +#include "pinout.h" -#include "pico.h" -#include "pico/stdlib.h" -#include "pico/stdio/driver.h" -#include "pico/multicore.h" -#include "pico/bootrom.h" +#include "RP2040.h" +#include "cmsis_compiler.h" +#include "hardware/clocks.h" #include "hardware/structs/mpu.h" #include "hardware/watchdog.h" -#include "hardware/clocks.h" -#include "cmsis_compiler.h" -#include "RP2040.h" +#include "pico.h" +#include "pico/bootrom.h" +#include "pico/multicore.h" +#include "pico/stdio/driver.h" +#include "pico/stdlib.h" #include "vga_660x477_60.pio.h" @@ -22,10 +26,10 @@ int pixels_sm; -#define WRITE_PIXDATA \ - (pio0->txf[0] = pixels) -#define FIFO_WAIT \ - do { /* NOTHING */ } while(pio_sm_get_tx_fifo_level(pio0, 0) > 2) +#define WRITE_PIXDATA (pio0->txf[0] = pixels) +#define FIFO_WAIT \ + do { /* NOTHING */ \ + } while (pio_sm_get_tx_fifo_level(pio0, 0) > 2) #define FB_WIDTH_CHAR (132) #define FB_HEIGHT_CHAR (53) @@ -36,52 +40,79 @@ int pixels_sm; struct lw_terminal_vt100 *vt100; // declaring this static breaks it (why?) -void scan_convert(const uint32_t * restrict cptr32, const uint16_t * restrict cgptr, const uint16_t * restrict shade); -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++) -#define ONE_CHAR(in_shift, op, out_shift) \ - do { \ - chardata = cgptr[(ch>>(in_shift)) & 0xff]; \ - mask = shade[(ch>>(8 + (in_shift)))&7]; \ - pixels op (shade[(ch >>(11 + (in_shift)))&7] ^ (chardata & mask)) out_shift; \ - } while(0) - +void scan_convert(const uint32_t *restrict cptr32, + const uint16_t *restrict cgptr, + const uint16_t *restrict shade); +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++) +#define ONE_CHAR(in_shift, op, out_shift) \ + do { \ + chardata = cgptr[(ch >> (in_shift)) & 0xff]; \ + mask = shade[(ch >> (8 + (in_shift))) & 7]; \ + pixels op(shade[(ch >> (11 + (in_shift))) & 7] ^ (chardata & mask)) \ + out_shift; \ + } while (0) + uint32_t ch; uint16_t chardata, mask; uint32_t pixels; -#define SIX_CHARS \ - do { \ - READ_CHARDATA; \ - ONE_CHAR(0, =, << 20); \ - ONE_CHAR(16, |=, << 10); \ - READ_CHARDATA; \ - ONE_CHAR(0, |=, ); \ - WRITE_PIXDATA; \ - ONE_CHAR(16, =, << 20); \ - READ_CHARDATA; \ - ONE_CHAR(0, |=, << 10); \ - ONE_CHAR(16, |=, ); \ - WRITE_PIXDATA; \ - } while(0) +#define SIX_CHARS \ + do { \ + READ_CHARDATA; \ + ONE_CHAR(0, =, << 20); \ + ONE_CHAR(16, |=, << 10); \ + READ_CHARDATA; \ + ONE_CHAR(0, |=, ); \ + WRITE_PIXDATA; \ + ONE_CHAR(16, =, << 20); \ + READ_CHARDATA; \ + ONE_CHAR(0, |=, << 10); \ + ONE_CHAR(16, |=, ); \ + WRITE_PIXDATA; \ + } while (0) - SIX_CHARS; SIX_CHARS; SIX_CHARS; FIFO_WAIT; /* 18 */ \ - SIX_CHARS; SIX_CHARS; SIX_CHARS; FIFO_WAIT; /* 36 */ \ - SIX_CHARS; SIX_CHARS; SIX_CHARS; FIFO_WAIT; /* 54 */ \ - SIX_CHARS; SIX_CHARS; SIX_CHARS; FIFO_WAIT; /* 72 */ \ - SIX_CHARS; SIX_CHARS; SIX_CHARS; FIFO_WAIT; /* 90 */ \ - SIX_CHARS; SIX_CHARS; SIX_CHARS; FIFO_WAIT; /* 108 */ \ - SIX_CHARS; SIX_CHARS; SIX_CHARS; FIFO_WAIT; /* 126 */ \ - SIX_CHARS; /* 132 */ \ + SIX_CHARS; + SIX_CHARS; + SIX_CHARS; + FIFO_WAIT; /* 18 */ + + SIX_CHARS; + SIX_CHARS; + SIX_CHARS; + FIFO_WAIT; /* 36 */ + + SIX_CHARS; + SIX_CHARS; + SIX_CHARS; + FIFO_WAIT; /* 54 */ + + SIX_CHARS; + SIX_CHARS; + SIX_CHARS; + FIFO_WAIT; /* 72 */ + + SIX_CHARS; + SIX_CHARS; + SIX_CHARS; + FIFO_WAIT; /* 90 */ + + SIX_CHARS; + SIX_CHARS; + SIX_CHARS; + FIFO_WAIT; /* 108 */ + + SIX_CHARS; + SIX_CHARS; + SIX_CHARS; + FIFO_WAIT; /* 126 */ + + SIX_CHARS; /* 132 */ } -#include -#include -#include -#include - -uint16_t chargen[256*CHAR_Y] = { +uint16_t chargen[256 * CHAR_Y] = { #include "5x9.h" }; @@ -89,16 +120,15 @@ _Static_assert(FB_WIDTH_CHAR % 6 == 0); lw_cell_t statusline[FB_WIDTH_CHAR]; -static -int status_printf(const char *fmt, ...) { - char buf[2*FB_WIDTH_CHAR + 1]; +static int status_printf(const char *fmt, ...) { + char buf[2 * FB_WIDTH_CHAR + 1]; va_list ap; va_start(ap, fmt); int n = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); int attr = 0x300; int i, j; - for(i=j=0; j < FB_WIDTH_CHAR && buf[i]; i++) { + for (i = j = 0; j < FB_WIDTH_CHAR && buf[i]; i++) { int c = (unsigned char)buf[i]; if (c < 32) { attr = c << 8; @@ -106,7 +136,7 @@ int status_printf(const char *fmt, ...) { statusline[j++] = c | attr; } } - while(j < FB_WIDTH_CHAR) { + while (j < FB_WIDTH_CHAR) { statusline[j++] = 32 | attr; } return n; @@ -122,8 +152,8 @@ int scrnprintf(const char *fmt, ...) { return n; } -static -uint16_t base_shade[] = {0, 0x554, 0xaa8, 0xffc, 0, 0x554, 0xaa8, 0xffc, 0, 0, 0, 0}; +static uint16_t base_shade[] = {0, 0x554, 0xaa8, 0xffc, 0, 0x554, + 0xaa8, 0xffc, 0, 0, 0, 0}; #if !STANDALONE static void setup_vga_hsync(PIO pio) { @@ -152,39 +182,40 @@ static void setup_vga(void) { setup_vga_hsync(pio0); } - -__attribute__((noreturn,noinline)) -static void __not_in_flash_func(core1_loop)(void) { +__attribute__((noreturn, noinline)) static void +__not_in_flash_func(core1_loop)(void) { int frameno = 0; - while(true) { - for(int row = 0; row < FB_HEIGHT_CHAR; row++) { - uint32_t *chardata = row == FB_HEIGHT_CHAR - 1 - ? (uint32_t*) statusline - : (uint32_t*)lw_terminal_vt100_getline(vt100, row); - for(int j=0; jCTRL = MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk; MPU->RNR = 6; // 7 is used by pico-sdk stack protection. MPU->RBAR = XIP_MAIN_BASE | MPU_RBAR_VALID_Msk; - MPU->RASR = MPU_RASR_XN_Msk | // Set execute never and everything else is restricted. - MPU_RASR_ENABLE_Msk | - (0x1b << MPU_RASR_SIZE_Pos); // Size is 0x10000000 which masks up to SRAM region. - MPU->RNR = 7; + MPU->RASR = MPU_RASR_XN_Msk | // Set execute never and everything else is + // restricted. + MPU_RASR_ENABLE_Msk | + (0x1b << MPU_RASR_SIZE_Pos); // Size is 0x10000000 which masks + // up to SRAM region. + MPU->RNR = 7; core1_loop(); } @@ -193,19 +224,21 @@ void __not_in_flash_func(core1_entry)(void) { #define BG_ATTR(x) ((x) << 11) #define FG_ATTR(x) ((x) << 8) -#define MAKE_ATTR(fg, bg) (((fg) ^ (((bg) * 9) & 073)) << 8) +#define MAKE_ATTR(fg, bg) (((fg) ^ (((bg)*9) & 073)) << 8) -static int map_one(int i) { - return (i > 0) + (i > 6); -} +static int map_one(int i) { return (i > 0) + (i > 6); } static 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 (fg == bg && attr->fg != attr->bg) { fg = bg + 1; } - if(attr->bold) fg = 3; - if(attr->blink) fg ^= 4; - if(attr->inverse) { + if (fg == bg && attr->fg != attr->bg) { + fg = bg + 1; + } + if (attr->bold) + fg = 3; + if (attr->blink) + fg ^= 4; + if (attr->inverse) { return MAKE_ATTR(bg, fg); } return MAKE_ATTR(fg, bg); @@ -213,8 +246,7 @@ static lw_cell_t char_attr(void *user_data, const struct lw_parsed_attr *attr) { queue_t keyboard_queue; -static -void reset_cpu(void) { +static void reset_cpu(void) { watchdog_reboot(0, SRAM_END, 0); watchdog_start_tick(12); @@ -227,7 +259,7 @@ int current_port; #define COUNT_OF(x) ((sizeof(x) / sizeof((x)[0]))) -uint baudrates[] = { 300, 1200, 2400, 9600, 19200, 38400, 115200 }; +uint baudrates[] = {300, 1200, 2400, 9600, 19200, 38400, 115200}; #define N_BAUDRATES (COUNT_OF(baudrates)) typedef struct { @@ -237,14 +269,10 @@ typedef struct { } uart_config_t; const uart_config_t uart_configs[] = { - { 8, 1, UART_PARITY_NONE, "8N1" }, - { 8, 2, UART_PARITY_NONE, "8N2" }, - { 8, 1, UART_PARITY_EVEN, "8E1" }, - { 8, 1, UART_PARITY_ODD, "8O1" }, - { 7, 1, UART_PARITY_NONE, "7N1" }, - { 7, 2, UART_PARITY_NONE, "7N2" }, - { 7, 1, UART_PARITY_EVEN, "7E1" }, - { 7, 1, UART_PARITY_ODD, "7O1" }, + {8, 1, UART_PARITY_NONE, "8N1"}, {8, 2, UART_PARITY_NONE, "8N2"}, + {8, 1, UART_PARITY_EVEN, "8E1"}, {8, 1, UART_PARITY_ODD, "8O1"}, + {7, 1, UART_PARITY_NONE, "7N1"}, {7, 2, UART_PARITY_NONE, "7N2"}, + {7, 1, UART_PARITY_EVEN, "7E1"}, {7, 1, UART_PARITY_ODD, "7O1"}, }; #define N_CONFIGS (COUNT_OF(uart_configs)) @@ -253,8 +281,8 @@ typedef struct uart_data { } uart_data_t; uart_data_t uart_data[] = { - { 0, 0, 1 }, - { 0, 12, 13 }, + {0, 0, 1}, + {0, 12, 13}, }; #define N_UARTS (COUNT_OF(uart_data)) @@ -269,7 +297,6 @@ static void uart_activate(void *data_in) { gpio_set_function(data->rx, UART_FUNCSEL_NUM(inst, data->rx)); gpio_set_function(data->tx, UART_FUNCSEL_NUM(inst, data->tx)); gpio_pull_up(data->rx); - } static void uart_deactivate(void *data_in) { @@ -282,14 +309,18 @@ static void uart_deactivate(void *data_in) { static int uart_getc_nonblocking(void *data_in) { uart_data_t *data = (uart_data_t *)data_in; uart_inst_t *inst = uart_get_instance(data->uart); - if (!uart_is_readable(inst)) { return EOF; } + if (!uart_is_readable(inst)) { + return EOF; + } return uart_getc(inst); } static void uart_putc_nonblocking(void *data_in, int c) { uart_data_t *data = (uart_data_t *)data_in; uart_inst_t *inst = uart_get_instance(data->uart); - if (uart_is_writable(inst)) { uart_putc_raw(inst, c); } + if (uart_is_writable(inst)) { + uart_putc_raw(inst, c); + } } static void uart_cycle_baud_rate(void *data_in) { @@ -310,21 +341,18 @@ static void uart_cycle_settings(void *data_in) { static void uart_describe(void *data_in, char *buf, size_t buflen) { uart_data_t *data = (uart_data_t *)data_in; const uart_config_t *config = &uart_configs[data->cfg_idx]; - snprintf(buf, buflen, "UART%d %5d %s", current_port, baudrates[data->baud_idx], config->label); + snprintf(buf, buflen, "UART%d %5d %s", current_port, + baudrates[data->baud_idx], config->label); } -static void usb_activate(void *data) { - vt100->unicode = 1; -} +static void usb_activate(void *data) { vt100->unicode = 1; } static void usb_deactivate(void *data) {} static int usb_getc_nonblocking(void *data) { int c = getchar_timeout_us(1); return (c < 0) ? EOF : c; } -static void usb_putc_nonblocking(void *data, int c) { - stdio_putchar_raw(c); -} +static void usb_putc_nonblocking(void *data, int c) { stdio_putchar_raw(c); } static void usb_cycle_baud_rate(void *data) {} static void usb_cycle_settings(void *data) {} @@ -376,7 +404,6 @@ static const port_descr_t ports[] = { }; #define NUM_PORTS (COUNT_OF(ports)) - #define CURRENT_PORT (ports[current_port]) static bool status_refresh = true; @@ -386,9 +413,7 @@ static void port_deactivate(void) { CURRENT_PORT.deactivate(CURRENT_PORT.data); } -static void port_activate(void) { - CURRENT_PORT.activate(CURRENT_PORT.data); -} +static void port_activate(void) { CURRENT_PORT.activate(CURRENT_PORT.data); } static int port_getc(void) { return CURRENT_PORT.getc_nonblocking(CURRENT_PORT.data); @@ -421,25 +446,24 @@ static void switch_port(void) { port_activate(); } -static -int stdio_kbd_in_chars(char *buf, int length) { +static int stdio_kbd_in_chars(char *buf, int length) { int rc = 0; int code; keyboard_poll(&keyboard_queue); while (length && queue_try_remove(&keyboard_queue, &code)) { if ((code & 0xc000) == 0xc000) { - switch(code) { - case CMD_SWITCH_RATE: - port_cycle_baud_rate(); - break; - case CMD_SWITCH_SETTINGS: - port_cycle_settings(); - break; - case CMD_SWITCH_PORT: - switch_port(); - break; - case CMD_REBOOT: - reset_cpu(); + switch (code) { + case CMD_SWITCH_RATE: + port_cycle_baud_rate(); + break; + case CMD_SWITCH_SETTINGS: + port_cycle_settings(); + break; + case CMD_SWITCH_PORT: + switch_port(); + break; + case CMD_REBOOT: + reset_cpu(); } continue; } @@ -453,7 +477,9 @@ int stdio_kbd_in_chars(char *buf, int length) { static int kbd_getc_nonblocking(void) { char c; int result = stdio_kbd_in_chars(&c, 1); - if (result == PICO_ERROR_NO_DATA) { return EOF; } + if (result == PICO_ERROR_NO_DATA) { + return EOF; + } return c; } @@ -463,42 +489,72 @@ static stdio_driver_t stdio_kbd = { }; #endif -static -void master_write(void *user_data, void *buffer_in, size_t len) { +static void master_write(void *user_data, void *buffer_in, size_t len) { const char *buffer = buffer_in; - for(;len--;buffer++) { port_putc(*buffer); } + for (; len--; buffer++) { + port_putc(*buffer); + } } -static -int map_unicode(void *unused, int n) { switch(n) { -case 9670: return 1; -case 9618: return 2; -case 9225: return 3; -case 9228: return 4; -case 9229: return 5; -case 9226: return 6; -case 9252: return 9; -case 9227: return 10; -case 9496: return 11; -case 9488: return 12; -case 9484: return 13; -case 9492: return 14; -case 9532: return 15; -case 9146: return 16; -case 9147: return 17; -case 9472: return 18; -case 9148: return 19; -case 9149: return 20; -case 9500: return 21; -case 9508: return 22; -case 9524: return 23; -case 9516: return 24; -case 9474: return 25; -case 8804: return 26; -case 8805: return 27; -case 960: return 28; -case 8800: return 29; -}return '?';} +static int map_unicode(void *unused, int n) { + switch (n) { + case 9670: + return 1; + case 9618: + return 2; + case 9225: + return 3; + case 9228: + return 4; + case 9229: + return 5; + case 9226: + return 6; + case 9252: + return 9; + case 9227: + return 10; + case 9496: + return 11; + case 9488: + return 12; + case 9484: + return 13; + case 9492: + return 14; + case 9532: + return 15; + case 9146: + return 16; + case 9147: + return 17; + case 9472: + return 18; + case 9148: + return 19; + case 9149: + return 20; + case 9500: + return 21; + case 9508: + return 22; + case 9524: + return 23; + case 9516: + return 24; + case 9474: + return 25; + case 8804: + return 26; + case 8805: + return 27; + case 960: + return 28; + case 8800: + return 29; + } + return '?'; +} static int old_keyboard_leds; int main(void) { @@ -506,12 +562,13 @@ int main(void) { set_sys_clock_khz(vga_660x477_60_sys_clock_khz, false); stdio_init_all(); #endif - for(int i=0; imap_unicode = map_unicode; multicore_launch_core1(core1_entry); @@ -540,10 +597,9 @@ int main(void) { } if (status_refresh) { - status_printf("\3%s\3 \2 %s %s", - port_describe(), - keyboard_leds & LED_CAPS ? "\22 CAPS \2" : " ", - keyboard_leds & LED_NUM ? "\22 NUM \2" : " "); + status_printf("\3%s\3 \2 %s %s", port_describe(), + keyboard_leds & LED_CAPS ? "\22 CAPS \2" : " ", + keyboard_leds & LED_NUM ? "\22 NUM \2" : " "); status_refresh = false; } } diff --git a/hl-vt100/example/parser.c b/hl-vt100/example/parser.c index 84393d9..079708b 100644 --- a/hl-vt100/example/parser.c +++ b/hl-vt100/example/parser.c @@ -1,25 +1,21 @@ -#include -#include #include "../src/lw_terminal_parser.h" +#include +#include static void vt100_write(struct lw_terminal *term_emul __attribute__((unused)), - char c) -{ + char c) { printf("Got a char : %c\n", c); } -static void csi_f(struct lw_terminal *term_emul) -{ +static void csi_f(struct lw_terminal *term_emul) { printf("\\033[...f with %d parameters\n", term_emul->argc); } -static void csi_K(struct lw_terminal *term_emul) -{ +static void csi_K(struct lw_terminal *term_emul) { printf("\\033[...K with %d parameters\n", term_emul->argc); } -int main(void) -{ +int main(void) { struct lw_terminal *lw_terminal; lw_terminal = lw_terminal_parser_init(); diff --git a/hl-vt100/example/top.c b/hl-vt100/example/top.c index 6cf9f72..c298de2 100644 --- a/hl-vt100/example/top.c +++ b/hl-vt100/example/top.c @@ -1,15 +1,12 @@ +#include "hl_vt100.h" #include #include -#include "hl_vt100.h" - -void changed(struct vt100_headless *vt100) -{ +void changed(struct vt100_headless *vt100) { const char **lines; lines = vt100_headless_getlines(vt100); - for (unsigned int y = 0; y < vt100->term->height; ++y) - { + for (unsigned int y = 0; y < vt100->term->height; ++y) { write(1, "|", 1); write(1, lines[y], vt100->term->width); write(1, "|\n", 2); @@ -17,8 +14,7 @@ void changed(struct vt100_headless *vt100) write(1, "\n", 1); } -int main(int ac, char **av) -{ +int main(int ac, char **av) { struct vt100_headless *vt100; char *argv[] = {"top", NULL}; diff --git a/hl-vt100/example/top.py b/hl-vt100/example/top.py index b72ee30..c745dc5 100644 --- a/hl-vt100/example/top.py +++ b/hl-vt100/example/top.py @@ -11,9 +11,9 @@ def dump(vt100): def main(): vt100 = hl_vt100.vt100_headless() vt100.changed_callback = lambda: dump(vt100) - vt100.fork('top', ['top']) + vt100.fork("top", ["top"]) vt100.main_loop() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/hl-vt100/setup.py b/hl-vt100/setup.py index 45a382f..6162ad5 100644 --- a/hl-vt100/setup.py +++ b/hl-vt100/setup.py @@ -9,31 +9,37 @@ from pathlib import Path from setuptools import setup, Extension -hl_vt100_module = Extension('hl_vt100', - include_dirs=['src'], - define_macros=[('NDEBUG', '1')], - sources=['src/vt100_module.c', - 'src/hl_vt100.c', - 'src/lw_terminal_parser.c', - 'src/lw_terminal_vt100.c']) +hl_vt100_module = Extension( + "hl_vt100", + include_dirs=["src"], + define_macros=[("NDEBUG", "1")], + sources=[ + "src/vt100_module.c", + "src/hl_vt100.c", + "src/lw_terminal_parser.c", + "src/lw_terminal_vt100.c", + ], +) -setup(name='hl_vt100', - version='0.2', - url='https://github.com/JulienPalard/vt100-emulator', - author="Julien Palard", - author_email='julien@palard.fr', - description="""Headless vt100 emulator""", - long_description=(Path(__file__).parent / "README.md").read_text(encoding="UTF-8"), - long_description_content_type="text/markdown", - ext_modules=[hl_vt100_module], - include_package_data=True, - py_modules=["hl_vt100"], - classifiers=[ - "Programming Language :: C", - "Programming Language :: Python", - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: BSD License", - "Operating System :: OS Independent", - "Topic :: System :: Emulators", - "Topic :: Terminals :: Terminal Emulators/X Terminals" - ]) +setup( + name="hl_vt100", + version="0.2", + url="https://github.com/JulienPalard/vt100-emulator", + author="Julien Palard", + author_email="julien@palard.fr", + description="""Headless vt100 emulator""", + long_description=(Path(__file__).parent / "README.md").read_text(encoding="UTF-8"), + long_description_content_type="text/markdown", + ext_modules=[hl_vt100_module], + include_package_data=True, + py_modules=["hl_vt100"], + classifiers=[ + "Programming Language :: C", + "Programming Language :: Python", + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Topic :: System :: Emulators", + "Topic :: Terminals :: Terminal Emulators/X Terminals", + ], +) diff --git a/hl-vt100/src/hl_vt100.c b/hl-vt100/src/hl_vt100.c index 2a727fd..88e8993 100644 --- a/hl-vt100/src/hl_vt100.c +++ b/hl-vt100/src/hl_vt100.c @@ -24,26 +24,20 @@ */ #define _XOPEN_SOURCE -#include -#include -#include -#include -#include -#include #include "hl_vt100.h" +#include +#include +#include +#include +#include -struct vt100_headless *new_vt100_headless(void) -{ +struct vt100_headless *new_vt100_headless(void) { return calloc(1, sizeof(struct vt100_headless)); } -void delete_vt100_headless(struct vt100_headless *this) -{ - free(this); -} +void delete_vt100_headless(struct vt100_headless *this) { free(this); } -static void set_non_canonical(struct vt100_headless *this, int fd) -{ +static void set_non_canonical(struct vt100_headless *this, int fd) { struct termios termios; ioctl(fd, TCGETS, &this->backup); @@ -54,16 +48,13 @@ static void set_non_canonical(struct vt100_headless *this, int fd) ioctl(fd, TCSETS, &termios); } -static void restore_termios(struct vt100_headless *this, int fd) -{ +static void restore_termios(struct vt100_headless *this, int fd) { ioctl(fd, TCSETS, &this->backup); } #ifndef NDEBUG -static void strdump(char *str) -{ - while (*str != '\0') - { +static void strdump(char *str) { + while (*str != '\0') { if (*str >= ' ' && *str <= '~') fprintf(stderr, "%c", *str); else @@ -74,44 +65,34 @@ static void strdump(char *str) } #endif -void vt100_headless_stop(struct vt100_headless *this) -{ - this->should_quit = 1; -} +void vt100_headless_stop(struct vt100_headless *this) { this->should_quit = 1; } -int vt100_headless_main_loop(struct vt100_headless *this) -{ +int vt100_headless_main_loop(struct vt100_headless *this) { char buffer[4096]; fd_set rfds; int retval; ssize_t read_size; - while (!this->should_quit) - { + while (!this->should_quit) { FD_ZERO(&rfds); FD_SET(this->master, &rfds); FD_SET(0, &rfds); retval = select(this->master + 1, &rfds, NULL, NULL, NULL); - if (retval == -1) - { + if (retval == -1) { perror("select()"); } - if (FD_ISSET(0, &rfds)) - { + if (FD_ISSET(0, &rfds)) { read_size = read(0, &buffer, 4096); - if (read_size == -1) - { + if (read_size == -1) { perror("read"); return EXIT_FAILURE; } buffer[read_size] = '\0'; write(this->master, buffer, read_size); } - if (FD_ISSET(this->master, &rfds)) - { + if (FD_ISSET(this->master, &rfds)) { read_size = read(this->master, &buffer, 4096); - if (read_size == -1) - { + if (read_size == -1) { if (errno == EIO) { return EXIT_SUCCESS; } @@ -130,23 +111,19 @@ int vt100_headless_main_loop(struct vt100_headless *this) return EXIT_SUCCESS; } -void master_write(void *user_data, void *buffer, size_t len) -{ +void master_write(void *user_data, void *buffer, size_t len) { struct vt100_headless *this; - this = (struct vt100_headless*)user_data; + this = (struct vt100_headless *)user_data; write(this->master, buffer, len); } -const lw_cell_t **vt100_headless_getlines(struct vt100_headless *this) -{ +const lw_cell_t **vt100_headless_getlines(struct vt100_headless *this) { return lw_terminal_vt100_getlines(this->term); } -void vt100_headless_fork(struct vt100_headless *this, - const char *progname, - char **argv) -{ +void vt100_headless_fork(struct vt100_headless *this, const char *progname, + char **argv) { int child; struct winsize winsize; @@ -154,16 +131,15 @@ void vt100_headless_fork(struct vt100_headless *this, winsize.ws_row = 24; winsize.ws_col = 80; child = forkpty(&this->master, NULL, NULL, NULL); - if (child == CHILD) - { + if (child == CHILD) { setsid(); putenv("TERM=vt100"); execvp(progname, argv); - return ; - } - else - { - this->term = lw_terminal_vt100_init(this, lw_terminal_parser_default_unimplemented, master_write, NULL, winsize.ws_col, winsize.ws_row); + return; + } else { + this->term = lw_terminal_vt100_init( + this, lw_terminal_parser_default_unimplemented, master_write, NULL, + winsize.ws_col, winsize.ws_row); ioctl(this->master, TIOCSWINSZ, &winsize); } restore_termios(this, 0); diff --git a/hl-vt100/src/hl_vt100.h b/hl-vt100/src/hl_vt100.h index cdbb185..e7c5441 100644 --- a/hl-vt100/src/hl_vt100.h +++ b/hl-vt100/src/hl_vt100.h @@ -28,14 +28,13 @@ #define CHILD 0 -#include -#include -#include -#include #include "lw_terminal_vt100.h" +#include +#include +#include +#include -struct vt100_headless -{ +struct vt100_headless { int master; struct termios backup; struct lw_terminal_vt100 *term; @@ -43,8 +42,8 @@ struct vt100_headless void (*changed)(struct vt100_headless *this); }; - -void vt100_headless_fork(struct vt100_headless *this, const char *progname, char **argv); +void vt100_headless_fork(struct vt100_headless *this, const char *progname, + char **argv); int vt100_headless_main_loop(struct vt100_headless *this); void delete_vt100_headless(struct vt100_headless *this); struct vt100_headless *new_vt100_headless(void); diff --git a/hl-vt100/src/lw_terminal_parser.c b/hl-vt100/src/lw_terminal_parser.c index 7ccce47..4fe6826 100644 --- a/hl-vt100/src/lw_terminal_parser.c +++ b/hl-vt100/src/lw_terminal_parser.c @@ -25,36 +25,30 @@ #include #ifndef NDEBUG -# include +#include #endif #include "lw_terminal_parser.h" -static void lw_terminal_parser_push(struct lw_terminal *this, char c) -{ +static void lw_terminal_parser_push(struct lw_terminal *this, char c) { if (this->stack_ptr >= TERM_STACK_SIZE) - return ; + return; this->stack[this->stack_ptr++] = c; } -static void lw_terminal_parser_parse_params(struct lw_terminal *this) -{ +static void lw_terminal_parser_parse_params(struct lw_terminal *this) { unsigned int i; int got_something; got_something = 0; this->argc = 0; this->argv[0] = 0; - for (i = 0; i < this->stack_ptr; ++i) - { - if (this->stack[i] >= '0' && this->stack[i] <= '9') - { + for (i = 0; i < this->stack_ptr; ++i) { + if (this->stack[i] >= '0' && this->stack[i] <= '9') { got_something = 1; - this->argv[this->argc] = this->argv[this->argc] * 10 - + this->stack[i] - '0'; - } - else if (this->stack[i] == ';') - { + this->argv[this->argc] = + this->argv[this->argc] * 10 + this->stack[i] - '0'; + } else if (this->stack[i] == ';') { got_something = 0; this->argc += 1; this->argv[this->argc] = 0; @@ -63,11 +57,9 @@ static void lw_terminal_parser_parse_params(struct lw_terminal *this) this->argc += got_something; } -static void lw_terminal_parser_call_CSI(struct lw_terminal *this, char c) -{ +static void lw_terminal_parser_call_CSI(struct lw_terminal *this, char c) { lw_terminal_parser_parse_params(this); - if (((term_action *)&this->callbacks.csi)[c - '0'] == NULL) - { + if (((term_action *)&this->callbacks.csi)[c - '0'] == NULL) { if (this->unimplemented != NULL) this->unimplemented(this, "CSI", c); goto leave; @@ -80,10 +72,8 @@ leave: this->argc = 0; } -static void lw_terminal_parser_call_ESC(struct lw_terminal *this, char c) -{ - if (((term_action *)&this->callbacks.esc)[c - '0'] == NULL) - { +static void lw_terminal_parser_call_ESC(struct lw_terminal *this, char c) { + if (((term_action *)&this->callbacks.esc)[c - '0'] == NULL) { if (this->unimplemented != NULL) this->unimplemented(this, "ESC", c); goto leave; @@ -95,10 +85,8 @@ leave: this->argc = 0; } -static void lw_terminal_parser_call_HASH(struct lw_terminal *this, char c) -{ - if (((term_action *)&this->callbacks.hash)[c - '0'] == NULL) - { +static void lw_terminal_parser_call_HASH(struct lw_terminal *this, char c) { + if (((term_action *)&this->callbacks.hash)[c - '0'] == NULL) { if (this->unimplemented != NULL) this->unimplemented(this, "HASH", c); goto leave; @@ -110,11 +98,9 @@ leave: this->argc = 0; } -static void lw_terminal_parser_call_GSET(struct lw_terminal *this, char c) -{ - if (c < '0' || c > 'B' - || ((term_action *)&this->callbacks.scs)[c - '0'] == NULL) - { +static void lw_terminal_parser_call_GSET(struct lw_terminal *this, char c) { + if (c < '0' || c > 'B' || + ((term_action *)&this->callbacks.scs)[c - '0'] == NULL) { if (this->unimplemented != NULL) this->unimplemented(this, "GSET", c); goto leave; @@ -141,17 +127,13 @@ leave: ** | | \_ term_call_GSET() ** \_ term->write() */ -void lw_terminal_parser_read(struct lw_terminal *this, char c) -{ - if (this->state == INIT) - { +void lw_terminal_parser_read(struct lw_terminal *this, char c) { + if (this->state == INIT) { if (c == '\033') this->state = ESC; else this->write(this, c); - } - else if (this->state == ESC) - { + } else if (this->state == ESC) { if (c == '[') this->state = CSI; else if (c == '#') @@ -162,21 +144,16 @@ void lw_terminal_parser_read(struct lw_terminal *this, char c) this->state = G1SET; else if (c >= '0' && c <= 'z') lw_terminal_parser_call_ESC(this, c); - else this->write(this, c); - } - else if (this->state == HASH) - { + else + this->write(this, c); + } else if (this->state == HASH) { if (c >= '0' && c <= '9') lw_terminal_parser_call_HASH(this, c); else this->write(this, c); - } - else if (this->state == G0SET || this->state == G1SET) - { + } else if (this->state == G0SET || this->state == G1SET) { lw_terminal_parser_call_GSET(this, c); - } - else if (this->state == CSI) - { + } else if (this->state == CSI) { if (c == '?') this->flag = '?'; else if (c == '>') @@ -190,26 +167,24 @@ void lw_terminal_parser_read(struct lw_terminal *this, char c) } } -void lw_terminal_parser_read_buf(struct lw_terminal *this, const char *c, size_t n) -{ +void lw_terminal_parser_read_buf(struct lw_terminal *this, const char *c, + size_t n) { while (n--) lw_terminal_parser_read(this, *c++); } -void lw_terminal_parser_read_str(struct lw_terminal *this, const char *c) -{ +void lw_terminal_parser_read_str(struct lw_terminal *this, const char *c) { while (*c) lw_terminal_parser_read(this, *c++); } #ifndef NDEBUG -void lw_terminal_parser_default_unimplemented(struct lw_terminal* this, char *seq, char chr) -{ +void lw_terminal_parser_default_unimplemented(struct lw_terminal *this, + char *seq, char chr) { unsigned int argc; fprintf(stderr, "WARNING: UNIMPLEMENTED %s (", seq); - for (argc = 0; argc < this->argc; ++argc) - { + for (argc = 0; argc < this->argc; ++argc) { fprintf(stderr, "%d", this->argv[argc]); if (argc != this->argc - 1) fprintf(stderr, ", "); @@ -217,20 +192,16 @@ void lw_terminal_parser_default_unimplemented(struct lw_terminal* this, char *se fprintf(stderr, ")%o\n", chr); } #else -void lw_terminal_parser_default_unimplemented(struct lw_terminal* this, char *seq, char chr) -{ +void lw_terminal_parser_default_unimplemented(struct lw_terminal *this, + char *seq, char chr) { this = this; seq = seq; chr = chr; } #endif -struct lw_terminal *lw_terminal_parser_init(void) -{ +struct lw_terminal *lw_terminal_parser_init(void) { return calloc(1, sizeof(struct lw_terminal)); } -void lw_terminal_parser_destroy(struct lw_terminal* this) -{ - free(this); -} +void lw_terminal_parser_destroy(struct lw_terminal *this) { free(this); } diff --git a/hl-vt100/src/lw_terminal_parser.h b/hl-vt100/src/lw_terminal_parser.h index 767a560..414f8e2 100644 --- a/hl-vt100/src/lw_terminal_parser.h +++ b/hl-vt100/src/lw_terminal_parser.h @@ -23,8 +23,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __TERMINAL_H__ -#define __TERMINAL_H__ +#pragma once + +#include /* ** @@ -97,22 +98,13 @@ #define TERM_STACK_SIZE 1024 -enum term_state -{ - INIT, - ESC, - HASH, - G0SET, - G1SET, - CSI -}; +enum term_state { INIT, ESC, HASH, G0SET, G1SET, CSI }; struct lw_terminal; typedef void (*term_action)(struct lw_terminal *emul); -struct ascii_callbacks -{ +struct ascii_callbacks { term_action n0; term_action n1; term_action n2; @@ -194,35 +186,33 @@ struct ascii_callbacks term_action z; }; -struct term_callbacks -{ +struct term_callbacks { struct ascii_callbacks esc; struct ascii_callbacks csi; struct ascii_callbacks hash; struct ascii_callbacks scs; }; -struct lw_terminal -{ - unsigned int cursor_pos_x; - unsigned int cursor_pos_y; - enum term_state state; - unsigned int argc; - unsigned int argv[TERM_STACK_SIZE]; - void (*write)(struct lw_terminal *, char c); - char stack[TERM_STACK_SIZE]; - unsigned int stack_ptr; - struct term_callbacks callbacks; - char flag; - void *user_data; - void (*unimplemented)(struct lw_terminal*, - char *seq, char chr); +struct lw_terminal { + unsigned int cursor_pos_x; + unsigned int cursor_pos_y; + enum term_state state; + unsigned int argc; + unsigned int argv[TERM_STACK_SIZE]; + void (*write)(struct lw_terminal *, char c); + char stack[TERM_STACK_SIZE]; + unsigned int stack_ptr; + struct term_callbacks callbacks; + char flag; + void *user_data; + void (*unimplemented)(struct lw_terminal *, char *seq, char chr); }; struct lw_terminal *lw_terminal_parser_init(void); -void lw_terminal_parser_default_unimplemented(struct lw_terminal* this, char *seq, char chr); +void lw_terminal_parser_default_unimplemented(struct lw_terminal *this, + char *seq, char chr); void lw_terminal_parser_read(struct lw_terminal *this, char c); void lw_terminal_parser_read_str(struct lw_terminal *this, const char *c); -void lw_terminal_parser_read_buf(struct lw_terminal *this, const char *c, size_t n); -void lw_terminal_parser_destroy(struct lw_terminal* this); -#endif +void lw_terminal_parser_read_buf(struct lw_terminal *this, const char *c, + size_t n); +void lw_terminal_parser_destroy(struct lw_terminal *this); diff --git a/hl-vt100/src/lw_terminal_vt100.c b/hl-vt100/src/lw_terminal_vt100.c index 50715ba..8a14095 100644 --- a/hl-vt100/src/lw_terminal_vt100.c +++ b/hl-vt100/src/lw_terminal_vt100.c @@ -23,27 +23,36 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include -#include #include "lw_terminal_vt100.h" +#include +#include +#include +#include -static unsigned int get_mode_mask(unsigned int mode) -{ - switch (mode) - { - case LNM : return MASK_LNM; - case DECCKM : return MASK_DECCKM; - case DECANM : return MASK_DECANM; - case DECCOLM : return MASK_DECCOLM; - case DECSCLM : return MASK_DECSCLM; - case DECSCNM : return MASK_DECSCNM; - case DECOM : return MASK_DECOM; - case DECAWM : return MASK_DECAWM; - case DECARM : return MASK_DECARM; - case DECINLM : return MASK_DECINLM; - default: return 0; +static unsigned int get_mode_mask(unsigned int mode) { + switch (mode) { + case LNM: + return MASK_LNM; + case DECCKM: + return MASK_DECCKM; + case DECANM: + return MASK_DECANM; + case DECCOLM: + return MASK_DECCOLM; + case DECSCLM: + return MASK_DECSCLM; + case DECSCNM: + return MASK_DECSCNM; + case DECOM: + return MASK_DECOM; + case DECAWM: + return MASK_DECAWM; + case DECARM: + return MASK_DECARM; + case DECINLM: + return MASK_DECINLM; + default: + return 0; } } @@ -179,63 +188,57 @@ static unsigned int get_mode_mask(unsigned int mode) #define MOD1(a, b) ((a < b) ? a : a - b) -#define SCREEN_PTR(vt100, x, y) \ - MOD1((vt100->top_line * vt100->width + x + vt100->width * y), \ - (vt100->width * SCROLLBACK * vt100->height)) +#define SCREEN_PTR(vt100, x, y) \ + MOD1((vt100->top_line * vt100->width + x + vt100->width * y), \ + (vt100->width * SCROLLBACK * vt100->height)) -#define FROZEN_SCREEN_PTR(vt100, x, y) \ - (MOD1(x + vt100->width * y, \ - (vt100->width * SCROLLBACK * vt100->height))) +#define FROZEN_SCREEN_PTR(vt100, x, y) \ + (MOD1(x + vt100->width * y, (vt100->width * SCROLLBACK * vt100->height))) -static lw_cell_t aget(struct lw_terminal_vt100 *headless_term, - unsigned int x, unsigned int y) -{ +static lw_cell_t aget(struct lw_terminal_vt100 *headless_term, unsigned int x, + unsigned int y) { if (y < headless_term->margin_top || y > headless_term->margin_bottom) - return headless_term->afrozen_screen[FROZEN_SCREEN_PTR(headless_term, x, y)]; + return headless_term + ->afrozen_screen[FROZEN_SCREEN_PTR(headless_term, x, y)]; else return headless_term->ascreen[SCREEN_PTR(headless_term, x, y)]; } -static void aset(struct lw_terminal_vt100 *headless_term, - unsigned int x, unsigned int y, - lw_cell_t c) -{ +static void aset(struct lw_terminal_vt100 *headless_term, unsigned int x, + unsigned int y, lw_cell_t c) { if (y < headless_term->margin_top || y > headless_term->margin_bottom) - headless_term->afrozen_screen[FROZEN_SCREEN_PTR(headless_term, x, y)] = c; + headless_term->afrozen_screen[FROZEN_SCREEN_PTR(headless_term, x, y)] = + c; else headless_term->ascreen[SCREEN_PTR(headless_term, x, y)] = c; } -static void set(struct lw_terminal_vt100 *headless_term, - unsigned int x, unsigned int y, - char c) { - aset( headless_term, x, y, (unsigned char)c | headless_term->attr); +static void set(struct lw_terminal_vt100 *headless_term, unsigned int x, + unsigned int y, char c) { + aset(headless_term, x, y, (unsigned char)c | headless_term->attr); } -lw_cell_t lw_terminal_vt100_aget(struct lw_terminal_vt100 *vt100, unsigned int x, unsigned int y) -{ +lw_cell_t lw_terminal_vt100_aget(struct lw_terminal_vt100 *vt100, + unsigned int x, unsigned int y) { if (y < vt100->margin_top || y > vt100->margin_bottom) return vt100->afrozen_screen[FROZEN_SCREEN_PTR(vt100, x, y)]; else return vt100->ascreen[SCREEN_PTR(vt100, x, y)]; } -static void froze_line(struct lw_terminal_vt100 *vt100, unsigned int y) -{ +static void froze_line(struct lw_terminal_vt100 *vt100, unsigned int y) { memcpy(vt100->afrozen_screen + vt100->width * y, vt100->ascreen + SCREEN_PTR(vt100, 0, y), vt100->width * sizeof(lw_cell_t)); } -static void unfroze_line(struct lw_terminal_vt100 *vt100, unsigned int y) -{ +static void unfroze_line(struct lw_terminal_vt100 *vt100, unsigned int y) { memcpy(vt100->ascreen + SCREEN_PTR(vt100, 0, y), vt100->afrozen_screen + vt100->width * y, vt100->width * sizeof(lw_cell_t)); } -static void blank_screen(struct lw_terminal_vt100 *lw_terminal_vt100) -{ +static void blank_screen(struct lw_terminal_vt100 *lw_terminal_vt100) { unsigned int x; unsigned int y; @@ -252,8 +255,7 @@ static void blank_screen(struct lw_terminal_vt100 *lw_terminal_vt100) This sequence causes the cursor position, graphic rendition, and character set to be saved. (See DECRC). */ -static void DECSC(struct lw_terminal *term_emul) -{ +static void DECSC(struct lw_terminal *term_emul) { /*TODO: Save graphic rendition and charset.*/ struct lw_terminal_vt100 *vt100; @@ -273,17 +275,14 @@ static void DECSC(struct lw_terminal *term_emul) Modes following this section). */ -static void RM(struct lw_terminal *term_emul) -{ +static void RM(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int mode; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; - if (term_emul->argc > 0) - { + if (term_emul->argc > 0) { mode = term_emul->argv[0]; - if (mode == DECCOLM) - { + if (mode == DECCOLM) { vt100->width = 80; vt100->x = vt100->y = 0; blank_screen(vt100); @@ -335,11 +334,10 @@ x Pm = 97 / 107 fg/bg Bright White x Pm = 99 / 109 fg/bg Bright Default */ -static int default_map_unicode(void *user_data, int c) { - return '?'; -} +static int default_map_unicode(void *user_data, int c) { return '?'; } -static lw_cell_t default_encode_attr(void *user_data, const struct lw_parsed_attr *attr) { +static lw_cell_t default_encode_attr(void *user_data, + const struct lw_parsed_attr *attr) { (void)user_data; lw_cell_t result; @@ -350,29 +348,33 @@ static lw_cell_t default_encode_attr(void *user_data, const struct lw_parsed_att result = attr->fg; result |= attr->bg << 4; } - if (attr->bold) result ^= 0x08; - if (attr->blink) result ^= 0x80; + if (attr->bold) + result ^= 0x08; + if (attr->blink) + result ^= 0x80; return result << 8; } -static void SGR(struct lw_terminal *term_emul) -{ - struct lw_terminal_vt100 *vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; +static void SGR(struct lw_terminal *term_emul) { + struct lw_terminal_vt100 *vt100 = + (struct lw_terminal_vt100 *)term_emul->user_data; // vim sends "CSI > 4 ; 2 m" and you can't stop it - if (term_emul->flag == '>') { return; } + if (term_emul->flag == '>') { + return; + } if (term_emul->argc == 0) { term_emul->argc = 1; term_emul->argv[0] = 0; } - for (unsigned int i=0; iargc; i++) { + for (unsigned int i = 0; i < term_emul->argc; i++) { int p = term_emul->argv[i]; - switch(p) { - case 0: - vt100->parsed_attr = LW_DEFAULT_ATTR; + switch (p) { + case 0: + vt100->parsed_attr = LW_DEFAULT_ATTR; break; case 1: @@ -447,8 +449,7 @@ static void SGR(struct lw_terminal *term_emul) The numbering of lines depends on the state of the Origin Mode (DECOM). */ -static void CUP(struct lw_terminal *term_emul) -{ +static void CUP(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; int arg0; int arg1; @@ -465,14 +466,17 @@ static void CUP(struct lw_terminal *term_emul) if (arg1 < 0) arg1 = 0; - if (MODE_IS_SET(vt100, DECOM)) - { + if (MODE_IS_SET(vt100, DECOM)) { arg0 += vt100->margin_top; if ((unsigned int)arg0 > vt100->margin_bottom) arg0 = vt100->margin_bottom; } - if (arg0 >= vt100->height) { arg0 = vt100->height - 1; } - if (arg1 >= vt100->width) { arg1 = vt100->width - 1; } + if (arg0 >= vt100->height) { + arg0 = vt100->height - 1; + } + if (arg1 >= vt100->width) { + arg1 = vt100->width - 1; + } vt100->y = arg0; vt100->x = arg1; } @@ -488,30 +492,25 @@ static void CUP(struct lw_terminal *term_emul) it is reset by a reset mode (RM) control sequence. */ -static void SM(struct lw_terminal *term_emul) -{ +static void SM(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int mode; unsigned int saved_argc; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; - if (term_emul->argc > 0) - { + if (term_emul->argc > 0) { mode = term_emul->argv[0]; SET_MODE(vt100, mode); - if (mode == DECANM) - { + if (mode == DECANM) { /* TODO: Support vt52 mode */ - return ; + return; } - if (mode == DECCOLM) - { + if (mode == DECCOLM) { vt100->width = 132; vt100->x = vt100->y = 0; blank_screen(vt100); } - if (mode == DECOM) - { + if (mode == DECOM) { saved_argc = term_emul->argc; term_emul->argc = 0; CUP(term_emul); @@ -534,8 +533,7 @@ static void SM(struct lw_terminal *term_emul) cursor is placed in the home position (see Origin Mode DECOM). */ -static void DECSTBM(struct lw_terminal *term_emul) -{ +static void DECSTBM(struct lw_terminal *term_emul) { unsigned int margin_top; unsigned int margin_bottom; struct lw_terminal_vt100 *vt100; @@ -543,17 +541,14 @@ static void DECSTBM(struct lw_terminal *term_emul) vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; - if (term_emul->argc == 2) - { + if (term_emul->argc == 2) { margin_top = term_emul->argv[0] - 1; margin_bottom = term_emul->argv[1] - 1; if (margin_bottom >= vt100->height) - return ; + return; if (margin_bottom - margin_top <= 0) - return ; - } - else - { + return; + } else { margin_top = 0; margin_bottom = vt100->height - 1; } @@ -594,16 +589,14 @@ static void DECSTBM(struct lw_terminal *term_emul) GPO, STP and AVO ESC [?1;7c */ -static void DA(struct lw_terminal *term_emul) -{ +static void DA(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; vt100->master_write(vt100->user_data, "\033[?1;0c", 7); } -static void DSR(struct lw_terminal *term_emul) -{ +static void DSR(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; @@ -611,20 +604,18 @@ static void DSR(struct lw_terminal *term_emul) return; } - switch(term_emul->argv[0]) { - case 5: - vt100->master_write(vt100->user_data, "\033[0n", 4); - break; - - case 6: - { - char buf[16]; - snprintf(buf, sizeof(buf), "\033[%d;%dR", vt100->y + 1, vt100->x + 1); - vt100->master_write(vt100->user_data, buf, strlen(buf)); - } + switch (term_emul->argv[0]) { + case 5: + vt100->master_write(vt100->user_data, "\033[0n", 4); + break; - default: - ; + case 6: { + char buf[16]; + snprintf(buf, sizeof(buf), "\033[%d;%dR", vt100->y + 1, vt100->x + 1); + vt100->master_write(vt100->user_data, buf, strlen(buf)); + } + + default:; } } @@ -636,8 +627,7 @@ static void DSR(struct lw_terminal *term_emul) This sequence causes the previously saved cursor position, graphic rendition, and character set to be restored. */ -static void DECRC(struct lw_terminal *term_emul) -{ +static void DECRC(struct lw_terminal *term_emul) { /*TODO Save graphic rendition and charset */ struct lw_terminal_vt100 *vt100; @@ -655,8 +645,7 @@ static void DECRC(struct lw_terminal *term_emul) focus and alignment. This command is used by DEC manufacturing and Field Service personnel. */ -static void DECALN(struct lw_terminal *term_emul) -{ +static void DECALN(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int x; unsigned int y; @@ -676,22 +665,18 @@ static void DECALN(struct lw_terminal *term_emul) without changing the column position. If the active position is at the bottom margin, a scroll up is performed. Format Effector */ -static void IND(struct lw_terminal *term_emul) -{ +static void IND(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int x; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; - if (vt100->y >= vt100->margin_bottom) - { + if (vt100->y >= vt100->margin_bottom) { /* SCROLL */ vt100->top_line = (vt100->top_line + 1) % (vt100->height * SCROLLBACK); for (x = 0; x < vt100->width; ++x) set(vt100, x, vt100->margin_bottom, ' '); - } - else - { + } else { /* Do not scroll, just move downward on the current display space */ vt100->y += 1; } @@ -705,18 +690,14 @@ static void IND(struct lw_terminal *term_emul) preceding line. If the active position is at the top margin, a scroll down is performed. Format Effector */ -static void RI(struct lw_terminal *term_emul) -{ +static void RI(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; - if (vt100->y == 0) - { + if (vt100->y == 0) { /* SCROLL */ vt100->top_line = (vt100->top_line - 1) % (vt100->height * SCROLLBACK); - } - else - { + } else { /* Do not scroll, just move upward on the current display space */ vt100->y -= 1; } @@ -731,21 +712,17 @@ static void RI(struct lw_terminal *term_emul) on the next line downward. If the active position is at the bottom margin, a scroll up is performed. Format Effector */ -static void NEL(struct lw_terminal *term_emul) -{ +static void NEL(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int x; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; - if (vt100->y >= vt100->margin_bottom) - { + if (vt100->y >= vt100->margin_bottom) { /* SCROLL */ vt100->top_line = (vt100->top_line + 1) % (vt100->height * SCROLLBACK); for (x = 0; x < vt100->width; ++x) set(vt100, x, vt100->margin_bottom, ' '); - } - else - { + } else { /* Do not scroll, just move downward on the current display space */ vt100->y += 1; } @@ -764,8 +741,7 @@ static void NEL(struct lw_terminal *term_emul) upward. If an attempt is made to move the cursor above the top margin, the cursor stops at the top margin. Editor Function */ -static void CUU(struct lw_terminal *term_emul) -{ +static void CUU(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int arg0; @@ -794,8 +770,7 @@ static void CUU(struct lw_terminal *term_emul) cursor below the bottom margin, the cursor stops at the bottom margin. Editor Function */ -static void CUD(struct lw_terminal *term_emul) -{ +static void CUD(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int arg0; @@ -822,8 +797,7 @@ static void CUD(struct lw_terminal *term_emul) is made to move the cursor to the right of the right margin, the cursor stops at the right margin. Editor Function */ -static void CUF(struct lw_terminal *term_emul) -{ +static void CUF(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int arg0; @@ -850,8 +824,7 @@ static void CUF(struct lw_terminal *term_emul) left. If an attempt is made to move the cursor to the left of the left margin, the cursor stops at the left margin. Editor Function */ -static void CUB(struct lw_terminal *term_emul) -{ +static void CUB(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int arg0; @@ -873,8 +846,7 @@ static void CUB(struct lw_terminal *term_emul) ESC [ Ps P default value: 1 */ -static void DCH(struct lw_terminal *term_emul) -{ +static void DCH(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int arg0; unsigned int x; @@ -913,8 +885,7 @@ static void DCH(struct lw_terminal *term_emul) 2 Erase all of the display – all lines are erased, changed to single-width, and the cursor does not move. */ -static void ED(struct lw_terminal *term_emul) -{ +static void ED(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int arg0; unsigned int x; @@ -924,25 +895,20 @@ static void ED(struct lw_terminal *term_emul) arg0 = 0; if (term_emul->argc > 0) arg0 = term_emul->argv[0]; - if (arg0 == 0) - { + if (arg0 == 0) { for (x = vt100->x; x < vt100->width; ++x) set(vt100, x, vt100->y, ' '); - for (x = 0 ; x < vt100->width; ++x) + for (x = 0; x < vt100->width; ++x) for (y = vt100->y + 1; y < vt100->height; ++y) set(vt100, x, y, ' '); - } - else if (arg0 == 1) - { - for (x = 0 ; x < vt100->width; ++x) + } else if (arg0 == 1) { + for (x = 0; x < vt100->width; ++x) for (y = 0; y < vt100->y; ++y) set(vt100, x, y, ' '); for (x = 0; x <= vt100->x; ++x) set(vt100, x, vt100->y, ' '); - } - else if (arg0 == 2) - { - for (x = 0 ; x < vt100->width; ++x) + } else if (arg0 == 2) { + for (x = 0; x < vt100->width; ++x) for (y = 0; y < vt100->height; ++y) set(vt100, x, y, ' '); } @@ -962,8 +928,7 @@ static void ED(struct lw_terminal *term_emul) 1 Erase from the start of the screen to the active position, inclusive 2 Erase all of the line, inclusive */ -static void EL(struct lw_terminal *term_emul) -{ +static void EL(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int arg0; unsigned int x; @@ -972,18 +937,13 @@ static void EL(struct lw_terminal *term_emul) arg0 = 0; if (term_emul->argc > 0) arg0 = term_emul->argv[0]; - if (arg0 == 0) - { + if (arg0 == 0) { for (x = vt100->x; x < vt100->width; ++x) set(vt100, x, vt100->y, ' '); - } - else if (arg0 == 1) - { + } else if (arg0 == 1) { for (x = 0; x <= vt100->x; ++x) set(vt100, x, vt100->y, ' '); - } - else if (arg0 == 2) - { + } else if (arg0 == 2) { for (x = 0; x < vt100->width; ++x) set(vt100, x, vt100->y, ' '); } @@ -1005,30 +965,22 @@ static void EL(struct lw_terminal *term_emul) columns depends on the reset or set state of the origin mode (DECOM). Format Effector */ -static void HVP(struct lw_terminal *term_emul) -{ - CUP(term_emul); -} +static void HVP(struct lw_terminal *term_emul) { CUP(term_emul); } -static void TBC(struct lw_terminal *term_emul) -{ +static void TBC(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; unsigned int i; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; - if (term_emul->argc == 0 || term_emul->argv[0] == 0) - { + if (term_emul->argc == 0 || term_emul->argv[0] == 0) { vt100->tabulations[vt100->x] = '-'; - } - else if (term_emul->argc == 1 && term_emul->argv[0] == 3) - { + } else if (term_emul->argc == 1 && term_emul->argv[0] == 3) { for (i = 0; i < 132; ++i) vt100->tabulations[i] = '-'; } } -static void HTS(struct lw_terminal *term_emul) -{ +static void HTS(struct lw_terminal *term_emul) { struct lw_terminal_vt100 *vt100; vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; @@ -1040,50 +992,43 @@ static void vt100_write_unicode(struct lw_terminal *term_emul, int c) { vt100 = (struct lw_terminal_vt100 *)term_emul->user_data; - if (c == '\r') - { + if (c == '\r') { vt100->x = 0; - return ; + return; } - if (c == '\n' || c == '\013' || c == '\014') - { + if (c == '\n' || c == '\013' || c == '\014') { if (MODE_IS_SET(vt100, LNM)) NEL(term_emul); else IND(term_emul); - return ; + return; } - if (c == '\010' && vt100->x > 0) - { + if (c == '\010' && vt100->x > 0) { if (vt100->x == vt100->width) vt100->x -= 1; vt100->x -= 1; - return ; + return; } - if (c == '\t') - { - do - { + if (c == '\t') { + do { set(vt100, vt100->x, vt100->y, ' '); vt100->x += 1; - } while (vt100->x < vt100->width && vt100->tabulations[vt100->x] == '-'); - return ; + } while (vt100->x < vt100->width && + vt100->tabulations[vt100->x] == '-'); + return; } - if (c == '\016') - { + if (c == '\016') { vt100->selected_charset = 0; - return ; + return; } - if (c == '\017') - { + if (c == '\017') { vt100->selected_charset = 1; - return ; + return; } if (c < ' ') { return; } - if (vt100->x == vt100->width) - { + if (vt100->x == vt100->width) { if (MODE_IS_SET(vt100, DECAWM)) NEL(term_emul); else @@ -1111,13 +1056,13 @@ static void vt100_write(struct lw_terminal *term_emul, char c) { if (vt100->ustate == 0) { if (uc < 0x80) { vt100_write_unicode(term_emul, uc); - } else if((uc & 0xe0) == 0xc0) { + } else if ((uc & 0xe0) == 0xc0) { vt100->ustate = 1; vt100->ubits = (uc & 0x1f); - } else if((uc & 0xf0) == 0xe0) { + } else if ((uc & 0xf0) == 0xe0) { vt100->ustate = 2; vt100->ubits = (uc & 0xf); - } else if((uc & 0xf8) == 0xf0) { + } else if ((uc & 0xf8) == 0xf0) { vt100->ustate = 3; vt100->ubits = (uc & 0x7); } else { @@ -1135,12 +1080,12 @@ static void vt100_write(struct lw_terminal *term_emul, char c) { vt100->ubits <<= 6; vt100->ubits |= uc & 0x3f; if (--vt100->ustate == 0) { - vt100_write_unicode(term_emul, vt100->ubits); + vt100_write_unicode(term_emul, vt100->ubits); } } } } else { - vt100_write_unicode(term_emul, uc); + vt100_write_unicode(term_emul, uc); } } @@ -1149,15 +1094,16 @@ static void vt100_write(struct lw_terminal *term_emul, char c) { #else #define __not_in_flash_func(x) x #endif -const lw_cell_t *__not_in_flash_func(lw_terminal_vt100_getline)(struct lw_terminal_vt100 *vt100, unsigned int y) { +const lw_cell_t * +__not_in_flash_func(lw_terminal_vt100_getline)(struct lw_terminal_vt100 *vt100, + unsigned int y) { if (y < vt100->margin_top || y > vt100->margin_bottom) return vt100->afrozen_screen + FROZEN_SCREEN_PTR(vt100, 0, y); else return vt100->ascreen + SCREEN_PTR(vt100, 0, y); } -const lw_cell_t **lw_terminal_vt100_getlines(struct lw_terminal_vt100 *vt100) -{ +const lw_cell_t **lw_terminal_vt100_getlines(struct lw_terminal_vt100 *vt100) { unsigned int y; for (y = 0; y < vt100->height; ++y) @@ -1166,15 +1112,17 @@ const lw_cell_t **lw_terminal_vt100_getlines(struct lw_terminal_vt100 *vt100) } static void setcells(lw_cell_t *buf, lw_cell_t c, size_t n) { - for(;n--;buf++) *buf = c; + for (; n--; buf++) + *buf = c; } -struct lw_terminal_vt100 *lw_terminal_vt100_init(void *user_data, - void (*unimplemented)(struct lw_terminal* term_emul, char *seq, char chr), - void (*master_write)(void *user_data, void *buffer, size_t len), - lw_cell_t (*encode_attr)(void *user_data, const struct lw_parsed_attr *attr), - unsigned int width, unsigned int height) -{ +struct lw_terminal_vt100 *lw_terminal_vt100_init( + void *user_data, + void (*unimplemented)(struct lw_terminal *term_emul, char *seq, char chr), + void (*master_write)(void *user_data, void *buffer, size_t len), + lw_cell_t (*encode_attr)(void *user_data, + const struct lw_parsed_attr *attr), + unsigned int width, unsigned int height) { struct lw_terminal_vt100 *this; this = calloc(1, sizeof(*this)); @@ -1192,7 +1140,7 @@ struct lw_terminal_vt100 *lw_terminal_vt100_init(void *user_data, this->tabulations = malloc(132); if (this->tabulations == NULL) goto free_frozen_screen; - for(int i=0; i<132; i++) { + for (int i = 0; i < 132; i++) { this->tabulations[i] = (i && i % 8 == 0) ? '|' : '-'; } this->margin_top = 0; @@ -1234,7 +1182,8 @@ struct lw_terminal_vt100 *lw_terminal_vt100_init(void *user_data, this->master_write = master_write; this->encode_attr = encode_attr ? encode_attr : default_encode_attr; this->map_unicode = default_map_unicode; - lw_terminal_vt100_read_str(this, "\033[m\033[?7h"); // set default attributes + lw_terminal_vt100_read_str(this, + "\033[m\033[?7h"); // set default attributes setcells(this->ascreen, ' ' | this->attr, 132 * SCROLLBACK * this->height); setcells(this->afrozen_screen, ' ' | this->attr, 132 * this->height); return this; @@ -1253,7 +1202,7 @@ free_this: static void show_cursor(struct lw_terminal_vt100 *this) { unsigned x = this->x, y = this->y; lw_cell_t cell; - if(x == this->width) + if (x == this->width) x -= 1; if (x >= this->width || y >= this->height) { this->cursor_saved_flag = false; @@ -1268,26 +1217,27 @@ static void show_cursor(struct lw_terminal_vt100 *this) { } static void hide_cursor(struct lw_terminal_vt100 *this) { - if (!this->cursor_saved_flag) { return; } + if (!this->cursor_saved_flag) { + return; + } this->cursor_saved_flag = false; unsigned x = this->cursor_saved_x, y = this->cursor_saved_y; aset(this, x, y, aget(this, x, y) ^ CURSOR_ATTR); } -void lw_terminal_vt100_read_str(struct lw_terminal_vt100 *this, const char *buffer) -{ +void lw_terminal_vt100_read_str(struct lw_terminal_vt100 *this, + const char *buffer) { lw_terminal_vt100_read_buf(this, buffer, strlen(buffer)); } -void lw_terminal_vt100_read_buf(struct lw_terminal_vt100 *this, const char *buffer, size_t len) -{ +void lw_terminal_vt100_read_buf(struct lw_terminal_vt100 *this, + const char *buffer, size_t len) { hide_cursor(this); lw_terminal_parser_read_buf(this->lw_terminal, buffer, len); show_cursor(this); } -void lw_terminal_vt100_destroy(struct lw_terminal_vt100 *this) -{ +void lw_terminal_vt100_destroy(struct lw_terminal_vt100 *this) { lw_terminal_parser_destroy(this->lw_terminal); free(this->tabulations); free(this->ascreen); diff --git a/hl-vt100/src/lw_terminal_vt100.h b/hl-vt100/src/lw_terminal_vt100.h index d3e7132..d109b58 100644 --- a/hl-vt100/src/lw_terminal_vt100.h +++ b/hl-vt100/src/lw_terminal_vt100.h @@ -26,8 +26,8 @@ #ifndef __LW_TERMINAL_VT100_H__ #define __LW_TERMINAL_VT100_H__ -#include #include +#include #include "lw_terminal_parser.h" @@ -39,29 +39,28 @@ #define SCROLLBACK 3 -#define MASK_LNM 1 -#define MASK_DECCKM 2 -#define MASK_DECANM 4 +#define MASK_LNM 1 +#define MASK_DECCKM 2 +#define MASK_DECANM 4 #define MASK_DECCOLM 8 #define MASK_DECSCLM 16 #define MASK_DECSCNM 32 -#define MASK_DECOM 64 -#define MASK_DECAWM 128 -#define MASK_DECARM 256 +#define MASK_DECOM 64 +#define MASK_DECAWM 128 +#define MASK_DECARM 256 #define MASK_DECINLM 512 -#define LNM 20 -#define DECCKM 1 -#define DECANM 2 +#define LNM 20 +#define DECCKM 1 +#define DECANM 2 #define DECCOLM 3 #define DECSCLM 4 #define DECSCNM 5 -#define DECOM 6 -#define DECAWM 7 -#define DECARM 8 +#define DECOM 6 +#define DECAWM 7 +#define DECARM 8 #define DECINLM 9 - #define SET_MODE(vt100, mode) ((vt100)->modes |= get_mode_mask(mode)) #define UNSET_MODE(vt100, mode) ((vt100)->modes &= ~get_mode_mask(mode)) #define MODE_IS_SET(vt100, mode) ((vt100)->modes & get_mode_mask(mode)) @@ -73,7 +72,7 @@ struct lw_parsed_attr { bool blink, bold, inverse; }; -#define LW_DEFAULT_ATTR ((struct lw_parsed_attr) { 7, 0, false, false, false }) +#define LW_DEFAULT_ATTR ((struct lw_parsed_attr){7, 0, false, false, false}) /* ** frozen_screen is the frozen part of the screen @@ -81,8 +80,7 @@ struct lw_parsed_attr { ** The top of the frozen_screen holds the top margin ** while the bottom holds the bottom margin. */ -struct lw_terminal_vt100 -{ +struct lw_terminal_vt100 { struct lw_terminal *lw_terminal; int ustate, ubits; unsigned int width; @@ -94,36 +92,42 @@ struct lw_terminal_vt100 unsigned int margin_top; unsigned int margin_bottom; unsigned int top_line; /* Line at the top of the display */ - lw_cell_t *ascreen; - lw_cell_t *afrozen_screen; - char *tabulations; - bool unicode; + lw_cell_t *ascreen; + lw_cell_t *afrozen_screen; + char *tabulations; + bool unicode; bool cursor_saved_flag; unsigned int selected_charset; unsigned int modes; struct lw_parsed_attr parsed_attr; - lw_cell_t attr; + lw_cell_t attr; int cursor_saved_x, cursor_saved_y; - const lw_cell_t *alines[80]; - void (*master_write)(void *user_data, void *buffer, size_t len); - lw_cell_t (*encode_attr)(void *user_data, const struct lw_parsed_attr *attr); - int (*map_unicode)(void *user_data, int c); - void *user_data; + const lw_cell_t *alines[80]; + void (*master_write)(void *user_data, void *buffer, size_t len); + lw_cell_t (*encode_attr)(void *user_data, + const struct lw_parsed_attr *attr); + int (*map_unicode)(void *user_data, int c); + void *user_data; }; -struct lw_terminal_vt100 *lw_terminal_vt100_init(void *user_data, - void (*unimplemented)(struct lw_terminal* term_emul, - char *seq, char chr), - void (*master_write)(void *user_data, void *buffer, size_t len), - lw_cell_t (*encode_attr)(void *user_data, - const struct lw_parsed_attr *attr), - unsigned int width, unsigned int height); -char lw_terminal_vt100_get(struct lw_terminal_vt100 *vt100, unsigned int x, unsigned int y); -lw_cell_t lw_terminal_vt100_aget(struct lw_terminal_vt100 *vt100, unsigned int x, unsigned int y); -const lw_cell_t *lw_terminal_vt100_getline(struct lw_terminal_vt100 *vt100, unsigned y); +struct lw_terminal_vt100 *lw_terminal_vt100_init( + void *user_data, + void (*unimplemented)(struct lw_terminal *term_emul, char *seq, char chr), + void (*master_write)(void *user_data, void *buffer, size_t len), + lw_cell_t (*encode_attr)(void *user_data, + const struct lw_parsed_attr *attr), + unsigned int width, unsigned int height); +char lw_terminal_vt100_get(struct lw_terminal_vt100 *vt100, unsigned int x, + unsigned int y); +lw_cell_t lw_terminal_vt100_aget(struct lw_terminal_vt100 *vt100, + unsigned int x, unsigned int y); +const lw_cell_t *lw_terminal_vt100_getline(struct lw_terminal_vt100 *vt100, + unsigned y); const lw_cell_t **lw_terminal_vt100_getlines(struct lw_terminal_vt100 *vt100); void lw_terminal_vt100_destroy(struct lw_terminal_vt100 *this); -void lw_terminal_vt100_read_str(struct lw_terminal_vt100 *this, const char *buffer); -void lw_terminal_vt100_read_buf(struct lw_terminal_vt100 *this, const char *buffer, size_t n); +void lw_terminal_vt100_read_str(struct lw_terminal_vt100 *this, + const char *buffer); +void lw_terminal_vt100_read_buf(struct lw_terminal_vt100 *this, + const char *buffer, size_t n); #endif diff --git a/hl-vt100/src/test.c b/hl-vt100/src/test.c index 3f89d87..d931f06 100644 --- a/hl-vt100/src/test.c +++ b/hl-vt100/src/test.c @@ -23,23 +23,21 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include -#include +#include "hl_vt100.h" #include #include -#include "hl_vt100.h" +#include +#include +#include +#include -void disp(struct vt100_headless *vt100) -{ +void disp(struct vt100_headless *vt100) { unsigned int x, y; const lw_cell_t **lines; lines = vt100_headless_getlines(vt100); write(1, "\n", 1); - for (y = 0; y < vt100->term->height; ++y) - { + for (y = 0; y < vt100->term->height; ++y) { write(1, "|", 1); for (x = 0; x < vt100->term->width; x++) { write(1, &lines[y][x], 1); @@ -48,12 +46,10 @@ void disp(struct vt100_headless *vt100) } } -int main(int ac, char **av) -{ +int main(int ac, char **av) { struct vt100_headless *vt100_headless; - if (ac == 1) - { + if (ac == 1) { puts("Usage: test PROGNAME"); return EXIT_FAILURE; } diff --git a/hl-vt100/src/vt100_module.c b/hl-vt100/src/vt100_module.c index 9a9e898..19ae390 100644 --- a/hl-vt100/src/vt100_module.c +++ b/hl-vt100/src/vt100_module.c @@ -12,39 +12,33 @@ other files, you'll have to create a file "foobarobject.h"; see floatobject.h for an example. */ - #include #include "Python.h" #include "structmember.h" -#include "lw_terminal_vt100.h" #include "hl_vt100.h" +#include "lw_terminal_vt100.h" typedef struct { - PyObject_HEAD - struct vt100_headless *obj; + PyObject_HEAD struct vt100_headless *obj; PyObject *changed_callback; } VT100Object; static PyTypeObject VT100_Type; -#define VT100Object_Check(v) Py_IS_TYPE(v, &VT100_Type) - +#define VT100Object_Check(v) Py_IS_TYPE(v, &VT100_Type) VT100Object **allocated; size_t allocated_size; /* VT100 methods */ -PyDoc_STRVAR(vt100_headless_fork_doc, -"fork(progname, argv)\n\ +PyDoc_STRVAR(vt100_headless_fork_doc, "fork(progname, argv)\n\ \n\ Fork a process in a new PTY handled by an headless VT100 emulator."); -static PyObject * -VT100_fork(VT100Object *self, PyObject *args) -{ +static PyObject *VT100_fork(VT100Object *self, PyObject *args) { char *progname; PyObject *pyargv; const char **argv; @@ -53,17 +47,14 @@ VT100_fork(VT100Object *self, PyObject *args) if (!PyArg_ParseTuple(args, "sO:fork", &progname, &pyargv)) return NULL; - if (!PyList_Check(pyargv)) - { + if (!PyList_Check(pyargv)) { PyErr_SetString(PyExc_TypeError, "not a list"); return NULL; } argc = PyList_Size(pyargv); - for (i = 0; i < argc; i++) - { + for (i = 0; i < argc; i++) { PyObject *o = PyList_GetItem(pyargv, i); - if (!PyUnicode_Check(o)) - { + if (!PyUnicode_Check(o)) { PyErr_SetString(PyExc_TypeError, "argv list must contain strings"); return NULL; } @@ -77,14 +68,12 @@ VT100_fork(VT100Object *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(vt100_headless_getattrlines_doc, -"getattrlines()\n\ +PyDoc_STRVAR(vt100_headless_getattrlines_doc, "getattrlines()\n\ \n\ Get a list of lines (with attributes) as currently seen by the emulator."); -static PyObject * -VT100_getattrlines(VT100Object *self, PyObject *Py_UNUSED(ignored)) -{ +static PyObject *VT100_getattrlines(VT100Object *self, + PyObject *Py_UNUSED(ignored)) { const lw_cell_t **lines; PyObject *result; @@ -111,14 +100,12 @@ VT100_getattrlines(VT100Object *self, PyObject *Py_UNUSED(ignored)) return result; } -PyDoc_STRVAR(vt100_headless_getlines_doc, -"getlines()\n\ +PyDoc_STRVAR(vt100_headless_getlines_doc, "getlines()\n\ \n\ Get a list of lines as currently seen by the emulator."); -static PyObject * -VT100_getlines(VT100Object *self, PyObject *Py_UNUSED(ignored)) -{ +static PyObject *VT100_getlines(VT100Object *self, + PyObject *Py_UNUSED(ignored)) { const lw_cell_t **lines; PyObject *result; @@ -140,63 +127,48 @@ VT100_getlines(VT100Object *self, PyObject *Py_UNUSED(ignored)) return result; } -PyDoc_STRVAR(vt100_headless_main_loop_doc, -"main_loop()\n\ +PyDoc_STRVAR(vt100_headless_main_loop_doc, "main_loop()\n\ \n\ Enter the emulator main loop."); -static PyObject * -VT100_main_loop(VT100Object *self, PyObject *Py_UNUSED(ignored)) -{ +static PyObject *VT100_main_loop(VT100Object *self, + PyObject *Py_UNUSED(ignored)) { vt100_headless_main_loop(self->obj); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; } - -PyDoc_STRVAR(vt100_headless_stop_doc, -"stop()\n\ +PyDoc_STRVAR(vt100_headless_stop_doc, "stop()\n\ \n\ Stop emulator main loop."); -static PyObject * -VT100_stop(VT100Object *self, PyObject *Py_UNUSED(ignored)) -{ +static PyObject *VT100_stop(VT100Object *self, PyObject *Py_UNUSED(ignored)) { vt100_headless_stop(self->obj); Py_RETURN_NONE; } - -static int -vt100_add_to_allocated(VT100Object *obj) -{ - for (size_t i = 0; i < allocated_size; i++) - { - if (allocated[i] == NULL) - { +static int vt100_add_to_allocated(VT100Object *obj) { + for (size_t i = 0; i < allocated_size; i++) { + if (allocated[i] == NULL) { allocated[i] = obj; return 0; } } /* Out of allocated memory, realloc. */ allocated_size *= 2; - allocated = PyMem_Realloc(allocated, allocated_size * sizeof(VT100Object*)); - if (allocated == NULL) - { + allocated = + PyMem_Realloc(allocated, allocated_size * sizeof(VT100Object *)); + if (allocated == NULL) { PyErr_SetString(PyExc_MemoryError, "cannot allocate vt100 emulator"); return -1; } return vt100_add_to_allocated(obj); } -static int -vt100_del_from_allocated(VT100Object *obj) -{ - for (size_t i = 0; i < allocated_size; i++) - { - if (allocated[i] == obj) - { +static int vt100_del_from_allocated(VT100Object *obj) { + for (size_t i = 0; i < allocated_size; i++) { + if (allocated[i] == obj) { allocated[i] = NULL; return 0; } @@ -204,59 +176,45 @@ vt100_del_from_allocated(VT100Object *obj) return -1; } -VT100Object * -vt100_find_in_allocated(struct vt100_headless *obj) -{ +VT100Object *vt100_find_in_allocated(struct vt100_headless *obj) { for (size_t i = 0; i < allocated_size; i++) if (allocated[i]->obj == obj) return allocated[i]; return NULL; } -void -hl_vt100_changed_cb(struct vt100_headless *this) -{ +void hl_vt100_changed_cb(struct vt100_headless *this) { VT100Object *obj; PyObject *result; obj = vt100_find_in_allocated(this); - if (obj->changed_callback != NULL && obj->changed_callback != Py_None) - { + if (obj->changed_callback != NULL && obj->changed_callback != Py_None) { result = PyObject_CallNoArgs(obj->changed_callback); if (result == NULL) this->should_quit = 1; } } -static int -VT100_init(VT100Object *self, PyObject *args, PyObject *kwds) -{ +static int VT100_init(VT100Object *self, PyObject *args, PyObject *kwds) { self->obj = new_vt100_headless(); vt100_add_to_allocated(self); self->obj->changed = hl_vt100_changed_cb; - if (self->obj == NULL) - { + if (self->obj == NULL) { PyErr_SetString(PyExc_MemoryError, "cannot allocate vt100 emulator"); return -1; } return 0; } -static PyObject * -VT100_getwidth(VT100Object *self, void *closure) -{ +static PyObject *VT100_getwidth(VT100Object *self, void *closure) { return PyLong_FromUnsignedLong(self->obj->term->width); } -static PyObject * -VT100_getheight(VT100Object *self, void *closure) -{ +static PyObject *VT100_getheight(VT100Object *self, void *closure) { return PyLong_FromUnsignedLong(self->obj->term->height); } -static void -VT100_dealloc(VT100Object *self) -{ +static void VT100_dealloc(VT100Object *self) { vt100_del_from_allocated(self); Py_XDECREF(self->changed_callback); delete_vt100_headless(self->obj); @@ -264,30 +222,31 @@ VT100_dealloc(VT100Object *self) } static PyMethodDef VT100_methods[] = { - {"fork", (PyCFunction)VT100_fork, METH_VARARGS, vt100_headless_fork_doc}, - {"getlines", (PyCFunction)VT100_getlines, METH_NOARGS, vt100_headless_getlines_doc}, - {"getattrlines", (PyCFunction)VT100_getattrlines, METH_NOARGS, vt100_headless_getattrlines_doc}, - {"main_loop", (PyCFunction)VT100_main_loop, METH_NOARGS, vt100_headless_main_loop_doc}, - {"stop", (PyCFunction)VT100_stop, METH_NOARGS, vt100_headless_stop_doc}, - {NULL, NULL} /* sentinel */ + {"fork", (PyCFunction)VT100_fork, METH_VARARGS, vt100_headless_fork_doc}, + {"getlines", (PyCFunction)VT100_getlines, METH_NOARGS, + vt100_headless_getlines_doc}, + {"getattrlines", (PyCFunction)VT100_getattrlines, METH_NOARGS, + vt100_headless_getattrlines_doc}, + {"main_loop", (PyCFunction)VT100_main_loop, METH_NOARGS, + vt100_headless_main_loop_doc}, + {"stop", (PyCFunction)VT100_stop, METH_NOARGS, vt100_headless_stop_doc}, + {NULL, NULL} /* sentinel */ }; - static PyMemberDef VT100_members[] = { - {"changed_callback", T_OBJECT_EX, offsetof(VT100Object, changed_callback), 0, - "Changed Callback"}, - {NULL} /* Sentinel */ + {"changed_callback", T_OBJECT_EX, offsetof(VT100Object, changed_callback), + 0, "Changed Callback"}, + {NULL} /* Sentinel */ }; static PyGetSetDef VT100_getsetters[] = { - {"width", (getter) VT100_getwidth, NULL, "Terminal width", NULL}, - {"height", (getter) VT100_getheight, NULL, "Terminal height", NULL}, - {NULL} /* Sentinel */ + {"width", (getter)VT100_getwidth, NULL, "Terminal width", NULL}, + {"height", (getter)VT100_getheight, NULL, "Terminal height", NULL}, + {NULL} /* Sentinel */ }; static PyTypeObject VT100_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "hl_vt100.vt100_headless", + PyVarObject_HEAD_INIT(NULL, 0).tp_name = "hl_vt100.vt100_headless", .tp_basicsize = sizeof(VT100Object), .tp_dealloc = (destructor)VT100_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, @@ -298,8 +257,7 @@ static PyTypeObject VT100_Type = { .tp_getset = VT100_getsetters, }; -PyDoc_STRVAR(module_doc, -"Headless VT100 Terminal Emulator."); +PyDoc_STRVAR(module_doc, "Headless VT100 Terminal Emulator."); static struct PyModuleDef hl_vt100_module = { PyModuleDef_HEAD_INIT, @@ -307,13 +265,11 @@ static struct PyModuleDef hl_vt100_module = { .m_doc = module_doc, }; -PyMODINIT_FUNC -PyInit_hl_vt100(void) -{ +PyMODINIT_FUNC PyInit_hl_vt100(void) { PyObject *m; m = PyModule_Create(&hl_vt100_module); - allocated = PyMem_Calloc(4096, sizeof(VT100Object*)); + allocated = PyMem_Calloc(4096, sizeof(VT100Object *)); allocated_size = 4096; if (m == NULL) return NULL; diff --git a/keyboard.c b/keyboard.c index 52297af..c1202b3 100644 --- a/keyboard.c +++ b/keyboard.c @@ -1,11 +1,11 @@ -#include "atkbd.pio.h" #include "keyboard.h" -#include "pinout.h" +#include "atkbd.pio.h" #include "chargen.h" +#include "pinout.h" +#include "hardware/clocks.h" #include "pico.h" #include "pico/stdlib.h" -#include "hardware/clocks.h" #define EOF (-1) @@ -18,14 +18,18 @@ static int kbd_sm; static int ll_kbd_read_timeout(int timeout_us) { uint64_t deadline = time_us_64() + timeout_us; while (pio_sm_is_rx_fifo_empty(kbd_pio, kbd_sm)) { - if(time_us_64() > deadline) { return EOF; } + if (time_us_64() > deadline) { + return EOF; + } } return pio_sm_get_blocking(kbd_pio, kbd_sm); } static int kbd_read_timeout(int timeout_us) { int r = ll_kbd_read_timeout(timeout_us); - if (r == EOF) { return EOF; } + if (r == EOF) { + return EOF; + } r = (r >> 22) & 0xff; return r; // todo: check parity, start & end bits! } @@ -54,7 +58,6 @@ static bool write_expect_fa(int value, const char *msg) { pio_sm_clear_fifos(kbd_pio, kbd_sm); kbd_write_blocking(value); return expect(0xfa, msg); - } bool keyboard_setup(PIO pio) { gpio_init(KEYBOARD_DATA_PIN); @@ -64,14 +67,14 @@ bool keyboard_setup(PIO pio) { gpio_pull_down(KEYBOARD_DATA_PIN + 1); int i = 0, j = 1; - while(!(gpio_get(KEYBOARD_DATA_PIN) && gpio_get(KEYBOARD_DATA_PIN + 1))) { - if(i ++ == j) { + while (!(gpio_get(KEYBOARD_DATA_PIN) && gpio_get(KEYBOARD_DATA_PIN + 1))) { + if (i++ == j) { scrnprintf("Waiting for keyboard to boot... %d ms so far\r", i); j *= 10; } sleep_ms(1); } - + sleep_ms(10); kbd_pio = pio; @@ -99,17 +102,20 @@ bool keyboard_setup(PIO pio) { return ok; } - -enum { LSHIFT=1, LCTRL=2, LALT=4, RSHIFT = 8, RCTRL = 16, RALT = 32, MOD_CAPS=64, MOD_NUM = 128, TOGGLING_MODIFIERS = MOD_CAPS | MOD_NUM }; +enum { + LSHIFT = 1, + LCTRL = 2, + LALT = 4, + RSHIFT = 8, + RCTRL = 16, + RALT = 32, + MOD_CAPS = 64, + MOD_NUM = 128, + TOGGLING_MODIFIERS = MOD_CAPS | MOD_NUM +}; const char keyboard_modifiers[256] = { - [0x12] = LSHIFT, - [0x59] = RSHIFT, - [0x11] = LCTRL, - [0x58] = RCTRL, - [0x19] = LALT, - [0x39] = RALT, - [0x14] = MOD_CAPS, - [0x76] = MOD_NUM, + [0x12] = LSHIFT, [0x59] = RSHIFT, [0x11] = LCTRL, [0x58] = RCTRL, + [0x19] = LALT, [0x39] = RALT, [0x14] = MOD_CAPS, [0x76] = MOD_NUM, }; enum SYMBOLS { @@ -143,37 +149,21 @@ enum SYMBOLS { const char *const symtab[MAX_SYMBOLS] = { #define ENT(x, y) [x] = y - ENT(F1, "\eOP"), - ENT(F2, "\eOQ"), - ENT(F3, "\eOR"), - ENT(F4, "\eOS"), - ENT(F5, "\e[15~"), - ENT(F6, "\e[17~"), - ENT(F7, "\e[18~"), - ENT(F8, "\e[19~"), - ENT(F9, "\e[20~"), - ENT(F10, "\e[21~"), - ENT(F11, "\e[23~"), - ENT(F12, "\e[24~"), - ENT(PRTSCR, "\ei"), - ENT(PAUSE, ""), - ENT(INSERT, "\e[2~"), - ENT(DELETE, "\e[3~"), - ENT(UPARROW, "\e[A"), - ENT(DOWNARROW, "\e[B"), - ENT(RIGHTARROW, "\e[C"), - ENT(LEFTARROW, "\e[D"), - ENT(HOME, "\e[H"), - ENT(END, "\e[F"), - ENT(PAGEUP, "\e[5~"), - ENT(PAGEDOWN, "\e[6~"), + ENT(F1, "\eOP"), ENT(F2, "\eOQ"), ENT(F3, "\eOR"), + ENT(F4, "\eOS"), ENT(F5, "\e[15~"), ENT(F6, "\e[17~"), + ENT(F7, "\e[18~"), ENT(F8, "\e[19~"), ENT(F9, "\e[20~"), + ENT(F10, "\e[21~"), ENT(F11, "\e[23~"), ENT(F12, "\e[24~"), + ENT(PRTSCR, "\ei"), ENT(PAUSE, ""), ENT(INSERT, "\e[2~"), + ENT(DELETE, "\e[3~"), ENT(UPARROW, "\e[A"), ENT(DOWNARROW, "\e[B"), + ENT(RIGHTARROW, "\e[C"), ENT(LEFTARROW, "\e[D"), ENT(HOME, "\e[H"), + ENT(END, "\e[F"), ENT(PAGEUP, "\e[5~"), ENT(PAGEDOWN, "\e[6~"), #undef ENT }; #define SYM(x) (0x8000 | (int)(x)) #define CMD(x) (0xc000 | (int)(x)) -#define CHAR2(c, d) (int) c | (((int) d) << 8) -#define CHAR2(c, d) (int) c | (((int) d) << 8) +#define CHAR2(c, d) (int)c | (((int)d) << 8) +#define CHAR2(c, d) (int)c | (((int)d) << 8) #define ALPHA(c) CHAR2(c, c ^ ('a' ^ 'A')) #define NOMOD(c) CHAR2(c, c) @@ -199,7 +189,7 @@ const uint16_t keyboard_codes[256] = { [0x62] = SYM(PAUSE), [0x67] = SYM(INSERT), [0x64] = SYM(DELETE), - + [0x0e] = CHAR2('`', '~'), [0x16] = CHAR2('1', '!'), [0x1e] = CHAR2('2', '@'), @@ -260,7 +250,6 @@ const uint16_t keyboard_codes[256] = { [0x6a] = SYM(RIGHTARROW), [0x60] = SYM(DOWNARROW), - [0x6e] = SYM(HOME), [0x65] = SYM(END), [0x6f] = SYM(PAGEUP), @@ -275,20 +264,19 @@ static void queue_add_data(queue_t *q, int data) { } static void queue_add_str(queue_t *q, const char *s) { - while(*s) queue_add_data(q, *s++); + while (*s) + queue_add_data(q, *s++); } - -static -void queue_handle_event(queue_t *q, bool release, int value) { +static void queue_handle_event(queue_t *q, bool release, int value) { int modifiers = keyboard_modifiers[value]; if (modifiers) { - if(release) { + if (release) { if (modifiers & TOGGLING_MODIFIERS) { current_modifiers ^= modifiers; keyboard_set_leds( - ((current_modifiers & MOD_NUM) ? LED_NUM : 0) | - ((current_modifiers & MOD_CAPS) ? LED_CAPS : 0)); + ((current_modifiers & MOD_NUM) ? LED_NUM : 0) | + ((current_modifiers & MOD_CAPS) ? LED_CAPS : 0)); } else { current_modifiers &= ~modifiers; } @@ -301,7 +289,9 @@ void queue_handle_event(queue_t *q, bool release, int value) { } return; } - if(release) { return; } + if (release) { + return; + } bool is_shift = current_modifiers & (LSHIFT | RSHIFT); bool is_ctrl = current_modifiers & (LCTRL | RCTRL); @@ -309,19 +299,19 @@ void queue_handle_event(queue_t *q, bool release, int value) { bool is_caps = current_modifiers & (MOD_CAPS); int kc = keyboard_codes[value]; - if(!kc) { - scrnprintf("\r\nUn-mapped key: 0x%02x\r\n", value); + if (!kc) { + scrnprintf("\r\nUn-mapped key: 0x%02x\r\n", value); return; } - if((kc & 0xc000) == 0xc000) { + if ((kc & 0xc000) == 0xc000) { queue_add_data(q, kc); return; } - if(kc & 0x8000) { + if (kc & 0x8000) { int sym = kc & 0x7fff; - if(is_ctrl && is_alt) { + if (is_ctrl && is_alt) { if (sym == DELETE) { queue_add_data(q, CMD_REBOOT); } @@ -342,19 +332,20 @@ void queue_handle_event(queue_t *q, bool release, int value) { int c = LO(kc); // scrnprintf("c=%d HI=%d is_shift=%d\n", c, HI(kc), is_shift); - if(HI(kc) && is_shift) c = HI(kc); + if (HI(kc) && is_shift) + c = HI(kc); #define CTRLABLE(c) (c >= 64 && c <= 127) - if(is_ctrl && CTRLABLE(c)) { + if (is_ctrl && CTRLABLE(c)) { c = c & 0x1f; } - if(is_ctrl && c == 010) { + if (is_ctrl && c == 010) { c = 0377; // ctrl-backspace = RUBOUT } #define IS_ALPHA(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) - if(is_caps && IS_ALPHA(c)) { + if (is_caps && IS_ALPHA(c)) { c ^= ('a' ^ 'A'); } - if(is_alt) { + if (is_alt) { queue_add_data(q, '\033'); } queue_add_data(q, c); @@ -364,9 +355,8 @@ void keyboard_poll(queue_t *q) { int value = kbd_read_timeout(0); if (value == EOF) { return; - } - else if (value == 0xfa) { - if(pending_led_flag) { + } else if (value == 0xfa) { + if (pending_led_flag) { kbd_write_blocking(pending_led_value); pending_led_flag = false; } diff --git a/mkfont/adafruit_bitmap_font/ttf.py b/mkfont/adafruit_bitmap_font/ttf.py index 807ac79..af3595c 100644 --- a/mkfont/adafruit_bitmap_font/ttf.py +++ b/mkfont/adafruit_bitmap_font/ttf.py @@ -28,7 +28,7 @@ class TTF: s = struct.calcsize(format) return struct.unpack_from(format, f.read(s)) - scalar_type = read(">I") + read(">I") # discard "scalar_type numTables, searchRange, entrySelector, rangeShift = read(">HHHH") print(numTables) diff --git a/mkfont/mkfont.py b/mkfont/mkfont.py index 4064bd2..4aa25f1 100644 --- a/mkfont/mkfont.py +++ b/mkfont/mkfont.py @@ -1,10 +1,10 @@ import array -from dataclasses import dataclass import sys import click from adafruit_bitmap_font import bitmap_font, Bitmap + def extract_deposit_bits(*positions): data_out = 0 for p in positions: @@ -13,6 +13,7 @@ def extract_deposit_bits(*positions): data_out |= 1 << dest return data_out + class OffsetBitmap: def __init__(self, dx, dy, glyph): self.dx = dx @@ -26,21 +27,22 @@ class OffsetBitmap: print(pos, x, y) if 0 <= x < self.glyph.bitmap.width and 0 <= y < self.glyph.bitmap.height: - return self.glyph.bitmap[x,y] + return self.glyph.bitmap[x, y] return 0 + @click.command @click.argument("bdf", type=click.Path(exists=True)) -@click.argument("header", type=click.File(mode='w'), default=sys.stdout) +@click.argument("header", type=click.File(mode="w"), default=sys.stdout) def main(bdf, header): font = bitmap_font.load_font(bdf, Bitmap) width, height, dx, dy = font.get_bounding_box() print(width, height, dx, dy) -# if width != 5 or height != 9: -# raise SystemExit("sorry, only 5x9 monospace fonts supported") + # if width != 5 or height != 9: + # raise SystemExit("sorry, only 5x9 monospace fonts supported") - output_data = array.array('H', [0] * 9 * 256) + output_data = array.array("H", [0] * 9 * 256) font.load_glyphs(range(256)) @@ -56,9 +58,11 @@ def main(bdf, header): (bitmap[3, j], 2, 3), (bitmap[2, j], 4, 5), (bitmap[1, j], 6, 7), - (bitmap[0, j], 8, 9)) + (bitmap[0, j], 8, 9), + ) output_data[j * 256 + i] = d << 2 print(", ".join(f"0x{x:04x}" for x in output_data), file=header) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/vgamode.py b/vgamode.py index 369a0cb..5bd923b 100644 --- a/vgamode.py +++ b/vgamode.py @@ -1,13 +1,14 @@ #!/usr/bin/env python import sys -from enum import Enum, auto from dataclasses import dataclass, replace + class Polarity: Negative = 0 Positive = 1 + @dataclass(frozen=True) class VideoMode: pixel_clock_khz: int @@ -20,7 +21,9 @@ class VideoMode: @property def total_width(self): - return self.visible_width + self.hfront_porch + self.hsync_pulse + self.hback_porch + return ( + self.visible_width + self.hfront_porch + self.hsync_pulse + self.hback_porch + ) @property def line_rate_khz(self): @@ -42,7 +45,12 @@ class VideoMode: @property def total_lines(self): - return self.visible_height + self.vfront_porch + self.vsync_pulse + self.vback_porch + return ( + self.visible_height + + self.vfront_porch + + self.vsync_pulse + + self.vback_porch + ) @property def frame_rate_hz(self): @@ -55,17 +63,18 @@ class VideoMode: def __repr__(self): return f"" + def change_visible_width(mode_in, new_w, new_clock=None): print(mode_in) if new_clock is None: - new_clock = mode_in.pixel_clock_khz * new_w / mode_in.visible_width - new_mode = replace(mode_in, - pixel_clock_khz = new_clock, - visible_width = new_w, + new_clock = mode_in.pixel_clock_khz * new_w / mode_in.visible_width + new_mode = replace( + mode_in, + pixel_clock_khz=new_clock, + visible_width=new_w, ) print(new_mode) ratio = new_clock / mode_in.pixel_clock_khz - new_visible_time = new_mode.visible_line_time_us new_line_counts = round(mode_in.total_width * ratio) print(new_line_counts, mode_in.total_width * ratio) new_pulse = round(mode_in.hsync_pulse * ratio) @@ -73,29 +82,35 @@ def change_visible_width(mode_in, new_w, new_clock=None): porch_ratio = mode_in.hfront_porch / (mode_in.hfront_porch + mode_in.hback_porch) new_front = round(new_porch_counts * porch_ratio) new_back = new_porch_counts - new_front - print((mode_in.hfront_porch, mode_in.hsync_pulse, mode_in.hback_porch), "->", (new_front, new_pulse, new_back)) + print( + (mode_in.hfront_porch, mode_in.hsync_pulse, mode_in.hback_porch), + "->", + (new_front, new_pulse, new_back), + ) new_mode = replace( - new_mode, - hfront_porch = new_front, - hsync_pulse = new_pulse, - hback_porch = new_back) + new_mode, hfront_porch=new_front, hsync_pulse=new_pulse, hback_porch=new_back + ) print(new_mode) print() return new_mode + def change_visible_height(mode_in, new_h): delta_rows = mode_in.visible_height - new_h delta_front_porch = delta_rows // 2 delta_back_porch = delta_rows - delta_front_porch - new_mode = replace(mode_in, - visible_height = new_h, - vfront_porch = mode_in.vfront_porch + delta_front_porch, - vback_porch = mode_in.vback_porch + delta_back_porch) + new_mode = replace( + mode_in, + visible_height=new_h, + vfront_porch=mode_in.vfront_porch + delta_front_porch, + vback_porch=mode_in.vback_porch + delta_back_porch, + ) print(new_mode) print() assert new_mode.total_lines == mode_in.total_lines return new_mode + def pio_hard_delay(instr, n, file): assert n > 0 assert n < 128 @@ -105,10 +120,14 @@ def pio_hard_delay(instr, n, file): n -= cycles print(file=file) -def print_pio_hsync_program(program_name_base, mode, h_divisor, cycles_per_pixel, file=sys.stdout): + +def print_pio_hsync_program( + program_name_base, mode, h_divisor, cycles_per_pixel, file=sys.stdout +): net_khz = mode.pixel_clock_khz / h_divisor err = (mode.visible_width + mode.hfront_porch) % h_divisor - print(f""" + print( + f""" ; Horizontal sync program for {mode} ; PIO clock frequency = {mode.pixel_clock_khz:.1f}/{h_divisor}khz = {net_khz:.1f} ; @@ -119,19 +138,28 @@ def print_pio_hsync_program(program_name_base, mode, h_divisor, cycles_per_pixel activeporch: jmp x-- activeporch ; Remain high in active mode and front porch -""", file=file) +""", + file=file, + ) cycles, err = divmod(mode.hsync_pulse + err, h_divisor) - print(f"syncpulse: ; {mode.hsync_pulse}/{h_divisor} clocks [actual {cycles} error {err}]", file=file) + print( + f"syncpulse: ; {mode.hsync_pulse}/{h_divisor} clocks [actual {cycles} error {err}]", + file=file, + ) pio_hard_delay(f"set pins, {mode.hsync_polarity:d}", cycles, file=file) cycles, err = divmod(mode.hback_porch + err, h_divisor) - print(f"backporch: ; {mode.hback_porch}/{h_divisor} clocks [actual {cycles} error {err}]", file=file) + print( + f"backporch: ; {mode.hback_porch}/{h_divisor} clocks [actual {cycles} error {err}]", + file=file, + ) pio_hard_delay(f"set pins, {not mode.hsync_polarity:d}", cycles - 1, file=file) print(" irq 0 [1]", file=file) print(".wrap", file=file) - print(f""" + print( + f""" % c-sdk {{ static inline void {program_name_base}_hsync_program_init(PIO pio, uint sm, uint offset, uint pin) {{ @@ -152,13 +180,16 @@ static inline void {program_name_base}_hsync_program_init(PIO pio, uint sm, uint // Set up the value in the OSR register pio_sm_put(pio, sm, {mode.visible_width} + {mode.hfront_porch} - 1); pio_sm_exec_wait_blocking(pio, sm, pio_encode_pull(false, true)); - + // Set the state machine running pio_sm_set_enabled(pio, sm, true); }} %}} -""", file=file) +""", + file=file, + ) + def pio_yloop(instr, n, label, comment, file): assert n <= 65 @@ -183,22 +214,45 @@ def pio_yloop(instr, n, label, comment, file): print(f" {instr}", file=file) print(file=file) + def print_pio_vsync_program(program_name_base, mode, cycles_per_pixel, file=sys.stdout): - print(f""" + print( + f""" .program {program_name_base}_vsync .side_set 1 opt ; Vertical sync program for {mode} ; .wrap_target ; Program wraps to here -""", file=file) +""", + file=file, + ) - pio_yloop("wait 1 irq 0", mode.vfront_porch, "frontporch", f"{mode.vfront_porch} lines", file=file) + pio_yloop( + "wait 1 irq 0", + mode.vfront_porch, + "frontporch", + f"{mode.vfront_porch} lines", + file=file, + ) - pio_yloop(f"wait 1 irq 0 side {mode.vsync_polarity:d}", mode.vsync_pulse, "syncpulse", f"{mode.vsync_pulse} lines", file=file) + pio_yloop( + f"wait 1 irq 0 side {mode.vsync_polarity:d}", + mode.vsync_pulse, + "syncpulse", + f"{mode.vsync_pulse} lines", + file=file, + ) - pio_yloop(f"wait 1 irq 0 side {not mode.vsync_polarity:d}", mode.vback_porch, "backporch", f"{mode.vback_porch} lines", file=file) + pio_yloop( + f"wait 1 irq 0 side {not mode.vsync_polarity:d}", + mode.vback_porch, + "backporch", + f"{mode.vback_porch} lines", + file=file, + ) - print(f""" + print( + """ ; ACTIVE mov x, osr ; Copy value from OSR to x scratch register active: @@ -206,12 +260,14 @@ active: irq 1 ; Signal that we're in active mode jmp x-- active ; Remain in active mode, decrementing counter -""", file=file) - +""", + file=file, + ) print(".wrap", file=file) - print(f""" + print( + f""" % c-sdk {{ static inline void {program_name_base}_vsync_program_init(PIO pio, uint sm, uint offset, uint pin) {{ @@ -242,14 +298,18 @@ static inline void {program_name_base}_vsync_program_init(PIO pio, uint sm, uint }} %}} -""", file=file) +""", + file=file, + ) - -def print_pio_pixel_program(program_name_base, mode, out_instr, cycles_per_pixel, file=sys.stdout): +def print_pio_pixel_program( + program_name_base, mode, out_instr, cycles_per_pixel, file=sys.stdout +): net_khz = cycles_per_pixel * mode.pixel_clock_khz assert cycles_per_pixel >= 2 - print(f""" + print( + f""" .program {program_name_base}_pixel ; Pixel generator program for {mode} ; PIO clock frequency = {cycles_per_pixel}×{mode.pixel_clock_khz}khz = {net_khz} @@ -264,9 +324,12 @@ colorout: {out_instr} [{cycles_per_pixel-2}] jmp x-- colorout ; Stay here thru horizontal active mode -.wrap""", file=file) +.wrap""", + file=file, + ) - print(f""" + print( + f""" % c-sdk {{ enum {{ {program_name_base}_pixel_clock_khz = {mode.pixel_clock_khz}, {program_name_base}_sys_clock_khz = {cycles_per_pixel * mode.pixel_clock_khz} }}; @@ -283,7 +346,7 @@ static inline void {program_name_base}_pixel_program_init(PIO pio, uint sm, uint // Set this pin's GPIO function (connect PIO to the pad) for(uint i=0; i