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

	Nazev:				GENERATOR FUNKCI DDS 10 MHz 1.0
	Autor:				GAL Radek
	Zarizeni:			ATmega32
	Vyvoj. prostr.:		AVR Studio 4.18

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

#define XTAL 		1000000
#define F_CPU 		1000000
#define SINE	 	0x2028		//SINE = 0b10 0000 0010 1000
#define TRIANGLE 	0x2002		//TRIANGLE = 0b10 0000 0000 0010

#include <avr/io.h>
#include "lcd_h.h"
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>

unsigned long frequency=0;
unsigned long bits;
unsigned long lsb_bits=0;
unsigned long msb_bits=0;
unsigned long deltafreq=1;
unsigned long waveform=SINE;
unsigned char lcd_freq[16];
unsigned char lcd_voltage[8];

volatile unsigned char znak[];

void USART0SendByte(uint8_t u8Data){	//Funkce pro odeslani

	while(!(UCSRA&(1<<UDRE))){};	//Cekani pro kompletni odelsani dat
	// Transmit data
	UDR = u8Data;					//Vyslani dat
}

uint8_t USART0ReceiveByte(){	//Funkce pro prijem

	while(!(UCSRA&(1<<RXC))){};	//Cekani pro prijem
	// Return received data
	return UDR;
}

void USART0Init(void)	//Inicializace UART jednotkz
{
	
	UCSRA=0x00;
	UCSRB=0x98;	//povoli preruseni pri prijmu
	UCSRC=0x86;
	UBRRH=0x00;
	UBRRL=0x0C;	
}

ISR(USART_RXC_vect){	//Obsluha UART pri prijmu preruseni
	

		uint8_t u8TempData;
		u8TempData = USART0ReceiveByte();
		USART0SendByte(u8TempData);
		
		switch( u8TempData){
			
		case 253:	lcd_gotoxy( 13, 1);	//Nastaveni harm. prubehu
					lcd_puts( "SIN");	//Indikace prubehu na displeji
					PORTD &= ~(1<<PD7);//Sepne RE2
					send( SINE);
					break;

		case 254:	lcd_gotoxy( 13, 1);	//Nast. troj. prubehu
					lcd_puts( "TRI");	//Indikace prubehu na displeji
					PORTD |= (1<<PD7);
					send( TRIANGLE);
					break;

		case 255:	lcd_gotoxy( 15, 0);		//Sepnuti rele
					if((PIND & (1<<PD6))==0){//Pokud je rele sepnuto
						PORTD |= (1<<PD6);
						PORTD |= (1<<PD7);	//Vypne rele
						lcd_putc( ' ');}	//Indikace sepnuti
					else{
						PORTD &= ~(1<<PD6);
						PORTD &= ~(1<<PD7);
						lcd_putc( 'O');}
					break;

		default:	frequency = u8TempData;	//Nastaveni frekvence
					
					lcd_gotoxy( 3, 0);
					sprintf( lcd_freq,"%d Hz     " ,frequency);
					lcd_puts( lcd_freq);
					send( waveform);	//waveform = sinus
					word( frequency);	//frequency = 0 Hz
					//deltafreq=1;
		}		
}	

void send( unsigned long bits){	//Funkce pro komunikaci s AD9834


	//PB0 = SDATA
	//PB1 = SCLK
	//PB3 = FSYNC
	PORTB &= ~(1<<PB3);		//FSYNC=0
	PORTB |= (1<<PB1);		//SCLK=1

	for( int i=0; i<16; i++){
		if( bits&0x8000)//testovani bitu s 1000 0000 0000 0000
			PORTB |= (1<<PB0);	//SDATA=1
		else
			PORTB &= ~(1<<PB0);	//SDATA=0
			PORTB &= ~(1<<PB1);	//SCLK=0
			PORTB |= (1<<PB1);	//SCLK=1
			bits=bits<<1;	//Posuv doleva
		};	//konec for cyklu
			
	PORTB |= (1<<PB3);	//FSYNC=1
};	//konec send


void word( unsigned long frequency){	//Funkce pro upravu FSW slova
	
	unsigned long lsb, msb;
	frequency=frequency*8.94785;	//Vynasobeno 2^28/fclk
	frequency=frequency<<2;			//Zarovnani MSB poloviny doprava
	lsb=frequency;
	msb=frequency>>16;
	lsb=lsb>>2;						//Zpetne zarovnani LSB poloviny

	lsb=(lsb&0x7FFF)|0x4000;		//Volba FREQ0
	msb=(msb&0x7FFF)|0x4000;

	send( lsb);
	send( msb);
};	//konec word

ISR(ADC_vect){	//Zpracovani namerenych hodnot

	int voltage;

	voltage=ADCW-840;	//Nastaveni referencni urovne 0 dBV
	lcd_gotoxy( 0, 1);
	sprintf( lcd_voltage, "U= %.2f dBV ", voltage);
	lcd_puts( lcd_voltage);
};

int main ( void){


	//Inicializace portu	
	DDRA=0x00;	//Port A vstupni	
	PORTA=0xFC;	//Nastavi na pinech PA2-PA7 PULL-UP rezistory

	DDRB=0x0F;	//Spodni polovina portu B vystupni
	PORTB=0x0F;	//Na spodni polovine portu nastavi 1

	DDRD=0xF2;	//DDRB=0b11110010
	PORTD=0xFF;	//Na vystupech nastavi uroven H

	USART0Init();	//Inicializace jednotky UART
	lcd_init();	//Inicializace LCD displeje
	lcd_puts( "Generator funkciDDS 10 MHz");	//Tisk uvodniho textu

	ADMUX |= ( 1<<REFS0) | ( 1<<REFS1);// | (1<<MUX4);
	ADCSRA |= ( 1<<ADEN) | ( 1<<ADSC) | ( 0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

	//Inicializace DDS obvodu
	send(0x2100);	//0b10 0001 0000 0000
	send(0x2000);	//0b10 0000 0000 0000
	send( waveform);	//waveform = sinus
	word( frequency);	//frequency = 0 Hz

	_delay_ms(500);
	lcd_clrscr();		//Smazani obsahu LCD displeje
	lcd_gotoxy( 0, 0);	
	lcd_puts("f= 0 Hz");		//Tisk frekvence
	lcd_gotoxy( 15, 0);
	lcd_putc( 'O');		//Tisk indikace sepnuti vystupu
	lcd_gotoxy( 0, 1);
	lcd_puts( "U=");	//Tisk urovne
	lcd_gotoxy( 8, 1);
	lcd_puts( "dBV");
	lcd_gotoxy( 13, 1);
	lcd_puts( "SIN");	//Tisk prubehu

	sei();

	PORTD=0x0F;		//Po probehnuti celkove inicializace sepne vystup
	uint8_t u8TempData;

	while( 1){	//Nekonecna smycka

		//Ovladani vystupnich rele RE1=PD6, RE2=PD7
		if((PINA & (1<<PA2))==0){		//Pokud je stisknuto tlacitko RE
		_delay_ms(100);					//Osetreni zakmitu tlacitka
		if((PINA & (1<<PA2))==0)		//Pokud je stale stisknuto tlacitko RE
			
			if(PIND & (1<<PD6 )){		//Pokud je RE1 vypnuto
			if( waveform==SINE){		//Pokud je generovan sinus
			PORTD &= ~(1<<PD6);			//Sepne RE1, PD6=0
			PORTD &= ~(1<<PD7);}		//Sepne RE2, PD7=0
			else{						//Pokud je generovan trojuhelnik
			PORTD &= ~(1<<PD6);}		//Sepne pouze RE1, PD6=0
			lcd_gotoxy( 15, 0);
			lcd_putc( 'O');}			//Indikace sepnuti na displeji
			
			else{						//Pokud je RE1 sepnuto
			if( waveform==SINE){		//Pokud je generovan sinus
			PORTD |= (1<<PD6);			//Vypne RE1
			PORTD |= (1<<PD7);}			//Vypne RE2
			else{						//Pokud je generovan trojuhelnik
			PORTD |= (1<<PD6);}			//Zapne pouze RE1				
			lcd_gotoxy( 15, 0);
			lcd_putc( ' ');}				//Indikace vypnuti na displeji
			
			while( (PINA & (1<<PA2))==0){	//Cekani na uvolneni tlacitka
			};
		};

	
		if((PINA & (1<<PA4))==0){		//Zmena prubehu
			_delay_ms(100);				//Osetreni zakmitu tlacitka
			if((PINA & (1<<PA4))==0)	//Pokud je stale stisknuto tlacitko
			
				if( waveform==SINE){	//Pokud je generovan sinus
					waveform=TRIANGLE;	//Zmeni se na trojuhelnik
					lcd_gotoxy( 13, 1);
					lcd_puts( "TRI");	//Indikace prubehu na displeji
					PORTD |= (1<<PD7);}	//Vypne RE2
					
				else{					//Pokud je generovan trojuhelnik
					waveform=SINE;		//Zmeni se na sinus
					lcd_gotoxy( 13, 1);
					lcd_puts( "SIN");	//Indikace prubehu na displeji
					PORTD &= ~(1<<PD7);}//Sepne RE2
					
				send( waveform);		//Posle zmenu prubehu do DDS obvodu

				while( (PINA & (1<<PA4))==0){	//Cekani na uvolneni tlacitka
				};	
			};


		if((PINA & (1<<PA5))==0){		//Kurzor doprava
			_delay_ms(100);				//Osetreni zakmitu tlacitka
			if((PINA & (1<<PA5))==0)	//Pokud je stale stisknuto tlacitko
				if( deltafreq==1){		//Osetreni, aby deltafreq nebylo mensi nez 1
					deltafreq=10000000;}	
				else{
					deltafreq=deltafreq/10;}
					
			while( (PINA & (1<<PA5))==0){	//Cekani na uvolneni tlacitka
				};		
			};	
	

		if((PINA & (1<<PA7))==0){		//Kurzor doleva
			_delay_ms(100);				//Osetreni zakmitu tlacitka
			if((PINA & (1<<PA7))==0)
				if( deltafreq==10000000){
					deltafreq=1;}
				else{
					deltafreq=(deltafreq*10);
					}
			while( (PINA & (1<<PA7))==0){	//Cekani na uvolneni tlacitka
				};
			};
		

			if((PINA & (1<<PA3))==0){		//Inkrementace
			_delay_ms(100);					//Osetreni zakmitu tlacitka
			if((PINA & (1<<PA3))==0){
				frequency=frequency+deltafreq;
				
				if( frequency>=10000000)	frequency=10000000;	//Osetreni pri preteceni
				sprintf( lcd_freq,"f= %d Hz ",frequency);	//Tisk frekvence
				lcd_firstline() ;			//Vymazani a skok na prvni radek
				lcd_puts( lcd_freq);		//Tisk frekvence

				send( waveform);			//Vysle informaci o prubehu
				word( frequency);}			//Vysle cislo frekvence	
			};


			if((PINA & (1<<PA6))==0){		//Dekrementace
			_delay_ms(100);				//Osetreni zakmitu tlacitka
			if((PINA & (1<<PA6))==0){
				frequency=frequency-deltafreq;
				
					if( deltafreq==1000000 && frequency<1000000){	//Osetreni, aby nedochazelo k nastaveni "zaporne" frekvence
					frequency=999999;
					deltafreq=deltafreq/10;}
					if( deltafreq==100000 && frequency<100000){
					frequency=99999;
					deltafreq=deltafreq/10;}
					if( deltafreq==10000 && frequency<10000){
					frequency=9999;
					deltafreq=deltafreq/10;}
					if( deltafreq==1000 && frequency<1000){
					frequency=999;
					deltafreq=deltafreq/10;}
					if( deltafreq==100 && frequency<100){
					frequency=99;
					deltafreq=deltafreq/10;}
					if( deltafreq==10 && frequency<10){
					frequency=9;
					deltafreq=deltafreq/10;}
					if( frequency<=1)	frequency=1;
				
				sprintf( lcd_freq,"f= %d Hz ",frequency);	//Vypis na LCD
				lcd_firstline() ;
				lcd_puts( lcd_freq);
					
				send( waveform);
				word( frequency);}			//Nastaveni AD9834
			};



		if((PIND & (1<<PD2))==0){		//Obsluha rotacniho tlacitka
			_delay_ms(20);
			while( ((PIND & (1<<PD2))==0)){	//Cekani na sestupnou hranu
			};
		//	int n;	
			if((PIND & (1<<PD3))==0){		//Pokud bude PD3=0
				
				frequency=frequency+deltafreq;
				if( frequency>=10000000)	frequency=10000000;	//Osetreni pri preteceni
				sprintf( lcd_freq,"f= %d Hz",frequency);	//Tisk frekvence
				lcd_firstline() ;			//Vymazani a skok na prvni radek
				lcd_puts( lcd_freq);		//Tisk frekvence

				send( waveform);			//Vysle informaci o prubehu
				word( frequency);}	
			else{
				if( frequency==1){			//Osetreni proti zapornym frekvencim
					}
				else{
					frequency=frequency-deltafreq;
				
					if( deltafreq==1000000 && frequency<1000000){	//Osetreni, aby nedochazelo k nastaveni "zaporne" frekvence
					frequency=999999;
					deltafreq=deltafreq/10;}
					if( deltafreq==100000 && frequency<100000){
					frequency=99999;
					deltafreq=deltafreq/10;}
					if( deltafreq==10000 && frequency<10000){
					frequency=9999;
					deltafreq=deltafreq/10;}
					if( deltafreq==1000 && frequency<1000){
					frequency=999;
					deltafreq=deltafreq/10;}
					if( deltafreq==100 && frequency<100){
					frequency=99;
					deltafreq=deltafreq/10;}
					if( deltafreq==10 && frequency<10){
					frequency=9;
					deltafreq=deltafreq/10;}
					if( frequency<=1)	frequency=1;
				
				sprintf( lcd_freq,"f= %d Hz",frequency);	//Tisk frekvence
				lcd_firstline() ;
				lcd_puts( lcd_freq);
					
				send( waveform);
				word( frequency);}			//Nastaveni AD9834
				}
			//_delay_ms(10);
			};
	
	/*n++; 

	if( n==10000){
	ADCSRA |= (1<<ADEN) | (1<<ADSC);
	n=0;}*/

	};	//konec smycky while

	return 0;
}





// END
