BeRTOS
|
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