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 #include <cfg/arch.h>
00083 #include <cfg/arch/gpio.h>
00084 #include <cfg/lcd.h>
00085
00086 #if 0
00087
00088 #define LCD_DATA_LSB 0
00089 #define LCD_ENABLE_BIT 4
00090 #define LCD_RW_BIT 5
00091 #define LCD_REGSEL_BIT 7
00092
00093 #endif
00094
00095 #include <stdlib.h>
00096 #include <string.h>
00097
00098 #include <sys/nutconfig.h>
00099 #include <dev/hd44780.h>
00100 #include <dev/term.h>
00101 #include <sys/timer.h>
00102
00103 #if !defined(LCD_4x20) && !defined(LCD_4x16)
00104 #if !defined(LCD_2x40) && !defined(LCD_2x20) && !defined(LCD_2x16) && !defined(LCD_2x8)
00105 #if !defined(LCD_1x20) && !defined(LCD_1x16) && !defined(LCD_1x8)
00106 #if !defined(KS0073_CONTROLLER)
00107 #define LCD_2x16
00108 #endif
00109 #endif
00110 #endif
00111 #endif
00112
00113 #ifndef LCD_ROWS
00114 #if defined(LCD_4x20) || defined(LCD_4x16) || defined(KS0073_CONTROLLER)
00115 #define LCD_ROWS 4
00116 #elif defined(LCD_1x20) || defined(LCD_1x16) || defined(LCD_1x8)
00117 #define LCD_ROWS 1
00118 #else
00119 #define LCD_ROWS 2
00120 #endif
00121 #endif
00122
00123 #ifndef LCD_COLS
00124 #if defined(LCD_2x40)
00125 #define LCD_COLS 40
00126 #elif defined(LCD_4x20) || defined(LCD_2x20) || defined(LCD_1x20) || defined(KS0073_CONTROLLER)
00127 #define LCD_COLS 20
00128 #elif defined(LCD_2x8) || defined(LCD_1x8)
00129 #define LCD_COLS 8
00130 #else
00131 #define LCD_COLS 16
00132 #endif
00133 #endif
00134
00138 #if !defined(LCD_PIO_ID)
00139 #if defined(MCU_AT91SAM7X256) || defined (MCU_AT91SAM7S256) || defined (MCU_AT91SAM7SE512)
00140 #define LCD_PIO_ID PIOA_ID
00141 #elif defined(MCU_AT91SAM9260) || defined(MCU_AT91SAM9XE512)
00142 #define LCD_PIO_ID PIOB_ID
00143 #else
00144 #define LCD_PIO_ID PIO_ID
00145 #endif
00146 #endif
00147
00151 #if !defined(LCD_PIO_PE_REG)
00152 #if LCD_PIO_ID == PIOA_ID
00153 #define LCD_PIO_PE_REG PIOA_PER
00154 #elif LCD_PIO_ID == PIOB_ID
00155 #define LCD_PIO_PE_REG PIOB_PER
00156 #elif LCD_PIO_ID == PIOC_ID
00157 #define LCD_PIO_PE_REG PIOC_PER
00158 #else
00159 #define LCD_PIO_PE_REG PIO_PER
00160 #endif
00161 #endif
00162
00166 #if !defined(LCD_PIO_OE_REG)
00167 #if LCD_PIO_ID == PIOA_ID
00168 #define LCD_PIO_OE_REG PIOA_OER
00169 #elif LCD_PIO_ID == PIOB_ID
00170 #define LCD_PIO_OE_REG PIOB_OER
00171 #elif LCD_PIO_ID == PIOC_ID
00172 #define LCD_PIO_OE_REG PIOC_OER
00173 #else
00174 #define LCD_PIO_OE_REG PIO_OER
00175 #endif
00176 #endif
00177
00181 #ifdef LCD_RW_BIT
00182 #if !defined(LCD_PIO_OD_REG)
00183 #if LCD_PIO_ID == PIOA_ID
00184 #define LCD_PIO_OD_REG PIOA_ODR
00185 #elif LCD_PIO_ID == PIOB_ID
00186 #define LCD_PIO_OD_REG PIOB_ODR
00187 #elif LCD_PIO_ID == PIOC_ID
00188 #define LCD_PIO_OD_REG PIOC_ODR
00189 #else
00190 #define LCD_PIO_OD_REG PIO_ODR
00191 #endif
00192 #endif
00193 #endif
00194
00198 #if !defined(LCD_PIO_SOD_REG)
00199 #if LCD_PIO_ID == PIOA_ID
00200 #define LCD_PIO_SOD_REG PIOA_SODR
00201 #elif LCD_PIO_ID == PIOB_ID
00202 #define LCD_PIO_SOD_REG PIOB_SODR
00203 #elif LCD_PIO_ID == PIOC_ID
00204 #define LCD_PIO_SOD_REG PIOC_SODR
00205 #else
00206 #define LCD_PIO_SOD_REG PIO_SODR
00207 #endif
00208 #endif
00209
00213 #if !defined(LCD_PIO_COD_REG)
00214 #if LCD_PIO_ID == PIOA_ID
00215 #define LCD_PIO_COD_REG PIOA_CODR
00216 #elif LCD_PIO_ID == PIOB_ID
00217 #define LCD_PIO_COD_REG PIOB_CODR
00218 #elif LCD_PIO_ID == PIOC_ID
00219 #define LCD_PIO_COD_REG PIOC_CODR
00220 #else
00221 #define LCD_PIO_COD_REG PIO_CODR
00222 #endif
00223 #endif
00224
00228 #ifdef LCD_RW_BIT
00229 #if !defined(LCD_PIO_PDS_REG)
00230 #if LCD_PIO_ID == PIOA_ID
00231 #define LCD_PIO_PDS_REG PIOA_PDSR
00232 #elif LCD_PIO_ID == PIOB_ID
00233 #define LCD_PIO_PDS_REG PIOB_PDSR
00234 #elif LCD_PIO_ID == PIOC_ID
00235 #define LCD_PIO_PDS_REG PIOC_PDSR
00236 #else
00237 #define LCD_PIO_PDS_REG PIO_PDSR
00238 #endif
00239 #endif
00240 #endif
00241
00242 #if !defined(LCD_DATA_LSB) && !defined(LCD_DATA_BIT0)
00243 #define LCD_DATA_LSB 0
00244 #endif
00245
00246 #ifdef LCD_DATA_LSB
00247 #define LCD_DATA (0xF << LCD_DATA_LSB)
00248 #else
00249 #define LCD_D0 _BV(LCD_DATA_BIT0)
00250 #define LCD_D1 _BV(LCD_DATA_BIT1)
00251 #define LCD_D2 _BV(LCD_DATA_BIT2)
00252 #define LCD_D3 _BV(LCD_DATA_BIT3)
00253 #define LCD_DATA (LCD_D0 | LCD_D1 | LCD_D2 | LCD_D3)
00254 #endif
00255
00256 #ifndef LCD_ENABLE_BIT
00257 #define LCD_ENABLE_BIT 4
00258 #endif
00259 #define LCD_EN _BV(LCD_ENABLE_BIT)
00260
00261 #ifndef LCD_REGSEL_BIT
00262 #define LCD_REGSEL_BIT 7
00263 #endif
00264 #define LCD_RS _BV(LCD_REGSEL_BIT)
00265
00266 #ifdef LCD_RW_BIT
00267 #define LCD_RW _BV(LCD_RW_BIT)
00268 #endif
00269
00270 #ifndef LCD_SHORT_DELAY
00271 #define LCD_SHORT_DELAY 10
00272 #endif
00273
00274 #ifndef LCD_LONG_DELAY
00275 #define LCD_LONG_DELAY 1000
00276 #endif
00277
00282
00293 static void LcdDelay(u_int cycles)
00294 {
00295 while (cycles--) {
00296 _NOP(); _NOP(); _NOP(); _NOP();
00297 _NOP(); _NOP(); _NOP(); _NOP();
00298 _NOP(); _NOP(); _NOP(); _NOP();
00299 _NOP(); _NOP(); _NOP(); _NOP();
00300 _NOP(); _NOP(); _NOP(); _NOP();
00301 _NOP(); _NOP(); _NOP(); _NOP();
00302 _NOP(); _NOP(); _NOP(); _NOP();
00303 _NOP(); _NOP(); _NOP(); _NOP();
00304 _NOP(); _NOP(); _NOP(); _NOP();
00305 _NOP(); _NOP(); _NOP(); _NOP();
00306 _NOP(); _NOP(); _NOP(); _NOP();
00307 _NOP(); _NOP(); _NOP(); _NOP();
00308 }
00309 }
00310
00311 static void INLINE LcdSetBits(u_int mask)
00312 {
00313 outr(LCD_PIO_SOD_REG, mask);
00314 outr(LCD_PIO_OE_REG, mask);
00315 }
00316
00317 static void INLINE LcdClrBits(u_int mask)
00318 {
00319 outr(LCD_PIO_COD_REG, mask);
00320 outr(LCD_PIO_OE_REG, mask);
00321 }
00322
00323 #ifdef LCD_RW_BIT
00324
00325 static u_int LcdReadNibble(void)
00326 {
00327 u_int rc;
00328
00329 LcdSetBits(LCD_EN);
00330 LcdDelay(LCD_SHORT_DELAY);
00331 rc = inr(LCD_PIO_PDS_REG) & LCD_DATA;
00332 LcdClrBits(LCD_EN);
00333 LcdDelay(LCD_SHORT_DELAY);
00334
00335 #ifdef LCD_DATA_LSB
00336 rc >>= LCD_DATA_LSB
00337 #else
00338 {
00339 u_int val = 0;
00340
00341 if (rc & LCD_D0) {
00342 val |= 0x01;
00343 }
00344 if (rc & LCD_D1) {
00345 val |= 0x02;
00346 }
00347 if (rc & LCD_D2) {
00348 val |= 0x04;
00349 }
00350 if (rc & LCD_D3) {
00351 val |= 0x08;
00352 }
00353 rc = val;
00354 }
00355 #endif
00356 return rc;
00357 }
00358
00362 static u_int LcdReadByte(void)
00363 {
00364 outr(LCD_PIO_OD_REG, LCD_DATA);
00365 LcdDelay(LCD_SHORT_DELAY);
00366 LcdSetBits(LCD_RW);
00367 LcdDelay(LCD_SHORT_DELAY);
00368 return (LcdReadNibble() << 4) | LcdReadNibble();
00369 }
00370
00374 static u_int LcdReadStatus(void)
00375 {
00376
00377 LcdClrBits(LCD_RS);
00378 return LcdReadByte();
00379 }
00380
00381 #endif
00382
00383 static void LcdWaitReady(u_int delay)
00384 {
00385 while (delay--) {
00386 #if defined(LCD_RW_BIT)
00387 if ((LcdReadStatus() & _BV(LCD_BUSY)) == 0) {
00388 break;
00389 }
00390 #endif
00391 _NOP();
00392 }
00393 }
00394
00400 static void LcdWriteNibble(u_int nib)
00401 {
00402 #ifdef LCD_DATA_LSB
00403 nib <<= LCD_DATA_LSB;
00404 #else
00405 {
00406 u_int val = 0;
00407 if (nib & 0x01) {
00408 val |= LCD_D0;
00409 }
00410 if (nib & 0x02) {
00411 val |= LCD_D1;
00412 }
00413 if (nib & 0x04) {
00414 val |= LCD_D2;
00415 }
00416 if (nib & 0x08) {
00417 val |= LCD_D3;
00418 }
00419 nib = val;
00420 }
00421 #endif
00422 LcdSetBits(nib & LCD_DATA);
00423 LcdClrBits(~nib & LCD_DATA);
00424
00425 LcdDelay(LCD_SHORT_DELAY);
00426 LcdSetBits(LCD_EN);
00427 LcdDelay(LCD_SHORT_DELAY);
00428 LcdClrBits(LCD_EN);
00429 LcdDelay(LCD_SHORT_DELAY);
00430 }
00431
00437 static void LcdWriteByte(u_int data)
00438 {
00439 #ifdef LCD_RW_BIT
00440 LcdClrBits(LCD_RW);
00441 #endif
00442 LcdWriteNibble(data >> 4);
00443 LcdWriteNibble(data);
00444 LcdWaitReady(LCD_LONG_DELAY);
00445 }
00446
00452 static void LcdWriteCmd(uint8_t cmd)
00453 {
00454
00455 LcdClrBits(LCD_RS);
00456 LcdWriteByte(cmd);
00457 }
00458
00459 static void LcdWriteInstruction(uint8_t cmd, uint8_t xt)
00460 {
00461 LcdWriteCmd(cmd);
00462 }
00463
00469 static void LcdWriteData(uint8_t data)
00470 {
00471
00472 LcdSetBits(LCD_RS);
00473 LcdWriteByte(data);
00474 }
00475
00476 static void LcdSetCursor(uint8_t pos)
00477 {
00478 uint8_t offset[] = {
00479 #ifdef KS0073_CONTROLLER
00480 0x00, 0x20, 0x40, 0x60
00481 #elif LCD_COLS == 20
00482 0x00, 0x40, 0x14, 0x54
00483 #else
00484 0x00, 0x40, 0x10, 0x50
00485 #endif
00486 };
00487
00488 pos = offset[(pos / LCD_COLS) % LCD_ROWS] + pos % LCD_COLS;
00489 LcdWriteCmd(1 << LCD_DDRAM | pos);
00490 }
00491
00492 static void LcdCursorHome(void)
00493 {
00494 LcdWriteCmd(1 << LCD_HOME);
00495 LcdDelay(10 * LCD_LONG_DELAY);
00496 }
00497
00498 static void LcdCursorLeft(void)
00499 {
00500 LcdWriteCmd(1 << LCD_MOVE);
00501 }
00502
00503 static void LcdCursorRight(void)
00504 {
00505 LcdWriteCmd(1 << LCD_MOVE | 1 << LCD_MOVE_RIGHT);
00506 }
00507
00508 static void LcdClear(void)
00509 {
00510 LcdWriteCmd(_BV(LCD_CLR));
00511 LcdDelay(10 * LCD_LONG_DELAY);
00512 }
00513
00514 static void LcdCursorMode(uint8_t on)
00515 {
00516 LcdWriteCmd(1 << LCD_ON_CTRL | on ? 1 << LCD_ON_CURSOR : 0x00);
00517 LcdDelay(10 * LCD_LONG_DELAY);
00518 }
00519
00520 static void LcdInit(NUTDEVICE * dev)
00521 {
00522 #if defined(PMC_PCER)
00523 outr(PMC_PCER, _BV(LCD_PIO_ID));
00524 #endif
00525
00526
00527 #ifdef LCD_RW_BIT
00528 outr(LCD_PIO_PE_REG, LCD_RW);
00529 LcdClrBits(LCD_RW);
00530 #endif
00531 outr(LCD_PIO_PE_REG, LCD_EN | LCD_RS | LCD_DATA);
00532 LcdClrBits(LCD_DATA | LCD_RS);
00533 LcdDelay(LCD_LONG_DELAY);
00534 LcdClrBits(LCD_EN);
00535 LcdDelay(LCD_LONG_DELAY);
00536
00537
00538 NutSleep(16);
00539
00540
00541
00542 LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
00543 NutSleep(5);
00544 LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
00545 NutSleep(2);
00546 LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
00547 NutSleep(2);
00548 LcdWriteNibble(_BV(LCD_FUNCTION) >> 4);
00549 NutSleep(2);
00550
00551
00552 LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_2LINES)) >> 4);
00553 LcdWriteNibble(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_2LINES));
00554 NutSleep(2);
00555
00556
00557 LcdWriteNibble(_BV(LCD_ON_CTRL) >> 4);
00558 LcdWriteNibble(_BV(LCD_ON_CTRL));
00559 NutSleep(2);
00560
00561
00562 LcdClear();
00563
00564
00565 LcdWriteCmd(_BV(LCD_ENTRY_MODE) | _BV(LCD_ENTRY_INC));
00566
00567 LcdWriteCmd(_BV(LCD_ON_CTRL) | _BV(LCD_ON_DISPLAY));
00568
00569 LcdCursorHome();
00570
00571 LcdWriteCmd(_BV(LCD_DDRAM));
00572 }
00573
00577 TERMDCB dcb_term = {
00578 LcdInit,
00579 LcdWriteData,
00580 LcdWriteInstruction,
00581 LcdClear,
00582 LcdSetCursor,
00583 LcdCursorHome,
00584 LcdCursorLeft,
00585 LcdCursorRight,
00586 LcdCursorMode,
00587 0,
00588 0,
00589 LCD_ROWS,
00590 LCD_COLS,
00591 LCD_COLS,
00592 0,
00593 0,
00594 0
00595 };
00596
00600 NUTDEVICE devLcd = {
00601 0,
00602 {'l', 'c', 'd', 0, 0, 0, 0, 0, 0},
00603 IFTYP_STREAM,
00604 0,
00605 0,
00606 0,
00607 &dcb_term,
00608 TermInit,
00609 TermIOCtl,
00610 0,
00611 TermWrite,
00612 TermOpen,
00613 TermClose,
00614 0
00615 };
00616