
#define setb_LCD_E	LCD_E_PORT |= LCD_E;
#define clrb_LCD_E	LCD_E_PORT &= ~LCD_E;
#define setb_LCD_RS	LCD_RS_PORT |= LCD_RS;
#define clrb_LCD_RS	LCD_RS_PORT &= ~LCD_RS;

/*
#define setb_LCD_E	LCD_CONTROLPORT |= LCD_E;
#define clrb_LCD_E	LCD_CONTROLPORT &= ~LCD_E;
#define setb_LCD_RS	LCD_CONTROLPORT |= LCD_RS;
#define clrb_LCD_RS	LCD_CONTROLPORT &= ~LCD_RS;
// #define setb_LCD_RW	LCD_CONTROLPORT |= LCD_RW;
// #define clrb_LCD_RW	LCD_CONTROLPORT &= ~LCD_RW;
*/

void lcd_init_port(void)
{
	LCD_RS_DDR |= LCD_RS;
	LCD_E_DDR |= LCD_E;
}

void delay(unsigned short x) {
	for(unsigned short n=0;n<x;n++) _delay_ms(10);
}

#ifdef LCD_LO	// Data lines at low (Pn0-Pn3).
void lcd_command(unsigned char data)
{
	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	setb_LCD_E;
	_delay_us(1);
	LCD_DATAPORT |= ((data >> 4) & 0x0f);	// H
	_delay_us(1);
	clrb_LCD_E;
	_delay_us(1);
	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	setb_LCD_E;
	_delay_us(1);
	LCD_DATAPORT |= (data & 0x0f);		// L
	_delay_us(1);
	clrb_LCD_E;
	_delay_us(1);
	clrb_LCD_RS;
	_delay_us(1);
}
#endif

#ifdef LCD_HI	// Data lines at high (Pn4-Pn7).
void lcd_command(unsigned char data)
{
	LCD_DATAPORT = LCD_DATAPORT & 0x0f;
	setb_LCD_E;
	_delay_us(1);
	LCD_DATAPORT |= (data & 0xf0);		// H
	_delay_us(1);
	clrb_LCD_E;
	_delay_us(1);
	LCD_DATAPORT = LCD_DATAPORT & 0x0f;
	setb_LCD_E;
	_delay_us(1);
	LCD_DATAPORT |= ((data << 4) & 0xf0);	// L
	_delay_us(1);
	clrb_LCD_E;
	_delay_us(1);
	clrb_LCD_RS;
	_delay_us(1);
}
#endif

void lcd_data(unsigned char data)
{
	setb_LCD_RS;
	lcd_command(data);
	asm volatile("nop");
	_delay_us(500);
}

void lcd_clear(void)
{
	lcd_command(1);
	_delay_ms(3);
}

void lcd_addr(unsigned char data)
{
	data |= 128;
	lcd_command(data);
	_delay_ms(1);
}

void lcd_home(void)
{
	lcd_command(2);
	_delay_ms(1);
}

#ifdef LCD_LO
void lcd_init(void)
{
	clrb_LCD_E;
//	clrb_LCD_RW;
	clrb_LCD_RS;
	_delay_ms(250);

	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	setb_LCD_E;
	_delay_us(200);
	LCD_DATAPORT |= 3;
	_delay_us(200);
	clrb_LCD_E;
	_delay_ms(5);

	setb_LCD_E;
	_delay_us(200);
	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	LCD_DATAPORT |= 3;
	_delay_us(200);
	clrb_LCD_E;
	_delay_us(150);

	setb_LCD_E;
	_delay_us(200);
	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	LCD_DATAPORT |= 3;
	_delay_us(200);
	clrb_LCD_E;
	_delay_us(150);

	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	setb_LCD_E;
	_delay_us(200);
	LCD_DATAPORT |= 2;
	_delay_us(200);
	clrb_LCD_E;
	_delay_ms(2);

	lcd_command(0x28);			// 0x20: 1 lines, 0x28: 2 lines
	delay(2);
	lcd_command(12);
	delay(2);
	lcd_command(6);
	delay(5);
	lcd_clear();
}
#endif

#ifdef LCD_HI
void lcd_init(void)
{
	clrb_LCD_E;
//	clrb_LCD_RW;
	clrb_LCD_RS;
	_delay_ms(250);

	LCD_DATAPORT = LCD_DATAPORT & 0x0f;
	setb_LCD_E;
	_delay_us(200);
	LCD_DATAPORT |= 0b00110000;
	_delay_us(200);
	clrb_LCD_E;
	_delay_ms(5);

	setb_LCD_E;
	_delay_us(200);
	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	LCD_DATAPORT |= 0b00110000;
	_delay_us(200);
	clrb_LCD_E;
	_delay_us(150);

	setb_LCD_E;
	_delay_us(200);
	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	LCD_DATAPORT |= 0b00110000;
	_delay_us(200);
	clrb_LCD_E;
	_delay_us(150);

	LCD_DATAPORT = LCD_DATAPORT & 0xf0;
	setb_LCD_E;
	_delay_us(200);
	LCD_DATAPORT |= 0b00100000;
	_delay_us(200);
	clrb_LCD_E;
	_delay_ms(2);

	lcd_command(0x28);
	delay(2);
	lcd_command(12);
	delay(2);
	lcd_command(6);
	delay(5);
	lcd_clear();
}
#endif

void lcd_print(unsigned char *str)
{
	while(*str != 0) {
//		if(*str == '\n') {
//			lcd_addr();
//		} else {
			lcd_data(*str);
//		}
		str++;
	}
}
