aboutsummaryrefslogtreecommitdiff
#include <tft.h>
#include <zeta.h>
#include <tty.h>

struct color {
	uint8_t r, g, b;
};

static u16 row = 0;
static u16 col = 0;

// Index of first row inside buf
static volatile u8 head = 0;

// TTY's current contents
static volatile u8 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 u8 font[97][8];


static u8 cursor = 0;
static u8 timer = 0;
u8 blink = 0;

void
blink_cursor(void) __critical __interrupt(3)
{
	if (++timer >= 75 && blink) {
		u8 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)
{
	u16 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;
	}

	DI;
	u8 tmp = blink;
	blink = 0;
	EI;

	tft_set_area(8 * col, 8 * row, 8, 8);
	draw(c);

	DI;
	blink = tmp;
	EI;

	buf[(head + row) % TTY_HEIGHT][col] = c;
	advance();
}

void
setcur(u16 ncol, u16 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;
	}
}