st7036_at91.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 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: st7036_at91.c,v $
00036  * Revision 1.4  2008/06/06 10:28:21  haraldkipp
00037  * ST7036 LCD controller settings moved from source to configuration files.
00038  *
00039  * Revision 1.3  2008/02/15 16:59:02  haraldkipp
00040  * Spport for AT91SAM7SE512 added.
00041  *
00042  * Revision 1.2  2007/10/04 20:01:50  olereinhardt
00043  * Support for SAM7S256 added
00044  *
00045  * Revision 1.1  2007/02/15 16:09:07  haraldkipp
00046  * Tested with EA DOG-M LCDs.
00047  *
00048  */
00049 
00050 #include <cfg/arch.h>
00051 #include <cfg/arch/gpio.h>
00052 #include <cfg/lcd.h>
00053 
00054 #include <stdlib.h>
00055 #include <string.h>
00056 
00057 #include <sys/nutconfig.h>
00058 #include <dev/st7036.h>
00059 #include <dev/term.h>
00060 #include <sys/timer.h>
00061 
00062 #ifndef LCD_ROWS
00063 #define LCD_ROWS    2
00064 #endif
00065 
00066 #ifndef LCD_COLS
00067 #define LCD_COLS    16
00068 #endif
00069 
00070 #ifndef LCD_SHORT_DELAY
00071 #define LCD_SHORT_DELAY 100
00072 #endif
00073 
00074 #ifndef LCD_LONG_DELAY
00075 #define LCD_LONG_DELAY  1000
00076 #endif
00077 
00078 
00079 #ifdef LCD_CS_BIT
00080 #define LCD_CS      _BV(LCD_CS_BIT)
00081 #if LCD_CS_PIO_ID == PIOA_ID
00082 #define LCD_CS_SET() { outr(PIOA_PER, LCD_CS); outr(PIOA_SODR, LCD_CS); outr(PIOA_OER, LCD_CS); }
00083 #define LCD_CS_CLR() { outr(PIOA_PER, LCD_CS); outr(PIOA_CODR, LCD_CS); outr(PIOA_OER, LCD_CS); }
00084 #elif LCD_CS_PIO_ID == PIOB_ID
00085 #define LCD_CS_SET() { outr(PIOB_PER, LCD_CS); outr(PIOB_SODR, LCD_CS); outr(PIOB_OER, LCD_CS); }
00086 #define LCD_CS_CLR() { outr(PIOB_PER, LCD_CS); outr(PIOB_CODR, LCD_CS); outr(PIOB_OER, LCD_CS); }
00087 #elif LCD_CS_PIO_ID == PIOC_ID
00088 #define LCD_CS_SET() { outr(PIOC_PER, LCD_CS); outr(PIOC_SODR, LCD_CS); outr(PIOC_OER, LCD_CS); }
00089 #define LCD_CS_CLR() { outr(PIOC_PER, LCD_CS); outr(PIOC_CODR, LCD_CS); outr(PIOC_OER, LCD_CS); }
00090 #else
00091 #define LCD_CS_SET() { outr(PIO_PER, LCD_CS); outr(PIO_SODR, LCD_CS); outr(PIO_OER, LCD_CS); }
00092 #define LCD_CS_CLR() { outr(PIO_PER, LCD_CS); outr(PIO_CODR, LCD_CS); outr(PIO_OER, LCD_CS); }
00093 #endif /* LCD_CS_PIO_ID */
00094 #else /* LCD_CS_BIT */
00095 #define LCD_CS_SET()
00096 #define LCD_CS_CLR()
00097 #endif /* LCD_CS_BIT */
00098 
00099 #ifdef LCD_RS_BIT
00100 #define LCD_RS      _BV(LCD_RS_BIT)
00101 #if LCD_RS_PIO_ID == PIOA_ID
00102 #define LCD_RS_SET() { outr(PIOA_PER, LCD_RS); outr(PIOA_SODR, LCD_RS); outr(PIOA_OER, LCD_RS); }
00103 #define LCD_RS_CLR() { outr(PIOA_PER, LCD_RS); outr(PIOA_CODR, LCD_RS); outr(PIOA_OER, LCD_RS); }
00104 #elif LCD_RS_PIO_ID == PIOB_ID
00105 #define LCD_RS_SET() { outr(PIOB_PER, LCD_RS); outr(PIOB_SODR, LCD_RS); outr(PIOB_OER, LCD_RS); }
00106 #define LCD_RS_CLR() { outr(PIOB_PER, LCD_RS); outr(PIOB_CODR, LCD_RS); outr(PIOB_OER, LCD_RS); }
00107 #elif LCD_RS_PIO_ID == PIOC_ID
00108 #define LCD_RS_SET() { outr(PIOC_PER, LCD_RS); outr(PIOC_SODR, LCD_RS); outr(PIOC_OER, LCD_RS); }
00109 #define LCD_RS_CLR() { outr(PIOC_PER, LCD_RS); outr(PIOC_CODR, LCD_RS); outr(PIOC_OER, LCD_RS); }
00110 #else
00111 #define LCD_RS_SET() { outr(PIO_PER, LCD_RS); outr(PIO_SODR, LCD_RS); outr(PIO_OER, LCD_RS); }
00112 #define LCD_RS_CLR() { outr(PIO_PER, LCD_RS); outr(PIO_CODR, LCD_RS); outr(PIO_OER, LCD_RS); }
00113 #endif /* LCD_RS_PIO_ID */
00114 #else /* LCD_RS_BIT */
00115 #define LCD_RS_SET()
00116 #define LCD_RS_CLR()
00117 #endif /* LCD_RS_BIT */
00118 
00119 #ifdef LCD_CLK_BIT
00120 #define LCD_CLK     _BV(LCD_CLK_BIT)
00121 #if LCD_CLK_PIO_ID == PIOA_ID
00122 #define LCD_CLK_SET() { outr(PIOA_PER, LCD_CLK); outr(PIOA_SODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00123 #define LCD_CLK_CLR() { outr(PIOA_PER, LCD_CLK); outr(PIOA_CODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00124 #elif LCD_CLK_PIO_ID == PIOB_ID
00125 #define LCD_CLK_SET() { outr(PIOB_PER, LCD_CLK); outr(PIOB_SODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00126 #define LCD_CLK_CLR() { outr(PIOB_PER, LCD_CLK); outr(PIOB_CODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00127 #elif LCD_CLK_PIO_ID == PIOC_ID
00128 #define LCD_CLK_SET() { outr(PIOC_PER, LCD_CLK); outr(PIOC_SODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00129 #define LCD_CLK_CLR() { outr(PIOC_PER, LCD_CLK); outr(PIOC_CODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00130 #else
00131 #define LCD_CLK_SET() { outr(PIO_PER, LCD_CLK); outr(PIO_SODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00132 #define LCD_CLK_CLR() { outr(PIO_PER, LCD_CLK); outr(PIO_CODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00133 #endif /* LCD_CLK_PIO_ID */
00134 #else /* LCD_CLK_BIT */
00135 #define LCD_CLK_SET()
00136 #define LCD_CLK_CLR()
00137 #endif /* LCD_CLK_BIT */
00138 
00139 #ifdef LCD_MOSI_BIT
00140 #define LCD_MOSI    _BV(LCD_MOSI_BIT)
00141 #if LCD_MOSI_PIO_ID == PIOA_ID
00142 #define LCD_MOSI_SET() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_SODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00143 #define LCD_MOSI_CLR() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_CODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00144 #elif LCD_MOSI_PIO_ID == PIOB_ID
00145 #define LCD_MOSI_SET() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_SODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00146 #define LCD_MOSI_CLR() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_CODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00147 #elif LCD_MOSI_PIO_ID == PIOC_ID
00148 #define LCD_MOSI_SET() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_SODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00149 #define LCD_MOSI_CLR() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_CODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00150 #else
00151 #define LCD_MOSI_SET() { outr(PIO_PER, LCD_MOSI); outr(PIO_SODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00152 #define LCD_MOSI_CLR() { outr(PIO_PER, LCD_MOSI); outr(PIO_CODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00153 #endif /* LCD_MOSI_PIO_ID */
00154 #else /* LCD_MOSI_BIT */
00155 #define LCD_MOSI_SET()
00156 #define LCD_MOSI_CLR()
00157 #endif /* LCD_MOSI_BIT */
00158 
00163 
00174 static void LcdDelay(u_int cycles)
00175 {
00176     while (cycles--) {
00177         _NOP(); _NOP(); _NOP(); _NOP();
00178         _NOP(); _NOP(); _NOP(); _NOP();
00179         _NOP(); _NOP(); _NOP(); _NOP();
00180         _NOP(); _NOP(); _NOP(); _NOP();
00181         _NOP(); _NOP(); _NOP(); _NOP();
00182         _NOP(); _NOP(); _NOP(); _NOP();
00183         _NOP(); _NOP(); _NOP(); _NOP();
00184         _NOP(); _NOP(); _NOP(); _NOP();
00185         _NOP(); _NOP(); _NOP(); _NOP();
00186         _NOP(); _NOP(); _NOP(); _NOP();
00187         _NOP(); _NOP(); _NOP(); _NOP();
00188         _NOP(); _NOP(); _NOP(); _NOP();
00189     }
00190 }
00191 
00192 #if 0
00193 static void INLINE LcdSetBits(u_int mask)
00194 {
00195     outr(LCD_PIO_SOD_REG, mask);
00196     outr(LCD_PIO_OE_REG, mask);
00197 }
00198 
00199 static void INLINE LcdClrBits(u_int mask)
00200 {
00201     outr(LCD_PIO_COD_REG, mask);
00202     outr(LCD_PIO_OE_REG, mask);
00203 }
00204 #endif
00205 
00206 static void LcdWaitReady(u_int delay)
00207 {
00208     while (delay--) {
00209         _NOP();
00210     }
00211 }
00212 
00218 static void LcdWriteByte(u_int data)
00219 {
00220     u_char msk = 0x80;
00221 
00222     while (msk) {
00223         LCD_CLK_CLR();
00224         if (data & msk) {
00225             LCD_MOSI_SET();
00226         } else {
00227             LCD_MOSI_CLR();
00228         }
00229         LCD_CLK_SET();
00230         msk >>= 1;
00231         LcdDelay(1);
00232     }
00233     LcdWaitReady(LCD_LONG_DELAY);
00234 }
00235 
00241 static void LcdWriteCmd(u_char cmd)
00242 {
00243     /* RS low selects instruction register. */
00244     LCD_CS_CLR();
00245     LcdDelay(LCD_SHORT_DELAY);
00246     LCD_RS_CLR();
00247     LcdDelay(LCD_SHORT_DELAY);
00248     LcdWriteByte(cmd);
00249     LcdDelay(LCD_SHORT_DELAY);
00250     LCD_RS_SET();
00251     LcdDelay(LCD_SHORT_DELAY);
00252     LCD_CS_SET();
00253     LcdDelay(LCD_SHORT_DELAY);
00254 }
00255 
00256 static void LcdWriteInstruction(u_char cmd, u_char xt)
00257 {
00258     LcdWriteCmd(cmd);
00259 }
00260 
00266 static void LcdWriteData(u_char data)
00267 {
00268     /* RS high selects data register. */
00269     LCD_CS_CLR();
00270     LcdDelay(LCD_SHORT_DELAY);
00271     LCD_RS_SET();
00272     LcdDelay(LCD_SHORT_DELAY);
00273     LcdWriteByte(data);
00274     LcdDelay(LCD_SHORT_DELAY);
00275     LCD_CS_SET();
00276     LcdDelay(LCD_SHORT_DELAY);
00277 }
00278 
00279 static void LcdSetCursor(u_char pos)
00280 {
00281     u_char offset[] = {
00282         0x00, 0x40, 0x10, 0x50
00283     };
00284 
00285     pos = offset[(pos / LCD_COLS) % LCD_ROWS] + pos % LCD_COLS;
00286     LcdWriteCmd(0x80 | pos);
00287 }
00288 
00289 static void LcdCursorHome(void)
00290 {
00291     LcdWriteCmd(0x02);
00292     LcdDelay(10 * LCD_LONG_DELAY);
00293 }
00294 
00295 static void LcdCursorLeft(void)
00296 {
00297     LcdWriteCmd(0x10);
00298 }
00299 
00300 static void LcdCursorRight(void)
00301 {
00302     LcdWriteCmd(0x14);
00303 }
00304 
00305 static void LcdClear(void)
00306 {
00307     LcdWriteCmd(0x01);
00308     LcdDelay(10 * LCD_LONG_DELAY);
00309 }
00310 
00311 static void LcdCursorMode(u_char on)
00312 {
00313     if (on) {
00314         LcdWriteCmd(0x0D);
00315     } else {
00316         LcdWriteCmd(0x0C);
00317     }
00318     LcdDelay(10 * LCD_LONG_DELAY);
00319 }
00320 
00321 static void LcdInit(NUTDEVICE * dev)
00322 {
00323 #if defined(PMC_PCER)
00324     u_int pcer = 0;
00325 #if defined(LCD_CS_PIO_ID)
00326     pcer = _BV(LCD_CS_PIO_ID);
00327 #endif
00328 #if defined(LCD_RS_PIO_ID)
00329     pcer |= _BV(LCD_RS_PIO_ID);
00330 #endif
00331 #if defined(LCD_CLK_PIO_ID)
00332     pcer |= _BV(LCD_CLK_PIO_ID);
00333 #endif
00334 #if defined(LCD_MOSI_PIO_ID)
00335     pcer |= _BV(LCD_MOSI_PIO_ID);
00336 #endif
00337     outr(PMC_PCER, pcer);
00338 #endif
00339 
00340     /* Initialize GPIO lines. */
00341     LCD_CS_SET();
00342     LCD_RS_SET();
00343     LCD_CLK_SET();
00344     LCD_MOSI_SET();
00345 
00346     /* Initial delay. Actually only required after power on. */
00347     NutSleep(50);
00348 
00349     LCD_RS_CLR();
00350     LCD_CS_CLR();
00351 
00352     LcdWriteCmd(0x38);    /* Function set. */
00353     NutSleep(2);
00354     LcdWriteCmd(0x39);    /* Function set. */
00355     NutSleep(2);
00356     LcdWriteCmd(0x14);    /* Bias 1/5, 2 lines. */
00357     NutSleep(1);
00358     LcdWriteCmd(0x55);    /* Power/ICON/Contrast control. */
00359     NutSleep(1);
00360     LcdWriteCmd(0x6D);    /* Follower control. */
00361     NutSleep(1);
00362     LcdWriteCmd(0x78);    /* Booster on, Contrast set. */
00363     NutSleep(1);
00364     LcdWriteCmd(0x0F);    /* Display on. */
00365     NutSleep(1);
00366     LcdWriteCmd(0x01);    /* Clear display. */
00367     NutSleep(1);
00368     LcdWriteCmd(0x06);    /* Entry mode set. */
00369     NutSleep(1);
00370 
00371     LCD_CS_SET();
00372     LCD_RS_SET();
00373 
00374     /* Clear display. */
00375     LcdClear();
00376     /* Move cursor home. */
00377     LcdCursorHome();
00378 }
00379 
00383 static TERMDCB dcb_term = {
00384     LcdInit,                    
00385     LcdWriteData,               
00386     LcdWriteInstruction,        
00387     LcdClear,                   
00388     LcdSetCursor,               
00389     LcdCursorHome,              
00390     LcdCursorLeft,              
00391     LcdCursorRight,             
00392     LcdCursorMode,              
00393     0,                          
00394     0,                          
00395     LCD_ROWS,                   
00396     LCD_COLS,                   
00397     LCD_COLS,                   
00398     0,                          
00399     0,                          
00400     0                           
00401 };
00402 
00406 NUTDEVICE devSbiLcd = {
00407     0,                          
00408     {'s', 'b', 'i', 'l', 'c', 'd', 0, 0, 0},  
00409     IFTYP_STREAM,               
00410     0,                          
00411     0,                          
00412     0,                          
00413     &dcb_term,                  
00414     TermInit,                   
00415     TermIOCtl,                  
00416     0,
00417     TermWrite,
00418     TermOpen,
00419     TermClose,
00420     0
00421 };
00422 

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