// ChibiMo Firmware // Version 0.20110212 // // (c)k.k. q61.org 2011. // All rights reserved. // This firmware is provided AS-IS. No warranty. // pin assignment // 13 -> PB5 -> /RESET // 12 -> PB4 -> CS2 // 11 -> PB3 -> CS1 // 10 -> PB2 -> (NC) // 9 -> PB1 -> DB7 // 8 -> PB0 -> DB6 // 7 -> PD7 -> DB5 // 6 -> PD6 -> DB4 // 5 -> PD5 -> DB3 // 4 -> PD4 -> DB2 // 3 -> PD3 -> DB1 // 2 -> PD2 -> DB0 // 1 -> PD1 -> (USART TxD) // 0 -> PD0 <- (USART RxD) // A5 -> PC5 -> E // A4 -> PC4 -> RW // A3 -> PC3 -> RS // A2 -> PC2 -> (NC) // A1 -> PC1 -> (NC) // A0 -> PC0 -> (NC) #define LCD_RESET_VAL 0x20 #define LCD_CS2_VAL 0x10 #define LCD_CS1_VAL 0x08 #define LCD_E_VAL 0x20 #define LCD_RS_VAL 0x08 static uint8_t g_cs; void lcd_write(byte val, byte dt) { uint8_t valpc; valpc = (dt) ? LCD_RS_VAL : 0; PORTC = valpc; PORTB = LCD_RESET_VAL | g_cs | (val >> 6); PORTD = (val << 2); PORTC |= LCD_E_VAL; delayMicroseconds(1); PORTC = valpc; } void lcd_init() { g_cs = (LCD_CS1_VAL | LCD_CS2_VAL); delay(500); lcd_write(0x3e, 0); delay(500); lcd_write(0x3f, 0); delay(100); lcd_write(0xc0, 0); delay(10); lcd_write(0xb8, 0); delay(10); lcd_write(0x40, 0); delay(10); } void serial_init(long baud) { uint16_t baud_setting; UCSR0A = 0; baud_setting = (F_CPU / 8 / baud - 1) / 2; UBRR0H = baud_setting >> 8; UBRR0L = baud_setting; UCSR0B = 1 << RXEN0; } volatile uint8_t serial_data_ready() { return ((UCSR0A & (1 << RXC0)) >> RXC0); } volatile uint8_t serial_data_read() { return (UDR0); } void setup() { DDRB = 0x3f; DDRC = 0x3f; DDRD = 0xfc; lcd_init(); g_cs = 0; serial_init(500000); g_cs = (LCD_CS1_VAL | LCD_CS2_VAL); for (uint8_t i = 0; i < 64; i++) { lcd_write(i, 1); delayMicroseconds(5); } } void loop() { static uint8_t x = 0; static uint8_t y = 0; static uint8_t ph = 0; static uint8_t pxdt[10]; uint8_t dt; while (!serial_data_ready()) { ; } { dt = serial_data_read(); switch (ph++) { case 0: if (dt & 0x80) { ph = 0; // invalid address, reset state } else { y = dt >> 4; g_cs = LCD_CS1_VAL + (dt & 0x08); lcd_write(0xb8 | y, 0); x = (dt & 0x07) << 3; } break; case 1: delayMicroseconds(5); lcd_write(0x40 | x, 0); pxdt[ph] = dt; break; case 2: case 3: case 4: case 5: case 6: case 7: lcd_write(pxdt[ph - 1], 1); pxdt[ph] = dt; break; case 8: lcd_write(pxdt[ph - 1], 1); delayMicroseconds(5); lcd_write(dt, 1); ph = 0; break; default: ph = 0; break; } } }