hd44780_bus.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 by Ole Reinhardt <ole.reinhardt@kernelconcepts.de>,
00003  *                       Kernelconcepts http://www.kernelconcepts.de
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00022  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  *
00033  */
00034 
00049 /*
00050  * $Log: hd44780_bus.c,v $
00051  * Revision 1.2  2005/09/07 16:23:11  christianwelzel
00052  * Added support for MMnet02 display
00053  *
00054  * Revision 1.1  2005/07/26 18:02:27  haraldkipp
00055  * Moved from dev.
00056  *
00057  * Revision 1.8  2005/05/27 14:05:25  olereinhardt
00058  * Added support for new display sizes configurable by macros
00059  * LCD_4x20, LCD_4x16, LCD_2x40, LCD_2x20, LCD_2x16, LCD_2x8,
00060  * LCD_1x20, LCD_1x16, LCD_1x8, KS0073_CONTROLLER (4x20))
00061  *
00062  * Revision 1.7  2004/10/14 08:55:38  olereinhardt
00063  * Added default LCD type to avoid compiling bug if no type is defined
00064  *
00065  * Revision 1.6  2004/09/17 14:31:06  olereinhardt
00066  * Compile only if __GNUC__ defined
00067  *
00068  * Revision 1.5  2004/08/26 14:00:04  olereinhardt
00069  * Fixed cursor positioning for different devices
00070  *
00071  * Revision 1.4  2004/05/27 15:03:14  olereinhardt
00072  * Changed copyright notice
00073  *
00074  * Revision 1.3  2004/05/25 17:33:01  drsung
00075  * Added 'log' keyword for CVS.
00076  *
00077  */
00078 
00079 /* Not ported. */
00080 #ifdef __GNUC__
00081 
00082 #include <stdlib.h>
00083 #include <string.h>
00084 #include <stdio.h>
00085 
00086 #include <sys/nutconfig.h>
00087 #include <dev/hd44780_bus.h>
00088 #include <dev/term.h>
00089 #include <sys/timer.h>
00090 
00091 static u_short lcd_base = 0x0000;
00092 
00093 #ifndef LCD_4x20
00094 #ifndef LCD_4x16
00095 #ifndef LCD_2x40
00096 #ifndef LCD_2x20
00097 #ifndef LCD_2x16
00098 #ifndef LCD_2x8
00099 #ifndef LCD_1x20
00100 #ifndef LCD_1x16
00101 #ifndef LCD_1x8
00102 #ifndef KS0073_CONTROLLER
00103 #define LCD_2x16
00104 #endif
00105 #endif
00106 #endif
00107 #endif
00108 #endif
00109 #endif
00110 #endif
00111 #endif
00112 #endif
00113 #endif
00114 
00115 #define LCD_DELAY       asm volatile ("nop"); asm volatile ("nop")
00116 
00117 
00122 
00128 static inline void LcdBusyWait(void)
00129 {
00130 #ifndef MMNET02
00131     // wait until LCD busy bit goes to zero
00132     // do a read from control register
00133     while (*(volatile u_char *) (LCD_CTRL_ADDR + LCD_READ_OFFSET) & 1 << LCD_BUSY)
00134         LCD_DELAY;
00135     LCD_DELAY;
00136     LCD_DELAY;
00137     LCD_DELAY;
00138     LCD_DELAY;
00139     LCD_DELAY;
00140     LCD_DELAY;
00141     LCD_DELAY;
00142     LCD_DELAY;
00143     LCD_DELAY;
00144     LCD_DELAY;
00145     LCD_DELAY;
00146     LCD_DELAY;
00147 #else
00148     /* MMnet02 can not read the control register */
00149     NutDelay(5);
00150 #endif
00151 }
00152 
00159 static void LcdWriteData(u_char data)
00160 {
00161     LcdBusyWait();              // wait until LCD not busy
00162     *(volatile u_char *) (LCD_DATA_ADDR) = data;
00163 }
00164 
00168 static void LcdWriteCmd(u_char cmd, u_char delay)
00169 {
00170     LcdBusyWait();              // wait until LCD not busy
00171     *(volatile u_char *) (LCD_CTRL_ADDR) = cmd;
00172 }
00173 
00174 static void LcdSetCursor(u_char pos)
00175 {
00176     u_char x = 0;
00177     u_char y = 0;
00178 
00179 #ifdef KS0073_CONTROLLER
00180     u_char  offset[4] = {0x00, 0x20, 0x40, 0x60};
00181     y = pos / 20;
00182     x = pos % 20;
00183     if (y > 3) y = 3;
00184 #endif
00185 
00186 #if defined(LCD_2x40) 
00187     u_char  offset  [2] = {0x00, 0x40};
00188     y = pos / 40;
00189     x = pos % 40;
00190     if (y > 1) y = 1;
00191 #endif    
00192     
00193 #if defined(LCD_4x20) || defined(LCD_2x20)
00194     u_char  offset  [4] = {0x00, 0x40, 0x14, 0x54};
00195     y = pos / 20;
00196     x = pos % 20;
00197     if (y>3) y=3;
00198 #endif    
00199     
00200 #if defined(LCD_4x16) || defined(LCD_2x16)
00201     u_char  offset  [4] = {0x00, 0x40, 0x10, 0x50};
00202     y = pos / 16;
00203     x = pos % 16;
00204     if (y>3) y=3;
00205 #endif    
00206 
00207 #if defined(LCD_2x8)
00208     u_char  offset  [2] = {0x00, 0x40};
00209     y = pos / 8;
00210     x = pos % 8;
00211     if (y>1) y=1;
00212 #endif    
00213 
00214 #if defined(LCD_1x8) || defined(LCD_1x16) || defined(LCD_1x20)
00215     u_char  offset  [1] = { 0x00 };
00216     y = 0;
00217     x = pos;
00218 #endif 
00219     
00220     pos = x + offset[y];
00221     LcdWriteCmd(1 << LCD_DDRAM | pos, 0);
00222 }
00223 
00224 static void LcdCursorHome(void)
00225 {
00226     LcdWriteCmd(1 << LCD_HOME, 0);
00227 }
00228 
00229 static void LcdCursorLeft(void)
00230 {
00231     LcdWriteCmd(1 << LCD_MOVE, 0);
00232 }
00233 
00234 static void LcdCursorRight(void)
00235 {
00236     LcdWriteCmd(1 << LCD_MOVE | 1 << LCD_MOVE_RIGHT, 0);
00237 }
00238 
00239 static void LcdClear(void)
00240 {
00241     LcdWriteCmd(1 << LCD_CLR, 0);
00242 }
00243 
00244 static void LcdCursorMode(u_char on)
00245 {
00246     LcdWriteCmd(1 << LCD_ON_CTRL | on ? 1 << LCD_ON_CURSOR : 0x00, 0);
00247 }
00248 
00253 static void LcdInit(NUTDEVICE * dev)
00254 {
00255     lcd_base = dev->dev_base;
00256 #ifdef  KS0073_CONTROLLER
00257     // LCD function set with extended Register Set.
00258     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00259     NutDelay(50);
00260     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00261     NutDelay(50);
00262     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00263     NutDelay(50);
00264 
00265     LcdWriteCmd((1 << LCD_EXT) | ((((TERMDCB *) dev->dev_dcb)->dcb_nrows > 2) ? (1 << LCD_EXT_4LINES) : 0), 0);
00266     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT, 0);
00267 
00268 #else
00269 
00270     // LCD function set
00271 
00272     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00273     NutDelay(50);
00274     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00275     NutDelay(50);
00276     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00277     NutDelay(50);
00278 #endif
00279     // clear LCD
00280     LcdWriteCmd(1 << LCD_CLR, 0);
00281     // set entry mode
00282     LcdWriteCmd(1 << LCD_ENTRY_MODE | 1 << LCD_ENTRY_INC, 0);
00283     // set display to on
00284     LcdWriteCmd(1 << LCD_ON_CTRL | 1 << LCD_ON_DISPLAY, 0);
00285     // move cursor to home
00286     LcdWriteCmd(1 << LCD_HOME, 0);
00287     // set data address to 0
00288     LcdWriteCmd(1 << LCD_DDRAM | 0x00, 0);
00289 }
00290 
00294 TERMDCB dcb_term = {
00295     LcdInit,                    
00296     LcdWriteData,               
00297     LcdWriteCmd,                
00298     LcdClear,                   
00299     LcdSetCursor,               
00300     LcdCursorHome,              
00301     LcdCursorLeft,              
00302     LcdCursorRight,             
00303     LcdCursorMode,              
00304     0,                          
00305     0,                          
00306 #ifdef KS0073_CONTROLLER
00307     4,                  
00308     20,                 
00309     20,                 
00310 #endif
00311 #ifdef LCD_4x20
00312     4,                  
00313     20,                 
00314     20,                 
00315 #endif
00316 #ifdef LCD_4x16
00317     4,                  
00318     16,                 
00319     16,                 
00320 #endif    
00321 #ifdef LCD_2x40    
00322     2,                  
00323     40,                 
00324     40,                 
00325 #endif
00326 #ifdef LCD_2x20    
00327     2,                  
00328     20,                 
00329     20,                 
00330 #endif
00331 #ifdef LCD_2x16    
00332     2,                  
00333     16,                 
00334     16,                 
00335 #endif
00336 #ifdef LCD_2x8    
00337     2,                  
00338     8,                 
00339     8,                 
00340 #endif
00341 #ifdef LCD_1x20    
00342     1,                  
00343     20,                 
00344     20,                 
00345 #endif
00346 #ifdef LCD_1x16    
00347     1,                  
00348     16,                 
00349     16,                 
00350 #endif
00351 #ifdef LCD_1x8    
00352     1,                  
00353     8,                 
00354     8,                 
00355 #endif
00356     0,                  
00357     0,                  
00358     0                   
00359 };
00360 
00364 NUTDEVICE devLcdBus = {
00365     0,                          
00366     {'l', 'c', 'd', 'b', 'u', 's', 0, 0, 0},    
00367     IFTYP_STREAM,               
00368     0,                          
00369     0,                          
00370     0,                          
00371     &dcb_term,                  
00372     TermInit,                   
00373     TermIOCtl,                  
00374     0,
00375     TermWrite,
00376     TermWrite_P,
00377     TermOpen,
00378     TermClose,
00379     0
00380 };
00381 
00382 
00383 #else
00384 void keep_icc_happy(void)
00385 {
00386 }
00387 
00388 #endif
00389 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/