summaryrefslogtreecommitdiff
path: root/lcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcd.c')
-rw-r--r--lcd.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/lcd.c b/lcd.c
new file mode 100644
index 0000000..927b90f
--- /dev/null
+++ b/lcd.c
@@ -0,0 +1,69 @@
+#include "lcd.h"
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+#define B_SRCLK PB0
+#define B_LCDE PB3
+#define B_SRD_LCDRS PB4
+
+static void lcd_pin(bool value)
+{
+ /* cheat, put the clock in front.
+ * result:
+ * clk, d0 | clk, d1 | clk... d7 | clk, rs.
+ * ^- first clk ignored ^- last clk from setting R/S
+ */
+ PORTB |= (1 << B_SRCLK);
+ PORTB &= ~(1 << B_SRCLK);
+
+ if (value)
+ PORTB |= (1 << B_SRD_LCDRS);
+ else
+ PORTB &= ~(1 << B_SRD_LCDRS);
+}
+
+void lcd_command(uint8_t cmd, bool isdata)
+{
+ uint8_t i;
+
+ for (i = 1; i; i <<= 2)
+ lcd_pin(cmd & i);
+ for (i = 1 << 7; i; i >>= 2)
+ lcd_pin(cmd & i);
+
+ lcd_pin(isdata);
+ __asm__ ("nop\n");
+ PORTB |= (1 << B_LCDE);
+ __asm__ ("nop\n");
+ PORTB &= ~(1 << B_LCDE);
+ __asm__ ("nop\n");
+ if (!isdata)
+ _delay_us(50);
+}
+
+void lcd_puts(const char * PROGMEM ptr, uint8_t cnt)
+{
+ while (cnt--) {
+ uint8_t ch = __LPM(ptr++);
+ lcd_put(ch);
+ }
+}
+
+const char PROGMEM boot[] = "boot";
+
+void lcd_init(void)
+{
+ PORTB &= ~((1 << B_SRCLK) | (1 << B_LCDE) | (1 << B_SRD_LCDRS));
+ DDRB |= (1 << B_SRCLK) | (1 << B_LCDE) | (1 << B_SRD_LCDRS);
+ _delay_ms(15);
+
+ lcd_command(0x38, 0);
+ lcd_command(0x0c, 0);
+ lcd_command(0x06, 0);
+ lcd_command(0x02, 0);
+ _delay_ms(2);
+
+ lcd_line1();
+ lcd_puts(boot, sizeof(boot) - 1);
+}