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.3  2008/02/15 16:59:02  haraldkipp
00037  * Spport for AT91SAM7SE512 added.
00038  *
00039  * Revision 1.2  2007/10/04 20:01:50  olereinhardt
00040  * Support for SAM7S256 added
00041  *
00042  * Revision 1.1  2007/02/15 16:09:07  haraldkipp
00043  * Tested with EA DOG-M LCDs.
00044  *
00045  */
00046 
00047 #include <cfg/arch.h>
00048 #include <cfg/arch/gpio.h>
00049 #include <cfg/lcd.h>
00050 
00051 #include <stdlib.h>
00052 #include <string.h>
00053 
00054 #include <sys/nutconfig.h>
00055 #include <dev/st7036.h>
00056 #include <dev/term.h>
00057 #include <sys/timer.h>
00058 
00059 #ifndef LCD_ROWS
00060 #define LCD_ROWS    2
00061 #endif
00062 
00063 #ifndef LCD_COLS
00064 #define LCD_COLS    16
00065 #endif
00066 
00067 #ifndef LCD_SHORT_DELAY
00068 #define LCD_SHORT_DELAY 100
00069 #endif
00070 
00071 #ifndef LCD_LONG_DELAY
00072 #define LCD_LONG_DELAY  1000
00073 #endif
00074 
00078 #if defined(AT91SAM7X_EK)
00079 
00080 #ifndef LCD_CS_PIO_ID
00081 #define LCD_CS_PIO_ID   PIOB_ID
00082 #endif
00083 #ifndef LCD_CS_BIT
00084 #define LCD_CS_BIT      24
00085 #endif
00086 
00087 #ifndef LCD_RS_PIO_ID
00088 #define LCD_RS_PIO_ID   PIOB_ID
00089 #endif
00090 #ifndef LCD_RS_BIT
00091 #define LCD_RS_BIT      23
00092 #endif
00093 
00094 #ifndef LCD_CLK_PIO_ID
00095 #define LCD_CLK_PIO_ID  PIOA_ID
00096 #endif
00097 #ifndef LCD_CLK_BIT
00098 #define LCD_CLK_BIT     18
00099 #endif
00100 
00101 #ifndef LCD_MOSI_PIO_ID
00102 #define LCD_MOSI_PIO_ID PIOA_ID
00103 #endif
00104 #ifndef LCD_MOSI_BIT
00105 #define LCD_MOSI_BIT    17
00106 #endif
00107 
00108 #elif defined(AT91SAM7S) || defined(MCU_AT91SAM7SE512)
00109 
00110 #ifndef LCD_CS_PIO_ID
00111 #define LCD_CS_PIO_ID   PIOA_ID
00112 #endif
00113 #ifndef LCD_CS_BIT
00114 #define LCD_CS_BIT      28
00115 #endif
00116 
00117 #ifndef LCD_RS_PIO_ID
00118 #define LCD_RS_PIO_ID   PIOA_ID
00119 #endif
00120 #ifndef LCD_RS_BIT
00121 #define LCD_RS_BIT      26
00122 #endif
00123 
00124 #ifndef LCD_CLK_PIO_ID
00125 #define LCD_CLK_PIO_ID  PIOA_ID
00126 #endif
00127 #ifndef LCD_CLK_BIT
00128 #define LCD_CLK_BIT     14
00129 #endif
00130 
00131 #ifndef LCD_MOSI_PIO_ID
00132 #define LCD_MOSI_PIO_ID PIOA_ID
00133 #endif
00134 #ifndef LCD_MOSI_BIT
00135 #define LCD_MOSI_BIT    13
00136 #endif
00137 
00138 #elif defined(AT91SAM9260_EK)
00139 
00140 #ifndef LCD_CS_PIO_ID
00141 #define LCD_CS_PIO_ID   PIOB_ID
00142 #endif
00143 #ifndef LCD_CS_BIT
00144 #define LCD_CS_BIT      11
00145 #endif
00146 
00147 #ifndef LCD_RS_PIO_ID
00148 #define LCD_RS_PIO_ID   PIOB_ID
00149 #endif
00150 #ifndef LCD_RS_BIT
00151 #define LCD_RS_BIT      20
00152 #endif
00153 
00154 #ifndef LCD_CLK_PIO_ID
00155 #define LCD_CLK_PIO_ID  PIOB_ID
00156 #endif
00157 #ifndef LCD_CLK_BIT
00158 #define LCD_CLK_BIT     2
00159 #endif
00160 
00161 #ifndef LCD_MOSI_PIO_ID
00162 #define LCD_MOSI_PIO_ID PIOB_ID
00163 #endif
00164 #ifndef LCD_MOSI_BIT
00165 #define LCD_MOSI_BIT    1
00166 #endif
00167 
00168 #else
00169 
00170 #ifndef LCD_CS_PIO_ID
00171 #define LCD_CS_PIO_ID   PIO_ID
00172 #endif
00173 #ifndef LCD_CS_BIT
00174 #define LCD_CS_BIT      0
00175 #endif
00176 
00177 #ifndef LCD_RS_PIO_ID
00178 #define LCD_RS_PIO_ID   PIO_ID
00179 #endif
00180 #ifndef LCD_RS_BIT
00181 #define LCD_RS_BIT      3
00182 #endif
00183 
00184 #ifndef LCD_CLK_PIO_ID
00185 #define LCD_CLK_PIO_ID  PIO_ID
00186 #endif
00187 #ifndef LCD_CLK_BIT
00188 #define LCD_CLK_BIT     1
00189 #endif
00190 
00191 #ifndef LCD_MOSI_PIO_ID
00192 #define LCD_MOSI_PIO_ID PIO_ID
00193 #endif
00194 #ifndef LCD_MOSI_BIT
00195 #define LCD_MOSI_BIT    2
00196 #endif
00197 
00198 #endif
00199 
00200 #define LCD_CS      _BV(LCD_CS_BIT)
00201 #define LCD_RS      _BV(LCD_RS_BIT)
00202 #define LCD_CLK     _BV(LCD_CLK_BIT)
00203 #define LCD_MOSI    _BV(LCD_MOSI_BIT)
00204 
00205 
00206 #if LCD_CS_PIO_ID == PIOA_ID
00207 #define LCD_CS_SET() { outr(PIOA_PER, LCD_CS); outr(PIOA_SODR, LCD_CS); outr(PIOA_OER, LCD_CS); }
00208 #define LCD_CS_CLR() { outr(PIOA_PER, LCD_CS); outr(PIOA_CODR, LCD_CS); outr(PIOA_OER, LCD_CS); }
00209 #elif LCD_CS_PIO_ID == PIOB_ID
00210 #define LCD_CS_SET() { outr(PIOB_PER, LCD_CS); outr(PIOB_SODR, LCD_CS); outr(PIOB_OER, LCD_CS); }
00211 #define LCD_CS_CLR() { outr(PIOB_PER, LCD_CS); outr(PIOB_CODR, LCD_CS); outr(PIOB_OER, LCD_CS); }
00212 #elif LCD_CS_PIO_ID == PIOC_ID
00213 #define LCD_CS_SET() { outr(PIOC_PER, LCD_CS); outr(PIOC_SODR, LCD_CS); outr(PIOC_OER, LCD_CS); }
00214 #define LCD_CS_CLR() { outr(PIOC_PER, LCD_CS); outr(PIOC_CODR, LCD_CS); outr(PIOC_OER, LCD_CS); }
00215 #else
00216 #define LCD_CS_SET() { outr(PIO_PER, LCD_CS); outr(PIO_SODR, LCD_CS); outr(PIO_OER, LCD_CS); }
00217 #define LCD_CS_CLR() { outr(PIO_PER, LCD_CS); outr(PIO_CODR, LCD_CS); outr(PIO_OER, LCD_CS); }
00218 #endif
00219 
00220 #if LCD_RS_PIO_ID == PIOA_ID
00221 #define LCD_RS_SET() { outr(PIOA_PER, LCD_RS); outr(PIOA_SODR, LCD_RS); outr(PIOA_OER, LCD_RS); }
00222 #define LCD_RS_CLR() { outr(PIOA_PER, LCD_RS); outr(PIOA_CODR, LCD_RS); outr(PIOA_OER, LCD_RS); }
00223 #elif LCD_RS_PIO_ID == PIOB_ID
00224 #define LCD_RS_SET() { outr(PIOB_PER, LCD_RS); outr(PIOB_SODR, LCD_RS); outr(PIOB_OER, LCD_RS); }
00225 #define LCD_RS_CLR() { outr(PIOB_PER, LCD_RS); outr(PIOB_CODR, LCD_RS); outr(PIOB_OER, LCD_RS); }
00226 #elif LCD_RS_PIO_ID == PIOC_ID
00227 #define LCD_RS_SET() { outr(PIOC_PER, LCD_RS); outr(PIOC_SODR, LCD_RS); outr(PIOC_OER, LCD_RS); }
00228 #define LCD_RS_CLR() { outr(PIOC_PER, LCD_RS); outr(PIOC_CODR, LCD_RS); outr(PIOC_OER, LCD_RS); }
00229 #else
00230 #define LCD_RS_SET() { outr(PIO_PER, LCD_RS); outr(PIO_SODR, LCD_RS); outr(PIO_OER, LCD_RS); }
00231 #define LCD_RS_CLR() { outr(PIO_PER, LCD_RS); outr(PIO_CODR, LCD_RS); outr(PIO_OER, LCD_RS); }
00232 #endif
00233 
00234 #if LCD_CLK_PIO_ID == PIOA_ID
00235 #define LCD_CLK_SET() { outr(PIOA_PER, LCD_CLK); outr(PIOA_SODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00236 #define LCD_CLK_CLR() { outr(PIOA_PER, LCD_CLK); outr(PIOA_CODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00237 #elif LCD_CLK_PIO_ID == PIOB_ID
00238 #define LCD_CLK_SET() { outr(PIOB_PER, LCD_CLK); outr(PIOB_SODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00239 #define LCD_CLK_CLR() { outr(PIOB_PER, LCD_CLK); outr(PIOB_CODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00240 #elif LCD_CLK_PIO_ID == PIOC_ID
00241 #define LCD_CLK_SET() { outr(PIOC_PER, LCD_CLK); outr(PIOC_SODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00242 #define LCD_CLK_CLR() { outr(PIOC_PER, LCD_CLK); outr(PIOC_CODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00243 #else
00244 #define LCD_CLK_SET() { outr(PIO_PER, LCD_CLK); outr(PIO_SODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00245 #define LCD_CLK_CLR() { outr(PIO_PER, LCD_CLK); outr(PIO_CODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00246 #endif
00247 
00248 #if LCD_MOSI_PIO_ID == PIOA_ID
00249 #define LCD_MOSI_SET() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_SODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00250 #define LCD_MOSI_CLR() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_CODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00251 #elif LCD_MOSI_PIO_ID == PIOB_ID
00252 #define LCD_MOSI_SET() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_SODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00253 #define LCD_MOSI_CLR() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_CODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00254 #elif LCD_MOSI_PIO_ID == PIOC_ID
00255 #define LCD_MOSI_SET() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_SODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00256 #define LCD_MOSI_CLR() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_CODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00257 #else
00258 #define LCD_MOSI_SET() { outr(PIO_PER, LCD_MOSI); outr(PIO_SODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00259 #define LCD_MOSI_CLR() { outr(PIO_PER, LCD_MOSI); outr(PIO_CODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00260 #endif
00261 
00266 
00277 static void LcdDelay(u_int cycles)
00278 {
00279     while (cycles--) {
00280         _NOP(); _NOP(); _NOP(); _NOP();
00281         _NOP(); _NOP(); _NOP(); _NOP();
00282         _NOP(); _NOP(); _NOP(); _NOP();
00283         _NOP(); _NOP(); _NOP(); _NOP();
00284         _NOP(); _NOP(); _NOP(); _NOP();
00285         _NOP(); _NOP(); _NOP(); _NOP();
00286         _NOP(); _NOP(); _NOP(); _NOP();
00287         _NOP(); _NOP(); _NOP(); _NOP();
00288         _NOP(); _NOP(); _NOP(); _NOP();
00289         _NOP(); _NOP(); _NOP(); _NOP();
00290         _NOP(); _NOP(); _NOP(); _NOP();
00291         _NOP(); _NOP(); _NOP(); _NOP();
00292     }
00293 }
00294 
00295 #if 0
00296 static void INLINE LcdSetBits(u_int mask)
00297 {
00298     outr(LCD_PIO_SOD_REG, mask);
00299     outr(LCD_PIO_OE_REG, mask);
00300 }
00301 
00302 static void INLINE LcdClrBits(u_int mask)
00303 {
00304     outr(LCD_PIO_COD_REG, mask);
00305     outr(LCD_PIO_OE_REG, mask);
00306 }
00307 #endif
00308 
00309 static void LcdWaitReady(u_int delay)
00310 {
00311     while (delay--) {
00312         _NOP();
00313     }
00314 }
00315 
00321 static void LcdWriteByte(u_int data)
00322 {
00323     u_char msk = 0x80;
00324 
00325     while (msk) {
00326         LCD_CLK_CLR();
00327         if (data & msk) {
00328             LCD_MOSI_SET();
00329         } else {
00330             LCD_MOSI_CLR();
00331         }
00332         LCD_CLK_SET();
00333         msk >>= 1;
00334         LcdDelay(1);
00335     }
00336     LcdWaitReady(LCD_LONG_DELAY);
00337 }
00338 
00344 static void LcdWriteCmd(u_char cmd)
00345 {
00346     /* RS low selects instruction register. */
00347     LCD_CS_CLR();
00348     LcdDelay(LCD_SHORT_DELAY);
00349     LCD_RS_CLR();
00350     LcdDelay(LCD_SHORT_DELAY);
00351     LcdWriteByte(cmd);
00352     LcdDelay(LCD_SHORT_DELAY);
00353     LCD_RS_SET();
00354     LcdDelay(LCD_SHORT_DELAY);
00355     LCD_CS_SET();
00356     LcdDelay(LCD_SHORT_DELAY);
00357 }
00358 
00359 static void LcdWriteInstruction(u_char cmd, u_char xt)
00360 {
00361     LcdWriteCmd(cmd);
00362 }
00363 
00369 static void LcdWriteData(u_char data)
00370 {
00371     /* RS high selects data register. */
00372     LCD_CS_CLR();
00373     LcdDelay(LCD_SHORT_DELAY);
00374     LCD_RS_SET();
00375     LcdDelay(LCD_SHORT_DELAY);
00376     LcdWriteByte(data);
00377     LcdDelay(LCD_SHORT_DELAY);
00378     LCD_CS_SET();
00379     LcdDelay(LCD_SHORT_DELAY);
00380 }
00381 
00382 static void LcdSetCursor(u_char pos)
00383 {
00384     u_char offset[] = {
00385         0x00, 0x40, 0x10, 0x50
00386     };
00387 
00388     pos = offset[(pos / LCD_COLS) % LCD_ROWS] + pos % LCD_COLS;
00389     LcdWriteCmd(0x80 | pos);
00390 }
00391 
00392 static void LcdCursorHome(void)
00393 {
00394     LcdWriteCmd(0x02);
00395     LcdDelay(10 * LCD_LONG_DELAY);
00396 }
00397 
00398 static void LcdCursorLeft(void)
00399 {
00400     LcdWriteCmd(0x10);
00401 }
00402 
00403 static void LcdCursorRight(void)
00404 {
00405     LcdWriteCmd(0x14);
00406 }
00407 
00408 static void LcdClear(void)
00409 {
00410     LcdWriteCmd(0x01);
00411     LcdDelay(10 * LCD_LONG_DELAY);
00412 }
00413 
00414 static void LcdCursorMode(u_char on)
00415 {
00416     if (on) {
00417         LcdWriteCmd(0x0D);
00418     } else {
00419         LcdWriteCmd(0x0C);
00420     }
00421     LcdDelay(10 * LCD_LONG_DELAY);
00422 }
00423 
00424 static void LcdInit(NUTDEVICE * dev)
00425 {
00426 #if defined(PMC_PCER)
00427     outr(PMC_PCER, _BV(LCD_CS_PIO_ID) | _BV(LCD_RS_PIO_ID) | _BV(LCD_CLK_PIO_ID) | _BV(LCD_MOSI_PIO_ID));
00428 #endif
00429 
00430     /* Initialize GPIO lines. */
00431     LCD_CS_SET();
00432     LCD_RS_SET();
00433     LCD_CLK_SET();
00434     LCD_MOSI_SET();
00435 
00436     /* Initial delay. Actually only required after power on. */
00437     NutSleep(50);
00438 
00439     LCD_RS_CLR();
00440     LCD_CS_CLR();
00441 
00442     LcdWriteCmd(0x38);    /* Function set. */
00443     NutSleep(2);
00444     LcdWriteCmd(0x39);    /* Function set. */
00445     NutSleep(2);
00446     LcdWriteCmd(0x14);    /* Bias 1/5, 2 lines. */
00447     NutSleep(1);
00448     LcdWriteCmd(0x55);    /* Power/ICON/Contrast control. */
00449     NutSleep(1);
00450     LcdWriteCmd(0x6D);    /* Follower control. */
00451     NutSleep(1);
00452     LcdWriteCmd(0x78);    /* Booster on, Contrast set. */
00453     NutSleep(1);
00454     LcdWriteCmd(0x0F);    /* Display on. */
00455     NutSleep(1);
00456     LcdWriteCmd(0x01);    /* Clear display. */
00457     NutSleep(1);
00458     LcdWriteCmd(0x06);    /* Entry mode set. */
00459     NutSleep(1);
00460 
00461     LCD_CS_SET();
00462     LCD_RS_SET();
00463 
00464     /* Clear display. */
00465     LcdClear();
00466     /* Move cursor home. */
00467     LcdCursorHome();
00468 }
00469 
00473 static TERMDCB dcb_term = {
00474     LcdInit,                    
00475     LcdWriteData,               
00476     LcdWriteInstruction,        
00477     LcdClear,                   
00478     LcdSetCursor,               
00479     LcdCursorHome,              
00480     LcdCursorLeft,              
00481     LcdCursorRight,             
00482     LcdCursorMode,              
00483     0,                          
00484     0,                          
00485     LCD_ROWS,                   
00486     LCD_COLS,                   
00487     LCD_COLS,                   
00488     0,                          
00489     0,                          
00490     0                           
00491 };
00492 
00496 NUTDEVICE devSbiLcd = {
00497     0,                          
00498     {'s', 'b', 'i', 'l', 'c', 'd', 0, 0, 0},  
00499     IFTYP_STREAM,               
00500     0,                          
00501     0,                          
00502     0,                          
00503     &dcb_term,                  
00504     TermInit,                   
00505     TermIOCtl,                  
00506     0,
00507     TermWrite,
00508     TermOpen,
00509     TermClose,
00510     0
00511 };
00512 

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