#define F_CPU 3686000UL  //nastaveni frekvence oscilátoru
#include <avr/io.h> 			// hlavickovy soubor pro MCU
#include <avr/interrupt.h>
#include <util/delay.h>
#include "krokac.h"

const int turn = 25;	//doba buzení fáze
volatile unsigned char last = 0;	//paměť posledního seplého koncáku
volatile unsigned char usart = 0,buf[7]; //prom. pro vyčtení UDR a buffer pro tréningovou sekvenci
volatile unsigned int cnt = 0;	//čítač pro ADC
volatile unsigned char aut = 0;		//režim automatiky vyp/zap
volatile unsigned char autoinit = 0;	//výchozí poloha automatiky

//********************  inicializace periferií  ****************************************
void uart0_init(void)
 {
 UCSRB = 0x00;		 // Stop USART
 UBRRL = 0b01011111; // Set baud rate 2400Bd
 UBRRH = 0b00000000; // Set baud rate 
 UCSRB = 0b00010000; // Start USART
}

void timer0_init(void)
{
 TCCR0 = 0x00; // Stop the timer
 TCNT0 = 0x00; // 8-bit counter
 OCR0  = 0x39; // přerušení každou 1ms
 TIMSK = 0b00000010; //povolení přerušení při shodě TCNT a OCR
 TCCR0 = 0b00001011; //zapne časovač s předděličkou 8
}

void adc_init(void)
{
 ADCSRA = 0b00000000; // A/D disable
 ADMUX = 0b11100000; // vnitřní ref 2,56V; výsledek zarovnat doleva; channel 0
 ADCSRA = 0b11000000; // povolí ADC a zapne převádění
}


//******************** definice funkcí ****************************************

void turn_right(void){	//toč doprava o 1 krok
	A=1;B=0;C=0;D=0;
	_delay_ms(turn);
	A=1;B=1;C=0;D=0;
	_delay_ms(turn);
	A=0;B=1;C=0;D=0;
	_delay_ms(turn);
	A=0;B=1;C=1;D=0;
	_delay_ms(turn);
	A=0;B=0;C=1;D=0;
	_delay_ms(turn);
	A=0;B=0;C=1;D=1;
	_delay_ms(turn);
	A=0;B=0;C=0;D=1;
	_delay_ms(turn);
	A=0;B=0;C=0;D=0;
}

void turn_left(void){
	A=0;B=0;C=0;D=1;
	_delay_ms(turn);
	A=0;B=0;C=1;D=1;
	_delay_ms(turn);
	A=0;B=0;C=1;D=0;
	_delay_ms(turn);
	A=0;B=1;C=1;D=0;
	_delay_ms(turn);
	A=0;B=1;C=0;D=0;
	_delay_ms(turn);
	A=1;B=1;C=0;D=0;
	_delay_ms(turn);
	A=1;B=0;C=0;D=0;
	_delay_ms(turn);
	A=0;B=0;C=0;D=0;
}

void turn_up(void){
	E=0;F=0;G=0;H=1;
	_delay_ms(turn);
	E=0;F=0;G=1;H=1;
	_delay_ms(turn);
	E=0;F=0;G=1;H=0;
	_delay_ms(turn);
	E=0;F=1;G=1;H=0;
	_delay_ms(turn);
	E=0;F=1;G=0;H=0;
	_delay_ms(turn);
	E=1;F=1;G=0;H=0;
	_delay_ms(turn);
	E=1;F=0;G=0;H=0;
	_delay_ms(turn);
	E=0;F=0;G=0;H=0;
}

void turn_down(void){
	E=1;F=0;G=0;H=0;
	_delay_ms(turn);
	E=1;F=1;G=0;H=0;
	_delay_ms(turn);
	E=0;F=1;G=0;H=0;
	_delay_ms(turn);
	E=0;F=1;G=1;H=0;
	_delay_ms(turn);
	E=0;F=0;G=1;H=0;
	_delay_ms(turn);
	E=0;F=0;G=1;H=1;
	_delay_ms(turn);
	E=0;F=0;G=0;H=1;
	_delay_ms(turn);
	E=0;F=0;G=0;H=0;
}

void faze(void){		//testovací nabuzení fáze
	A=1;B=0;C=0;D=0;
	_delay_ms(3000);
	A=0;
}

void play(unsigned char set){	//start/stop přehrávače
	PLAY=set;
}

void next(void){		//přehraj další skladbu(nepoužito)
	NEXT=1;
	_delay_ms(100);
	NEXT=0;
}
//************************* začátek automat funkce ********************************
void automat(void){

	unsigned char i=0;

	while((END3)&&(!autoinit))	//dokud je nesepnut doraz a zároven není auto režim připraven
		turn_left();		//najede si na kraj otáčení
		_delay_ms(400);
	if(autoinit==0){	//poodjede o 5 kroků od kraje otáčení, pak začne automatika
		for(i=0;i<5;i++){
			turn_right();
			_delay_ms(4);
		}
		_delay_ms(200);
		autoinit=1;		//bylo bezpečně odjeto od kraje otáčení
	}
	for(i=0;i<26;i++)	//točí 180st doprava 
		turn_right();
	_delay_ms(800);
	play(1);			//začne hrát zvuk
	for(i=0;i<5;i++)	//naklopí hore dole
		turn_down();
	_delay_ms(1000);
	for(i=0;i<10;i++)
		turn_up();
	_delay_ms(1000);
	for(i=0;i<5;i++)
		turn_down();
	_delay_ms(5000);	//počká 5 s
	play(0);			//vypne přehrávku
	_delay_ms(25000);	//ještě 25 s počká

	for(i=0;i<26;i++)	//to stejné zpět doleva
		turn_left();
	_delay_ms(800);
	play(1);
	for(i=0;i<5;i++)
		turn_down();
	_delay_ms(1000);
	for(i=0;i<10;i++)
		turn_up();
	_delay_ms(1000);
	for(i=0;i<5;i++)
		turn_down();
	_delay_ms(5000);		
	play(0);
	_delay_ms(25000);

}
//************************* konec automat funkce ********************************

//************************* obsluha přerušení od časovače0 ********************************
ISR(TIMER0_COMP_vect) {

unsigned char i,tresh;

	cnt++;	//čítač milisekundy
	usart=UDR;	//vyčtení každého přijatého znaku z USART jednotky
	if(END4==0){	//kontrola jestli není dosažen koncový spínač je-li otáčeno
		last='r'; //naposledy byl dosažen pravý doraz!
	}
	if(END3==0){
		last='l'; //naposledy byl dosažen levý doraz!
	}
	if(usart!=0){	//není-li USART jednotka prázdná
		for(i=6;i!=0;i--)	//vytvoř v bufferu místo pro nový znak
			buf[i]=buf[i-1];
		buf[0]=usart;		//nový znak ulož na začátek bufferu
		if((buf[1]==170)&&(buf[2]==170)&&(buf[3]==170)&&(buf[4]==170)&&(buf[5]==170)&&(buf[6]==170)){ //znak 170 6x po sobě?
			switch(buf[0]){ // rozhodni o příkazu
				case ('r'): if(last!='r'){		//manuální povely
								turn_right();
								last=0;
							}
							break;
				case ('l'): if(last!='l'){
								turn_left();
								last=0;
							}
							break;
				case ('u'): turn_up();break;
				case ('d'): turn_down();break;
				case ('p'): play(1);break;
				case ('s'): play(0);break;
				case ('a'):	aut=1;break;	//zapíná automatiku v hlavní smyčce programu
				case ('m'):	aut=0;	//vypíná automatiku
							autoinit=0;	//není zaručena inicializace polohy pro automatiku
							break;
				default: ;
			}
		}
	}

	if(cnt==5001){	
		ADCSRA |= 0x40;  
		while ((ADCSRA & 0x10)==0);  
    	ADCSRA |= 0x10;  
		tresh=ADCH;		//každých 5 s změř napětí baterky
		if(tresh<(0xC1))	//je-li menší než 6,22 V
			LED_RED=1;		//zapni výstražnou LED_RED
		else LED_RED=0;	
		cnt=0;  
	}
}
//*********************** konec obsluhy přerušení od časovače0******************



//*********************  začátek main funkce  ********************************************************
void main(void){

	DDRA=0b11111100;		//PORTA vystupy pro motory
	DDRD=0b00111110;		//koncove spinace, play, next, int1, enable Rx, USART_Tx, USART_Rx
	DDRB=0b10111111;		//PORTB vystupy pro motory
	PORTA=0b00000011;		//žádná fáze buzena, nastaveny int. pull-upy
	PORTD=0b11000000;		//nastaveni pullupů a počáteční hodnoty enable Rx=0
	_delay_ms(1000);		//počká na inicializaci Rx modulu
	bit_set(PORTD,2);		//zapne Rx modul
	uart0_init();			//inicializuje uart0
	adc_init();				//inicializuje AD převodník
	timer0_init();			//zapne časovač 1 ms
//	asm volatile("WDR"::);
//	WDTCR=0b00001111;		//zapne watchdog s intervalem 2,1 s
	LED_GR=1;				//indikace zapnutého stavu
	asm volatile("sei"::);	//povolí všechna přerušení

	
	for(;;)
	{
		if(aut==1){		//hlídá jestli má zapnout automatiku, jinak jede manuál
			automat();
		}
//		asm volatile("WDR"::);
	}	

}



