#include #include #define BAUD 57600 #include #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) { (void)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 */ static void full_display(void) { 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"); } /**/ static 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'; } full_display(); } static void display_init(void) { uart_init(); /* FIXME hack: stdout not guaranteed to be assignable */ stdout = &uart_out; printf("\n\n\n\n\n\n"); display_clear(); cursor_x = cursor_y = 0; } static void display_write(const char *text) { char c = '\0'; while (cursor_x < LCD_WIDTH && *text) { c = *(text++); /* 0-7 are custom chars in CGRAM on real LCD */ if ((unsigned int)c < 8) c = '_'; display[cursor_y][cursor_x++] = c; } full_display(); } static void display_set_cursor(int x, int y) { cursor_x = x; cursor_y = y; } void get_system_display(struct display *display) { display->init = display_init; display->clear = display_clear; display->write = display_write; display->set_cursor = display_set_cursor; }