Main Page   Data Structures   File List   Data Fields   Globals  

ks0108.c

Go to the documentation of this file.
00001 /*! \file ks0108.c \brief Graphic LCD driver for HD61202/KS0108 displays. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'ks0108.c'
00005 // Title        : Graphic LCD driver for HD61202/KS0108 displays
00006 // Author       : Pascal Stang - Copyright (C) 2001-2002
00007 // Date         : 10/19/2002
00008 // Revised      : 5/30/2002
00009 // Version      : 0.5
00010 // Target MCU   : Atmel AVR
00011 // Editor Tabs  : 4
00012 //
00013 // NOTE: This code is currently below version 1.0, and therefore is considered
00014 // to be lacking in some functionality or documentation, or may not be fully
00015 // tested.  Nonetheless, you can expect most functions to work.
00016 //
00017 // This code is distributed under the GNU Public License
00018 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00019 //
00020 //*****************************************************************************
00021 
00022 #ifndef WIN32
00023 // AVR specific includes
00024     #include <avr/io.h>
00025     #include <avr/interrupt.h>
00026 #endif
00027 
00028 #include "global.h"
00029 #include "ks0108.h"
00030 
00031 // global variables
00032 GrLcdStateType GrLcdState;
00033 
00034 /*************************************************************/
00035 /********************** LOCAL FUNCTIONS **********************/
00036 /*************************************************************/
00037 
00038 void glcdInitHW(void)
00039 {
00040     // initialize I/O ports
00041     // if I/O interface is in use
00042 #ifdef LCD_PORT_INTERFACE
00043     // initialize LCD control port to output
00044     sbi(LCD_CTRL_DDR, LCD_CTRL_RS);
00045     sbi(LCD_CTRL_DDR, LCD_CTRL_RW);
00046     sbi(LCD_CTRL_DDR, LCD_CTRL_E);
00047     sbi(LCD_CTRL_DDR, LCD_CTRL_CS0);
00048     sbi(LCD_CTRL_DDR, LCD_CTRL_CS1);
00049     sbi(LCD_CTRL_DDR, LCD_CTRL_RESET);
00050     // initialize LCD control lines levels
00051     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
00052     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00053     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
00054     sbi(LCD_CTRL_PORT, LCD_CTRL_CS0);
00055     sbi(LCD_CTRL_PORT, LCD_CTRL_CS1);
00056     cbi(LCD_CTRL_PORT, LCD_CTRL_RESET);
00057     // initialize LCD data port to output
00058     outp(0xFF, LCD_DATA_DDR);
00059     // initialize LCD data
00060     outp(0x00, LCD_DATA_PORT);
00061 #endif
00062 }
00063 
00064 void glcdControllerSelect(u08 controller)
00065 {
00066     // select requested controller
00067     switch(controller)
00068     {
00069     case 0: sbi(LCD_CTRL_PORT, LCD_CTRL_CS0); cbi(LCD_CTRL_PORT, LCD_CTRL_CS1); break;
00070     case 1: cbi(LCD_CTRL_PORT, LCD_CTRL_CS0); sbi(LCD_CTRL_PORT, LCD_CTRL_CS1); break;
00071     default: break;
00072     }
00073 }
00074 
00075 void glcdBusyWait(u08 controller)
00076 {
00077 #ifdef LCD_PORT_INTERFACE
00078     cli();
00079     // wait until LCD busy bit goes to zero
00080     // select the controller chip
00081     glcdControllerSelect(controller);
00082     // do a read from control register
00083     outp(0xFF, LCD_DATA_PORT);
00084     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
00085     outp(0x00, LCD_DATA_DDR);
00086     sbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00087     sbi(LCD_CTRL_PORT, LCD_CTRL_E);
00088     asm volatile ("nop"); asm volatile ("nop");
00089     while(inp(LCD_DATA_PIN) & GLCD_STATUS_BUSY)
00090     {
00091         cbi(LCD_CTRL_PORT, LCD_CTRL_E);
00092         asm volatile ("nop"); asm volatile ("nop");
00093         asm volatile ("nop"); asm volatile ("nop");
00094         sbi(LCD_CTRL_PORT, LCD_CTRL_E);
00095         asm volatile ("nop"); asm volatile ("nop");
00096         asm volatile ("nop"); asm volatile ("nop");
00097     }
00098     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
00099     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00100     outp(0xFF, LCD_DATA_DDR);
00101     sei();
00102 #else
00103     // sbi(MCUCR, SRW);         // enable RAM waitstate
00104     // wait until LCD busy bit goes to zero
00105     while(*(volatile unsigned char *) (LCD_CTRL_ADDR) & 1<<LCD_BUSY);
00106     // cbi(MCUCR, SRW);         // disable RAM waitstate
00107 #endif
00108 }
00109 
00110 void glcdControlWrite(u08 controller, u08 data)
00111 {
00112 #ifdef LCD_PORT_INTERFACE
00113     cli();
00114     glcdBusyWait(controller);   // wait until LCD not busy
00115     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
00116     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00117     sbi(LCD_CTRL_PORT, LCD_CTRL_E);
00118     outp(0xFF, LCD_DATA_DDR);
00119     outp(data, LCD_DATA_PORT);
00120     asm volatile ("nop"); asm volatile ("nop");
00121     asm volatile ("nop"); asm volatile ("nop");
00122     asm volatile ("nop"); asm volatile ("nop");
00123     asm volatile ("nop"); asm volatile ("nop");
00124     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
00125     sei();
00126 #else
00127     sbi(MCUCR, SRW);                // enable RAM waitstate
00128     glcdBusyWait(controller);       // wait until LCD not busy
00129     *(volatile unsigned char *) (LCD_CTRL_ADDR) = data;
00130     cbi(MCUCR, SRW);                // disable RAM waitstate
00131 #endif
00132 }
00133 
00134 u08 glcdControlRead(u08 controller)
00135 {
00136     register u08 data;
00137 #ifdef LCD_PORT_INTERFACE
00138     cli();
00139     glcdBusyWait(controller);       // wait until LCD not busy
00140     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
00141     outp(0x00, LCD_DATA_DDR);
00142     sbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00143     sbi(LCD_CTRL_PORT, LCD_CTRL_E);
00144     asm volatile ("nop"); asm volatile ("nop");
00145     asm volatile ("nop"); asm volatile ("nop");
00146     asm volatile ("nop"); asm volatile ("nop");
00147     asm volatile ("nop"); asm volatile ("nop");
00148     data = inp(LCD_DATA_PIN);
00149     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
00150     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00151     outp(0xFF, LCD_DATA_DDR);
00152     sei();
00153 #else
00154     sbi(MCUCR, SRW);                // enable RAM waitstate
00155     glcdBusyWait(controller);       // wait until LCD not busy
00156     data = *(volatile unsigned char *) (LCD_CTRL_ADDR);
00157     cbi(MCUCR, SRW);                // disable RAM waitstate
00158 #endif
00159     return data;
00160 }
00161 
00162 void glcdDataWrite(u08 data)
00163 {
00164     register u08 controller = (GrLcdState.lcdXAddr/GLCD_CONTROLLER_WIDTH);
00165 #ifdef LCD_PORT_INTERFACE
00166     cli();
00167     glcdBusyWait(controller);       // wait until LCD not busy
00168     sbi(LCD_CTRL_PORT, LCD_CTRL_RS);
00169     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00170     sbi(LCD_CTRL_PORT, LCD_CTRL_E);
00171     outp(0xFF, LCD_DATA_DDR);
00172     outp(data, LCD_DATA_PORT);
00173     asm volatile ("nop"); asm volatile ("nop");
00174     asm volatile ("nop"); asm volatile ("nop");
00175     asm volatile ("nop"); asm volatile ("nop");
00176     asm volatile ("nop"); asm volatile ("nop");
00177     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
00178     sei();
00179 #else
00180     sbi(MCUCR, SRW);                // enable RAM waitstate
00181     glcdBusyWait(controller);       // wait until LCD not busy
00182     *(volatile unsigned char *) (LCD_DATA_ADDR) = data;
00183     cbi(MCUCR, SRW);                // disable RAM waitstate
00184 #endif
00185     // increment our local address counter
00186     GrLcdState.ctrlr[controller].xAddr++;
00187     GrLcdState.lcdXAddr++;
00188     if(GrLcdState.lcdXAddr > GLCD_XPIXELS)
00189     {
00190         GrLcdState.lcdYAddr++;
00191         glcdSetYAddress(GrLcdState.lcdYAddr);
00192         glcdSetXAddress(0);
00193     }
00194 }
00195 
00196 u08 glcdDataRead(void)
00197 {
00198     register u08 data;
00199     register u08 controller = (GrLcdState.lcdXAddr/GLCD_CONTROLLER_WIDTH);
00200 #ifdef LCD_PORT_INTERFACE
00201     cli();
00202     glcdBusyWait(controller);       // wait until LCD not busy
00203     sbi(LCD_CTRL_PORT, LCD_CTRL_RS);
00204     outp(0x00, LCD_DATA_DDR);
00205     sbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00206     sbi(LCD_CTRL_PORT, LCD_CTRL_E);
00207     asm volatile ("nop"); asm volatile ("nop");
00208     asm volatile ("nop"); asm volatile ("nop");
00209     asm volatile ("nop"); asm volatile ("nop");
00210     asm volatile ("nop"); asm volatile ("nop");
00211     data = inp(LCD_DATA_PIN);
00212     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
00213     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
00214     outp(0xFF, LCD_DATA_DDR);
00215     sei();
00216 #else
00217     sbi(MCUCR, SRW);                // enable RAM waitstate
00218     glcdBusyWait(controller);       // wait until LCD not busy
00219     data = *(volatile unsigned char *) (LCD_DATA_ADDR);
00220     cbi(MCUCR, SRW);                // disable RAM waitstate
00221 #endif
00222     // increment our local address counter
00223     GrLcdState.ctrlr[controller].xAddr++;
00224     GrLcdState.lcdXAddr++;
00225     if(GrLcdState.lcdXAddr > GLCD_XPIXELS)
00226     {
00227         GrLcdState.lcdYAddr++;
00228         glcdSetYAddress(GrLcdState.lcdYAddr);
00229         glcdSetXAddress(0);
00230     }
00231     return data;
00232 }
00233 
00234 void glcdReset(u08 resetState)
00235 {
00236     // reset lcd if argument is true
00237     // run lcd if argument is false
00238     if(resetState)
00239         cbi(LCD_CTRL_PORT, LCD_CTRL_RESET);
00240     else
00241         sbi(LCD_CTRL_PORT, LCD_CTRL_RESET);
00242 }
00243 
00244 void glcdSetXAddress(u08 xAddr)
00245 {
00246     // record address change locally
00247     GrLcdState.lcdXAddr = xAddr;
00248     // clear y (col) address on both controllers
00249     glcdControlWrite(0, GLCD_Y_ADDR | 0x00);
00250     GrLcdState.ctrlr[0].xAddr = 0;
00251     glcdControlWrite(1, GLCD_Y_ADDR | 0x00);
00252     GrLcdState.ctrlr[1].xAddr = 0;
00253     // set y (col) address on destination controller
00254     glcdControlWrite((GrLcdState.lcdXAddr/GLCD_CONTROLLER_WIDTH),
00255         GLCD_Y_ADDR | (GrLcdState.lcdXAddr & 0x3F));
00256 }
00257 
00258 void glcdSetYAddress(u08 yAddr)
00259 {
00260     // record address change locally
00261     GrLcdState.lcdYAddr = yAddr;
00262     // set page address for both controllers
00263     glcdControlWrite(0, GLCD_SET_PAGE | yAddr);
00264     glcdControlWrite(1, GLCD_SET_PAGE | yAddr);
00265 }
00266 
00267 /*************************************************************/
00268 /********************* PUBLIC FUNCTIONS **********************/
00269 /*************************************************************/
00270 
00271 void glcdInit()
00272 {
00273     // initialize hardware
00274     glcdInitHW();
00275     // bring lcd out of reset
00276     glcdReset(FALSE);
00277     // Turn on LCD
00278     glcdControlWrite(0, GLCD_ON_CTRL | GLCD_ON_DISPLAY);
00279     glcdControlWrite(1, GLCD_ON_CTRL | GLCD_ON_DISPLAY);
00280     // clear lcd
00281     glcdClearScreen();
00282     // initialize positions
00283     glcdHome();
00284 }
00285 
00286 void glcdHome(void)
00287 {
00288     // initialize addresses/positions
00289     glcdStartLine(0);
00290     glcdSetAddress(0,0);
00291     // initialize local data structures
00292     GrLcdState.ctrlr[0].xAddr = 0;
00293     GrLcdState.ctrlr[0].yAddr = 0;
00294     GrLcdState.ctrlr[0].xAddr = 0;
00295     GrLcdState.ctrlr[0].yAddr = 0;
00296 }
00297 
00298 void glcdClearScreen(void)
00299 {
00300     u08 pageAddr;
00301     u08 xAddr;
00302 
00303     // clear LCD
00304     // loop through all pages
00305     for(pageAddr=0; pageAddr<(GLCD_YPIXELS>>3); pageAddr++)
00306     {
00307         // set page address
00308         glcdSetAddress(0, pageAddr);
00309         // clear the 128 lines of this page
00310         for(xAddr=0; xAddr<GLCD_XPIXELS; xAddr++)
00311         {
00312             glcdDataWrite(0x00);
00313         }
00314     }
00315 }
00316 
00317 void glcdStartLine(u08 start)
00318 {
00319     glcdControlWrite(0, GLCD_START_LINE | start);
00320     glcdControlWrite(1, GLCD_START_LINE | start);
00321 }
00322 
00323 void glcdSetAddress(u08 x, u08 yLine)
00324 {
00325     // set addresses
00326     glcdSetYAddress(yLine);
00327     glcdSetXAddress(x);
00328 }
00329 
00330 void glcdGotoChar(u08 line, u08 col)
00331 {
00332     glcdSetAddress(col*6, line);
00333 }
00334 
00335 void glcdDelay(u16 p)           // 1-8us      ...2-13us     ...5-31us
00336 {                               // 10-60us    ...50-290us
00337     unsigned int i;             // 100-580us  ...500-2,9ms
00338     unsigned char j;            // 1000-5,8ms ...5000-29ms
00339                                 // 10000-56ms ...30000-170ms
00340                                 // 50000-295ms...60000-345ms
00341 //  for (i = 0; i < p; i++) for (j = 0; j < 10; j++) asm volatile ("nop");
00342     for (i = 0; i < p; i++) for (j = 0; j < 10; j++);
00343 }
00344 
00345 /*
00346 void glcdWriteChar(u08 asciiIdx)
00347 {
00348     u08 horizIdx;
00349 
00350     // write the lines of the desired character to the display
00351     for(horizIdx=0; horizIdx<6; horizIdx++)
00352     {
00353         // write the line
00354         glcdDataWrite(PRG_RDB(LcdAscii+(asciiIdx*6)+horizIdx));
00355     }
00356 }
00357 
00358 void glcdWriteGr(u08 grIdx)
00359 {
00360     u08 idx;
00361     u08 grLength;
00362     u08 grStartIdx = 0;
00363 
00364     // get starting index of graphic bitmap
00365     for(idx=0; idx<grIdx; idx++)
00366     {
00367         // add this graphic's length to the startIdx
00368         // to get the startIdx of the next one
00369         grStartIdx += PRG_RDB(LcdCustomGr+grStartIdx);
00370     }
00371     grLength = PRG_RDB(LcdCustomGr+grStartIdx);
00372 
00373     // write the lines of the desired graphic to the display
00374     for(idx=0; idx<grLength; idx++)
00375     {
00376         // write the line
00377         glcdDataWrite(PRG_RDB(LcdCustomGr+(grStartIdx+1)+idx));
00378     }
00379 }
00380 */

Generated on Tue Feb 4 20:18:37 2003 for Procyon AVRlib by doxygen1.3-rc2