/*******************************************************************************
* File Name		: lcd.h
* Author		: luboss17
* Date			: 13.11.2012
* Description		: library from luboss17 - LCD - HD44780 driver
* Other			: luboss17@gmail.com  -- http://lubosweb.php5.sk
* Version		: 2.0
********************************************************************************
* MCU			: AVR
********************************************************************************
* License		: GNU GPL
*******************************************************************************/

#include "lcd.h"

/************************************************
    inicializacna funkcia
************************************************/

void lcd_init(void)
{
    LCD_DDR |= (1<<LCD_E_PIN) | (1<<LCD_BCK_PIN) | (1<<LCD_RS_PIN);
	LCD_DDR |= (1<<LCD_DATA0_PIN) | (1<<LCD_DATA1_PIN) | (1<<LCD_DATA2_PIN) | (1<<LCD_DATA3_PIN);

    _delay_ms(15);  //cakanie

	LCD_PORT &= ~(1<<LCD_DATA0_PIN);
	LCD_PORT &= ~(1<<LCD_DATA1_PIN);
	LCD_PORT &= ~(1<<LCD_DATA2_PIN);
	LCD_PORT &= ~(1<<LCD_DATA3_PIN);
	LCD_PORT &= ~(1<<LCD_RS_PIN);
	LCD_PORT &= ~(1<<LCD_E_PIN);
	LCD_PORT &= ~(1<<LCD_BCK_PIN);

	_delay_ms(20);

	LCD_SET_ENABLE;
	LCD_PORT |= (1<<LCD_DATA0_PIN);
	LCD_PORT |= (1<<LCD_DATA1_PIN);
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_ms(5);

	LCD_SET_ENABLE;
	LCD_PORT |= (1<<LCD_DATA0_PIN);
	LCD_PORT |= (1<<LCD_DATA1_PIN);
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(150);

	LCD_SET_ENABLE;
	LCD_PORT |= (1<<LCD_DATA0_PIN);
	LCD_PORT |= (1<<LCD_DATA1_PIN);
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(50);

	LCD_PORT &= ~(1<<LCD_DATA0_PIN);
	LCD_PORT |= (1<<LCD_DATA1_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(50);

	LCD_PORT &= ~(1<<LCD_DATA0_PIN);
	LCD_PORT |= (1<<LCD_DATA1_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	LCD_PORT &= ~(1<<LCD_DATA1_PIN);
	LCD_PORT |= (1<<LCD_DATA3_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(50);

	LCD_PORT &= ~(1<<LCD_DATA0_PIN);
	LCD_PORT &= ~(1<<LCD_DATA1_PIN);
	LCD_PORT &= ~(1<<LCD_DATA3_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	LCD_PORT |= (1<<LCD_DATA0_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_ms(2);

	LCD_PORT &= ~(1<<LCD_DATA0_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	LCD_PORT |= (1<<LCD_DATA3_PIN);
	LCD_PORT |= (1<<LCD_DATA2_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(50);

	LCD_PORT &= ~(1<<LCD_DATA3_PIN);
	LCD_PORT &= ~(1<<LCD_DATA2_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	LCD_PORT |= (1<<LCD_DATA2_PIN);
	LCD_PORT |= (1<<LCD_DATA1_PIN);
	LCD_SET_ENABLE;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(50);
}

/************************************************
    funkcia na zapis datoveho byte-u do LCD
************************************************/

void lcd_data(unsigned char data)
{
	if (data & (0x80)) LCD_PORT |= (1<<LCD_DATA3_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA3_PIN);
	if (data & (0x40)) LCD_PORT |= (1<<LCD_DATA2_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA2_PIN);
	if (data & (0x20)) LCD_PORT |= (1<<LCD_DATA1_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA1_PIN);
	if (data & (0x10)) LCD_PORT |= (1<<LCD_DATA0_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA0_PIN);

	LCD_SET_ENABLE;
	LCD_RS_DATA;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(1);

	if (data & (0x08)) LCD_PORT |= (1<<LCD_DATA3_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA3_PIN);
	if (data & (0x04)) LCD_PORT |= (1<<LCD_DATA2_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA2_PIN);
	if (data & (0x02)) LCD_PORT |= (1<<LCD_DATA1_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA1_PIN);
	if (data & (0x01)) LCD_PORT |= (1<<LCD_DATA0_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA0_PIN);

	LCD_SET_ENABLE;
	LCD_RS_DATA;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(50);
}

/************************************************
    funkcia na zapis prikazu pre LCD
************************************************/

void lcd_command(unsigned char command)
{
	if (command & (0x80)) LCD_PORT |= (1<<LCD_DATA3_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA3_PIN);
	if (command & (0x40)) LCD_PORT |= (1<<LCD_DATA2_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA2_PIN);
	if (command & (0x20)) LCD_PORT |= (1<<LCD_DATA1_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA1_PIN);
	if (command & (0x10)) LCD_PORT |= (1<<LCD_DATA0_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA0_PIN);

	LCD_SET_ENABLE;
	LCD_RS_COMMAND;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(1);

	if (command & (0x08)) LCD_PORT |= (1<<LCD_DATA3_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA3_PIN);
	if (command & (0x04)) LCD_PORT |= (1<<LCD_DATA2_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA2_PIN);
	if (command & (0x02)) LCD_PORT |= (1<<LCD_DATA1_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA1_PIN);
	if (command & (0x01)) LCD_PORT |= (1<<LCD_DATA0_PIN);
	else LCD_PORT &= ~(1<<LCD_DATA0_PIN);

	LCD_SET_ENABLE;
	LCD_RS_COMMAND;
	_delay_us(1);
	LCD_CLR_ENABLE;
	_delay_us(50);
}

/************************************************
    funkcia na nastavenie pozicie na LCD
************************************************/

void lcd_position(unsigned char row, unsigned char column)
{
    unsigned char box = 0;

    switch(row)  //vyber riadku
    {
        case 1: box |= 0x00;
        break;
        case 2: box |= 0x40;
        break;
        case 3: box |= 0x10;
        break;
        case 4: box |= 0x50;
        break;
        default: return;
    }

    if (column > 17) return; //max. 16 stlpcov

    box |= (column-1);  //pripocitanie cisla stlpca
    box |= 0x80;  // + prikaz pre nastavovanie pozicie

    lcd_command(box);  //odoslanie prikazu z poziciou
}

/************************************************
    funkcia na vypis znaku na LCD
************************************************/

void lcd_putc(char c)
{
    lcd_data(c);
}

/************************************************
    funkcia na vypis retazca na LCD
************************************************/

void lcd_puts(char *s)
{
    register char c;

    while ((c = *s++)) {
        lcd_data(c);
    }
}

/************************************************
    dalsie uzitocne funkcie
************************************************/

//zmaze displej
void lcd_clear(void)
{
    lcd_command(1);
}

//nastavi na zaciatok displeja
void lcd_home(void)
{
    lcd_command(2);
}

//nastavi inkrementaciu - pohyb vpred na displeji
void lcd_inc(void)
{
    lcd_command(6);
}

//nastavi dekrementaciu
void lcd_dec(void)
{
    lcd_command(4);
}

//zapne displej
void lcd_displayOn(void)
{
    lcd_command(12);
}

//vypne displej
void lcd_displayOff(void)
{
    lcd_command(8);
}

//zobrazi kurzor
void lcd_cursorOn(void)
{
    lcd_command(14);
}

//schova kurzor
void lcd_cursorOff(void)
{
    lcd_displayOn();
}

//rozblika kurzor
void lcd_cursorBlink(void)
{
    lcd_command(15);
}
