/*! \file lcd.c \brief Character LCD driver for HD44780/SED1278 displays. */ //***************************************************************************** // // File Name : 'lcd.c' // Title : Character LCD driver for HD44780/SED1278 displays // (usable in mem-mapped, or I/O mode) // Author : Pascal Stang // Created : 11/22/2000 // Revised : 4/30/2002 // Version : 1.1 // Target MCU : Atmel AVR series // Editor Tabs : 4 // // This code is distributed under the GNU Public License // which can be found at http://www.gnu.org/licenses/gpl.txt // //***************************************************************************** #include #include #include "global.h" #include "timer.h" #include "lcd.h" // custom LCD characters unsigned char __attribute__ ((progmem)) LcdCustomChar[] = { 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, // 0. 0/5 full progress block 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, // 1. 1/5 full progress block 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, // 2. 2/5 full progress block 0x00, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x00, // 3. 3/5 full progress block 0x00, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x00, // 4. 4/5 full progress block 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 5. 5/5 full progress block 0x03, 0x07, 0x0F, 0x1F, 0x0F, 0x07, 0x03, 0x00, // 6. rewind arrow 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 7. stop block 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, // 8. pause bars 0x18, 0x1C, 0x1E, 0x1F, 0x1E, 0x1C, 0x18, 0x00, // 9. fast-forward arrow 0x00, 0x04, 0x04, 0x0E, 0x0E, 0x1F, 0x1F, 0x00, // 10. scroll up arrow 0x00, 0x1F, 0x1F, 0x0E, 0x0E, 0x04, 0x04, 0x00, // 11. scroll down arrow 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 12. blank character 0x00, 0x0E, 0x19, 0x15, 0x13, 0x0E, 0x00, 0x00, // 13. animated play icon frame 0 0x00, 0x0E, 0x15, 0x15, 0x15, 0x0E, 0x00, 0x00, // 14. animated play icon frame 1 0x00, 0x0E, 0x13, 0x15, 0x19, 0x0E, 0x00, 0x00, // 15. animated play icon frame 2 0x00, 0x0E, 0x11, 0x1F, 0x11, 0x0E, 0x00, 0x00, // 16. animated play icon frame 3 }; /*************************************************************/ /********************** LOCAL FUNCTIONS **********************/ /*************************************************************/ void lcdInitHW(void) { // initialize I/O ports // if I/O interface is in use #ifdef LCD_PORT_INTERFACE // initialize LCD control lines cbi(LCD_CTRL_PORT, LCD_CTRL_RS); cbi(LCD_CTRL_PORT, LCD_CTRL_RW); cbi(LCD_CTRL_PORT, LCD_CTRL_E); // initialize LCD control lines to output sbi(LCD_CTRL_DDR, LCD_CTRL_RS); sbi(LCD_CTRL_DDR, LCD_CTRL_RW); sbi(LCD_CTRL_DDR, LCD_CTRL_E); // initialize LCD data port to input // initialize LCD data lines to pull-up #ifdef LCD_DATA_4BIT outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit) outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit) #else outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit) outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit) #endif #else // enable external memory bus if not already enabled sbi(MCUCR, SRE); // enable bus interface #endif } void lcdBusyWait(void) { // wait until LCD busy bit goes to zero // do a read from control register #ifdef LCD_PORT_INTERFACE cbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control" #ifdef LCD_DATA_4BIT outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit) outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit) #else outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit) outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit) #endif sbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read" sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line LCD_DELAY; // wait while(inb(LCD_DATA_PIN) & 1<>4; // input data, low 4 bits cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line #else // 8 bit read sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line LCD_DELAY; // wait LCD_DELAY; // wait data = inb(LCD_DATA_PIN); // input data, 8bits cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line #endif // leave data lines in input mode so they can be most easily used for other purposes #else //sbi(MCUCR, SRW); // enable RAM waitstate lcdBusyWait(); // wait until LCD not busy data = *((volatile unsigned char *) (LCD_CTRL_ADDR)); //cbi(MCUCR, SRW); // disable RAM waitstate #endif return data; } void lcdDataWrite(u08 data) { // write a data byte to the display #ifdef LCD_PORT_INTERFACE lcdBusyWait(); // wait until LCD not busy sbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "data" cbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "write" #ifdef LCD_DATA_4BIT // 4 bit write sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)|0xF0); // set data I/O lines to output (4bit) outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data&0xF0) ); // output data, high 4 bits LCD_DELAY; // wait LCD_DELAY; // wait cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line LCD_DELAY; // wait LCD_DELAY; // wait sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data<<4) ); // output data, low 4 bits LCD_DELAY; // wait LCD_DELAY; // wait cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line #else // 8 bit write sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line outb(LCD_DATA_DDR, 0xFF); // set data I/O lines to output (8bit) outb(LCD_DATA_POUT, data); // output data, 8bits LCD_DELAY; // wait LCD_DELAY; // wait cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line #endif // leave data lines in input mode so they can be most easily used for other purposes #ifdef LCD_DATA_4BIT outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit) outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit) #else outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit) outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit) #endif #else // memory bus write //sbi(MCUCR, SRW); // enable RAM waitstate lcdBusyWait(); // wait until LCD not busy *((volatile unsigned char *) (LCD_DATA_ADDR)) = data; //cbi(MCUCR, SRW); // disable RAM waitstate #endif } u08 lcdDataRead(void) { // read a data byte from the display register u08 data; #ifdef LCD_PORT_INTERFACE lcdBusyWait(); // wait until LCD not busy #ifdef LCD_DATA_4BIT outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit) outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit) #else outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit) outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit) #endif sbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "data" sbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read" #ifdef LCD_DATA_4BIT // 4 bit read sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line LCD_DELAY; // wait LCD_DELAY; // wait data = inb(LCD_DATA_PIN)&0xF0; // input data, high 4 bits cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line LCD_DELAY; // wait LCD_DELAY; // wait sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line LCD_DELAY; // wait LCD_DELAY; // wait data |= inb(LCD_DATA_PIN)>>4; // input data, low 4 bits cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line #else // 8 bit read sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line LCD_DELAY; // wait LCD_DELAY; // wait data = inb(LCD_DATA_PIN); // input data, 8bits cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line #endif // leave data lines in input mode so they can be most easily used for other purposes #else // memory bus read //sbi(MCUCR, SRW); // enable RAM waitstate lcdBusyWait(); // wait until LCD not busy data = *((volatile unsigned char *) (LCD_DATA_ADDR)); //cbi(MCUCR, SRW); // disable RAM waitstate #endif return data; } /*************************************************************/ /********************* PUBLIC FUNCTIONS **********************/ /*************************************************************/ void lcdInit() { // initialize hardware lcdInitHW(); // LCD function set lcdControlWrite(LCD_FUNCTION_DEFAULT); // clear LCD lcdControlWrite(1< pixelprogress ) { // this is a partial or empty block if( ((i*(u16)PROGRESSPIXELS_PER_CHAR)) > pixelprogress ) { // this is an empty block // use space character? c = 0; } else { // this is a partial block c = pixelprogress % PROGRESSPIXELS_PER_CHAR; } } else { // this is a full block c = 5; } // write character to display lcdDataWrite(c); } }