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

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