Nut/OS  4.10.3
API Reference
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 #ifdef LCD_CLK_BIT
00070 #define LCD_CLK     _BV(LCD_CLK_BIT)
00071 #if LCD_CLK_PIO_ID == PIOA_ID
00072 #define LCD_CLK_SET() { outr(PIOA_PER, LCD_CLK); outr(PIOA_SODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00073 #define LCD_CLK_CLR() { outr(PIOA_PER, LCD_CLK); outr(PIOA_CODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00074 #elif LCD_CLK_PIO_ID == PIOB_ID
00075 #define LCD_CLK_SET() { outr(PIOB_PER, LCD_CLK); outr(PIOB_SODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00076 #define LCD_CLK_CLR() { outr(PIOB_PER, LCD_CLK); outr(PIOB_CODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00077 #elif LCD_CLK_PIO_ID == PIOC_ID
00078 #define LCD_CLK_SET() { outr(PIOC_PER, LCD_CLK); outr(PIOC_SODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00079 #define LCD_CLK_CLR() { outr(PIOC_PER, LCD_CLK); outr(PIOC_CODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00080 #else
00081 #define LCD_CLK_SET() { outr(PIO_PER, LCD_CLK); outr(PIO_SODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00082 #define LCD_CLK_CLR() { outr(PIO_PER, LCD_CLK); outr(PIO_CODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00083 #endif /* LCD_CLK_PIO_ID */
00084 #else /* LCD_CLK_BIT */
00085 #define LCD_CLK_SET()
00086 #define LCD_CLK_CLR()
00087 #endif /* LCD_CLK_BIT */
00088 
00089 #ifdef LCD_MOSI_BIT
00090 #define LCD_MOSI    _BV(LCD_MOSI_BIT)
00091 #if LCD_MOSI_PIO_ID == PIOA_ID
00092 #define LCD_MOSI_SET() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_SODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00093 #define LCD_MOSI_CLR() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_CODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00094 #elif LCD_MOSI_PIO_ID == PIOB_ID
00095 #define LCD_MOSI_SET() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_SODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00096 #define LCD_MOSI_CLR() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_CODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00097 #elif LCD_MOSI_PIO_ID == PIOC_ID
00098 #define LCD_MOSI_SET() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_SODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00099 #define LCD_MOSI_CLR() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_CODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00100 #else
00101 #define LCD_MOSI_SET() { outr(PIO_PER, LCD_MOSI); outr(PIO_SODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00102 #define LCD_MOSI_CLR() { outr(PIO_PER, LCD_MOSI); outr(PIO_CODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00103 #endif /* LCD_MOSI_PIO_ID */
00104 #else /* LCD_MOSI_BIT */
00105 #define LCD_MOSI_SET()
00106 #define LCD_MOSI_CLR()
00107 #endif /* LCD_MOSI_BIT */
00108 
00113 
00114 #ifndef LCD_SHORT_DELAY
00115 #define LCD_SHORT_DELAY 100
00116 #endif
00117 
00118 #ifndef LCD_LONG_DELAY
00119 #define LCD_LONG_DELAY  1000
00120 #endif
00121 
00132 static void LcdDelay(unsigned int cycles)
00133 {
00134     while (cycles--) {
00135         _NOP(); _NOP(); _NOP(); _NOP();
00136         _NOP(); _NOP(); _NOP(); _NOP();
00137         _NOP(); _NOP(); _NOP(); _NOP();
00138         _NOP(); _NOP(); _NOP(); _NOP();
00139         _NOP(); _NOP(); _NOP(); _NOP();
00140         _NOP(); _NOP(); _NOP(); _NOP();
00141         _NOP(); _NOP(); _NOP(); _NOP();
00142         _NOP(); _NOP(); _NOP(); _NOP();
00143         _NOP(); _NOP(); _NOP(); _NOP();
00144         _NOP(); _NOP(); _NOP(); _NOP();
00145         _NOP(); _NOP(); _NOP(); _NOP();
00146         _NOP(); _NOP(); _NOP(); _NOP();
00147     }
00148 }
00149 
00150 #if 0
00151 static void INLINE LcdSetBits(unsigned int mask)
00152 {
00153     outr(LCD_PIO_SOD_REG, mask);
00154     outr(LCD_PIO_OE_REG, mask);
00155 }
00156 
00157 static void INLINE LcdClrBits(unsigned int mask)
00158 {
00159     outr(LCD_PIO_COD_REG, mask);
00160     outr(LCD_PIO_OE_REG, mask);
00161 }
00162 #endif
00163 
00164 static void LcdWaitReady(unsigned int delay)
00165 {
00166     while (delay--) {
00167         _NOP();
00168     }
00169 }
00170 
00176 static void LcdWriteByte(unsigned int data)
00177 {
00178     uint8_t msk = 0x80;
00179 
00180     while (msk) {
00181         LCD_CLK_CLR();
00182         if (data & msk) {
00183             LCD_MOSI_SET();
00184         } else {
00185             LCD_MOSI_CLR();
00186         }
00187         LCD_CLK_SET();
00188         msk >>= 1;
00189         LcdDelay(1);
00190     }
00191     LcdWaitReady(LCD_LONG_DELAY);
00192 }
00193 
00199 static void LcdWriteCmd(uint8_t cmd)
00200 {
00201     /* RS low selects instruction register. */
00202     LCD_EN_CLR();
00203     LcdDelay(LCD_SHORT_DELAY);
00204     LCD_RS_CLR();
00205     LcdDelay(LCD_SHORT_DELAY);
00206     LcdWriteByte(cmd);
00207     LcdDelay(LCD_SHORT_DELAY);
00208     LCD_RS_SET();
00209     LcdDelay(LCD_SHORT_DELAY);
00210     LCD_EN_SET();
00211     LcdDelay(LCD_SHORT_DELAY);
00212 }
00213 
00214 static void LcdWriteInstruction(uint8_t cmd, uint8_t xt)
00215 {
00216     LcdWriteCmd(cmd);
00217 }
00218 
00224 static void LcdWriteData(uint8_t data)
00225 {
00226     /* RS high selects data register. */
00227         LCD_EN_CLR();
00228     LcdDelay(LCD_SHORT_DELAY);
00229     LCD_RS_SET();
00230     LcdDelay(LCD_SHORT_DELAY);
00231     LcdWriteByte(data);
00232     LcdDelay(LCD_SHORT_DELAY);
00233         LCD_EN_SET();
00234     LcdDelay(LCD_SHORT_DELAY);
00235 }
00236 
00237 static void LcdSetCursor(uint8_t pos)
00238 {
00239     uint8_t offset[] = {
00240         0x00, 0x40, 0x10, 0x50
00241     };
00242 
00243     pos = offset[(pos / LCD_COLS) % LCD_ROWS] + pos % LCD_COLS;
00244     LcdWriteCmd(0x80 | pos);
00245 }
00246 
00247 static void LcdCursorHome(void)
00248 {
00249     LcdWriteCmd(0x02);
00250     LcdDelay(10 * LCD_LONG_DELAY);
00251 }
00252 
00253 static void LcdCursorLeft(void)
00254 {
00255     LcdWriteCmd(0x10);
00256 }
00257 
00258 static void LcdCursorRight(void)
00259 {
00260     LcdWriteCmd(0x14);
00261 }
00262 
00263 static void LcdClear(void)
00264 {
00265     LcdWriteCmd(0x01);
00266     LcdDelay(10 * LCD_LONG_DELAY);
00267 }
00268 
00269 static void LcdCursorMode(uint8_t on)
00270 {
00271     if (on) {
00272         LcdWriteCmd(0x0D);
00273     } else {
00274         LcdWriteCmd(0x0C);
00275     }
00276     LcdDelay(10 * LCD_LONG_DELAY);
00277 }
00278 
00279 static int LcdInit(NUTDEVICE * dev)
00280 {
00281 #if defined(PMC_PCER)
00282     unsigned int pcer = 0;
00283 #if defined(LCD_EN_PIO_ID)
00284     pcer = _BV(LCD_EN_PIO_ID);
00285 #endif
00286 #if defined(LCD_RS_PIO_ID)
00287     pcer |= _BV(LCD_RS_PIO_ID);
00288 #endif
00289 #if defined(LCD_CLK_PIO_ID)
00290     pcer |= _BV(LCD_CLK_PIO_ID);
00291 #endif
00292 #if defined(LCD_MOSI_PIO_ID)
00293     pcer |= _BV(LCD_MOSI_PIO_ID);
00294 #endif
00295     outr(PMC_PCER, pcer);
00296 #endif
00297 
00298     /* Initialize GPIO lines. */
00299     LCD_EN_SET();
00300     LCD_RS_SET();
00301     LCD_CLK_SET();
00302     LCD_MOSI_SET();
00303 
00304     /* Initial delay. Actually only required after power on. */
00305     NutSleep(50);
00306 
00307         LCD_RS_CLR();
00308         LCD_EN_CLR();
00309 
00310         LcdWriteCmd(0x38);    /* Function set. */
00311         NutSleep(2);
00312         LcdWriteCmd(0x39);    /* Function set. */
00313         NutSleep(2);
00314         LcdWriteCmd(0x14);    /* Bias 1/5, 2 lines. */
00315         NutSleep(1);
00316         LcdWriteCmd(0x55);    /* Power/ICON/Contrast control. */
00317         NutSleep(1);
00318         LcdWriteCmd(0x6D);    /* Follower control. */
00319         NutSleep(1);
00320         LcdWriteCmd(0x78);    /* Booster on, Contrast set. */
00321         NutSleep(1);
00322         LcdWriteCmd(0x0F);    /* Display on. */
00323         NutSleep(1);
00324         LcdWriteCmd(0x01);    /* Clear display. */
00325         NutSleep(1);
00326         LcdWriteCmd(0x06);    /* Entry mode set. */
00327         NutSleep(1);
00328 
00329         LCD_EN_SET();
00330         LCD_RS_SET();
00331 
00332     /* Clear display. */
00333     LcdClear();
00334     /* Move cursor home. */
00335     LcdCursorHome();
00336 
00337     return 0;
00338 }
00339 
00343 static TERMDCB dcb_term = {
00344     LcdInit,                    
00345     LcdWriteData,               
00346     LcdWriteInstruction,        
00347     LcdClear,                   
00348     LcdSetCursor,               
00349     LcdCursorHome,              
00350     LcdCursorLeft,              
00351     LcdCursorRight,             
00352     LcdCursorMode,              
00353     0,                          
00354     0,                          
00355     LCD_ROWS,                   
00356     LCD_COLS,                   
00357     LCD_COLS,                   
00358     0,                          
00359     0,                          
00360     0                           
00361 };
00362 
00366 NUTDEVICE devSbiLcd = {
00367     0,                          
00368     {'s', 'b', 'i', 'l', 'c', 'd', 0, 0, 0},  
00369     IFTYP_STREAM,               
00370     0,                          
00371     0,                          
00372     0,                          
00373     &dcb_term,                  
00374     TermInit,                   
00375     TermIOCtl,                  
00376     0,
00377     TermWrite,
00378     TermOpen,
00379     TermClose,
00380     0
00381 };
00382