aboutsummaryrefslogtreecommitdiff
path: root/src/tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tty.c')
-rw-r--r--src/tty.c164
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;
+ }
+}