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