#include <avr/io.h>
#include <util/delay.h>

#define	LCDBUS_PORT	PORTA
#define	LCDBUS_DDR	DDRA

#define USART_BAUDRATE 4800
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

//B.0 - used for LCD RS
//B.1 - used for LCD R/W
//B.2 - used for LCD EN
	
//#define	ZERO       0x77 
//#define	ONE        0x41

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif

#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

unsigned char LCD_msg1[]="Welcome to AVR1234Hello World567";
unsigned char LCD_msg2[]="This is my firstLCD program12345";

void init_ports(void);
void LCD_init(void);
void LCD_cmd(void);
void LCD_data(void);
void display_msg1(void);
void display_msg2(void);

void init_serial(void);
void serial_msg1(void);
void serial_msg2(void);


int main(void)
{	
	init_ports();			//initialize all ports		
	LCD_init();				// LCD initialization routines
	
	init_serial();
	
	int one = 1;
	int two = 2;
	int three = 3;
	int a;
	int b;
	int c;
	
	while(1)
	{
		display_msg1();
		serial_msg1();
		_delay_ms(2000);
		_delay_ms(2000);
		_delay_ms(2000);
		_delay_ms(2000);
		
		a = 48 + one;
		b = 48 + two;
		c = 48 + three;
		
		LCDBUS_PORT = 0xcd;
		LCD_cmd();
		LCDBUS_PORT = a;
		LCD_data();
		
		LCDBUS_PORT = 0xce;
		LCD_cmd();
		LCDBUS_PORT = b;
		LCD_data();
		
		LCDBUS_PORT = 0xcf;
		LCD_cmd();
		LCDBUS_PORT = c;
		LCD_data();
		
		_delay_ms(2000);
		_delay_ms(2000);
		_delay_ms(2000);
		_delay_ms(2000);
		
		
		display_msg2();
		serial_msg2();
		_delay_ms(2000);
		_delay_ms(2000);
		_delay_ms(2000);
		_delay_ms(2000);
		
	}
	return 0;
}

void init_ports(void)
{
	LCDBUS_DDR = 0xFF;
	
	sbi(DDRB,0);	//set B.0 as output - used for LCD RS
	sbi(DDRB,1);	//set B.1 as output - used for LCD R/W
	sbi(DDRB,2);	//set B.2 as output - used for LCD EN

}

void LCD_init(void)
{
	LCDBUS_PORT = 0x38;
	LCD_cmd();
	LCDBUS_PORT = 0x38;
	LCD_cmd();
	LCDBUS_PORT = 0x38;
	LCD_cmd();
	LCDBUS_PORT = 0x38;
	LCD_cmd();
	LCDBUS_PORT = 0x0c;
	LCD_cmd();
	LCDBUS_PORT = 0x01;
	LCD_cmd();
	LCDBUS_PORT = 0x06;
	LCD_cmd();
	return;				// not sure weather to use this or not
}

void LCD_cmd(void)
{
	cbi(PORTB,0);	//clear B.0 - used for LCD RS
	cbi(PORTB,1);	//clear B.1 - used for LCD R/W
	sbi(PORTB,2);	//set B.2 - used for LCD EN
	_delay_us(5);
	cbi(PORTB,2);	//clear B.2 - used for LCD EN
	_delay_ms(5);
	return;				// not sure weather to use this or not
}

void LCD_data(void)
{
	sbi(PORTB,0);	//clear B.0 - used for LCD RS
	cbi(PORTB,1);	//clear B.1 - used for LCD R/W
	sbi(PORTB,2);	//set B.2 - used for LCD EN
	_delay_us(5);
	cbi(PORTB,2);	//clear B.2 - used for LCD EN
	_delay_ms(5);
	return;				// not sure weather to use this or not
}

void display_msg1(void)
{
	int char_count;
	LCDBUS_PORT = 0x01;
	LCD_cmd();	
	for(char_count=0;char_count<16;char_count++)
	{		
		LCDBUS_PORT = LCD_msg1[char_count];
		LCD_data();
	}

	LCDBUS_PORT = 0xc0;
	LCD_cmd();
	
	for(char_count=16;char_count<32;char_count++)
	{			
		LCDBUS_PORT = LCD_msg1[char_count];
		LCD_data();
	}
}


void display_msg2(void)
{
	int char_count;
	LCDBUS_PORT = 0x01;
	LCD_cmd();	
	for(char_count=0;char_count<16;char_count++)
	{		
		LCDBUS_PORT = LCD_msg2[char_count];
		LCD_data();
	}

	LCDBUS_PORT = 0xc0;
	LCD_cmd();
	
	for(char_count=16;char_count<32;char_count++)
	{			
		LCDBUS_PORT = LCD_msg2[char_count];
		LCD_data();
	}
}


void init_serial(void)
{
	UCSRB |= (1 << RXEN) | (1 << TXEN);
	
	UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
	
	UBRRL = BAUD_PRESCALE;
	
	UBRRH = (BAUD_PRESCALE >> 8);
	
	UCSRC = UCSRC & 0b11110111;			//stop bit

}

void serial_msg1(void)
{
	while((UCSRA & (1 << UDRE)) == 0) {};
	UDR = 10;
	
	while((UCSRA & (1 << UDRE)) == 0) {};
	UDR = 13;
	
	int i;
	
	for(i = 0 ; i <= 32 ; i++)
	{
		while((UCSRA & (1 << UDRE)) == 0) {};
		
		UDR = LCD_msg1[i];
		
		PORTA = i;
		_delay_ms(200);	
		
	}

}

void serial_msg2(void)
{
	while((UCSRA & (1 << UDRE)) == 0) {};
	UDR = 10;
	
	while((UCSRA & (1 << UDRE)) == 0) {};
	UDR = 13;
	
	int i;
	
	for(i = 0 ; i <= 32 ; i++)
	{
		while((UCSRA & (1 << UDRE)) == 0) {};
		
		UDR = LCD_msg2[i];
		
		PORTA = i;
		_delay_ms(200);	
		
	}

}






