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
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 #include <stdlib.h>
00099 #include <string.h>
00100
00101 #include <cfg/arch/avr.h>
00102 #include <dev/hd44780.h>
00103 #include <dev/term.h>
00104 #include <sys/timer.h>
00105
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
00118 #ifndef LCD_COLS
00119 #if defined(LCD_2x40)
00120 #define LCD_COLS 40
00121 #elif defined(LCD_4x20) || defined(LCD_2x20) || defined(LCD_1x20) || defined(KS0073_CONTROLLER)
00122 #define LCD_COLS 20
00123 #elif defined(LCD_2x8) || defined(LCD_1x8)
00124 #define LCD_COLS 8
00125 #else
00126 #define LCD_COLS 16
00127 #endif
00128 #endif
00129
00130
00131
00132
00133
00134
00135 #if ( LCD_DATA_AVRPORT == AVRPORTA )
00136 #define LCD_DATA_PORT PORTA
00137 #define LCD_DATA_PIN PINA
00138 #define LCD_DATA_DDR DDRA
00139
00140 #elif ( LCD_DATA_AVRPORT == AVRPORTB )
00141 #define LCD_DATA_PORT PORTB
00142 #define LCD_DATA_PIN PINB
00143 #define LCD_DATA_DDR DDRB
00144
00145 #elif ( LCD_DATA_AVRPORT == AVRPORTC )
00146 #define LCD_DATA_PORT PORTC
00147 #define LCD_DATA_PIN PINC
00148 #define LCD_DATA_DDR DDRC
00149
00150 #elif ( LCD_DATA_AVRPORT == AVRPORTE )
00151 #define LCD_DATA_PORT PORTE
00152 #define LCD_DATA_PIN PINE
00153 #define LCD_DATA_DDR DDRE
00154
00155 #elif ( LCD_DATA_AVRPORT == AVRPORTF )
00156 #define LCD_DATA_PORT PORTF
00157 #define LCD_DATA_PIN PINF
00158 #define LCD_DATA_DDR DDRF
00159
00160 #elif ( LCD_DATA_AVRPORT == AVRPORTG )
00161 #define LCD_DATA_PORT PORTG
00162 #define LCD_DATA_PIN PING
00163 #define LCD_DATA_DDR DDRG
00164
00165 #else
00166 #define LCD_DATA_PORT PORTD
00167 #define LCD_DATA_PIN PIND
00168 #define LCD_DATA_DDR DDRD
00169
00170 #endif
00171
00172 #ifndef LCD_DATA_BITS
00173 #define LCD_DATA_BITS 0xF0
00174 #endif
00175
00176
00177 #if ( LCD_ENABLE_AVRPORT == AVRPORTA )
00178 #define LCD_ENABLE_PORT PORTA
00179 #define LCD_ENABLE_DDR DDRA
00180
00181 #elif ( LCD_ENABLE_AVRPORT == AVRPORTB )
00182 #define LCD_ENABLE_PORT PORTB
00183 #define LCD_ENABLE_DDR DDRB
00184
00185 #elif ( LCD_ENABLE_AVRPORT == AVRPORTC )
00186 #define LCD_ENABLE_PORT PORTC
00187 #define LCD_ENABLE_DDR DDRC
00188
00189 #elif ( LCD_ENABLE_AVRPORT == AVRPORTD )
00190 #define LCD_ENABLE_PORT PORTD
00191 #define LCD_ENABLE_DDR DDRD
00192
00193 #elif ( LCD_ENABLE_AVRPORT == AVRPORTF )
00194 #define LCD_ENABLE_PORT PORTF
00195 #define LCD_ENABLE_DDR DDRF
00196
00197 #elif ( LCD_ENABLE_AVRPORT == AVRPORTG )
00198 #define LCD_ENABLE_PORT PORTG
00199 #define LCD_ENABLE_DDR DDRG
00200
00201 #else
00202 #define LCD_ENABLE_PORT PORTE
00203 #define LCD_ENABLE_DDR DDRE
00204
00205 #endif
00206
00207 #ifndef LCD_ENABLE_BIT
00208 #define LCD_ENABLE_BIT 3
00209 #endif
00210
00211
00212 #if ( LCD_REGSEL_AVRPORT == AVRPORTA )
00213 #define LCD_REGSEL_PORT PORTA
00214 #define LCD_REGSEL_DDR DDRA
00215
00216 #elif ( LCD_REGSEL_AVRPORT == AVRPORTB )
00217 #define LCD_REGSEL_PORT PORTB
00218 #define LCD_REGSEL_DDR DDRB
00219
00220 #elif ( LCD_REGSEL_AVRPORT == AVRPORTC )
00221 #define LCD_REGSEL_PORT PORTC
00222 #define LCD_REGSEL_DDR DDRC
00223
00224 #elif ( LCD_REGSEL_AVRPORT == AVRPORTD )
00225 #define LCD_REGSEL_PORT PORTD
00226 #define LCD_REGSEL_DDR DDRD
00227
00228 #elif ( LCD_REGSEL_AVRPORT == AVRPORTF )
00229 #define LCD_REGSEL_PORT PORTF
00230 #define LCD_REGSEL_DDR DDRF
00231
00232 #elif ( LCD_REGSEL_AVRPORT == AVRPORTG )
00233 #define LCD_REGSEL_PORT PORTG
00234 #define LCD_REGSEL_DDR DDRG
00235
00236 #else
00237 #define LCD_REGSEL_PORT PORTE
00238 #define LCD_REGSEL_DDR DDRE
00239
00240 #endif
00241
00242 #ifndef LCD_REGSEL_BIT
00243 #define LCD_REGSEL_BIT 2
00244 #endif
00245
00246
00247 #if ( LCD_RW_AVRPORT == AVRPORTA )
00248 #define LCD_RW_PORT PORTA
00249 #define LCD_RW_DDR DDRA
00250
00251 #elif ( LCD_RW_AVRPORT == AVRPORTB )
00252 #define LCD_RW_PORT PORTB
00253 #define LCD_RW_DDR DDRB
00254
00255 #elif ( LCD_RW_AVRPORT == AVRPORTC )
00256 #define LCD_RW_PORT PORTC
00257 #define LCD_RW_DDR DDRC
00258
00259 #elif ( LCD_RW_AVRPORT == AVRPORTD )
00260 #define LCD_RW_PORT PORTD
00261 #define LCD_RW_DDR DDRD
00262
00263 #elif ( LCD_RW_AVRPORT == AVRPORTE )
00264 #define LCD_RW_PORT PORTE
00265 #define LCD_RW_DDR DDRE
00266
00267 #elif ( LCD_RW_AVRPORT == AVRPORTF )
00268 #define LCD_RW_PORT PORTF
00269 #define LCD_RW_DDR DDRF
00270
00271 #elif ( LCD_RW_AVRPORT == AVRPORTG )
00272 #define LCD_RW_PORT PORTG
00273 #define LCD_RW_DDR DDRG
00274 #endif
00275
00276
00277
00282
00283 #ifndef LCD_SHORT_DELAY
00284 #define LCD_SHORT_DELAY 1
00285 #endif
00286
00287 #ifndef LCD_LONG_DELAY
00288 #define LCD_LONG_DELAY 2
00289 #endif
00290
00302 static uint8_t during_init = 1;
00303 #define LCD_DELAY _NOP(); _NOP(); _NOP(); _NOP()
00304
00305 #ifdef LCD_RW_BIT
00306
00307 static INLINE uint8_t LcdReadNibble(void)
00308 {
00309
00310 uint8_t ret;
00311 sbi(LCD_RW_PORT, LCD_RW_BIT);
00312 outp(inp(LCD_DATA_DDR) & ~LCD_DATA_BITS, LCD_DATA_DDR);
00313 sbi(LCD_ENABLE_PORT, LCD_ENABLE_BIT);
00314 LCD_DELAY;
00315 ret = inp(LCD_DATA_PIN) & LCD_DATA_BITS;
00316 cbi(LCD_ENABLE_PORT, LCD_ENABLE_BIT);
00317 LCD_DELAY;
00318 return ret;
00319 }
00320
00321 static INLINE uint8_t LcdReadByte(void)
00322 {
00323 uint8_t data;
00324 #if LCD_DATA_BITS == 0x0F
00325 data = LcdReadNibble();
00326 data = data | (LcdReadNibble() << 4);
00327 #elif LCD_DATA_BITS == 0xF0
00328 data = LcdReadNibble() >> 4;
00329 data |= LcdReadNibble();
00330 #elif LCD_DATA_BITS == 0xFF
00331 data = LcdReadNibble();
00332 #else
00333 #error "Bad definition of LCD_DATA_BITS"
00334 #endif
00335 return data;
00336 }
00337
00342 static uint8_t LcdReadCmd(void)
00343 {
00344 sbi(LCD_REGSEL_DDR, LCD_REGSEL_BIT);
00345 cbi(LCD_REGSEL_PORT, LCD_REGSEL_BIT);
00346 return LcdReadByte();
00347 }
00348
00349 #endif
00350
00351
00352 static void LcdDelay(uint8_t xt)
00353 {
00354 if (during_init) {
00355 NutDelay(xt);
00356 } else {
00357 #if defined(LCD_RW_BIT)
00358 while (LcdReadCmd() & (1 << LCD_BUSY))
00359 LCD_DELAY;
00360 LCD_DELAY;
00361 LCD_DELAY;
00362 LCD_DELAY;
00363 LCD_DELAY;
00364 LCD_DELAY;
00365 LCD_DELAY;
00366 LCD_DELAY;
00367 LCD_DELAY;
00368 LCD_DELAY;
00369 LCD_DELAY;
00370 LCD_DELAY;
00371 #elif defined(NUT_CPU_FREQ)
00372 NutSleep(xt);
00373 #else
00374 NutDelay(xt);
00375 #endif
00376 }
00377 }
00378
00379 static INLINE void LcdSendNibble(uint8_t nib)
00380 {
00381 #ifdef LCD_RW_BIT
00382 cbi(LCD_RW_PORT, LCD_RW_BIT);
00383 #endif
00384 outp(inp(LCD_DATA_DDR) | LCD_DATA_BITS, LCD_DATA_DDR);
00385 outp((inp(LCD_DATA_PORT) & ~LCD_DATA_BITS) | (nib & LCD_DATA_BITS), LCD_DATA_PORT);
00386 sbi(LCD_ENABLE_PORT, LCD_ENABLE_BIT);
00387 LCD_DELAY;
00388 cbi(LCD_ENABLE_PORT, LCD_ENABLE_BIT);
00389 LCD_DELAY;
00390 }
00391
00401 static INLINE void LcdSendByte(uint8_t ch, uint8_t xt)
00402 {
00403 #if LCD_DATA_BITS == 0x0F
00404 LcdSendNibble(ch >> 4);
00405 if(xt)
00406 LcdDelay(xt);
00407 LcdSendNibble(ch);
00408 #elif LCD_DATA_BITS == 0xF0
00409 LcdSendNibble(ch);
00410 if(xt)
00411 LcdDelay(xt);
00412 LcdSendNibble(ch << 4);
00413 #elif LCD_DATA_BITS == 0xFF
00414 LcdSendNibble(ch);
00415 #else
00416 #error "Bad definition of LCD_DATA_BITS"
00417 #endif
00418 if(xt)
00419 LcdDelay(xt);
00420 }
00421
00422 static void LcdWriteData(uint8_t ch)
00423 {
00424 sbi(LCD_REGSEL_DDR, LCD_REGSEL_BIT);
00425 sbi(LCD_REGSEL_PORT, LCD_REGSEL_BIT);
00426 LcdSendByte(ch, LCD_SHORT_DELAY);
00427 }
00428
00432 static void LcdWriteCmd(uint8_t cmd, uint8_t xt)
00433 {
00434 sbi(LCD_REGSEL_DDR, LCD_REGSEL_BIT);
00435 cbi(LCD_REGSEL_PORT, LCD_REGSEL_BIT);
00436 LcdSendByte(cmd, xt);
00437 }
00438
00439 static void LcdSetCursor(uint8_t pos)
00440 {
00441 uint8_t offset[] = {
00442 #ifdef KS0073_CONTROLLER
00443 0x00, 0x20, 0x40, 0x60
00444 #elif LCD_COLS == 20
00445 0x00, 0x40, 0x14, 0x54
00446 #else
00447 0x00, 0x40, 0x10, 0x50
00448 #endif
00449 };
00450
00451 pos = offset[(pos / LCD_COLS) % LCD_ROWS] + pos % LCD_COLS;
00452 LcdWriteCmd(1 << LCD_DDRAM | pos, LCD_SHORT_DELAY);
00453 }
00454
00455 static void LcdCursorHome(void)
00456 {
00457 LcdWriteCmd(1 << LCD_HOME, LCD_LONG_DELAY);
00458 }
00459
00460 static void LcdCursorLeft(void)
00461 {
00462 LcdWriteCmd(1 << LCD_MOVE, LCD_SHORT_DELAY);
00463 }
00464
00465 static void LcdCursorRight(void)
00466 {
00467 LcdWriteCmd(1 << LCD_MOVE | 1 << LCD_MOVE_RIGHT, LCD_SHORT_DELAY);
00468 }
00469
00470 static void LcdClear(void)
00471 {
00472 LcdWriteCmd(1 << LCD_CLR, LCD_LONG_DELAY);
00473 }
00474
00475 static void LcdCursorMode(uint8_t on)
00476 {
00477 LcdWriteCmd(1 << LCD_ON_CTRL | on ? 1 << LCD_ON_CURSOR : 0x00, LCD_LONG_DELAY);
00478 }
00479
00480 static int LcdInit(NUTDEVICE *dev)
00481 {
00482
00483
00484
00485 sbi(LCD_REGSEL_DDR, LCD_REGSEL_BIT);
00486 sbi(LCD_ENABLE_DDR, LCD_ENABLE_BIT);
00487 #ifdef LCD_RW_BIT
00488 sbi(LCD_RW_DDR, LCD_RW_BIT);
00489 cbi(LCD_RW_PORT, LCD_RW_BIT);
00490 #endif
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 cbi(LCD_REGSEL_PORT, LCD_REGSEL_BIT);
00502
00503 #if (LCD_DATA_BITS == 0xFF) // 8 Bit initialisation
00504 LcdWriteCmd((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT), 50);
00505 LcdWriteCmd((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT), 50);
00506 LcdWriteCmd((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT), 50);
00507 #ifdef KS0073_CONTROLLER
00508 LcdWriteCmd((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT) | (1 << LCD_FUNCTION_RE), LCD_SHORT_DELAY);
00509 LcdWriteCmd((1 << LCD_EXT) | ((((TERMDCB *) dev->dev_dcb)->dcb_nrows > 2) ? (1 << LCD_EXT_4LINES) : 0), LCD_SHORT_DELAY);
00510 LcdWriteCmd((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT), LCD_SHORT_DELAY);
00511 #endif
00512 LcdWriteCmd((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT) | ((((TERMDCB *) dev->dev_dcb)->dcb_nrows > 1) ?(1 << LCD_FUNCTION_2LINES):0), LCD_SHORT_DELAY);
00513
00514
00515 #else // 4 Bit initialisation
00516 LcdSendNibble((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT) | (((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT)) >> 4));
00517 LcdDelay(50);
00518 LcdSendNibble((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT) | (((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT)) >> 4));
00519 LcdDelay(50);
00520 LcdSendNibble((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT) | (((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_8BIT)) >> 4));
00521 LcdDelay(50);
00522 LcdSendNibble((1 << LCD_FUNCTION) | ((1 << LCD_FUNCTION) >> 4));
00523 LcdDelay(50);
00524 #ifdef KS0073_CONTROLLER
00525 LcdWriteCmd((1 << LCD_FUNCTION) | (1 << LCD_FUNCTION_RE), LCD_SHORT_DELAY);
00526 LcdWriteCmd((1 << LCD_EXT) | ((((TERMDCB *) dev->dev_dcb)->dcb_nrows > 2) ? (1 << LCD_EXT_4LINES) : 0), LCD_LONG_DELAY);
00527 LcdWriteCmd((1 << LCD_FUNCTION), LCD_LONG_DELAY);
00528 #endif
00529 LcdWriteCmd((1 << LCD_FUNCTION) | ((((TERMDCB *) dev->dev_dcb)->dcb_nrows > 1) ? (1 << LCD_FUNCTION_2LINES):0), LCD_SHORT_DELAY);
00530 #endif
00531
00532
00533 LcdWriteCmd(1 << LCD_CLR, LCD_LONG_DELAY);
00534
00535 LcdWriteCmd(1 << LCD_ENTRY_MODE | 1 << LCD_ENTRY_INC, LCD_LONG_DELAY);
00536
00537 LcdWriteCmd(1 << LCD_ON_CTRL | 1 << LCD_ON_DISPLAY, LCD_LONG_DELAY);
00538
00539 LcdWriteCmd(1 << LCD_HOME, LCD_LONG_DELAY);
00540
00541 LcdWriteCmd(1 << LCD_DDRAM | 0x00, LCD_LONG_DELAY);
00542 during_init = 0;
00543
00544 return 0;
00545 }
00546
00550 TERMDCB dcb_term = {
00551 LcdInit,
00552 LcdWriteData,
00553 LcdWriteCmd,
00554 LcdClear,
00555 LcdSetCursor,
00556 LcdCursorHome,
00557 LcdCursorLeft,
00558 LcdCursorRight,
00559 LcdCursorMode,
00560 0,
00561 0,
00562 LCD_ROWS,
00563 LCD_COLS,
00564 LCD_COLS,
00565 0,
00566 0,
00567 0
00568 };
00569
00573 NUTDEVICE devLcd = {
00574 0,
00575 {'l', 'c', 'd', 0, 0, 0, 0, 0, 0},
00576 IFTYP_STREAM,
00577 0,
00578 0,
00579 0,
00580 &dcb_term,
00581 TermInit,
00582 TermIOCtl,
00583 0,
00584 TermWrite,
00585 TermWrite_P,
00586 TermOpen,
00587 TermClose,
00588 0
00589 };
00590