aboutsummaryrefslogtreecommitdiff
path: root/display_sim.c
diff options
context:
space:
mode:
authorDavid Phillips <david@yeah.nah.nz>2020-12-13 16:35:58 +1300
committerDavid Phillips <david@yeah.nah.nz>2020-12-13 20:42:33 +1300
commit7e26f31e221665ee059b02fc6beda025d39d6e75 (patch)
tree1a5f66e12680778b001f3cb1d2c49b0f2ce0f04c /display_sim.c
downloadaltimeter-7e26f31e221665ee059b02fc6beda025d39d6e75.tar.xz
Initial prototype
This patch adds a skeleton of AVR code for a "simulator" target (atmega2560) and for the real intended hardware target (atmega32u4). The simulator target is one that is supported by the QEMU AVR emulator, while the 32u4 is currently not.
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;
+}