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