
#include <mega8.h>
#include <delay.h>    

/*
LCD data port is PORTC
PORTC.0 -> DB4	LSB
PORTC.1 -> DB5
PORTC.2 -> DB6
PORTC.3 -> DB7	MSB

LCD control port is PORTB
RS - PORTB.5
RW - GND
E - PORTB.3
*/
// Declare your global variables here
void setRS(void)
{                                          
	PORTB.5 = 1;
	delay_us(3);
	PORTB.5 = 0;
}

void clrRS(void)
{
	PORTB.5 = 0;
}
void toggleEN(void)
{
	PORTB.3 = 1;
	delay_us(1);
	PORTB.3 = 0;
}
void lcd_out_low(unsigned char d)
{
	// Outputs low nibble
	if(d&0x01) PORTC.0 = 1; else PORTC.0 = 0;
	if(d&0x02) PORTC.1 = 1; else PORTC.1 = 0; 
	if(d&0x04) PORTC.2 = 1; else PORTC.2 = 0;
	if(d&0x08) PORTC.3 = 1; else PORTC.3 = 0;
}

void lcd_out_high(unsigned char d)
{
	// Outputs high nibble
	if(d&0x10) PORTC.0 = 1; else PORTC.0 = 0;
	if(d&0x20) PORTC.1 = 1; else PORTC.1 = 0;
	if(d&0x40) PORTC.2 = 1; else PORTC.2 = 0;
	if(d&0x80) PORTC.3 = 1; else PORTC.3 = 0;
}
void lcd_write(unsigned char data, unsigned char rs)
{
	// Sends data or command to the LCD
	
	if(rs) setRS();		// RS=1: data mode
	else clrRS();		// RS=0: instruction mode

	/* output high nibble first */	
	toggleEN();
	lcd_out_high(data);	// send high nibble		
	
	if(rs) setRS();		// RS=1: data mode
	else clrRS();		// RS=0: instruction mode
	
	/* output low nibble */
	toggleEN();
	lcd_out_low(data);	// send low nibble
}

void lcd_init(void)
{   
	clrRS();		//Set instruction mode
	toggleEN();
	lcd_out_high(0x30);	//Initially 8-bit mode
	delay_us(45);
	clrRS();
	toggleEN();
	lcd_out_high(0x30);
	delay_us(100);
	clrRS();
	toggleEN();
	lcd_out_high(0x30);
	delay_us(100);
	clrRS();
	toggleEN();
	lcd_out_high(0x20);	// set 4-bit mode
	delay_us(45);
	clrRS();
	toggleEN();
	lcd_out_high(0x28);	//set mode to 4-bit 2 lines 5*7 dots
	toggleEN();

	/* from now the lcd only accepts 4 bit I/O */
} 

void lcd_putchar(char ch)
{
	// prints character at current cursor position
	setRS();
	lcd_write((unsigned char)ch, 1);
}
void main(void)
{
PORTC=0x00;
DDRC=0xFF;

PORTB=0x00;
DDRB=0xFF;

lcd_init();
while (1)
      {
      lcd_putchar('A');
      delay_ms(100);
      };
}
