/**
 * @file    lcd_c.c
 * @author  Peter Fleury
 * @date    Thu Oct 29 09:06:19 CET 2015
 * @brief   LCD display library
 * @remarks
 *          - The library defines functions and constants for communication between
 *            HD44780 based text display and AVR microcontrollers.
 *          - There is a LCD display on ATmega16 development board interconnected
 *            to port A (PDA7:4 @ DB7:4, PD3 @ E, PD2 @ R/W, PD1 @ RS). See
 *            ATmega16 development board documentation for detailed description.
 *
 * @par Families supported:
 * AVR, tested with ATmega16
 *
 * @par Compilers supported:
 * avr-gcc, tested with avr-gcc (Fedora 4.5.0-2.el6) 4.5.0
 */

#include <avr/io.h>             // include definition file for Atmel MCU
#define F_CPU 4000000UL        // clock frequency (for delay library)
#include <util/delay.h>         // include delay library
#include "lcd_h.h"              // include LCD display library


/* global variables */
unsigned char x,y;              // current cursor position

///////////////////////////////////////////////////////yobraz byt na 3 mista
void lcd_byt(unsigned char byt)
{
unsigned char b1,b2=1;

	b1=byt/100;                    //b1=stovky
    if(b1==0) {b2=0; lcd_putc(32);}   //byt<100 zobraz mezeru
	else lcd_putc(b1+0x30);           //zobraz stovky

    b1=byt%100;                    //zbytek po dělení stem
	byt=b1;
	b1=b1/10;                      //b1=desítky
    if((b1==0) & (b2==0))          //byt<10 zobraz mezeru
	lcd_putc(32);
	else lcd_putc(b1+0x30);           //zobraz desítky

	b1=byt%10;                     //zbytek po dělení deseti
    lcd_putc(b1+0x30);                //zobraz jednotky
 }


/**
 * @brief   Initialization of communication between MCU and LCD display.
 * @return  No return value.
 * @remarks
 *          - Within the function, microcontroller port A (PA7:1) is configured as output.
 *          - Use only once in the application.
 */
void lcd_init(void)
{
    //DDRA |= (1<<DDA7) | (1<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1);
    DDRA = 0xff;
    _delay_ms(10);
    lcd_command(0b00100000);
    lcd_command(0b00101000);
    lcd_command(0b00000100);
    lcd_command(0b00001100);
    lcd_clrscr();
}


/**
 * @brief   Clear LCD screen and move cursor position to left upper corner.
 * @return  No return value.
 * @remarks
 *          - Within the function, short delay is called.
 */
void lcd_clrscr(void)
{
    lcd_command(0b00000001);
    x = 0;
    y = 0;
    _delay_ms(10);
}


/**
 * @brief   Send 1-byte instruction to LCD display.
 * @param   cmd   Instruction for LCD display.
 * @return  No return value.
 */
void lcd_command(char cmd)
{
    lcd_write(cmd, 0);
}


/**
 * @brief   Send 1-byte data to LCD display.
 * @param   data   Data for LCD display.
 * @return  No return value.
 */
void lcd_data(char data)
{
    lcd_write(data, 1);
}


/**
 * @brief   Send 1-byte instruction (rs=0) or data (rs=1) to LCD display.
 * @param   data   Instruction or data for LCD display.
 * @param   rs     Instruction/data identifier.
 * @return  No return value.
 * @remarks
 *          - Only the 4-bit mode of LCD communication is supported.
 *          - Within the function, E (enable) pin pulse is generated.
 */
void lcd_write(char data, char rs)
{
    char temp;

    if (rs)
        lcd_rs_high();          // data
    else
        lcd_rs_low();           // instruction
    temp = LCD_PORT & 0x0f;
    LCD_PORT = temp | (data & 0xf0);
    lcd_e_toggle();
    LCD_PORT = temp | ((data & 0x0f ) << 4);
    lcd_e_toggle();
    LCD_PORT = temp | 0xf0;
    _delay_ms(2);
}


/**
 * @brief   Generate one E (enable) pin pulse.
 * @return  No return value.
 */
void toggle_e(void)
{
    lcd_e_high();
    lcd_e_delay();
    lcd_e_low();
}


/**
 * @brief   Move cursor of LCD display to new position.
 *
 * @param   x_   New horizontal position.
 * @param   y_   New vertical position.
 * @return  No return value.
 * @remarks
 *          - Coordinates (0, 0) represent left upper corner of LCD display.
 */
void lcd_gotoxy(char x_, char y_)
{
    if (y_ == 0)
    {
        lcd_command((1<<LCD_DDRAM) + LCD_START_LINE1 + x_);
        y = 0;
    }
    else if (y_ == 1)
    {
        lcd_command((1<<LCD_DDRAM) + LCD_START_LINE2 + x_);
        y = 1;
    }
    else if (y_ == 2)
    {
        lcd_command((1<<LCD_DDRAM) + LCD_START_LINE3 + x_);
        y = 2;
    }
    else if (y_ == 3)
    {
        lcd_command((1<<LCD_DDRAM) + LCD_START_LINE4 + x_);
        y = 3;
    }
    x = x_;
}


/**
 * @brief   Put single character to LCD display.
 * @param   ch   Character to be displayed at current cursor position.
 * @return  No return value.
 * @remarks
 *          - Put characters to apostrophes ('.') or use ASCII code.
 */
void lcd_putc(char ch)
{
    if (ch=='\n')
        lcd_newline();
    else
    {
        if ((x == LCD_DISP_LENGTH) && (y == 0))
            lcd_secondline();
        else if ((x == LCD_DISP_LENGTH) && (y == 1))
            lcd_thirdline();
        else if ((x == LCD_DISP_LENGTH) && (y == 2))
            lcd_fourthline();
        else if ((x == LCD_DISP_LENGTH) && (y == 3))
            lcd_firstline();
        lcd_data(ch);
        x++;
    }
}


/**
 * @brief   Put string to LCD display.
 * @param   str   String (pointer to array of characters) to be displayed from current cursor position.
 * @return  No return value.
 * @remarks
 *          - Put strings to quotation marks (".").
 *          - Use "\n" identifier for new line.
 */
void lcd_put_string(const char *str)
{
    register char c;

    while ((c = *str++))
        lcd_putc(c);
}


/**
 * @brief   Move cursor position to the beginning of new line.
 * @return  No return value.
 */
void lcd_newline(void)
{
    if (y == 3)
        lcd_firstline();
    else if (y == 0)
        lcd_secondline();
    else if (y == 1)
        lcd_thirdline();
    else if (y == 2)
        lcd_fourthline();
}


/**
 * @brief   Move cursor position to the beginning of first line.
 * @return  No return value.
 */
void lcd_firstline(void)
{
    lcd_command((1<<LCD_DDRAM) + LCD_START_LINE1);
    x = 0;
    y = 0;
    lcd_put_string("                ");
    lcd_command((1<<LCD_DDRAM) + LCD_START_LINE1);
    x = 0;
    y = 0;
}


/**
 * @brief   Move cursor position to the beginning of second line.
 * @return  No return value.
 */
void lcd_secondline(void)
{
    lcd_command((1<<LCD_DDRAM) + LCD_START_LINE2);
    x = 0;
    y = 1;
    lcd_put_string("                ");
    lcd_command((1<<LCD_DDRAM) + LCD_START_LINE2);
    x = 0;
    y = 1;
}


/**
 * @brief   Move cursor position to the beginning of third line.
 * @return  No return value.
 */
void lcd_thirdline(void)
{
    lcd_command((1<<LCD_DDRAM) + LCD_START_LINE3);
    x = 0;
    y = 2;
    lcd_put_string("                ");
    lcd_command((1<<LCD_DDRAM) + LCD_START_LINE3);
    x = 0;
    y = 2;
}


/**
 * @brief   Move cursor position to the beginning of fourth line.
 * @return  No return value.
 */
void lcd_fourthline(void)
{
    lcd_command((1<<LCD_DDRAM) + LCD_START_LINE4);
    x = 0;
    y = 3;
    lcd_put_string("                ");
    lcd_command((1<<LCD_DDRAM) + LCD_START_LINE4);
    x = 0;
    y = 3;
}
