lcd_hd44.c

Go to the documentation of this file.
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     /* row 0 */
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     /* row 1 */
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     /* row 2 */
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     /* row 3 */
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 /* LCD_ROWS > 2 */
00108 };
00109 
00110 STATIC_ASSERT(countof(lcd_address) == LCD_ROWS * LCD_COLS);
00111 #else  /* CONFIG_LCD_ADDRESS_FAST == 0 */
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 /* CONFIG_LCD_ADDRESS_FAST */
00131 
00136 static lcdpos_t lcd_current_addr;
00137 
00138 
00139 #if !defined(ARCH_EMUL) || !(ARCH & ARCH_EMUL)
00140 /*      __________________
00141  * RS
00142  *
00143  * R/W  __________________
00144  *            _______
00145  * ENA  _____/       \____
00146  *
00147  * DATA -<================
00148  */
00149 INLINE void lcd_dataWrite(uint8_t data)
00150 {
00151 #if CONFIG_LCD_4BIT
00152     /* Write high nibble */
00153     LCD_WRITE_H(data);
00154     LCD_SET_E;
00155     LCD_DELAY_WRITE;
00156     LCD_CLR_E;
00157     LCD_DELAY_WRITE;
00158 
00159     /* Write low nibble */
00160     LCD_WRITE_L(data);
00161     LCD_SET_E;
00162     LCD_DELAY_WRITE;
00163     LCD_CLR_E;
00164     LCD_DELAY_WRITE;
00165 
00166 #else /* !CONFIG_LCD_4BIT */
00167 
00168     /* Write data */
00169     LCD_WRITE(data);
00170     LCD_SET_E;
00171     LCD_DELAY_WRITE;
00172     LCD_CLR_E;
00173     LCD_DELAY_WRITE;
00174 
00175 #endif /* !CONFIG_LCD_4BIT */
00176 }
00177 
00178 /*      __________________
00179  * RS
00180  *         ____________
00181  * R/W  __/            \__
00182  *            _______
00183  * ENA  _____/       \____
00184  *        ______      ____
00185  * DATA X/      \====/
00186  */
00187 INLINE uint8_t lcd_dataRead(void)
00188 {
00189     uint8_t data;
00190 
00191     LCD_SET_RD;
00192     LCD_DB_IN;  /* Set bus as input! */
00193     LCD_DELAY_READ;
00194 
00195 #if CONFIG_LCD_4BIT
00196 
00197     /* Read high nibble */
00198     LCD_SET_E;
00199     LCD_DELAY_READ;
00200     data = LCD_READ_H;
00201     LCD_CLR_E;
00202     LCD_DELAY_READ;
00203 
00204     /* Read low nibble */
00205     LCD_SET_E;
00206     LCD_DELAY_READ;
00207     data |= LCD_READ_L;
00208     LCD_CLR_E;
00209     LCD_DELAY_READ;
00210 
00211 #else /* !CONFIG_LCD_4BIT */
00212 
00213     /* Read data */
00214     LCD_SET_E;
00215     LCD_DELAY_READ;
00216     data = LCD_READ;
00217     LCD_CLR_E;
00218     LCD_DELAY_READ;
00219 
00220 #endif /* !CONFIG_LCD_4BIT */
00221 
00222     LCD_CLR_RD;
00223     LCD_DB_OUT; /* Reset bus as output! */
00224 
00225     return data;
00226 }
00227 
00228 /*      ___             __
00229  * RS      \___________/
00230  *
00231  * READ __________________
00232  *            _______
00233  * ENA  _____/       \____
00234  *
00235  * DATA --<===============
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  * RS     \_____________/
00246  *          ___________
00247  * READ ___/           \__
00248  *            _______
00249  * ENA  _____/       \____
00250  *        ______      ____
00251  * DATA X/      \====/
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 /* CONFIG_LCD_4BIT */
00279 
00280 #else /* ARCH_EMUL */
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 /* ARCH_EMUL */
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     /* If we are at end of display wrap the address to 0 */
00350     if (lcd_current_addr == LCD_COLS * LCD_ROWS)
00351         lcd_current_addr = 0;
00352 
00353     /* If we are at the end of a row put the cursor at the beginning of the next */
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     /* Set CG RAM address */
00370     lcd_setReg((uint8_t)((1<<6) | (code << 3)));
00371 
00372     /* Write bitmap data */
00373     for (i = 0; i < 8; i++)
00374     {
00375         lcd_waitBusy();
00376         lcd_dataWrite(glyph[i]);
00377     }
00378 
00379     /* Move back to original address */
00380     lcd_setReg(lcd_address(lcd_current_addr));
00381 }
00382 
00383 
00384 #if 0 /* unused */
00385 void lcd_remapfont(void)
00386 {
00387     static const char lcd_glyphs[8] =
00388     {
00389         0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x04, 0x00 /* up arrow */
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 /* unused */
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 /* CONFIG_LCD_4BIT */
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); // 4 bit mode doesn't allow char reprogramming
00425 #endif
00426     lcd_regWrite(LCD_CMD_DISPLAYMODE);
00427     timer_delay(2);
00428 }
00429 
00430