/*
 * displej.c
 *
 * Created: 22.2.2016 20:22:50
 *  Author: tomino
 */ 

#include <avr/io.h>
#include <util/delay.h>
#include "displej.h"

/***************************************************************************************************************
											DEFINICE VYRAZU
***************************************************************************************************************/


//definice nekterych jednodussich prikazu pro ovladani displeje

#define nastav_E() (PORTA|=(1<<PA6))
#define nastav_RS() (PORTA|=(1<<PA4))
//#define nastav_RW() (PORTA|=(1<<PA2))

#define NULUJ_E() (PORTA&=(~(1<<PA6)))
#define NULUJ_RS() (PORTA&=(~(1<<PA4)))
//#define NULUJ_RW() (PORTA&=(~(1<<PA2)))

/***************************************************************************************************************
											VNITRNI FUNKCE  
***************************************************************************************************************/


void zapis(void)		//jednoducha funkce pro bliknuti pinu E pro zapis dane ctverice bitu do displeje
{
	nastav_E();
	_delay_ms(1);
	NULUJ_E();
	_delay_ms(1);
}

/***************************************************************************************************************
											VOLATELNE FUNKCE
***************************************************************************************************************/


void zapisbajt(uint8_t bajt,uint8_t typ)		//funkce ktera zapise bajt na displej, druhy parametr udava typ zda se jedna o instrukci ci data pro vypis
{
	uint8_t high, low;		//pro rozdeleni bajtu na dve ctverice bitu
	uint8_t pomocna;		//predava na vypis
	
	high=bajt>>4;
	low=(bajt & 0x0F);
	
	if(typ==0)
	NULUJ_RS();
	else
	nastav_RS();
	pomocna=(PORTA & (~(0X0F<<PA0)))|((high<<PA0));
	PORTA=pomocna;
	zapis();
	pomocna=(PORTA & (~(0X0F<<PA0)))|((low<<PA0));
	PORTA=pomocna;
	zapis();
	
}

void skoc(uint8_t y, uint8_t x)			//skoci v pameti na konkretni pozici x,y
{
	x--;								//kdyz zatavam souradnice, zadavam od pozice [1][1], nikoliv [0][0]
	if (x>=20) return;
	switch (y)							//prepne se na dany radek
	{
		case 1:
		break;
		case 2:
		x|=0b01000000;
		break;
		case 3:
		x+=0x14;
		break;
		case 4:
		x+=0x54;
		break;
	}
	x|=0b10000000;
	zapisbajt(x, 0);				//zapise istrukci pro skok v pameti
}

void zapniLCD(void)			//tato funkce inicializuje displej do ctyrbitoveho rezimus vypnutym podtrzitkem a blikanim kurzoru
{
	//init 4 bit mod - presne podle postupu v data sheetu
	//_delay_us(1);

	PORTA|=((0b00000010)<<PA0); 
	zapis();
	
	zapisbajt(0b00101000, 0);
	
	zapisbajt(0b01000000, 0);

	
	zapisbajt(0b00000010, 0);		//skoci na zacatek (pozici [1][1])
	zapisbajt(0b00000001, 0);		//vymaze cely displej
	zapisbajt(0b00001100, 0);		//nastavi kurzor bez podtrzitka a neblikajici
}

void zapistext(uint8_t y, uint8_t x, const char *text) //vypis textu na display, predava se ukazatel na zacatek pole typu char
{
	skoc(y,x);											//skoci na souradnice radek, sloupec
	while (*text!='\0')									//prohledava retezec textu dokud nenarazi na null, proto je nutne mit retezec zadan tak, aby null obsahoval!
	{
		zapisbajt(*text, 1);							//vola funkci zapisu
		text++;											//inkrementuje pocitadlo
	}
	
		
}

void zapiscislo(uint8_t y, uint8_t x, int hodnota, unsigned int delka)  //zapise cislo na danou adresu a na dany pocet mist (usnadnuje prehlednost pri vypisu cisel s ruznym poctem cifer)
{
	char cislo[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	int i=19, mista=0;
	
	skoc(y,x);
	while (hodnota)
	{
		cislo[i]=hodnota%10;		//na pozici cislo [i] vypisuje jednotlive cifry cisla od posledni do první
		hodnota=hodnota/10;			//presouva na nizsi cifru
		i--;
	}
	if(delka==-1)					//hlida presne delku kterou chceme vypsat
	while(cislo[mista]==0) mista++;	//kdyz je zapsana nula na dane pozici, posune se na dalsi misto
	else		mista=20-delka;		//jinak dopocita z delky pocet mist		
	for(i=mista;i<20;i++)			//z vypoctene pozice az do dvacitky vypise vsechno postupne od jednotek vys
	{
		zapisbajt(48+cislo[i], 1);	//zapise bajt na displej
	}
		
}

void vymazLCD ()
{
	zapisbajt(0b00000001, 0);		//vymaze LCD displej
	zapisbajt(0b00000010, 0);		//skoci na zacatek displeje
}

void vycistiLCD ()	
{
	/*tato funkce vymaze cely displej krome prvniho radku (zapise vsude mezery takze se nic nezobrazi)-je to rychlejsi 
	nez vycist obsah prvniho radku, vymazat a zapsat prvni radek zpet a prvni radek by u tohoto postupu blikl*/
	
	zapistext(2,1,"                    ");
	zapistext(3,1,"                    ");
	zapistext(4,1,"                    ");
}

void vycisti_radek (uint8_t radek)		//stejne jako predchozi, jen cisti konkretni radek
{
	zapistext(radek,1,"                    ");
}

