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

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