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