#include #include #include #include #include "uart.h" #include "uart_ansi.h" void _vt_apply_style(); void _vt_reset_attribs_do(); void _vt_style_do(); void _vt_color_do(); void vt_goto(uint8_t x, uint8_t y) { uart_putc(27); uart_putc('['); uart_put8u(x); uart_putc(';'); uart_put8u(y); uart_putc('H'); } void vt_goto_x(uint8_t x) { uart_putc(27); uart_putc('['); uart_put8u(x); uart_putc('`'); } void vt_goto_y(uint8_t y) { uart_putc(27); uart_putc('['); uart_put8u(y); uart_putc('d'); } void vt_move(int8_t x, int8_t y) { vt_move_x(x); vt_move_y(y); } void vt_move_x(int8_t x) { if (x < 0) { vt_left(-x); } else { vt_right(x); } } void vt_move_y(int8_t y) { if (y < 0) { vt_up(-y); } else { vt_down(y); } } void vt_up(uint8_t y) { if (y == 0) return; uart_putc(27); uart_putc('['); uart_put8u(y); uart_putc('A'); } void vt_down(uint8_t y) { if (y == 0) return; uart_putc(27); uart_putc('['); uart_put8u(y); uart_putc('B'); } void vt_left(uint8_t x) { if (x == 0) return; uart_putc(27); uart_putc('['); uart_put8u(x); uart_putc('D'); } void vt_right(uint8_t x) { if (x == 0) return; uart_putc(27); uart_putc('['); uart_put8u(x); uart_putc('C'); } void vt_scroll(int8_t y) { while (y < 0) { uart_putc(27); uart_putc('D'); // up y++; } while (y > 0) { uart_putc(27); uart_putc('M'); // down y--; } } void vt_scroll_set(uint8_t from, uint8_t to) { uart_putc(27); uart_putc('['); uart_put8u(from); uart_putc(';'); uart_put8u(to); uart_putc('r'); } void vt_scroll_reset() { uart_putc(27); uart_putc('['); uart_putc('r'); } typedef struct { uint8_t flags; uint8_t fg; uint8_t bg; } vt_style_t; vt_style_t saved_style; vt_style_t current_style; void vt_save() { uart_puts_pgm(PSTR("\x1B[s")); saved_style = current_style; } void vt_restore() { uart_puts_pgm(PSTR("\x1B[u")); current_style = saved_style; } /** Disable all text attributes (excluding color) */ void vt_attr_reset() { current_style.flags = 0; _vt_reset_attribs_do(); _vt_apply_style(); } /** Set color to white on black */ void vt_color_reset() { current_style.fg = VT_WHITE; current_style.bg = VT_BLACK; _vt_color_do(); } /** Enable or disable a text attribute */ void vt_attr(uint8_t attribute, bool on) { // flags are powers of two // so this can handle multiple OR'd flags for(uint8_t c = 1; c <= VT_FAINT; c *= 2) { if (attribute & c) { if (on) { current_style.flags |= c; } else { current_style.flags &= ~c; } } } _vt_apply_style(); } /** Send style and color commands */ void _vt_apply_style() { _vt_reset_attribs_do(); _vt_style_do(); _vt_color_do(); } /** Set color 0..7 */ void vt_color(uint8_t fg, uint8_t bg) { current_style.fg = fg; current_style.bg = bg; _vt_color_do(); } /** Set FG color 0..7 */ void vt_color_fg(uint8_t fg) { current_style.fg = fg; _vt_color_do(); } /** Set BG color 0..7 */ void vt_color_bg(uint8_t bg) { current_style.bg = bg; _vt_color_do(); } /** Send reset command */ inline void _vt_reset_attribs_do() { uart_puts_pgm(PSTR("\x1B[m")); // reset } /** Send commands for text attribs */ void _vt_style_do() { if (current_style.flags & VT_BOLD) { uart_puts_pgm(PSTR("\x1B[1m")); } if (current_style.flags & VT_FAINT) { uart_puts_pgm(PSTR("\x1B[2m")); } if (current_style.flags & VT_ITALIC) { uart_puts_pgm(PSTR("\x1B[3m")); } if (current_style.flags & VT_UNDERLINE) { uart_puts_pgm(PSTR("\x1B[4m")); } if (current_style.flags & VT_BLINK) { uart_puts_pgm(PSTR("\x1B[5m")); } if (current_style.flags & VT_REVERSE) { uart_puts_pgm(PSTR("\x1B[7m")); } } /** Send commands for xolor */ void _vt_color_do() { uart_putc(27); uart_putc('['); uart_put8u(30 + current_style.fg); uart_putc(';'); uart_put8u(40 + current_style.bg); uart_putc('m'); } /** Insert blank lines febore the current line */ void vt_insert_lines(uint8_t count) { uart_putc(27); uart_putc('['); uart_put8u(count); uart_putc('L'); } /** Delete lines from the current line down */ void vt_delete_lines(uint8_t count) { uart_putc(27); uart_putc('['); uart_put8u(count); uart_putc('M'); } /** Insert empty characters at cursor */ void vt_insert_chars(uint8_t count) { uart_putc(27); uart_putc('['); uart_put8u(count); uart_putc('@'); } /** Delete characters at cursor */ void vt_delete_chars(uint8_t count) { uart_putc(27); uart_putc('['); uart_put8u(count); uart_putc('P'); } void vt_clear() { uart_puts_pgm(PSTR("\x1B[2J")); } void vt_erase_forth() { uart_puts_pgm(PSTR("\x1B[K")); } void vt_erase_back() { uart_puts_pgm(PSTR("\x1B[1K")); } void vt_erase_line() { uart_puts_pgm(PSTR("\x1B[2K")); } void vt_erase_above() { uart_puts_pgm(PSTR("\x1B[1J")); } void vt_erase_below() { uart_puts_pgm(PSTR("\x1B[J")); } void vt_home() { uart_puts_pgm(PSTR("\x1B[H")); } /** Initialize helper variables */ void vt_init() { vt_reset(); } /** Reset state and clear screen */ void vt_reset() { // reset color and attributes vt_color_reset(); vt_attr_reset(); vt_scroll_reset(); // clear screen vt_clear(); // go to top left vt_home(); // overwrite saved state vt_save(); }