/*
** ===================================================================
** Název souboru   : lcd_c.c
** Mikrokontroler  : ATmega16
** Popis           : Funkce pro ovládání lcd displeje
**
** Autor           : Peter Fleury ( http://homepage.hispeed.ch/peterfleury/ )
**                 : Tomáš Frýza ( fryza@feec.vutbr.cz )
** Předmět         : Mikroprocesorová technika
** Poslední změna  : 29.08.06 15:05
** ===================================================================
*/


/*
** Hlavičkové soubory
*/
#include <avr/io.h>			// hlavičkový soubor pro mikrokontrolér ATmega16
#define F_CPU 16000000UL	// frekvence krystalu (nutné pro delay.h)
#include <util/delay.h>     // hlavičkový soubor pro zpoždění
#include "lcd_h.h"          // hlavičkový soubor pro obsluhu lcd


/*
** Globální proměnné
*/
unsigned char x,y ;			// pomocné souřadnice pozice kurzoru



/*
** ===================================================================
**     Název funkce  : lcd_init
**
**     Popis         :
**         Inicializace lcd displeje. 4bitová komunikace; 2 řádky;
**         5x8 bodů; posun kurzoru doprava; bez posunu displeje;
**         displej zapnut; kurzor vypnut; blikání kurzoru vypnuto
**     Parametry     : žádné
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_init( void )
{
	
	DDR( LCD_PORT ) = 0b11111110 ;// deklarace výstupního portu pro lcd
    _delay_ms( 16 ) ;		// nutné zpoždění
	lcd_command( 0b00100000 ) ; // nastavení 4bitové komunikace
	lcd_command( 0b00101000 ) ;	// nastavení funkce displeje
	lcd_command( 0b00000100 ) ;	// nastavení směru pohybu kurzoru
	lcd_command( 0b00001100 ) ;	// nastavení displeje a kurzoru

	lcd_clrscr() ;			// smazání obsahu lcd displeje (dokončení inicializace)
}


/*
** ===================================================================
**     Název funkce  : lcd_clrscr
**
**     Popis         :
**         Smazání obsahu lcd displeje.
**     Parametry     : žádné
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_clrscr( void )
{
	lcd_command( 0b00000001 ) ;	// smazání displeje
	x = 0 ;					// nulování pomocných souřadnic ...
	y = 0 ;					// ... pozice kurzoru
	_delay_ms( 16 ) ;		// nutné zpoždění
}


/*
** ===================================================================
**     Název funkce  : lcd_command
**
**     Popis         :
**         Zápis 1bytové instrukce do lcd displeje.
**     Parametry     : data - instrukce pro lcd diplej
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_command( char data )
{
	lcd_write( data, 0 ) ;
}


/*
** ===================================================================
**     Název funkce  : lcd_data
**
**     Popis         :
**         Zápis 1bytového datového slova do lcd displeje.
**     Parametry     : data - data pro lcd displej
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_data( char data )
{
	lcd_write( data, 1 ) ;
}


/*
** ===================================================================
**     Název funkce  : lcd_write
**
**     Popis         :
**         Zápis instrukce nebo dat do lcd displeje.
**     Parametry     : data - instrukce/data pro lcd diplej
**                     rs   - 0: instrukce; 1: data
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_write( char data, char rs )
{
	unsigned char temp ;

    if( rs ) lcd_rs_high() ;
	else lcd_rs_low() ;

	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 ) ;
}


/*
** ===================================================================
**     Název funkce  : toggle_e
**
**     Popis         :
**         Realizace jednoho "enable" pulsu pro lcd displej.
**     Parametry     : žádné
**     Výst. hodnota : žádné
** ===================================================================
*/
void toggle_e( void )
{
    lcd_e_high() ;
    lcd_e_delay() ;
    lcd_e_low() ;
}


/*
** ===================================================================
**     Název funkce  : lcd_gotoxy
**
**     Popis         :
**         Přesun kurzoru na pozici x,y lcd displeje.
**     Parametry     : x_,y_ - nové pozice kurzoru lcd displeje
**     Výst. hodnota : žádné
** ===================================================================
*/
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 ;
	}
	x = x_ ;
}


/*
** ===================================================================
**     Název funkce  : lcd_putc
**
**     Popis         :
**         Zobrazení jednoho znaku na lcd displeji.
**     Parametry     : c - znak k zobrazení na lcd displeji
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_putc( char c )
{
    if (c=='\n')
		lcd_newline() ;
	else
	{
        if(( x == LCD_DISP_LENGTH  ) && ( y == 0 ))
			lcd_secondline() ;
		else if(( x == LCD_DISP_LENGTH ) && ( y == 1 ))
			lcd_firstline() ;
	    lcd_data( c ) ;
		x++ ;
	}
}


/*
** ===================================================================
**     Název funkce  : lcd_puts
**
**     Popis         :
**         Zobrazení řetězce znaků na lcd displeji.
**     Parametry     : *s - ukazatel na řetězec znaků
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_puts( const char *s )
{
    register char c ;

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


/*
** ===================================================================
**     Název funkce  : lcd_newline
**
**     Popis         :
**         Skok na nový řádek lcd displeje.
**     Parametry     : žádné
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_newline( void )
{
	if( y == 1 )
		lcd_firstline() ;
	else
		lcd_secondline() ;
}


/*
** ===================================================================
**     Název funkce  : lcd_firstline
**
**     Popis         :
**         Skok a vymazání prvního řádku lcd displeje.
**     Parametry     : žádné
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_firstline( void )
{
    lcd_command(( 1<<LCD_DDRAM ) + LCD_START_LINE1 ) ;
	x = 0 ;
	y = 0 ;
	lcd_puts( "                " ) ;
    lcd_command(( 1<<LCD_DDRAM ) + LCD_START_LINE1 ) ;
	x = 0 ;
	y = 0 ;
}


/*
** ===================================================================
**     Název funkce  : lcd_secondline
**
**     Popis         :
**         Skok a vymazání druhého řádku lcd displeje.
**     Parametry     : žádné
**     Výst. hodnota : žádné
** ===================================================================
*/
void lcd_secondline( void )
{
    lcd_command(( 1<<LCD_DDRAM ) + LCD_START_LINE2 ) ;
	x = 0 ;
	y = 1 ;
	lcd_puts( "                " ) ;
    lcd_command(( 1<<LCD_DDRAM ) + LCD_START_LINE2 ) ;
	x = 0 ;
	y = 1 ;
}


/*
** Konec zdrojového souboru
*/
