diff options
Diffstat (limited to 'lcd.c')
-rw-r--r-- | lcd.c | 69 |
1 files changed, 69 insertions, 0 deletions
@@ -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); +} |