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