Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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-2003
00007 // Date         : 10/19/2002
00008 // Revised      : 5/5/2003
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 GLCD_PORT_INTERFACE
00043 
00044     //TODO: make setup of chip select lines contingent on how
00045     // many controllers are actually in the display
00046     
00047     // initialize LCD control lines levels
00048     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
00049     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00050     cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00051     cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0);
00052     cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1);
00053     cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2);
00054     cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3);
00055     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
00056     // initialize LCD control port to output
00057     sbi(GLCD_CTRL_DDR, GLCD_CTRL_RS);
00058     sbi(GLCD_CTRL_DDR, GLCD_CTRL_RW);
00059     sbi(GLCD_CTRL_DDR, GLCD_CTRL_E);
00060     sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS0);
00061     sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS1);
00062     sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS2);
00063     sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS3);
00064     sbi(GLCD_CTRL_DDR, GLCD_CTRL_RESET);
00065     // initialize LCD data
00066     outb(GLCD_DATA_PORT, 0x00);
00067     // initialize LCD data port to output
00068     outb(GLCD_DATA_DDR, 0xFF);
00069 #endif
00070 }
00071 
00072 void glcdControllerSelect(u08 controller)
00073 {
00074 #ifdef GLCD_PORT_INTERFACE
00075     //TODO: make control of chip select lines contingent on how
00076     // many controllers are actually in the display
00077 
00078     // unselect all controllers
00079     cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0);
00080     cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1);
00081     cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2);
00082     cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3);
00083 
00084     // select requested controller
00085     switch(controller)
00086     {
00087     case 0: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0); break;
00088     case 1: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1); break;
00089     case 2: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2); break;
00090     case 3: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3); break;
00091     default: break;
00092     }
00093 #endif
00094 }
00095 
00096 void glcdBusyWait(u08 controller)
00097 {
00098 #ifdef GLCD_PORT_INTERFACE
00099     cli();
00100     // wait until LCD busy bit goes to zero
00101     // select the controller chip
00102     glcdControllerSelect(controller);
00103     // do a read from control register
00104     outb(GLCD_DATA_PORT, 0xFF);
00105     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
00106     outb(GLCD_DATA_DDR, 0x00);
00107     sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00108     sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00109     asm volatile ("nop"); asm volatile ("nop");
00110     while(inb(GLCD_DATA_PIN) & GLCD_STATUS_BUSY)
00111     {
00112         cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00113         asm volatile ("nop"); asm volatile ("nop");
00114         asm volatile ("nop"); asm volatile ("nop");
00115         sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00116         asm volatile ("nop"); asm volatile ("nop");
00117         asm volatile ("nop"); asm volatile ("nop");
00118     }
00119     cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00120     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00121     outb(GLCD_DATA_DDR, 0xFF);
00122     sei();
00123 #else
00124     // sbi(MCUCR, SRW);         // enable RAM waitstate
00125     // wait until LCD busy bit goes to zero
00126     while(*(volatile unsigned char *)
00127         (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) & GLCD_STATUS_BUSY);
00128     // cbi(MCUCR, SRW);         // disable RAM waitstate
00129 #endif
00130 }
00131 
00132 void glcdControlWrite(u08 controller, u08 data)
00133 {
00134 #ifdef GLCD_PORT_INTERFACE
00135     cli();
00136     glcdBusyWait(controller);   // wait until LCD not busy
00137     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
00138     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00139     sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00140     outb(GLCD_DATA_DDR, 0xFF);
00141     outb(GLCD_DATA_PORT, data);
00142     asm volatile ("nop"); asm volatile ("nop");
00143     asm volatile ("nop"); asm volatile ("nop");
00144     asm volatile ("nop"); asm volatile ("nop");
00145     asm volatile ("nop"); asm volatile ("nop");
00146     cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00147     sei();
00148 #else
00149     //sbi(MCUCR, SRW);              // enable RAM waitstate
00150     glcdBusyWait(controller);       // wait until LCD not busy
00151     *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) = data;
00152     //cbi(MCUCR, SRW);              // disable RAM waitstate
00153 #endif
00154 }
00155 
00156 u08 glcdControlRead(u08 controller)
00157 {
00158     register u08 data;
00159 #ifdef GLCD_PORT_INTERFACE
00160     cli();
00161     glcdBusyWait(controller);       // wait until LCD not busy
00162     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
00163     outb(GLCD_DATA_DDR, 0x00);
00164     sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00165     sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00166     asm volatile ("nop"); asm volatile ("nop");
00167     asm volatile ("nop"); asm volatile ("nop");
00168     asm volatile ("nop"); asm volatile ("nop");
00169     asm volatile ("nop"); asm volatile ("nop");
00170     data = inb(GLCD_DATA_PIN);
00171     cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00172     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00173     outb(GLCD_DATA_DDR, 0xFF);
00174     sei();
00175 #else
00176     //sbi(MCUCR, SRW);              // enable RAM waitstate
00177     glcdBusyWait(controller);       // wait until LCD not busy
00178     data = *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller);
00179     //cbi(MCUCR, SRW);              // disable RAM waitstate
00180 #endif
00181     return data;
00182 }
00183 
00184 void glcdDataWrite(u08 data)
00185 {
00186     register u08 controller = (GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS);
00187 #ifdef GLCD_PORT_INTERFACE
00188     cli();
00189     glcdBusyWait(controller);       // wait until LCD not busy
00190     sbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
00191     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00192     sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00193     outb(GLCD_DATA_DDR, 0xFF);
00194     outb(GLCD_DATA_PORT, data);
00195     asm volatile ("nop"); asm volatile ("nop");
00196     asm volatile ("nop"); asm volatile ("nop");
00197     asm volatile ("nop"); asm volatile ("nop");
00198     asm volatile ("nop"); asm volatile ("nop");
00199     cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00200     sei();
00201 #else
00202     //sbi(MCUCR, SRW);              // enable RAM waitstate
00203     glcdBusyWait(controller);       // wait until LCD not busy
00204     *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) = data;
00205     //cbi(MCUCR, SRW);              // disable RAM waitstate
00206 #endif
00207     // increment our local address counter
00208     GrLcdState.ctrlr[controller].xAddr++;
00209     GrLcdState.lcdXAddr++;
00210     if(GrLcdState.lcdXAddr >= GLCD_XPIXELS)
00211     {
00212         GrLcdState.lcdYAddr++;
00213         glcdSetYAddress(GrLcdState.lcdYAddr);
00214         glcdSetXAddress(0);
00215     }
00216 }
00217 
00218 u08 glcdDataRead(void)
00219 {
00220     register u08 data;
00221     register u08 controller = (GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS);
00222 #ifdef GLCD_PORT_INTERFACE
00223     cli();
00224     glcdBusyWait(controller);       // wait until LCD not busy
00225     sbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
00226     outb(GLCD_DATA_DDR, 0x00);
00227     sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00228     sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00229     asm volatile ("nop"); asm volatile ("nop");
00230     asm volatile ("nop"); asm volatile ("nop");
00231     asm volatile ("nop"); asm volatile ("nop");
00232     asm volatile ("nop"); asm volatile ("nop");
00233     data = inb(GLCD_DATA_PIN);
00234     cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
00235     cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
00236     sei();
00237 #else
00238     //sbi(MCUCR, SRW);              // enable RAM waitstate
00239     glcdBusyWait(controller);       // wait until LCD not busy
00240     data = *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller);
00241     //cbi(MCUCR, SRW);              // disable RAM waitstate
00242 #endif
00243     // increment our local address counter
00244     GrLcdState.ctrlr[controller].xAddr++;
00245     GrLcdState.lcdXAddr++;
00246     if(GrLcdState.lcdXAddr >= GLCD_XPIXELS)
00247     {
00248         GrLcdState.lcdYAddr++;
00249         glcdSetYAddress(GrLcdState.lcdYAddr);
00250         glcdSetXAddress(0);
00251     }
00252     return data;
00253 }
00254 
00255 void glcdReset(u08 resetState)
00256 {
00257     // reset lcd if argument is true
00258     // run lcd if argument is false
00259 #ifdef GLCD_PORT_INTERFACE
00260     if(resetState)
00261         cbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
00262     else
00263         sbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
00264 #endif
00265 }
00266 
00267 void glcdSetXAddress(u08 xAddr)
00268 {
00269     u08 i;
00270     // record address change locally
00271     GrLcdState.lcdXAddr = xAddr;
00272     
00273     // clear y (col) address on all controllers
00274     for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
00275     {
00276         glcdControlWrite(i, GLCD_SET_Y_ADDR | 0x00);
00277         GrLcdState.ctrlr[i].xAddr = 0;
00278     }
00279 
00280     // set y (col) address on destination controller
00281     glcdControlWrite((GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS),
00282         GLCD_SET_Y_ADDR | (GrLcdState.lcdXAddr & 0x3F));
00283 }
00284 
00285 void glcdSetYAddress(u08 yAddr)
00286 {
00287     u08 i;
00288     // record address change locally
00289     GrLcdState.lcdYAddr = yAddr;
00290     // set page address for all controllers
00291     for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
00292     {
00293         glcdControlWrite(i, GLCD_SET_PAGE | yAddr);
00294     }
00295 }
00296 
00297 /*************************************************************/
00298 /********************* PUBLIC FUNCTIONS **********************/
00299 /*************************************************************/
00300 
00301 void glcdInit()
00302 {
00303     u08 i;
00304     // initialize hardware
00305     glcdInitHW();
00306     // bring lcd out of reset
00307     glcdReset(FALSE);
00308     // Turn on LCD
00309     for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
00310     {
00311         glcdControlWrite(i, GLCD_ON_CTRL | GLCD_ON_DISPLAY);
00312     }
00313     // clear lcd
00314     glcdClearScreen();
00315     // initialize positions
00316     glcdHome();
00317 }
00318 
00319 void glcdHome(void)
00320 {
00321     u08 i;
00322     // initialize addresses/positions
00323     glcdStartLine(0);
00324     glcdSetAddress(0,0);
00325     // initialize local data structures
00326     for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
00327     {
00328         GrLcdState.ctrlr[i].xAddr = 0;
00329         GrLcdState.ctrlr[i].yAddr = 0;
00330     }
00331 }
00332 
00333 void glcdClearScreen(void)
00334 {
00335     u08 pageAddr;
00336     u08 xAddr;
00337 
00338     // clear LCD
00339     // loop through all pages
00340     for(pageAddr=0; pageAddr<(GLCD_YPIXELS>>3); pageAddr++)
00341     {
00342         // set page address
00343         glcdSetAddress(0, pageAddr);
00344         // clear all lines of this page of display memory
00345         for(xAddr=0; xAddr<GLCD_XPIXELS; xAddr++)
00346         {
00347             glcdDataWrite(0x00);
00348         }
00349     }
00350 }
00351 
00352 void glcdStartLine(u08 start)
00353 {
00354     glcdControlWrite(0, GLCD_START_LINE | start);
00355     glcdControlWrite(1, GLCD_START_LINE | start);
00356 }
00357 
00358 void glcdSetAddress(u08 x, u08 yLine)
00359 {
00360     // set addresses
00361     glcdSetYAddress(yLine);
00362     glcdSetXAddress(x);
00363 }
00364 
00365 void glcdGotoChar(u08 line, u08 col)
00366 {
00367     glcdSetAddress(col*6, line);
00368 }
00369 
00370 void glcdDelay(u16 p)           // 1-8us      ...2-13us     ...5-31us
00371 {                               // 10-60us    ...50-290us
00372     unsigned int i;             // 100-580us  ...500-2,9ms
00373     unsigned char j;            // 1000-5,8ms ...5000-29ms
00374                                 // 10000-56ms ...30000-170ms
00375                                 // 50000-295ms...60000-345ms
00376 //  for (i = 0; i < p; i++) for (j = 0; j < 10; j++) asm volatile ("nop");
00377     for (i = 0; i < p; i++) for (j = 0; j < 10; j++);
00378 }
00379 
00380 
00381 // Higher level functionality has been moved to the API-layer glcd.c/glcd.h

Generated on Sun Oct 29 03:41:07 2006 for Procyon AVRlib by  doxygen 1.4.2