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