diff options
Diffstat (limited to 'src/tty.c')
-rw-r--r-- | src/tty.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/tty.c b/src/tty.c new file mode 100644 index 0000000..f9413b4 --- /dev/null +++ b/src/tty.c @@ -0,0 +1,164 @@ +#include <tft.h> +#include <zeta.h> +#include <tty.h> + +struct color { + uint8_t r, g, b; +}; + +static unsigned int row = 0; +static unsigned int col = 0; + +// Index of first row inside buf +static volatile uint8_t head = 0; + +// TTY's current contents +static volatile uint8_t buf[TTY_HEIGHT][TTY_WIDTH]; + +static volatile struct color bg_color = {0x00, 0x00, 0x00}; +static volatile struct color fg_color = {0xFF, 0xFB, 0x00}; + +extern const uint8_t font[97][8]; + + +static uint8_t cursor = 0; +static uint8_t timer = 0; + +void +blink_cursor(void) __critical __interrupt(3) +{ + if (++timer >= 75) { + uint8_t i; + + tft_set_area(8 * col, 8 * row, 8, 8); + tft_ram_wr(); + + if ((cursor ^= 1)) { + for (i = 0; i < 64; ++i) + tft_pixel(fg_color.r, fg_color.g, fg_color.b); + } else { + for (i = 0; i < 64; ++i) + tft_pixel(bg_color.r, bg_color.g, bg_color.b); + } + timer = 0; + } +} + +static void +draw(u8 c) +{ + u8 i, j; + const u8 *chr; + + if (c < ' ') + return; + + chr = font[c - ' ']; + + tft_ram_wr(); + + for (i = 0; i < 8; ++i) { + u8 row = chr[i]; + for (j = 0; j < 8; ++j) { + if (row & 1) + tft_pixel(fg_color.r, fg_color.g, fg_color.b); + else + tft_pixel(bg_color.r, bg_color.g, bg_color.b); + row >>= 1; + } + } +} + +static void +scroll(void) +{ + uint16_t i, j; + head = (head + 1) % TTY_HEIGHT; + + for (i = head; i < TTY_HEIGHT; ++i) { + for (j = 0; j < TTY_WIDTH; ++j) { + tft_set_area(8 * j, 8 * (i - head), 8, 8); + draw(buf[i][j]); + } + } + + for (i = 0; i < head - 1; ++i) { + for (j = 0; j < TTY_WIDTH; ++j) { + tft_set_area(8 * j, 8 * (TTY_HEIGHT - head + i), 8, 8); + draw(buf[i][j]); + } + } + + for (j = 0; j < TTY_WIDTH; ++j) { + tft_set_area(8 * j, 8 * (TTY_HEIGHT - 1), 8, 8); + draw(' '); + } +} + +static void +newline(void) +{ + if (++row >= TTY_HEIGHT) { + row = TTY_HEIGHT - 1; + scroll(); + } +} + +static void +advance(void) +{ + if (++col >= TTY_WIDTH) { + newline(); + col = 0; + } +} + +void +addch(char c) +{ + switch (c) { + case '\b': + if (col != 0) + --col; + return; + + case '\r': + col = 0; + return; + + case '\n': + newline(); + return; + } + + tft_set_area(8 * col, 8 * row, 8, 8); + + draw(c); + + buf[(head + row) % TTY_HEIGHT][col] = c; + advance(); +} + +void +setcur(unsigned int ncol, unsigned int nrow) +{ + col = ncol; + row = nrow; +} + +void +swap_colors(void) +{ + struct color tmp = {fg_color.r, fg_color.g, fg_color.b}; + fg_color = bg_color; + bg_color = tmp; +} + +void +addstr(const char *str) +{ + while (*str) { + addch(*str); + ++str; + } +} |