/************************************************
	 Software pro pristroj opticky biosenzor
		
		- MCU: 			ATMEGA 128 (TQFP64)
		- prostredi:	AVR studio 4.15.623
		- programoval:	Jiri Sedlacek  

		- soubor: 		MCU_bio_hlavni.c	

***************************************************/

#define FOSC 11059200
#define BAUD 9600
#define MYUBRR 71//FOSC/(16*BAUD)-1 z katalogoveho listu
//#define VELIKOSTPOLE 20

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sleep.h>

//funkce pouzite v programu
void SetDA(unsigned char Data, unsigned char Prikaz, unsigned char Adresa); //hlavni pro DA prevodnik
void PosliData(unsigned char SendData);//pro DA prevodnik
void SpustLED(unsigned char poradi);// spusteni × vypnuti LED
//unsigned int prumer(void); //pocitani prumeru

/*void USART_INIT (unsigned int ubrr); //inicializace usartu
void USART_TX (unsigned char data) //vysilani
*/

volatile unsigned char maskaData; //pro DA
volatile unsigned char maskaHodin; //pro DA
volatile unsigned short int RxBuff[2]; //zasobnik prijatych dat
volatile unsigned char i=0; //index pole
volatile unsigned char mereni; // fce pro mereni je-li 1 měří se
volatile unsigned char perioda; //perioda pro blikani led


// fce pro USB - USART
//incializace
void USART_INIT (unsigned int ubrr) //inicializace usartu
{
	UCSR1A = 0x20;	
	UCSR1B = 0x98; // nataveni preruseni
	UCSR1C = 0x0E; 	//nastaveni parametru prenosu: 8b data, 2b stop, asynchronni, bez parity
	UBRR1H = (unsigned char) (ubrr>>8); //nastaveni rychlost prenosu podle vypoctu
	UBRR1L = (unsigned char) (ubrr & 0xFF);		//nastaveni rychlosti prenosu
}

//vysilani nekonecne
void USART_TX (unsigned char data) //vysilani
{
	while (!(UCSR1A &(1<<UDRE))); //cekani na prazdny vystupni zasobnik
	UDR1 = data;	//registr dat
}

//preruseni po prijmu dat
ISR(USART1_RX_vect)
{
	
	RxBuff[i]=UDR1;	//naplneneni pomocneho zasobniku pikaz pole 0 data pole 1	
	i++;
	if (i==2)
		{
		 	switch (RxBuff[0]) //povadeni porgramu
				{
				case 0: //spusteni LED 
					SpustLED(RxBuff[1]);
				break;
				
				case 1: //nastaveniDA
					SetDA(RxBuff[1],0,0);
				break;
				
				case 2: //nastaveniDA
					SetDA(RxBuff[1],0,1);
				break;
				
				case 3: //nastaveniDA
					SetDA(RxBuff[1],0,2);
				break;

				case 4: // spusteni × vypnuti mereni
					mereni=RxBuff[1]; 
				break;

				case 5: // prepinani LED cas
					perioda=RxBuff[1];
				break;	
				
				
					
				}
		i=0;		 
		}
}


ISR(ADC_vect) //preruseni pro prevod AD - kvuli sumu
{
}

ISR(TIMER1_COMPA_vect) //blikani v preruseni
{
static unsigned char cas=0;


if (perioda!=0)
	{
	if (perioda<cas) cas=perioda;
	cas--;
	if (cas == 0)
		{
		cas=perioda;
		PORTC ^= 0x03;	
		}
		
	}

}

//	funkce pro externi DA prevodnik na portech A0 ..A6
/*20 data 10 hodiny*/

void SetDA(unsigned char Data, unsigned char Prikaz, unsigned char Adresa)
{	
	switch (Adresa)
		{
		case 0:
			maskaData=0x02;
			maskaHodin=0x01;
			break;
		case 1:
			maskaData=0x08;
			maskaHodin=0x04;
			break;
		default:
			maskaData=0x20;
			maskaHodin=0x10;
			break;
		}
	
	PORTA |= maskaData | maskaHodin; //inicializace portu clk i data log 1 out
	_delay_us(100);
 	DDRA |= maskaData | maskaHodin;
	_delay_us(100);
	PORTA &= ~(maskaData); //Start bit data do log0 
	_delay_us(100);
 	PORTA &= ~(maskaHodin); //hoidny log 0
	_delay_us(100);

 	PosliData(0x90); //Adresa prevodniku
	_delay_us(100);
 	
	if ((PINA & maskaData)==0x00) // je li log 0 prislo spravne potvrzeni
 		{
			// posila data
			PORTA &= ~(maskaData); // port na vystup 
			_delay_us(100);
 			DDRA |= maskaData;
			_delay_us(100);
			PORTA &= ~(maskaHodin);
			_delay_us(100);
 			PosliData(Prikaz); //Prikaz
			_delay_us(100);
			
			
			if ((PINA & maskaData)==0x00)
				{
					PORTA &= ~(maskaData);
					_delay_us(100);
 					DDRA |= maskaData;
					_delay_us(100);
					PORTA &= ~(maskaHodin);
					_delay_us(100);
 					PosliData(Data); // posila data
					_delay_us(100);
				}
 		}
 	
	PORTA &= ~(maskaData);
	_delay_us(100);
 	DDRA |= maskaData;
	_delay_us(100);
 	PORTA &= ~(maskaHodin);
	_delay_us(100);
 	PORTA |= maskaHodin; //stop bit
	_delay_us(100);
 	PORTA |= maskaData;
	_delay_us(100);
}

// pole 8b a nastavi hodiny a data aby se dal prijmout info o spravnem prenosu
void PosliData(unsigned char SendData)
{	
	unsigned char P=8;
	unsigned char SendingData;
	SendingData = SendData;

	_delay_us(100);
	
	while (P!=0)
		{	
		if (SendingData & 0x80) //Vlozeni dat
			PORTA |= maskaData;
		else
			PORTA &= ~(maskaData);
			_delay_us(100);
			SendingData *= 0x02;
			_delay_us(100);
			PORTA |= maskaHodin; //Start Clocku
			_delay_us(100);
			PORTA &= ~(maskaHodin); //Zruseni Clocku
			_delay_us(100);
			P--;
		}
	
	PORTA &= ~(maskaData | maskaHodin); //Zruseni poslednich dat
	DDRA &= ~(maskaData); //Port Dat zmenit na vstupni
	_delay_us(100);
	PORTA |= maskaData;
	_delay_us(100);
	PORTA |= maskaHodin; //Start Clocku pro Acknowledge
	_delay_us(100);
}


//Spusti dane vystupni zdroje proudu, aktivni=log 0  
void SpustLED(unsigned char poradi)
{	
		switch (poradi) 
		{
			case 0: //spusteni prvni LED
			{
				PORTC |= 0x02; 
				PORTC &= 0xFE;
				break;
			}

			case 1: //spusteni druhe LED
			{
				PORTC |= 0x01;
				PORTC &= 0xFD;
				break;
			}
		
			case 2: //spusteni obou ledek
			{
				PORTC &= 0xFC; 
				break;	
			}

			default: // vypnuti obou ledek
			{
				PORTC |= 0x03; 
				break;	
			}
		}

}



// fce pro AD prevodnik 10bit
unsigned short int ADkonv (void)
{
	unsigned short int cislo;
	
	set_sleep_mode(SLEEP_MODE_ADC);

	sleep_mode();

	


	//ADCSRA |=0x40;
	while (ADCSRA & 0x40);
	
	cislo = (unsigned short int)(ADCL);
	cislo |= ((unsigned short int)(ADCH))<<8;
	
	return cislo;
}

//fce pro vypocet prumeru
/*unsigned int prumer(void)
{
	unsigned short int pole[VELIKOSTPOLE]; 	//pole pro ukladnai hodnot
	unsigned short int p; //pocitadlo
	unsigned short int soucet=0; //promena pro soucet
	unsigned short int avg; //vysledny prumer
	
	for(p=0;p<VELIKOSTPOLE;p++) //naplneni pole datama z AD prevodniku
		{
		pole[p]=ADkonv;
		}

	for(p=0;p<VELIKOSTPOLE;p++) //vypocet souctu prvku pole
		{
		soucet=soucet+pole[p];
		}
	
	avg=soucet/VELIKOSTPOLE; //vypocet prumeru
	return avg;
}*/

int main (void)
{
    unsigned short int data;
	unsigned char pomdat;	
	
	//inicializace
	 
	
	ADMUX = 0x40; //AD prevodnik
	ADCSRA = 0x8F;//AD prevodnik 
	
	DDRD = 0x08; //porty D pro vystup kvuli USARTU
	PORTD = 0x0C; 
	DDRC = 0xFF; //porty C pro vystup
	
	DDRF =0x00;
	PORTF = 0x00;	
	
	USART_INIT (MYUBRR); //USARTu komuniakce s FTDI 

	// nataveni casovace	
	TCCR1A = 0;
	TCCR1B = 0x0D;
	OCR1AH = 0x2A;
	OCR1AL = 0x2F;
	TIMSK |= 0x10;
	//perioda=1;
	
	sei();// povoleni preruseni
	//konec iniciliazace
	
	

	SpustLED(3); //vypnuti obou LED
	//Spusteni prevodniku
	SetDA (0,1,0); 
	SetDA (0,1,1);
	SetDA (0,1,2);

	/*SetDA(100,0,0);
	SetDA(100,0,1);
	SpustLED(1);	
*/
	while(1)
	{
		while(mereni==1)
		{
		data=ADkonv();
		//data=prumer();
		
		pomdat=(unsigned char)(PORTC << 5) & 0x60;
		
		//if((perioda!=0) && ((PORTC & 0x02)!=0)) data += 2048;
		//data=((unsigned short int)(PORTC) & 0x02)*100;
		
		USART_TX(((unsigned char) (data>>5) & 0x1F)|pomdat|0x80);
		USART_TX(((unsigned char) (data & 0x1F))|pomdat);
   		_delay_ms(10);
		}
	}

}
