aboutsummaryrefslogtreecommitdiff
path: root/display_sim.c
diff options
context:
space:
mode:
Diffstat (limited to 'display_sim.c')
-rw-r--r--display_sim.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/display_sim.c b/display_sim.c
new file mode 100644
index 0000000..b17979f
--- /dev/null
+++ b/display_sim.c
@@ -0,0 +1,118 @@
+#include <stdio.h>
+#include <avr/io.h>
+
+#define BAUD 57600
+#include <util/setbaud.h>
+
+#include "display.h"
+
+/* WIDTH+1 for string terminator */
+static char display[LCD_HEIGHT][LCD_WIDTH+1];
+static int cursor_x;
+static int cursor_y;
+
+/* Slightly icky hack to use first avaialable USART */
+#ifdef UDR0
+# define UBRRx UBRR0
+# define UCSRxA UCSR0A
+# define UCSRxB UCSR0B
+# define UCSRxC UCSR0C
+# define UCSZx0 UCSZ00
+# define UCSZx1 UCSZ01
+# define RXENx RXEN0
+# define TXENx TXEN0
+# define UDREx UDRE0
+# define UDRx UDR0
+# define U2Xx U2X0
+#else
+# define UBRRx UBRR1
+# define UCSRxA UCSR1A
+# define UCSRxB UCSR1B
+# define UCSRxC UCSR1C
+# define UCSZx0 UCSZ10
+# define UCSZx1 UCSZ11
+# define RXENx RXEN1
+# define TXENx TXEN1
+# define UDREx UDRE1
+# define UDRx UDR1
+# define U2Xx U2X1
+#endif
+
+static void uart_init(void)
+{
+ UBRRx = UBRR_VALUE;
+#if USE_2X
+ UCSRxA |= (1 << U2Xx);
+#else
+ UCSRxA &= ~(1 << U2Xx);
+#endif
+ UCSRxB = _BV(RXENx) | _BV(TXENx);
+ UCSRxC = _BV(UCSZx1) | _BV(UCSZx0);
+}
+
+static int uart_putc(char c, FILE *unused)
+{
+ UDRx = c;
+ loop_until_bit_is_set(UCSRxA, UDREx);
+ return 1;
+}
+
+/* uart_out is plopped on stdout so that prints go to it by default */
+static FILE uart_out = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
+
+/* internal function to dump the display contents to stdout, since there
+ * is no background thread for doing this constantly */
+void display_display(void)
+{
+ int x = 0;
+ int y = 0;
+ printf("\033[6A"); // hack: raw ANSI escape sequence to move up 6
+ printf(",--------------------.\n");
+ for (y = 0; y < LCD_HEIGHT; y++) {
+ printf("|%s|\n", display[y]);
+ }
+ printf("`--------------------'\n");
+}
+
+void display_clear(void)
+{
+ int x = 0;
+ int y = 0;
+ for (y = 0; y < LCD_HEIGHT; y++) {
+ for (x = 0; x < LCD_WIDTH; x++) {
+ display[y][x] = ' ';
+ }
+ display[y][x] = '\0';
+ }
+
+ display_display();
+}
+
+void display_init(void)
+{
+ uart_init();
+ /* FIXME hack: stdout not guaranteed to be assignable */
+ stdout = &uart_out;
+ display_clear();
+ cursor_x = cursor_y = 0;
+}
+
+void display_write(const char *text)
+{
+ size_t text_x = 0;
+ char c = '\0';
+ while (cursor_x < LCD_WIDTH && *text) {
+ c = *(text++);
+ /* 0-7 are custom chars in CGRAM on real LCD */
+ if (c < 8)
+ c = '_';
+ display[cursor_y][cursor_x++] = c;
+ }
+ display_display();
+}
+
+void display_set_cursor(int x, int y)
+{
+ cursor_x = x;
+ cursor_y = y;
+}