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