/*! \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 <avr/pgmspace.h>
#include "lcd.h"
#include "util/delay.h"
//#include <intrinsics.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
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_RS);
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_RW);
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_E);
// initialize LCD control lines to output
SET_BIT(LCD_CTRL_DDR, LCD_CTRL_RS);
SET_BIT(LCD_CTRL_DDR, LCD_CTRL_RW);
SET_BIT(LCD_CTRL_DDR, LCD_CTRL_E);
// initialize LCD data port to input
// initialize LCD data lines to pull-up
#ifdef LCD_DATA_4BIT
LCD_DATA_DDR=LCD_DATA_DDR & 0x0F; // set data I/O lines to input (4bit)
LCD_DATA_POUT=LCD_DATA_POUT |0xF0; // set pull-ups to on (4bit)
#else
LCD_DATA_DDR = 0x00; // set data I/O lines to input (8bit)
LCD_DATA_POUT= 0xFF; // set pull-ups to on (8bit)
#endif
#else
// enable external memory bus if not already enabled
SET_BIT(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
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
#ifdef LCD_DATA_4BIT
LCD_DATA_DDR = LCD_DATA_DDR & 0x0F; // set data I/O lines to input (4bit)
LCD_DATA_POUT = LCD_DATA_POUT | 0xF0; // set pull-ups to on (4bit)
#else
LCD_DATA_DDR = 0x00; // set data I/O lines to input (8bit)
LCD_DATA_POUT = 0xFF; // set pull-ups to on (8bit)
#endif
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read"
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_E ); // set "E" line
LCD_DELAY; // wait
while( TEST_BIT(LCD_DATA_PIN,LCD_BUSY) )
{
TOGG_BIT(PORTB,0);//------------------
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
LCD_DELAY; // wait
LCD_DELAY; // wait
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
LCD_DELAY; // wait
LCD_DELAY; // wait
#ifdef LCD_DATA_4BIT // do an extra clock for 4 bit reads
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
LCD_DELAY; // wait
LCD_DELAY; // wait
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
LCD_DELAY; // wait
LCD_DELAY; // wait
#endif
}
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
// leave data lines in input mode so they can be most easily used for other purposes
#else
// memory bus read
// SET_BIT(MCUCR, SRW); // enable RAM waitstate
// wait until LCD busy bit goes to zero
// while( (*((volatile unsigned char *) (LCD_CTRL_ADDR))) & (1<<LCD_BUSY) );
// CLR_BIT(MCUCR, SRW); // disable RAM waitstate
#endif
}
void lcdControlWrite(u08 data)
{
// write the control byte to the display controller
#ifdef LCD_PORT_INTERFACE
lcdBusyWait(); // wait until LCD not busy
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "write"
#ifdef LCD_DATA_4BIT
// 4 bit write
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
LCD_DATA_DDR = ( LCD_DATA_DDR | 0xF0 ); // set data I/O lines to output (4bit)
LCD_DATA_POUT = ( (LCD_DATA_POUT & 0x0F) | (data&0xF0) ); // output data, high 4 bits
LCD_DELAY; // wait
LCD_DELAY; // wait
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
LCD_DELAY; // wait
LCD_DELAY; // wait
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
LCD_DATA_POUT= ( (LCD_DATA_POUT & 0x0F) | (data << 4) ); // output data, low 4 bits
LCD_DELAY; // wait
LCD_DELAY; // wait
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
#else
// 8 bit write
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
LCD_DATA_DDR= 0xFF; // set data I/O lines to output (8bit)
LCD_DATA_POUT= data; // output data, 8bits
LCD_DELAY; // wait
LCD_DELAY; // wait
CLR_BIT(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
LCD_DATA_DDR = (LCD_DATA_DDR & 0x0F); // set data I/O lines to input (4bit)
LCD_DATA_POUT= (LCD_DATA_POUT | 0xF0); // set pull-ups to on (4bit)
#else
LCD_DATA_DDR= 0x00; // set data I/O lines to input (8bit)
LCD_DATA_POUT= 0xFF; // set pull-ups to on (8bit)
#endif
#else
// memory bus write
//SET_BIT(MCUCR, SRW); // enable RAM waitstate
lcdBusyWait(); // wait until LCD not busy
*((volatile unsigned char *) (LCD_CTRL_ADDR)) = data;
//CLR_BIT(MCUCR, SRW); // disable RAM waitstate
#endif
}
u08 lcdControlRead(void)
{
// read the control byte from the display controller
register u08 data;
#ifdef LCD_PORT_INTERFACE
lcdBusyWait(); // wait until LCD not busy
#ifdef LCD_DATA_4BIT
LCD_DATA_DDR = LCD_DATA_DDR & 0x0F; // set data I/O lines to input (4bit)
LCD_DATA_POUT= LCD_DATA_POUT | 0xF0; // set pull-ups to on (4bit)
#else
LCD_DATA_DDR = 0x00 ; // set data I/O lines to input (8bit)
LCD_DATA_POUT= 0xFF ; // set pull-ups to on (8bit)
#endif
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read"
#ifdef LCD_DATA_4BIT
// 4 bit read
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
LCD_DELAY; // wait
LCD_DELAY; // wait
data = LCD_DATA_PIN & 0xF0; // input data, high 4 bits
CLR_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
LCD_DELAY; // wait
LCD_DELAY; // wait
SET_BIT(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
LCD_DELAY; // wait
LCD_DELAY;