?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 6

?prevdifflink? - Blame - ?getfile?

/*! \file ks0108.c \brief Graphic LCD driver for HD61202/KS0108 displays. */
//*****************************************************************************
//
// File Name    : 'ks0108.c'
// Title                : Graphic LCD driver for HD61202/KS0108 displays
// Author               : Pascal Stang - Copyright (C) 2001-2003
// Date                 : 10/19/2002
// Revised              : 5/5/2003
// Version              : 0.5
// Target MCU   : Atmel AVR
// Editor Tabs  : 4
//
// NOTE: This code is currently below version 1.0, and therefore is considered
// to be lacking in some functionality or documentation, or may not be fully
// tested.  Nonetheless, you can expect most functions to work.
//
// This code is distributed under the GNU Public License
//              which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************

#ifndef WIN32
// AVR specific includes
        #include <avr/io.h>
        #include <avr/interrupt.h>
#endif

#include "global.h"
#include "ks0108.h"

// global variables
GrLcdStateType GrLcdState;

/*************************************************************/
/********************** LOCAL FUNCTIONS **********************/
/*************************************************************/

void glcdInitHW(void)
{
        // initialize I/O ports
        // if I/O interface is in use
#ifdef GLCD_PORT_INTERFACE

        //TODO: make setup of chip select lines contingent on how
        // many controllers are actually in the display
        
        // initialize LCD control lines levels
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
        // initialize LCD control port to output
        sbi(GLCD_CTRL_DDR, GLCD_CTRL_RS);
        sbi(GLCD_CTRL_DDR, GLCD_CTRL_RW);
        sbi(GLCD_CTRL_DDR, GLCD_CTRL_E);
        sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS0);
        sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS1);
        sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS2);
        sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS3);
        sbi(GLCD_CTRL_DDR, GLCD_CTRL_RESET);
        // initialize LCD data
        outb(GLCD_DATA_PORT, 0x00);
        // initialize LCD data port to output
        outb(GLCD_DATA_DDR, 0xFF);
#endif
}

void glcdControllerSelect(u08 controller)
{
#ifdef GLCD_PORT_INTERFACE
        //TODO: make control of chip select lines contingent on how
        // many controllers are actually in the display

        // unselect all controllers
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3);

        // select requested controller
        switch(controller)
        {
        case 0: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0); break;
        case 1: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1); break;
        case 2: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2); break;
        case 3: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3); break;
        default: break;
        }
#endif
}

void glcdBusyWait(u08 controller)
{
#ifdef GLCD_PORT_INTERFACE
        cli();
        // wait until LCD busy bit goes to zero
        // select the controller chip
        glcdControllerSelect(controller);
        // do a read from control register
        outb(GLCD_DATA_PORT, 0xFF);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
        outb(GLCD_DATA_DDR, 0x00);
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        asm volatile ("nop"); asm volatile ("nop");
        while(inb(GLCD_DATA_PIN) & GLCD_STATUS_BUSY)
        {
                cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
                asm volatile ("nop"); asm volatile ("nop");
                asm volatile ("nop"); asm volatile ("nop");
                sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
                asm volatile ("nop"); asm volatile ("nop");
                asm volatile ("nop"); asm volatile ("nop");
        }
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        outb(GLCD_DATA_DDR, 0xFF);
        sei();
#else
        // sbi(MCUCR, SRW);                     // enable RAM waitstate
        // wait until LCD busy bit goes to zero
        while(*(volatile unsigned char *)
                (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) & GLCD_STATUS_BUSY);
        // cbi(MCUCR, SRW);                     // disable RAM waitstate
#endif
}

void glcdControlWrite(u08 controller, u08 data)
{
#ifdef GLCD_PORT_INTERFACE
        cli();
        glcdBusyWait(controller);       // wait until LCD not busy
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        outb(GLCD_DATA_DDR, 0xFF);
        outb(GLCD_DATA_PORT, data);
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        sei();
#else
        //sbi(MCUCR, SRW);                              // enable RAM waitstate
        glcdBusyWait(controller);               // wait until LCD not busy
        *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) = data;
        //cbi(MCUCR, SRW);                              // disable RAM waitstate
#endif
}

u08 glcdControlRead(u08 controller)
{
        register u08 data;
#ifdef GLCD_PORT_INTERFACE
        cli();
        glcdBusyWait(controller);               // wait until LCD not busy
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
        outb(GLCD_DATA_DDR, 0x00);
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        data = inb(GLCD_DATA_PIN);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        outb(GLCD_DATA_DDR, 0xFF);
        sei();
#else
        //sbi(MCUCR, SRW);                              // enable RAM waitstate
        glcdBusyWait(controller);               // wait until LCD not busy
        data = *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller);
        //cbi(MCUCR, SRW);                              // disable RAM waitstate
#endif
        return data;
}

void glcdDataWrite(u08 data)
{
        register u08 controller = (GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS);
#ifdef GLCD_PORT_INTERFACE
        cli();
        glcdBusyWait(controller);               // wait until LCD not busy
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        outb(GLCD_DATA_DDR, 0xFF);
        outb(GLCD_DATA_PORT, data);
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        sei();
#else
        //sbi(MCUCR, SRW);                              // enable RAM waitstate
        glcdBusyWait(controller);               // wait until LCD not busy
        *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) = data;
        //cbi(MCUCR, SRW);                              // disable RAM waitstate
#endif
        // increment our local address counter
        GrLcdState.ctrlr[controller].xAddr++;
        GrLcdState.lcdXAddr++;
        if(GrLcdState.lcdXAddr >= GLCD_XPIXELS)
        {
                GrLcdState.lcdYAddr++;
                glcdSetYAddress(GrLcdState.lcdYAddr);
                glcdSetXAddress(0);
        }
}

u08 glcdDataRead(void)
{
        register u08 data;
        register u08 controller = (GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS);
#ifdef GLCD_PORT_INTERFACE
        cli();
        glcdBusyWait(controller);               // wait until LCD not busy
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
        outb(GLCD_DATA_DDR, 0x00);
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        asm volatile ("nop"); asm volatile ("nop");
        data = inb(GLCD_DATA_PIN);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
        cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
        sei();
#else
        //sbi(MCUCR, SRW);                              // enable RAM waitstate
        glcdBusyWait(controller);               // wait until LCD not busy
        data = *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller);
        //cbi(MCUCR, SRW);                              // disable RAM waitstate
#endif
        // increment our local address counter
        GrLcdState.ctrlr[controller].xAddr++;
        GrLcdState.lcdXAddr++;
        if(GrLcdState.lcdXAddr >= GLCD_XPIXELS)
        {
                GrLcdState.lcdYAddr++;
                glcdSetYAddress(GrLcdState.lcdYAddr);
                glcdSetXAddress(0);
        }
        return data;
}

void glcdReset(u08 resetState)
{
        // reset lcd if argument is true
        // run lcd if argument is false
#ifdef GLCD_PORT_INTERFACE
        if(resetState)
                cbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
        else
                sbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
#endif
}

void glcdSetXAddress(u08 xAddr)
{
        u08 i;
        // record address change locally
        GrLcdState.lcdXAddr = xAddr;
        
        // clear y (col) address on all controllers
        for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
        {
                glcdControlWrite(i, GLCD_SET_Y_ADDR | 0x00);
                GrLcdState.ctrlr[i].xAddr = 0;
        }

        // set y (col) address on destination controller
        glcdControlWrite((GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS),
                GLCD_SET_Y_ADDR | (GrLcdState.lcdXAddr & 0x3F));
}

void glcdSetYAddress(u08 yAddr)
{
        u08 i;
        // record address change locally
        GrLcdState.lcdYAddr = yAddr;
        // set page address for all controllers
        for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
        {
                glcdControlWrite(i, GLCD_SET_PAGE | yAddr);
        }
}

/*************************************************************/
/********************* PUBLIC FUNCTIONS **********************/
/*************************************************************/

void glcdInit()
{
        u08 i;
        // initialize hardware
        glcdInitHW();
        // bring lcd out of reset
        glcdReset(FALSE);
        // Turn on LCD
        for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
        {
                glcdControlWrite(i, GLCD_ON_CTRL | GLCD_ON_DISPLAY);
        }
        // clear lcd
        glcdClearScreen();
        // initialize positions
        glcdHome();
}

void glcdHome(void)
{
        u08 i;
        // initialize addresses/positions
        glcdStartLine(0);
        glcdSetAddress(0,0);
        // initialize local data structures
        for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
        {
                GrLcdState.ctrlr[i].xAddr = 0;
                GrLcdState.ctrlr[i].yAddr = 0;
        }
}

void glcdClearScreen(void)
{
        u08 pageAddr;
        u08 xAddr;

        // clear LCD
        // loop through all pages
        for(pageAddr=0; pageAddr<(GLCD_YPIXELS>>3); pageAddr++)
        {
                // set page address
                glcdSetAddress(0, pageAddr);
                // clear all lines of this page of display memory
                for(xAddr=0; xAddr<GLCD_XPIXELS; xAddr++)
                {
                        glcdDataWrite(0x00);
                }
        }
}

void glcdStartLine(u08 start)
{
        glcdControlWrite(0, GLCD_START_LINE | start);
        glcdControlWrite(1, GLCD_START_LINE | start);
}

void glcdSetAddress(u08 x, u08 yLine)
{
        // set addresses
        glcdSetYAddress(yLine);
        glcdSetXAddress(x);
}

void glcdGotoChar(u08 line, u08 col)
{
        glcdSetAddress(col*6, line);
}

void glcdDelay(u16 p)                   // 1-8us      ...2-13us     ...5-31us
{                                                               // 10-60us    ...50-290us
        unsigned int i;                         // 100-580us  ...500-2,9ms
        unsigned char j;                        // 1000-5,8ms ...5000-29ms
                                                                // 10000-56ms ...30000-170ms
                                                                // 50000-295ms...60000-345ms
//      for (i = 0; i < p; i++) for (j = 0; j < 10; j++) asm volatile ("nop");
        for (i = 0; i < p; i++) for (j = 0; j < 10; j++);
}


// Higher level functionality has been moved to the API-layer glcd.c/glcd.h
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3