summaryrefslogtreecommitdiff
path: root/src/drivers/ao_console.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2017-02-20 12:21:39 -0800
committerKeith Packard <keithp@keithp.com>2017-02-20 12:34:02 -0800
commitc296acd643698d0128e2f58f91a9cfeea63f580a (patch)
treeb8d5a5bd463c0c667f6cf8327f7a92a5175be04a /src/drivers/ao_console.c
parentc1d52178ce63ebdc44c83d1bca5027942e2d778c (diff)
altos: Add console driver using VGA and PS/2
Provides an interactive text console. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/drivers/ao_console.c')
-rw-r--r--src/drivers/ao_console.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/drivers/ao_console.c b/src/drivers/ao_console.c
new file mode 100644
index 00000000..cbde38c9
--- /dev/null
+++ b/src/drivers/ao_console.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_console.h"
+#include "ao_ps2.h"
+#include "ao_vga.h"
+
+static uint8_t console_row, console_col;
+
+#define ao_console_bitmap ao_vga_bitmap
+
+static uint8_t console_rows, console_cols;
+
+static void
+ao_console_scroll(void)
+{
+ ao_copy(&ao_console_bitmap,
+ 0, 0,
+ ao_console_bitmap.width,
+ ao_console_bitmap.height - ao_font.height,
+ &ao_console_bitmap,
+ 0, ao_font.height,
+ AO_COPY);
+ ao_rect(&ao_console_bitmap,
+ 0,
+ (console_rows - 1) * ao_font.height,
+ ao_console_bitmap.width,
+ ao_font.height,
+ 1,
+ AO_COPY);
+}
+
+static void
+ao_console_cursor(void)
+{
+ ao_rect(&ao_console_bitmap,
+ console_col * ao_font.width,
+ console_row * ao_font.height,
+ ao_font.width,
+ ao_font.height,
+ 1,
+ AO_XOR);
+}
+
+static void
+ao_console_clear(void)
+{
+ ao_rect(&ao_console_bitmap,
+ 0, 0,
+ ao_console_bitmap.width,
+ ao_console_bitmap.height,
+ 1,
+ AO_COPY);
+}
+
+static void
+ao_console_space(void)
+{
+ ao_rect(&ao_console_bitmap,
+ console_col * ao_font.width,
+ console_row * ao_font.height,
+ ao_font.width,
+ ao_font.height,
+ 1,
+ AO_COPY);
+}
+
+static void
+ao_console_newline(void)
+{
+ if (++console_row == console_rows) {
+ ao_console_scroll();
+ console_row--;
+ }
+}
+
+void
+ao_console_putchar(char c)
+{
+ if (' ' <= c && c < 0x7f) {
+ char text[2];
+ ao_console_space();
+ text[0] = c;
+ text[1] = '\0';
+ ao_text(&ao_console_bitmap,
+ console_col * ao_font.width,
+ console_row * ao_font.height + ao_font.ascent,
+ text,
+ 0,
+ AO_COPY);
+ if (++console_col == console_cols) {
+ console_col = 0;
+ ao_console_newline();
+ }
+ } else {
+ ao_console_cursor();
+ switch (c) {
+ case '\r':
+ console_col = 0;
+ break;
+ case '\t':
+ console_col += 8 - (console_col & 7);
+ if (console_col >= console_cols) {
+ console_col = 0;
+ ao_console_newline();
+ }
+ break;
+ case '\n':
+ ao_console_newline();
+ break;
+ case '\f':
+ console_col = console_row = 0;
+ ao_console_clear();
+ break;
+ case '\177':
+ case '\010':
+ if (console_col)
+ console_col--;
+ break;
+ }
+ }
+ ao_console_cursor();
+}
+
+void
+ao_console_init(void)
+{
+ console_cols = ao_console_bitmap.width / ao_font.width;
+ console_rows = ao_console_bitmap.height / ao_font.height;
+#if CONSOLE_STDIN
+ ao_ps2_stdin = 1;
+ ao_add_stdio(_ao_ps2_pollchar,
+ ao_console_putchar,
+ NULL);
+#endif
+ ao_console_clear();
+ ao_console_cursor();
+ ao_vga_enable(1);
+}