00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 #include <cfg/arch.h>
00087 #include <cfg/arch/armpio.h>
00088 #include <cfg/lcd.h>
00089
00090 #include <stdlib.h>
00091 #include <string.h>
00092
00093
00094 #include <sys/nutconfig.h>
00095 #include <dev/hd44780.h>
00096 #include <dev/term.h>
00097 #include <sys/timer.h>
00098
00099 #ifdef LCD_IF_4BIT
00100 #ifdef LCD_DATA_LSB
00101 #define LCD_DATA (0xF << LCD_DATA_LSB)
00102 #else
00103 #define LCD_D0 _BV(LCD_DATA_BIT0)
00104 #define LCD_D1 _BV(LCD_DATA_BIT1)
00105 #define LCD_D2 _BV(LCD_DATA_BIT2)
00106 #define LCD_D3 _BV(LCD_DATA_BIT3)
00107 #define LCD_DATA (LCD_D0 | LCD_D1 | LCD_D2 | LCD_D3)
00108 #endif
00109 #else
00110 #define LCD_DATA (0xFF << LCD_DATA_LSB)
00111 #endif
00112
00117
00129 #ifdef LCD_PW_EH
00130 void LcdNanoDelay( uint_fast16_t n)
00131 {
00132 while (n--) {
00133 _NOP();
00134 }
00135 }
00136 #else
00137 #define LcdNanoDelay( a)
00138 #endif
00139
00140
00141 static void INLINE LcdSetBits(unsigned int mask)
00142 {
00143 outr(LCD_DATA_BASE+PIO_SODR_OFF, mask);
00144 outr(LCD_DATA_BASE+PIO_OER_OFF, mask);
00145 }
00146
00147 static void INLINE LcdClrBits(unsigned int mask)
00148 {
00149 outr(LCD_DATA_BASE+PIO_CODR_OFF, mask);
00150 outr(LCD_DATA_BASE+PIO_OER_OFF, mask);
00151 }
00152
00153 #ifdef LCD_RW_BIT
00154 static unsigned int LcdReadNibble(void)
00155 {
00156 unsigned int rc;
00157
00158 LCD_EN_SET();
00159 LcdDelay(LCD_SHORT_DELAY);
00160 rc = inr(LCD_DATA_PIO_ID+PIO_PDSR_OFF) & LCD_DATA;
00161 LCD_EN_CLR();
00162 LcdDelay(LCD_SHORT_DELAY);
00163
00164 #ifdef LCD_DATA_LSB
00165 rc >>= LCD_DATA_LSB
00166 #else
00167 {
00168 unsigned int val = 0;
00169
00170 if (rc & LCD_D0) {
00171 val |= 0x01;
00172 }
00173 if (rc & LCD_D1) {
00174 val |= 0x02;
00175 }
00176 if (rc & LCD_D2) {
00177 val |= 0x04;
00178 }
00179 if (rc & LCD_D3) {
00180 val |= 0x08;
00181 }
00182 rc = val;
00183 }
00184 #endif
00185 return rc;
00186 }
00187
00191 static unsigned int LcdReadByte(void)
00192 {
00193 outr(LCD_DATA_PIO_ID+PIO_ODR_OFF, LCD_DATA);
00194 LcdDelay(LCD_SHORT_DELAY);
00195 LCD_RW_SET();
00196 LcdDelay(LCD_SHORT_DELAY);
00197 return (LcdReadNibble() << 4) | LcdReadNibble();
00198 }
00199
00203 static unsigned int LcdReadStatus(void)
00204 {
00205
00206 LCD_RS_CLR();
00207 return LcdReadByte();
00208 }
00209
00210 #endif
00211
00212 #if 0
00213
00214
00215
00216
00217 static void LcdWaitReady(unsigned int delay)
00218 {
00219 while (delay--) {
00220 #if defined(HD44_RW_BIT)
00221 if ((LcdReadStatus() & _BV(LCD_BUSY)) == 0) {
00222 break;
00223 }
00224 #endif
00225 NutMicroDelay(1);
00226 }
00227 }
00228 #endif
00229
00235 static void LcdWriteNibble(unsigned int nib)
00236 {
00237 #ifdef LCD_DATA_LSB
00238 nib <<= LCD_DATA_LSB;
00239 #else
00240 {
00241 unsigned int val = 0;
00242 if (nib & 0x01) {
00243 val |= LCD_D0;
00244 }
00245 if (nib & 0x02) {
00246 val |= LCD_D1;
00247 }
00248 if (nib & 0x04) {
00249 val |= LCD_D2;
00250 }
00251 if (nib & 0x08) {
00252 val |= LCD_D3;
00253 }
00254 nib = val;
00255 }
00256 #endif
00257 LcdSetBits(nib & LCD_DATA);
00258 LcdClrBits(~nib & LCD_DATA);
00259
00260
00261
00262
00263
00264
00265 LCD_EN_SET();
00266 LcdNanoDelay(LCD_PW_EH);
00267 LCD_EN_CLR();
00268 }
00269
00275 static void LcdWriteByte(unsigned int data)
00276 {
00277
00278 #ifdef LCD_RW_BIT
00279 LCD_RW_CLR();
00280 #endif
00281
00282
00283 #ifdef LCD_IF_4BIT
00284 LcdWriteNibble(data >> 4);
00285 LcdNanoDelay(LCD_PW_EH);
00286 LcdWriteNibble(data);
00287 #else
00288
00289 data <<= LCD_DATA_LSB;
00290 LcdSetBits(data & LCD_DATA);
00291 LcdClrBits(~data & LCD_DATA);
00292 #endif
00293
00294
00295 #if defined(LCD_SLEEP_DLY)
00296 NutSleep(1);
00297 #else
00298
00299 NutMicroDelay(LCD_E2E_DLY);
00300 #endif
00301 }
00302
00308 static void LcdWriteCmd(uint8_t cmd)
00309 {
00310
00311 LCD_RS_CLR();
00312 LcdWriteByte(cmd);
00313 }
00314
00315 static void LcdWriteInstruction(uint8_t cmd, uint8_t xt)
00316 {
00317 LcdWriteCmd(cmd);
00318 }
00319
00325 static void LcdWriteData(uint8_t data)
00326 {
00327
00328 LCD_RS_SET();
00329 LcdWriteByte(data);
00330 }
00331
00332 static void LcdSetCursor(uint8_t pos)
00333 {
00334 uint8_t offset[] = {
00335 #ifdef LCD_KS0073
00336 0x00, 0x20, 0x40, 0x60
00337 #elif (LCD_COLS >= 20)
00338 0x00, 0x40, 0x14, 0x54
00339 #else
00340 0x00, 0x40, 0x10, 0x50
00341 #endif
00342 };
00343
00344 pos = offset[(pos / LCD_COLS) % LCD_ROWS] + pos % LCD_COLS;
00345 LcdWriteCmd(1 << LCD_DDRAM | pos);
00346 }
00347
00348 static void LcdCursorHome(void)
00349 {
00350 LcdWriteCmd(1 << LCD_HOME);
00351 NutSleep(2);
00352 }
00353
00354 static void LcdCursorLeft(void)
00355 {
00356 LcdWriteCmd(1 << LCD_MOVE);
00357 }
00358
00359 static void LcdCursorRight(void)
00360 {
00361 LcdWriteCmd(1 << LCD_MOVE | 1 << LCD_MOVE_RIGHT);
00362 }
00363
00364 static void LcdClear(void)
00365 {
00366 LcdWriteCmd(_BV(LCD_CLR));
00367 NutSleep(2);
00368 }
00369
00370 static void LcdCursorMode(uint8_t on)
00371 {
00372 LcdWriteCmd(1 << LCD_ON_CTRL | on ? 1 << LCD_ON_CURSOR : 0x00);
00373 }
00374
00375 static int LcdInit(NUTDEVICE * dev)
00376 {
00377 #if defined(PMC_PCER)
00378 outr(PMC_PCER, _BV(LCD_RS_PIO_ID) | _BV(LCD_EN_PIO_ID));
00379 #endif
00380
00381
00382 #ifdef LCD_RW_BIT
00383 outr(PMC_PCER, _BV(LCD_RW_PIO_ID));
00384 LCD_RW_CLR();
00385 #endif
00386
00387 #ifdef LCD_EN2_BIT
00388 outr(PMC_PCER, _BV(LCD_EN2_PIO_ID));
00389 LCD_EN2_CLR();
00390 #endif
00391
00392 #ifdef LCD_RST_BIT
00393 outr(PMC_PCER, _BV(LCD_RST_PIO_ID));
00394 LCD_RST_CLR();
00395 #endif
00396
00397 LCD_RS_CLR();
00398 LCD_RW_CLR();
00399 LcdClrBits(LCD_DATA);
00400 NutMicroDelay(30);
00401 LCD_EN_CLR();
00402 NutMicroDelay(30);
00403
00404
00405 NutSleep(16);
00406
00407
00408
00409
00410
00411 LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
00412 NutSleep(15);
00413 LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
00414 NutSleep(4);
00415 LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
00416 NutSleep(2);
00417
00418 #ifdef LCD_IF_4BIT
00419
00420 LcdWriteNibble(_BV(LCD_FUNCTION) >> 4);
00421 NutSleep(2);
00422
00423
00424
00425 #if (LCD_ROWS == 2) || (LCD_ROWS==4)
00426 LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_2LINES)) >> 4);
00427 LcdWriteNibble(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_2LINES));
00428 #else
00429 LcdWriteNibble(_BV(LCD_FUNCTION) >> 4);
00430 LcdWriteNibble(_BV(LCD_FUNCTION) );
00431 #endif
00432 #else
00433 LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT));
00434 #endif
00435 NutSleep(2);
00436
00437
00438 LcdWriteNibble(_BV(LCD_ON_CTRL) >> 4);
00439 LcdWriteNibble(_BV(LCD_ON_CTRL));
00440 NutSleep(2);
00441
00442
00443 LcdClear();
00444
00445
00446 LcdWriteCmd(_BV(LCD_ENTRY_MODE) | _BV(LCD_ENTRY_INC));
00447
00448 LcdWriteCmd(_BV(LCD_ON_CTRL) | _BV(LCD_ON_DISPLAY));
00449
00450 LcdCursorHome();
00451
00452 LcdWriteCmd(_BV(LCD_DDRAM));
00453
00454 return 0;
00455 }
00456
00460 TERMDCB dcb_term = {
00461 LcdInit,
00462 LcdWriteData,
00463 LcdWriteInstruction,
00464 LcdClear,
00465 LcdSetCursor,
00466 LcdCursorHome,
00467 LcdCursorLeft,
00468 LcdCursorRight,
00469 LcdCursorMode,
00470 0,
00471 0,
00472 LCD_ROWS,
00473 LCD_COLS,
00474 LCD_COLS,
00475 0,
00476 0,
00477 0
00478 };
00479
00483 NUTDEVICE devLcd = {
00484 0,
00485 {'c', 'h', 'a', 'r', 'l', 'c', 'd', 0, 0},
00486 IFTYP_STREAM,
00487 0,
00488 0,
00489 0,
00490 &dcb_term,
00491 TermInit,
00492 TermIOCtl,
00493 0,
00494 TermWrite,
00495 TermOpen,
00496 TermClose,
00497 0
00498 };
00499