#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 AVR  Hello World     ";


void init_ports(void);
void LCD_init(void);
void LCD_cmd(void);
void LCD_data(void);
void display_msg1(void);

void eeprom_write(int memory_wrt_addr, int mem_wrt_data);
int eeprom_read(int memory_read_addr);

int main(void)
{	
	init_ports();			//initialize all ports		
	LCD_init();				// LCD initialization routines
	
	display_msg1();
	
	int count;	
	int disp_count;
	
	
	/* ========== READ operation STARTs here ========== */
	while(EECR & (1<<EEWE));
	/*Set up address register*/
	EEAR = 01;
	/*Start eeprom read by writing EERE*/
	EECR |= (1<<EERE);
	/*Return data from data register*/
	count = EEDR;
	/* ========== READ operation ENDs here =========== */
	
	disp_count = count + 48;
	
	LCDBUS_PORT = 0xcd;
	LCD_cmd();
	
	LCDBUS_PORT = disp_count;
	LCD_data();

	
	while(1)
	{
		if(bit_is_clear(PINB,7))
		{
			_delay_ms(5);
			if(bit_is_clear(PINB,7))
			{
				count++;
				
				eeprom_write(01,count);		
				
				disp_count = eeprom_read(01);
				
				disp_count = disp_count + 48;
				
				LCDBUS_PORT = 0xcd;
				LCD_cmd();				
				LCDBUS_PORT = disp_count;
				LCD_data();
				
				while(bit_is_clear(PINB,7))
				{
				}
			}
		}
		
		
		if(bit_is_clear(PINB,6))
		{
			_delay_ms(5);
			if(bit_is_clear(PINB,6))
			{
				count--;
				disp_count = count + 48;
				
				LCDBUS_PORT = 0xcd;
				LCD_cmd();
				
				LCDBUS_PORT = disp_count;
				LCD_data();
				
				while(bit_is_clear(PINB,6))
				{
				}
			}
		}
	}
	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
	cbi(DDRB,7);
	cbi(DDRB,6);

}

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 eeprom_write(int memory_wrt_addr, int mem_wrt_data)
{
/* ========== WRITE operation STARTs here ========== */
	EEAR = memory_wrt_addr;
	EEDR = mem_wrt_data;
	
	EECR |= (1<<EEMWE);		/*Write logical one to EEMWE*/
	
	EECR |= (1<<EEWE);			/*Start eeprom write by setting EEWE*/
	while(EECR & (1<<EEWE)); 	//wait
/* ========== WRITE operation ENDs here =========== */
}

int eeprom_read(int memory_read_addr)
{
/* ========== READ operation STARTs here ========== */
	while(EECR & (1<<EEWE));
	
	EEAR = memory_read_addr;	/*Set up address register*/
	
	EECR |= (1<<EERE);			/*Start eeprom read by writing EERE*/
	
	return EEDR;			/*Return data from data register*/
/* ========== READ operation ENDs here =========== */
}

