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

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