Nut/OS  4.10.3
API Reference
hd44780.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log$
00036  * Revision 1.7  2008/08/11 06:59:14  haraldkipp
00037  * BSD types replaced by stdint types (feature request #1282721).
00038  *
00039  * Revision 1.6  2008/04/29 16:58:21  thiagocorrea
00040  * Simplified HD44780 code for AVR based on the ARM driver.
00041  *
00042  * Revision 1.5  2006/10/08 16:40:17  haraldkipp
00043  * Many thanks to Thiago Correa for adding LCD port configuration.
00044  *
00045  * Revision 1.4  2006/09/11 09:13:18  olereinhardt
00046  * Another timing patch from Uwe Bonnes
00047  *
00048  * Revision 1.3  2006/09/07 15:53:27  olereinhardt
00049  * Added LCD timing patch from Uwe Bonnes
00050  *
00051  * Revision 1.2  2006/04/07 12:23:18  haraldkipp
00052  * Target specific delay defaults moved from global header to AVR specific
00053  * file.
00054  *
00055  * Revision 1.1  2005/07/26 18:02:27  haraldkipp
00056  * Moved from dev.
00057  *
00058  * Revision 1.6  2005/06/06 10:43:45  haraldkipp
00059  * Fixed to re-enable ICCAVR compilation.
00060  *
00061  * Revision 1.5  2005/05/27 14:02:11  olereinhardt
00062  * Added support for new display sizes configurable by macros
00063  * LCD_4x20, LCD_4x16, LCD_2x40, LCD_2x20, LCD_2x16, LCD_2x8,
00064  * LCD_1x20, LCD_1x16, LCD_1x8, KS0078_CONTROLLER (4x20))
00065  * Also added support for different delay types.
00066  * For not to wait busy too long, I added support for busy bit
00067  * read back and use NutSleep instead NutDelay if NUT_CPU_FREQ
00068  * is defined.
00069  *
00070  * Revision 1.4  2004/05/24 17:11:05  olereinhardt
00071  * dded terminal device driver for hd44780 compatible LCD displays directly
00072  * connected to the memory bus (memory mapped). See hd44780.c for more
00073  * information.Therefore some minor changed in include/dev/term.h and
00074  * dev/term.c are needet to
00075  * pass a base address to the lcd driver.
00076  *
00077  * Revision 1.3  2004/03/16 16:48:27  haraldkipp
00078  * Added Jan Dubiec's H8/300 port.
00079  *
00080  * Revision 1.2  2003/07/17 09:41:35  haraldkipp
00081  * Setting the data direction during init only may fail on some hardware.
00082  * We are now doing this immediately before using the port.
00083  *
00084  * Revision 1.1.1.1  2003/05/09 14:40:37  haraldkipp
00085  * Initial using 3.2.1
00086  *
00087  * Revision 1.3  2003/05/06 18:30:10  harald
00088  * ICCAVR port
00089  *
00090  * Revision 1.2  2003/04/21 16:22:46  harald
00091  * Moved back to outp/inp for portability
00092  *
00093  * Revision 1.1  2003/03/31 14:53:06  harald
00094  * Prepare release 3.1
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 /* Backward compatibility with old macros */
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                          /* LCD_ROWS */
00116 
00117 /* Backward compatibility with old macros */
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                          /* LCD_COLS */
00129 
00130 /*
00131  * Many thanks to Thiago Correa for adding LCD port configuration.
00132  */
00133 
00134 /* LCD_DATA_PORT and LCD_DATA_DDR switches */
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 /* LCD_ENABLE_PORT switches */
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 /* LCD_REGSEL_PORT switches */
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 /* LCD_RW_PORT switches */
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() /*Three Nops would fit too */
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);   // enable data input
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      * Set LCD register select and enable outputs.
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      * Send a dummy data byte.
00495      */
00496     //LcdWriteData(0);
00497 
00498     /*
00499      * Initialize for 4-bit operation.
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));    // Enter 4 Bit mode
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     // clear LCD
00533     LcdWriteCmd(1 << LCD_CLR, LCD_LONG_DELAY);
00534     // set entry mode
00535     LcdWriteCmd(1 << LCD_ENTRY_MODE | 1 << LCD_ENTRY_INC, LCD_LONG_DELAY);
00536     // set display to on
00537     LcdWriteCmd(1 << LCD_ON_CTRL | 1 << LCD_ON_DISPLAY, LCD_LONG_DELAY);
00538     // move cursor to home
00539     LcdWriteCmd(1 << LCD_HOME, LCD_LONG_DELAY);
00540     // set data address to 0
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