00001
00040 #include "lcd_hd44.h"
00041 #include "hw_lcd.h"
00042 #include <cfg/arch_config.h>
00043 #include <drv/timer.h>
00044
00045 #if defined(LCD_READ_H) && defined(LCD_READ_L) && defined(LCD_WRITE_H) && defined(LCD_WRITE_L)
00046 #define CONFIG_LCD_4BIT 1
00047 #elif defined(LCD_READ) && defined(LCD_WRITE)
00048 #define CONFIG_LCD_4BIT 0
00049 #else
00050 #error Incomplete or missing LCD_READ/LCD_WRITE macros
00051 #endif
00052
00054 #define LCDF_BUSY BV(7)
00055
00056 #if CONFIG_LCD_ADDRESS_FAST == 1
00057 #define lcd_address(x) lcd_address[x]
00058
00062 static const uint8_t lcd_address[] =
00063 {
00064
00065 0x80, 0x81, 0x82, 0x83,
00066 0x84, 0x85, 0x86, 0x87,
00067 0x88, 0x89, 0x8A, 0x8B,
00068 0x8C, 0x8D, 0x8E, 0x8F,
00069 #if LCD_COLS > 16
00070 0x90, 0x91, 0x92, 0x93,
00071 #endif
00072
00073
00074 0xC0, 0xC1, 0xC2, 0xC3,
00075 0xC4, 0xC5, 0xC6, 0xC7,
00076 0xC8, 0xC9, 0xCA, 0xCB,
00077 0xCC, 0xCD, 0xCE, 0xCF,
00078 #if LCD_COLS > 16
00079 0xD0, 0xD1, 0xD2, 0xD3,
00080 #endif
00081
00082 #if LCD_ROWS > 2
00083
00084 0x94, 0x95, 0x96, 0x97,
00085 0x98, 0x99, 0x9A, 0x9B,
00086 0x9C, 0x9D, 0x9E, 0x9F,
00087 0xA0, 0xA1, 0xA2, 0xA3,
00088 #if LCD_COLS > 16
00089 0xA4, 0xA5, 0xA6, 0xA7,
00090 #endif
00091
00092
00093 0xD4, 0xD5, 0xD6, 0xD7,
00094 0xD8, 0xD9, 0xDA, 0xDB,
00095 0xDC, 0xDD, 0xDE, 0xDF,
00096 0xE0, 0xE1, 0xE2, 0xE3,
00097 #if LCD_COLS > 16
00098 0xE4, 0xE5, 0xE6, 0xE7,
00099 #endif
00100
00101 #endif
00102 };
00103
00104 STATIC_ASSERT(countof(lcd_address) == LCD_ROWS * LCD_COLS);
00105 #else
00106
00107 static const uint8_t col_address[] =
00108 {
00109 0x80,
00110 0xC0,
00111 #if LCD_ROWS > 2
00112 0x94,
00113 0xD4
00114 #endif
00115 };
00116 STATIC_ASSERT(countof(col_address) == LCD_ROWS);
00120 static uint8_t lcd_address(uint8_t addr)
00121 {
00122 return col_address[addr / LCD_COLS] + addr % LCD_COLS;
00123 }
00124 #endif
00125
00130 static lcdpos_t lcd_current_addr;
00131
00132
00133 #if !defined(ARCH_EMUL) || !(ARCH & ARCH_EMUL)
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 INLINE void lcd_dataWrite(uint8_t data)
00144 {
00145 #if CONFIG_LCD_4BIT
00146
00147 LCD_WRITE_H(data);
00148 LCD_SET_E;
00149 LCD_DELAY_WRITE;
00150 LCD_CLR_E;
00151 LCD_DELAY_WRITE;
00152
00153
00154 LCD_WRITE_L(data);
00155 LCD_SET_E;
00156 LCD_DELAY_WRITE;
00157 LCD_CLR_E;
00158 LCD_DELAY_WRITE;
00159
00160 #else
00161
00162
00163 LCD_WRITE(data);
00164 LCD_SET_E;
00165 LCD_DELAY_WRITE;
00166 LCD_CLR_E;
00167 LCD_DELAY_WRITE;
00168
00169 #endif
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 INLINE uint8_t lcd_dataRead(void)
00182 {
00183 uint8_t data;
00184
00185 LCD_SET_RD;
00186 LCD_DB_IN;
00187 LCD_DELAY_READ;
00188
00189 #if CONFIG_LCD_4BIT
00190
00191
00192 LCD_SET_E;
00193 LCD_DELAY_READ;
00194 data = LCD_READ_H;
00195 LCD_CLR_E;
00196 LCD_DELAY_READ;
00197
00198
00199 LCD_SET_E;
00200 LCD_DELAY_READ;
00201 data |= LCD_READ_L;
00202 LCD_CLR_E;
00203 LCD_DELAY_READ;
00204
00205 #else
00206
00207
00208 LCD_SET_E;
00209 LCD_DELAY_READ;
00210 data = LCD_READ;
00211 LCD_CLR_E;
00212 LCD_DELAY_READ;
00213
00214 #endif
00215
00216 LCD_CLR_RD;
00217 LCD_DB_OUT;
00218
00219 return data;
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 INLINE void lcd_regWrite(uint8_t data)
00232 {
00233 LCD_CLR_RS;
00234 lcd_dataWrite(data);
00235 LCD_SET_RS;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 INLINE uint8_t lcd_regRead(void)
00248 {
00249 uint8_t data;
00250
00251 LCD_CLR_RS;
00252 data = lcd_dataRead();
00253 LCD_SET_RS;
00254 return data;
00255 }
00256
00257 #if CONFIG_LCD_4BIT
00258
00259 INLINE void lcd_mode4Bit(void)
00260 {
00261 LCD_CLR_RS;
00262
00263 LCD_WRITE_H(LCD_CMD_SETFUNC);
00264 LCD_SET_E;
00265 LCD_DELAY_WRITE;
00266 LCD_CLR_E;
00267 LCD_DELAY_WRITE;
00268
00269 LCD_SET_RS;
00270 }
00271
00272 #endif
00273
00274 #else
00275
00276 extern void Emul_LCDWriteReg(uint8_t d);
00277 extern uint8_t Emul_LCDReadReg(void);
00278 extern void Emul_LCDWriteData(uint8_t d);
00279 extern uint8_t Emul_LCDReadData(void);
00280
00281 #define lcd_regWrite(d) Emul_LCDWriteReg(d)
00282 #define lcd_regRead(d) Emul_LCDReadReg()
00283 #define lcd_dataWrite(d) Emul_LCDWriteData(d)
00284 #define lcd_dataRead(d) Emul_LCDReadData()
00285
00286 #endif
00287
00288
00292 void lcd_waitBusy(void)
00293 {
00294 for (;;)
00295 {
00296 uint8_t val = lcd_regRead();
00297 if (!(val & LCDF_BUSY))
00298 break;
00299 }
00300 }
00301
00302
00306 void lcd_moveTo(uint8_t addr)
00307 {
00308 if (addr != lcd_current_addr)
00309 {
00310 lcd_waitBusy();
00311 lcd_regWrite(lcd_address(addr));
00312 lcd_current_addr = addr;
00313 }
00314 }
00315
00316
00320 void lcd_setReg(uint8_t val)
00321 {
00322 lcd_waitBusy();
00323 lcd_regWrite(val);
00324 }
00325
00326 #include <cfg/debug.h>
00334 void lcd_putc(uint8_t addr, uint8_t c)
00335 {
00336 if (addr != lcd_current_addr)
00337 lcd_setReg(lcd_address(addr));
00338
00339 lcd_waitBusy();
00340 lcd_dataWrite(c);
00341 lcd_current_addr = addr + 1;
00342
00343
00344 if (lcd_current_addr == LCD_COLS * LCD_ROWS)
00345 lcd_current_addr = 0;
00346
00347
00348 if (!(lcd_current_addr % LCD_COLS))
00349 lcd_setReg(lcd_address(lcd_current_addr));
00350 }
00351
00352
00359 void lcd_remapChar(const char *glyph, char code)
00360 {
00361 int i;
00362
00363
00364 lcd_setReg((uint8_t)((1<<6) | (code << 3)));
00365
00366
00367 for (i = 0; i < 8; i++)
00368 {
00369 lcd_waitBusy();
00370 lcd_dataWrite(glyph[i]);
00371 }
00372
00373
00374 lcd_setReg(lcd_address(lcd_current_addr));
00375 }
00376
00377
00378 #if 0
00379 void lcd_remapfont(void)
00380 {
00381 static const char lcd_glyphs[8] =
00382 {
00383 0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x04, 0x00
00384 };
00385 int i;
00386
00387 for (i = 0; i < 15; i++)
00388 lcd_remapChar(i, bernie_char);
00389
00390
00391 lcd_setAddr(lcd_DefLayer, 0);
00392 for (i = 0; i < 80; i++)
00393 lcd_putCharUnlocked(i);
00394 }
00395 #endif
00396
00397 void lcd_hw_init(void)
00398 {
00399 lcd_bus_init();
00400
00401 timer_delay(50);
00402
00403 #if CONFIG_LCD_4BIT
00404 lcd_mode4Bit();
00405 timer_delay(2);
00406 #endif
00407
00408 lcd_regWrite(LCD_CMD_SETFUNC);
00409 timer_delay(2);
00410
00411 lcd_regWrite(LCD_CMD_DISPLAY_ON);
00412 timer_delay(2);
00413
00414 lcd_regWrite(LCD_CMD_CLEAR);
00415 timer_delay(2);
00416
00417 #if !CONFIG_LCD_4BIT
00418 lcd_regWrite(LCD_CMD_RESET_DDRAM);
00419 #endif
00420 lcd_regWrite(LCD_CMD_DISPLAYMODE);
00421 timer_delay(2);
00422 }
00423
00424 #if CONFIG_TEST
00425
00426 void lcd_hw_test(void)
00427 {
00428 lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 3);
00429 timer_delay(1);
00430 kprintf("3 -> %02X\n", lcd_regRead());
00431 timer_delay(1);
00432
00433 for (int i = 0; i < 10; i++)
00434 {
00435 lcd_dataWrite('c');
00436 timer_delay(1);
00437 kprintf("addr = %02X\n", lcd_regRead());
00438 timer_delay(1);
00439 }
00440
00441 lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x4a);
00442 timer_delay(1);
00443 kprintf("4A -> %02X\n", lcd_regRead());
00444 timer_delay(1);
00445
00446 lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x52);
00447 timer_delay(1);
00448 kprintf("52 -> %02X\n", lcd_regRead());
00449 timer_delay(1);
00450
00451 lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x1F);
00452 timer_delay(1);
00453 kprintf("1F -> %02X\n", lcd_regRead());
00454 timer_delay(1);
00455 }
00456
00457 #endif