// ChibiMo Firmware // Version 1.120107 // // (c)kuroi kouichi. q61.org 2011-2012. // This firmware is provided AS-IS. No warranty. // For personal and non-commercial use only. // For modifying and redistributing, follow GPL v2. #include // *** CHANGE THIS TO CHANGE BAUD RATE *** #define BAUD_RATE_1 500000 // pin assignment // Arduino -> UNO AVR -> MEGA AVR -> LCD // 13 -> PB5 -> PB7 -> /RESET // 12 -> PB4 -> PB6 -> CS2 // 11 -> PB3 -> PB5 -> CS1 // 10 -> PB2 -> PB4 -> (NC) // 9 -> PB1 -> PH6 -> DB7 // 8 -> PB0 -> PH5 -> DB6 // 7 -> PD7 -> PH4 -> DB5 // 6 -> PD6 -> PH3 -> DB4 // 5 -> PD5 -> PE3 -> DB3 // 4 -> PD4 -> PG5 -> DB2 // 3 -> PD3 -> PE5 -> DB1 // 2 -> PD2 -> PE4 -> DB0 // 1 -> PD1 -> PE1 -> (USART TxD) // 0 -> PD0 <- PE0 <- (USART RxD) // A5 -> PC5 -> PF5 -> E // A4 -> PC4 -> PF4 -> RW // A3 -> PC3 -> PF3 -> RS // A2 -> PC2 -> PF2 -> (NC) // A1 -> PC1 -> PF1 -> (NC) // A0 -> PC0 <- PF0 <- Btn #define BOARD_MEGA 0 #if BOARD_MEGA #define LCD_RESET_VAL 0x80 #define LCD_CS2_VAL 0x40 #define LCD_CS1_VAL 0x20 #define LCD_E_VAL 0x20 #define LCD_RS_VAL 0x08 #define lcd_write lcd_write_mega #else #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 #define PORTC_PULLUP_VAL 0x01 #define lcd_write lcd_write_uno #endif #define BAUD_RATE_2 38400 #define BAUD_RATE BAUD_RATE_1 #define LCD_WRITE_COMMAND 0 #define LCD_WRITE_DATA 1 #define uchar_t unsigned char static uchar_t g_cs; static long g_baud_rate; void lcd_write_uno(uchar_t val, uchar_t dt) { uint8_t valpc; valpc = PORTC_PULLUP_VAL | ((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; delayMicroseconds(1); } #if BOARD_MEGA void lcd_write_mega(uchar_t val, uchar_t dt) { uint8_t valpf; valpf = (dt) ? LCD_RS_VAL : 0; PORTF = valpf; PORTB = LCD_RESET_VAL | g_cs; PORTH = (val >> 2); PORTG = (val & 4) << 3; PORTE = ((val & 3) << 4) | (val & 8); PORTF |= LCD_E_VAL; delayMicroseconds(1); PORTF = valpf; delayMicroseconds(1); } #endif #define lcd_command_locate_y(YPOS) \ lcd_write(0xb8 | (YPOS), LCD_WRITE_COMMAND) #define lcd_command_locate_x(XPOS) \ lcd_write(0x40 | (XPOS), LCD_WRITE_COMMAND) #define lcd_write_data(DATA) \ lcd_write(DATA, LCD_WRITE_DATA) void lcd_init() { g_cs = (LCD_CS1_VAL | LCD_CS2_VAL); delay(500); lcd_write(0x3e, LCD_WRITE_COMMAND); delay(500); lcd_write(0x3f, LCD_WRITE_COMMAND); delay(100); lcd_write(0xc0, LCD_WRITE_COMMAND); delay(10); lcd_command_locate_y(0); delay(10); lcd_command_locate_x(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 uchar_t serial_data_ready() { return ((UCSR0A & (1 << RXC0)) >> RXC0); } volatile uchar_t serial_data_read() { return (UDR0); } void setup() { DDRB = 0x3f; DDRC = 0x3f; DDRD = 0xfc; lcd_init(); g_cs = 0; g_baud_rate = BAUD_RATE; serial_init(g_baud_rate); draw_splash(g_baud_rate); } void loop() { static uchar_t x = 0; static uchar_t y = 0; static uchar_t ph = 0; static uchar_t pxdt[20]; static uchar_t gotdata = 0; uchar_t dt; if (!gotdata) { while (!serial_data_ready()) { if ((PINC & 1) == 0) { g_baud_rate = (g_baud_rate == BAUD_RATE_1) ? BAUD_RATE_2 : BAUD_RATE_1; serial_init(g_baud_rate); draw_splash(g_baud_rate); delay(500); } } gotdata = 1; } else { while (!serial_data_ready()) { ; } } { dt = serial_data_read(); switch (ph++) { case 0: if (dt & 0xC0) { ph = 0; // invalid address, reset state } else { y = dt >> 3; x = dt & 0x07; g_cs = (x >= 4) ? LCD_CS2_VAL : LCD_CS1_VAL; lcd_command_locate_y(y); x <<= 4; } break; case 1: delayMicroseconds(5); lcd_command_locate_x(x); pxdt[ph] = dt; break; case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: lcd_write_data(pxdt[ph - 1]); pxdt[ph] = dt; break; case 16: lcd_write_data(pxdt[ph - 1]); delayMicroseconds(5); lcd_write_data(dt); ph = 0; break; default: ph = 0; break; } } } void draw_splash(long baud) { g_cs = (LCD_CS1_VAL | LCD_CS2_VAL); for (uchar_t y = 0; y < 8; y++) { lcd_command_locate_y(y); delay(5); lcd_command_locate_x(0); delay(5); for (uchar_t x = 0; x < 64; x++) { lcd_write_data(0); delayMicroseconds(5); } } g_cs = (LCD_CS1_VAL); lcd_command_locate_y(0); delay(5); lcd_command_locate_x(0); delay(5); lcd_write_logo(); lcd_command_locate_y(1); delay(5); lcd_command_locate_x(0); delay(5); lcd_write_char('C'); lcd_write_char('D'); lcd_write_char('Q'); lcd_write_num(6); lcd_write_num(1); lcd_write_char('@'); lcd_write_char('O'); lcd_write_char('R'); lcd_write_char('G'); lcd_command_locate_y(3); delay(5); lcd_command_locate_x(0); delay(5); if (baud >= 100000) lcd_write_num(baud / 100000 % 10); if (baud >= 10000) lcd_write_num(baud / 10000 % 10); lcd_write_num(baud / 1000 % 10); lcd_write_char('@'); lcd_write_num(baud / 100 % 10); lcd_write_num(0); lcd_write_num(0); lcd_write_char('K'); lcd_write_char('B'); lcd_write_char('P'); lcd_write_char('S'); g_cs = (LCD_CS2_VAL); lcd_command_locate_y(7); delay(5); lcd_command_locate_x(0); delay(5); lcd_write_char('F'); lcd_write_char('W'); lcd_write_char('@'); lcd_write_num(1); lcd_write_char('@'); lcd_write_num(1); lcd_write_num(2); lcd_write_num(0); lcd_write_num(1); lcd_write_num(0); lcd_write_num(7); } void lcd_write_logo() { const prog_char *logostr = "\0" "\076\177\101\101\101\0" "\177\177\004\004\170\0\0" "\175\175\0\0" "\177\177\104\104\070\0\0" "\175\175\0\0" "\177\177\006\034\006\177\0" "\070\174\104\104\070\0" "\0"; const prog_char *p = logostr; for (uchar_t i = 0; i < 42; i++) { lcd_write_data(*p++); delayMicroseconds(5); } } void lcd_write_num(uint8_t num) { const prog_char *numdata = "\076\121\111\105\076" "\102\102\177\100\100" "\102\141\121\111\106" "\042\101\111\111\066" "\030\024\022\177\020" "\047\105\105\105\071" "\074\112\111\111\060" "\003\001\141\031\007" "\066\111\111\111\066" "\006\111\111\051\036"; const prog_char *p = numdata + (num * 5); for (uchar_t i = 0; i < 5; i++) { lcd_write_data(*p++); delayMicroseconds(5); } lcd_write_data(0); delayMicroseconds(5); } void lcd_write_char(uint8_t num) { const prog_char *chardata = "\140\140\0\0\0" "\200\340\140\0\0" "\177\104\104\070\0" // b "\034\042\135\125\125" "\042\034\0\0\0" "\0\0\0\0\0" "\004\176\005\0\0" "\030\244\244\174\0" //g "\0\0\0\0\0" "\0\0\0\0\0" "\0\0\0\0\0" "\177\020\050\104\0" "\0\0\0\0\0" //l "\0\0\0\0\0" "\0\0\0\0\0" "\070\104\104\070\0" "\374\044\044\030\0" "\030\044\044\374\0" //q "\174\010\004\004\0" "\110\124\124\040\0" //s "\0\0\0\0\0" "\0\0\0\0\0" "\0\0\0\0\0" "\074\100\074\100\074" // w ; const prog_char *p = chardata + ((num - '@') * 5); uchar_t c; for (uchar_t i = 0; i < 5; i++) { c = *p++; if (c == 0) break; lcd_write_data(c); delayMicroseconds(5); } if (num != 'C') lcd_write_data(0); delayMicroseconds(5); }