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