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.6  2008/08/27 06:35:15  thornen
00052  * Added support for MMnet03..04 and MMnet102..104
00053  *
00054  * Revision 1.5  2008/08/26 17:36:45  haraldkipp
00055  * Revoked changes 2008/08/26 by thornen.
00056  *
00057  * Revision 1.3  2008/08/11 06:59:15  haraldkipp
00058  * BSD types replaced by stdint types (feature request #1282721).
00059  *
00060  * Revision 1.2  2005/09/07 16:23:11  christianwelzel
00061  * Added support for MMnet02 display
00062  *
00063  * Revision 1.1  2005/07/26 18:02:27  haraldkipp
00064  * Moved from dev.
00065  *
00066  * Revision 1.8  2005/05/27 14:05:25  olereinhardt
00067  * Added support for new display sizes configurable by macros
00068  * LCD_4x20, LCD_4x16, LCD_2x40, LCD_2x20, LCD_2x16, LCD_2x8,
00069  * LCD_1x20, LCD_1x16, LCD_1x8, KS0073_CONTROLLER (4x20))
00070  *
00071  * Revision 1.7  2004/10/14 08:55:38  olereinhardt
00072  * Added default LCD type to avoid compiling bug if no type is defined
00073  *
00074  * Revision 1.6  2004/09/17 14:31:06  olereinhardt
00075  * Compile only if __GNUC__ defined
00076  *
00077  * Revision 1.5  2004/08/26 14:00:04  olereinhardt
00078  * Fixed cursor positioning for different devices
00079  *
00080  * Revision 1.4  2004/05/27 15:03:14  olereinhardt
00081  * Changed copyright notice
00082  *
00083  * Revision 1.3  2004/05/25 17:33:01  drsung
00084  * Added 'log' keyword for CVS.
00085  *
00086  */
00087 
00088 /* Not ported. */
00089 #ifdef __GNUC__
00090 
00091 #include <stdlib.h>
00092 #include <string.h>
00093 #include <stdio.h>
00094 
00095 #include <sys/nutconfig.h>
00096 #include <dev/hd44780_bus.h>
00097 #include <dev/term.h>
00098 #include <sys/timer.h>
00099 
00100 static uint16_t lcd_base = 0x0000;
00101 
00102 #ifndef LCD_4x20
00103 #ifndef LCD_4x16
00104 #ifndef LCD_2x40
00105 #ifndef LCD_2x20
00106 #ifndef LCD_2x16
00107 #ifndef LCD_2x8
00108 #ifndef LCD_1x20
00109 #ifndef LCD_1x16
00110 #ifndef LCD_1x8
00111 #ifndef KS0073_CONTROLLER
00112 #define LCD_2x16
00113 #endif
00114 #endif
00115 #endif
00116 #endif
00117 #endif
00118 #endif
00119 #endif
00120 #endif
00121 #endif
00122 #endif
00123 
00124 #define LCD_DELAY       asm volatile ("nop"); asm volatile ("nop")
00125 
00126 
00131 
00137 static inline void LcdBusyWait(void)
00138 {
00139 #if !defined(MMNET02)  && !defined(MMNET03)  && !defined(MMNET04) && \
00140     !defined(MMNET102) && !defined(MMNET103) && !defined(MMNET104)
00141     // wait until LCD busy bit goes to zero
00142     // do a read from control register
00143     while (*(volatile uint8_t *) (LCD_CTRL_ADDR + LCD_READ_OFFSET) & 1 << LCD_BUSY)
00144         LCD_DELAY;
00145     LCD_DELAY;
00146     LCD_DELAY;
00147     LCD_DELAY;
00148     LCD_DELAY;
00149     LCD_DELAY;
00150     LCD_DELAY;
00151     LCD_DELAY;
00152     LCD_DELAY;
00153     LCD_DELAY;
00154     LCD_DELAY;
00155     LCD_DELAY;
00156     LCD_DELAY;
00157 #else
00158     /* MMnet02 can not read the control register */
00159     NutDelay(5);
00160 #endif
00161 }
00162 
00169 static void LcdWriteData(uint8_t data)
00170 {
00171     LcdBusyWait();              // wait until LCD not busy
00172     *(volatile uint8_t *) (LCD_DATA_ADDR) = data;
00173 }
00174 
00178 static void LcdWriteCmd(uint8_t cmd, uint8_t delay)
00179 {
00180     LcdBusyWait();              // wait until LCD not busy
00181     *(volatile uint8_t *) (LCD_CTRL_ADDR) = cmd;
00182 }
00183 
00184 static void LcdSetCursor(uint8_t pos)
00185 {
00186     uint8_t x = 0;
00187     uint8_t y = 0;
00188 
00189 #ifdef KS0073_CONTROLLER
00190     uint8_t  offset[4] = {0x00, 0x20, 0x40, 0x60};
00191     y = pos / 20;
00192     x = pos % 20;
00193     if (y > 3) y = 3;
00194 #endif
00195 
00196 #if defined(LCD_2x40) 
00197     uint8_t  offset  [2] = {0x00, 0x40};
00198     y = pos / 40;
00199     x = pos % 40;
00200     if (y > 1) y = 1;
00201 #endif    
00202     
00203 #if defined(LCD_4x20) || defined(LCD_2x20)
00204     uint8_t  offset  [4] = {0x00, 0x40, 0x14, 0x54};
00205     y = pos / 20;
00206     x = pos % 20;
00207     if (y>3) y=3;
00208 #endif    
00209     
00210 #if defined(LCD_4x16) || defined(LCD_2x16)
00211     uint8_t  offset  [4] = {0x00, 0x40, 0x10, 0x50};
00212     y = pos / 16;
00213     x = pos % 16;
00214     if (y>3) y=3;
00215 #endif    
00216 
00217 #if defined(LCD_2x8)
00218     uint8_t  offset  [2] = {0x00, 0x40};
00219     y = pos / 8;
00220     x = pos % 8;
00221     if (y>1) y=1;
00222 #endif    
00223 
00224 #if defined(LCD_1x8) || defined(LCD_1x16) || defined(LCD_1x20)
00225     uint8_t  offset  [1] = { 0x00 };
00226     y = 0;
00227     x = pos;
00228 #endif 
00229     
00230     pos = x + offset[y];
00231     LcdWriteCmd(1 << LCD_DDRAM | pos, 0);
00232 }
00233 
00234 static void LcdCursorHome(void)
00235 {
00236     LcdWriteCmd(1 << LCD_HOME, 0);
00237 }
00238 
00239 static void LcdCursorLeft(void)
00240 {
00241     LcdWriteCmd(1 << LCD_MOVE, 0);
00242 }
00243 
00244 static void LcdCursorRight(void)
00245 {
00246     LcdWriteCmd(1 << LCD_MOVE | 1 << LCD_MOVE_RIGHT, 0);
00247 }
00248 
00249 static void LcdClear(void)
00250 {
00251     LcdWriteCmd(1 << LCD_CLR, 0);
00252 }
00253 
00254 static void LcdCursorMode(uint8_t on)
00255 {
00256     LcdWriteCmd(1 << LCD_ON_CTRL | on ? 1 << LCD_ON_CURSOR : 0x00, 0);
00257 }
00258 
00263 static void LcdInit(NUTDEVICE * dev)
00264 {
00265     lcd_base = dev->dev_base;
00266 #ifdef  KS0073_CONTROLLER
00267     // LCD function set with extended Register Set.
00268     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00269     NutDelay(50);
00270     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00271     NutDelay(50);
00272     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00273     NutDelay(50);
00274 
00275     LcdWriteCmd((1 << LCD_EXT) | ((((TERMDCB *) dev->dev_dcb)->dcb_nrows > 2) ? (1 << LCD_EXT_4LINES) : 0), 0);
00276     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT, 0);
00277 
00278 #else
00279 
00280     // LCD function set
00281 
00282     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00283     NutDelay(50);
00284     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00285     NutDelay(50);
00286     LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00287     NutDelay(50);
00288 #endif
00289     // clear LCD
00290     LcdWriteCmd(1 << LCD_CLR, 0);
00291     // set entry mode
00292     LcdWriteCmd(1 << LCD_ENTRY_MODE | 1 << LCD_ENTRY_INC, 0);
00293     // set display to on
00294     LcdWriteCmd(1 << LCD_ON_CTRL | 1 << LCD_ON_DISPLAY, 0);
00295     // move cursor to home
00296     LcdWriteCmd(1 << LCD_HOME, 0);
00297     // set data address to 0
00298     LcdWriteCmd(1 << LCD_DDRAM | 0x00, 0);
00299 }
00300 
00304 TERMDCB dcb_term = {
00305     LcdInit,                    
00306     LcdWriteData,               
00307     LcdWriteCmd,                
00308     LcdClear,                   
00309     LcdSetCursor,               
00310     LcdCursorHome,              
00311     LcdCursorLeft,              
00312     LcdCursorRight,             
00313     LcdCursorMode,              
00314     0,                          
00315     0,                          
00316 #ifdef KS0073_CONTROLLER
00317     4,                  
00318     20,                 
00319     20,                 
00320 #endif
00321 #ifdef LCD_4x20
00322     4,                  
00323     20,                 
00324     20,                 
00325 #endif
00326 #ifdef LCD_4x16
00327     4,                  
00328     16,                 
00329     16,                 
00330 #endif    
00331 #ifdef LCD_2x40    
00332     2,                  
00333     40,                 
00334     40,                 
00335 #endif
00336 #ifdef LCD_2x20    
00337     2,                  
00338     20,                 
00339     20,                 
00340 #endif
00341 #ifdef LCD_2x16    
00342     2,                  
00343     16,                 
00344     16,                 
00345 #endif
00346 #ifdef LCD_2x8    
00347     2,                  
00348     8,                 
00349     8,                 
00350 #endif
00351 #ifdef LCD_1x20    
00352     1,                  
00353     20,                 
00354     20,                 
00355 #endif
00356 #ifdef LCD_1x16    
00357     1,                  
00358     16,                 
00359     16,                 
00360 #endif
00361 #ifdef LCD_1x8    
00362     1,                  
00363     8,                 
00364     8,                 
00365 #endif
00366     0,                  
00367     0,                  
00368     0                   
00369 };
00370 
00374 NUTDEVICE devLcdBus = {
00375     0,                          
00376     {'l', 'c', 'd', 'b', 'u', 's', 0, 0, 0},    
00377     IFTYP_STREAM,               
00378     0,                          
00379     0,                          
00380     0,                          
00381     &dcb_term,                  
00382     TermInit,                   
00383     TermIOCtl,                  
00384     0,
00385     TermWrite,
00386     TermWrite_P,
00387     TermOpen,
00388     TermClose,
00389     0
00390 };
00391 
00392 
00393 #else
00394 void keep_icc_happy(void)
00395 {
00396 }
00397 
00398 #endif
00399 

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