// ******************************************************************
// -------------------------zabezpečovací ústředna-------------------
#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define LCD
#include "mojelib1.h"
#include "DS18B20.h"
//globální proměnné ----------------------------------------
int key;								// stisknutá klávesa
int celkovy_klic [4] = {0,0,0,0};		// zadávání klíče z klávesnice
int klic[4]	=	{1,2,3,4};				// klíč uložený v systému
int pocitadlo = 0;						// ukazatel na pole s klíči
int stare_poc = 0;						// předchozí hodnota (pomocná proměná)
int ustredna = 0b10000000;				// registr ústředna	- obsahuje kontrolní bity b0 - poplach
int teplot_komp=29;						// hodnota pro komparaci teploty
int teplot_nacti[2];					// pole pro načítání teploty přes rozhraní UART
//----------------------------------------------------------
// 7-bit - určení zda se ukáže start obrazovka (aktivní pouze při spuštění nebo restartu)
// 6-bit - komunikace UART (1 - aktivní komunikace) - změna klíče - indikace UART
// 5-bit - požadavek na změnu zabezpečovacího kódu z klávesnice
// 4-bit - požadavek na změnu hodnoty teplotního čidla z klávesnice
// 3-bit 
// 2-bit - tichý poplach aktivní (blikání LED diod)
// 1-bit - změna hodnoty teplotního čidla pro komparaci (indikace přenosu UART)
// 0-bit - nastaví se pokud je vyhodnocen poplach od tlačítka (zvuk alarmu - poplach)

// prototypy funkcí ----------------------------------------
void zobraz_lcd(void);		// funkce zobrazující na lcd
void klavesa(void);			// ČTENÍ Z KLÁVESNICE
void kontrola (void);		// kontrola zadaného kódu
void start_lcd (void);		// úvodní podprogram
void provoz_lcd (void);		// standartní zobrazení na LCD za běžného provozu
void poplach (void);		// spuštění ALARMU
void vyhod_tepl(void);		// podprogram na vyhodnocení překročení dané teploty
void tichy_poplach (void);	// spuštění tichého poplachu - blikání LED
void vypni_poplach(void);	// vypnutí ALARMU
//----------------------------------------------------------

//hlavní program
int main (void)
{
	DDRB=0xff;
	DDRC = 0xff;
	PORTC = 0b11000010;	

	// povolení externího přerušení - tlačítko
	MCUCR = 0b00001111;	// povolení přerušení od INT1 a INT0
	GIFR= 0x00;			// vymazání příznakových bitů přerušení
	GICR = 0b11000000;	// povolení od INT1 a INT0

	// nastavení UART rozhraní
	UCSRA = 0b00100000;	// vymazání zásobníku UDR
	UCSRB = 0b10011000;	// nastavení přerušení a povolení módu přijímače
	UCSRC = 0b10000110;	// asynchroní mód, ;
	UBRRL = 103;		// pro SR = 9600 baud;

	
	init_lcd();			//inicializace LCD
	_delay_ms(10);
	cls();				// smazání LCD displeje
	_delay_ms(10);
	
	
	sei();				// povolení přerušení
	while(1)
	{	
		if (ustredna &0x80)	start_lcd();	// počáteční uvídání + teplota
		if (ustredna & 0x01)				// pokud je vyhodnocen poplach |(ustredna&=0x20)
		{
			klavesa();		// přečti z klávesnice
			zobraz_lcd();	// vypíše stav na LCD
		}
		else	
			{
			provoz_lcd();	// standartní zobrazení za běhu programu
			mereni();		// měření teploty (knihovna DS18B20)
			vyhod_tepl();	// uložení teploty do dané proměné (knihovna DS18B20)
			}
	}
}


void klavesa(void)			// čtení z klávesnice
{
	DDRC = 0xff;
	PORTC = 0b11000011;	

	DDRA=0x00;				//nastavení registrů pro klávesnici
	DDRB=0xff;
	DDRD=0b10110000;

	// ostatní sloupce krom prvního musí být v logické 1
	PORTD |= 0x30;

	
	PORTB &= 0b11111100;	//chci 1 sloupec
	_delay_ms(2);
		if (!(PINA&0b00000100)) 
			{
			key=1;
			pocitadlo++;
			}
		if (!(PINA&0b00001000))
			{
			 key=4;
			 pocitadlo++;
			 }
	
		if (!(PINA&0b00100000))
			{
			key=7;
			pocitadlo++;
			}
		if (!(PINA&0b01000000))
			{
			key='#';
			pocitadlo++;
			 }
	PORTB|=0b00000010;  // první sloupec nastavit opět do logické 1


	PORTD&=0b11011111;	//chci 2. sloupec
	_delay_ms(2);
	   	if (!(PINA&0b00000100))
			{
			 key=2;
			 pocitadlo++;
			 }
		if (!(PINA&0b00001000)) 
			{
			key=5;
			pocitadlo++;
			}
		if (!(PINA&0b00100000)) 
			{
			key=8;
			pocitadlo++;
			}
		if (!(PINA&0b01000000))
			{ 
			key=0;
			pocitadlo++;
			}

	PORTD |=0b00100000;

	
	PORTD&=0b11101111;	//chci 3. sloupec
	_delay_ms(2);
		if (!(PINA&0b00000100)) 
			{
			key=3;
			pocitadlo++;
			}
		if (!(PINA&0b00001000)) 
			{
			key=6;
			pocitadlo++;
			}
		if (!(PINA&0b00100000)) 
			{
			key=9;
			pocitadlo++;
			}
		if (!(PINA&0b01000000)) 	// mazání displeje
			{
			for(int i=0;i<4;i++) celkovy_klic[i]=0;
			pocitadlo=0;
			stare_poc = 0;
			}
	PORTD |=0b000100000;

	// zpracování stisknuté klávesy
	if (stare_poc<pocitadlo) 
		{
			if(pocitadlo == 5) 
				{
				pocitadlo = 1;
				for(int i=0;i<4;i++) celkovy_klic[i]=0;
				}
			celkovy_klic [pocitadlo-1] = key;
			stare_poc = pocitadlo;
		}	
}

void zobraz_lcd(void)
{
	DDRC=0xff;			
	PORTC=0b11000010;	

								
	gotoxy(1,12);				//jdi na pozici
	lcd_byt(celkovy_klic[3]);	//zapiš na pozici zmáčknutou klávesu
	gotoxy(1,11);
	lcd_byt(celkovy_klic[2]);		
	gotoxy(1,10);		
	lcd_byt(celkovy_klic[1]);		
	gotoxy(1,9);		
	lcd_byt(celkovy_klic[0]);		

	gotoxy(2,2);
	if (pocitadlo ==4)	kontrola();			// zkontroluje zadaný klíč
			else	lcd_text(" Zadej klic");
		_delay_ms(150);


}

void kontrola (void)			// zkontroluje zadaný klíč
{
	gotoxy(2,2);
	if((celkovy_klic[0]==klic[0])&(celkovy_klic[1]==klic[1])&(celkovy_klic[2]==klic[2])&(celkovy_klic[3]==klic[3]))
	{
			lcd_text(" Klic je OK");
			TCCR2 = 0x00;
			TCCR0 =0x00;
			_delay_ms(200);			// počká 1 sekundu, potom naběhne proces mazání displeje
			_delay_ms(200);
			_delay_ms(200);
			_delay_ms(200);
			_delay_ms(200);

			cls();					// smaže displej

			// mazání a nastavení nových čísel
			for(int i=0;i<4;i++) celkovy_klic[i]=0;
			pocitadlo=0;
			stare_poc = 0;

			ustredna &=FE;			// zrušení poplachového bitu

	}
	else 	lcd_text("Spatny klic");

	
}

// řízení časovače 2 pomocí časovače 0 pomocí ¨přerušení - komparace
ISR (TIMER0_COMP_vect)
{
	if (OCR0 == 128) OCR0 = 40;
		else OCR0 =128;
	
	if(TCCR2 == 0b00011101) TCCR2 = 0x00;
		else TCCR2 = 0b00011101;
}

ISR (INT1_vect)
{
	poplach();	// stisk tlačítka spustí poplach
}

void poplach (void)
{
// 1 časovač - samostatně bude vydávat tón 1 kHz	(timer2)
	TCCR2 = 0b00011101;		// nastavení děličky 1024, ovládání pinu OC2
	OCR2 = 61;				// nastavení komparační hladiny
	TIMSK = 0b00000010;		// povoleno přerušení od komparace TIMER0

// 2 časovač - nastavení (TIMER0) - bude ovládat časovač 1
	TCCR0 =0b00000101;
	OCR0 = 100;			// frekvence cca v řádech 250Hz


	GIFR = 0x00;

	// vyhodnocení poplachu v systému
	ustredna |=0x01;
	cls();
	_delay_ms(3);
}

/*
ISR (INT0_vect)			// požadavek na změnu kódu z klávesnice
{
	ustredna |=0x20;
}
*/

void vypni_poplach(void)	// vypnutí alarmu
{
	TCCR2 = 0x00;			// vypnutí poplachu
	TCCR0 =0x00;		

	// mazání a nastavení nových čísel
	for(int i=0;i<4;i++) celkovy_klic[i]=0;
	pocitadlo=0;
	stare_poc = 0;
	ustredna &=FE;			// zrušení poplachového bitu
}

void start_lcd (void)		// úvodní obrazovka
{

	DDRC=0xff;			
	PORTC=0b11000010;	

	gotoxy(1,1);
	lcd_text("  Bezpecnostni");
	gotoxy(2,1);
	lcd_text("    Ustredna");

	_delay_ms(200);			//zobrazení na 1 sekundu
	_delay_ms(200);
	_delay_ms(200);
	_delay_ms(200);
	_delay_ms(200);

	ustredna &= 0x7F; 		// zobrazení proběhlo

	cls();					// následné vymázání displeje
	_delay_ms(10);

}

void provoz_lcd (void)		// výpis LCD při normálním stavu
{
	int zbytek;

	DDRC=0xff;			
	PORTC=0b11000010;	

	gotoxy(1,1);					
	lcd_text("Status: ");
	// vypsání stavu ústředny
	gotoxy(1,9);
	if ((ustredna&0x40)|(ustredna&0x02))lcd_text("UART    ");
		else if (ustredna&0x04)lcd_text("Teplota!");
			else lcd_text("Ready   ");


	// převod z 16bitové proměnné a rozdělení celé části a zlomkové			
	zbytek=10000*(hodnota&15)/16;			// výpočet desetinné části
	
	// výpis na LCD displej
	gotoxy(2,1);
	lcd_text("Teplota:");

	gotoxy(2,12);
	lcd_byt(zbytek/100);			// výpis 2 desetiných míst

	gotoxy(2,9);
	lcd_byt(celocisel_teplota());	// výpis celého čísla

	gotoxy(2,12);
	lcd_text(",");

	gotoxy(2,15);
	lcd_text("C");

	gotoxy(2,9);
	if ((hodnota>>15)) lcd_text("-");	// výpis znaménka
	 	else lcd_text("+");

	if((zbytek/100)<10) 			// ošetření výpisu 0 na LCD
	{
	gotoxy(2,13);
	lcd_text("0");
	}
} 


ISR (USART_RXC_vect)			// komunikace rozhraní UART
{
	
	unsigned char prikaz = 0;

	prikaz = UDR-48;			// - offset pro ascii tabulku (asci => 1 = 49)

	
	if (ustredna & 0x40)		// pokud je nastavena změna klíče
	{
		if(ustredna&0x01)		// pokud je nastaven poplach
		{
			celkovy_klic[pocitadlo]=prikaz;
			if (pocitadlo==3) 
				{
				kontrola();
				pocitadlo=3;
				}
		}
		else 	klic[pocitadlo]=prikaz;

		pocitadlo++;
	}

	if (ustredna & 0x02)		// pokud je nastavena změna teploty
	{
		pocitadlo--;
		teplot_nacti[pocitadlo]=prikaz;	// naplnění pole hodnotami
		
		if (pocitadlo == 0) 
			{
			pocitadlo =4;
			teplot_komp=10*teplot_nacti[1]+teplot_nacti[0];
			}
	}		

	else
		switch (prikaz)
		{
			case 27: 	// K -nastavení akcí pro změnu klíče
				ustredna |=0x40;	
				break;

			case 17: 	// A - vypne a zapne poplach
				if(ustredna&0x01)  vypni_poplach();
				else
					poplach();
				break;

			case 35: 	// S - výpis statusu přes UART
				if (ustredna&0x01)		// alarm má přednost před teplotou
					{					// vypíše do UARTu (ALARM)
					UDR = 'A';
					UDR = 'L';
					_delay_ms(3);
					UDR = 'A';
					UDR = 'R';
					_delay_ms(3);
					UDR = 'M';
					UDR = ' ';
					_delay_ms(1);
					}
				else if (ustredna&0x04)	// pokud je překročena teplota a alarm neběží
					{					// vyšle TERMO
					UDR = 'T';
					UDR = 'E';
					_delay_ms(3);
					UDR = 'R';
					UDR = 'M';
					_delay_ms(3);
					UDR = 'O';
					UDR = ' ';
					_delay_ms(1);
					}
				else					// pokud běží vše v pořádku vyšle READY
					{
					UDR = 'R';
					UDR = 'E';
					_delay_ms(3);
					UDR = 'A';
					UDR = 'D';
					_delay_ms(3);
					UDR = 'Y';
					UDR = ' ';
					_delay_ms(1);
					}
				break;

			case 36:	// T - změna teploty
				ustredna |=0x02;	// nastavení bitu pro  změnu teploty
				pocitadlo = 2;		// nastavení připraveného počítadla
				break;
		}


	if (pocitadlo == 4) 			// pokud je zadání dokončeno
			{
			ustredna &=0xBF;		// nuluje zadání změnyx kódu
			ustredna &=0xFD;		// zruší zadání teplotní změny
			pocitadlo =0;			// nuluje pocitadlo pro další účel
			UDR = 'O';				// vyšle potvrzení o dokončené akci (OK )
			UDR = 'K';
			_delay_ms(3);
			UDR = ' ';		
			_delay_ms(1);
			}
}

void vyhod_tepl(void)		// vyhodnocení teplotního poplachu
{
	if (celocisel_teplota()>=teplot_komp)		// pokud je teplota větší než zadaná
	{
		tichy_poplach();		// spustí tichý poplach - blikání LED
		ustredna |=0x04;		// nastaví se bit pro teplotní poplach
	}
	else ustredna &=0xFB;		// nuluje bit pro teplotní poplach
}

void tichy_poplach (void)		// blikání LED - tichý poplach
{
	DDRA = 0xFF;
	PORTA = 0x00;				// vynuluje port A - zhasne LED	
	PORTC &=0b10111111; 		// povolení LED diod
	PORTA = 0xFF;				// nastaví všechny LED na portu A
	_delay_ms(200);				
	_delay_ms(200);
	PORTA = 0x00;				// zhasne LED
	_delay_ms(200);
	_delay_ms(200);
	PORTC  &=0xBF;				// zakáže LED diody
}
