/*
 * GccApplication1.c
 *
 * Created: 31.10.2016 17:13:54
 * Author : Sinan
 
 
 Aufgaben
 Variablen ordnen
 Quellcode vereinfachen
 
 Diese Headerdatei soll die erste Hauptheaderdatei sein.
 
 
 */ 

#include <stdio.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>




void set_timer1 (uint8_t mode, uint8_t config );

void set_timer1_CTC_freq(uint32_t f_CLK);
void set_timer1_CTC_freqchange (uint32_t freq, uint32_t acc);



//---------------------------------------------------------------------------------------------------------------------------

uint8_t acc_ctrlreg = 0;				// Bit 0 Beschleunigungs-Enable, Bit 1 Berechnungsfreigabe, Bit 2 Ganzzahldifferenzdetektierung, Bit 3 Beschleunigung / Verzögerung
uint8_t motor_ctrlreg = 1;				// 0 = Vollschritt, 1 = Halbschritt, 2 = 4* Mikroschritt, 3 = 8* Mikroschritt, 4 = 16* Mikroschritt, 5 = 32* Mikroschritt






double f_CLK_n1, f_CLK_n2 = 0;			// Faktor Tausend 1Hz --> 1000;		// Angabe für die aktuelle Taktfrequenz


uint32_t f_CLK_global = 0;





//---------------------------------------------------------------------------------------------------------------------------

uint32_t f_CPU = 8000000;











//EEPROM-Befehle
//eeprom_write_byte ((uint8_t*) 23, 64); //  write the byte 64 to location 23 of the EEPROM
//uint8_t byteRead = eeprom_read_byte((uint8_t*)23); // read the byte in location 23


/*
Ein-Ausgaberegister

Bit			7		6		5		4		3		2		1		0
0x05 (0x25) PORTB7 PORTB6	PORTB5	PORTB4	PORTB3	PORTB2	PORTB1 PORTB0	PORTB		// Bei DDxn == 1, PORTxn == 1 --> High, PORTxn == 0 --> low

Bit			7		6		5		4		3		2		1		0
0x04 (0x24) DDB7	DDB6	DDB5	DDB4	DDB3	DDB2	DDB1	DDB0	DDRB		// DDxn == 1 --> Ausgang, DDxn == 0 --> Eingang

Bit			7		6		5		4		3		2		1		0
0x03 (0x23) PINB7	PINB6	PINB5	PINB4	PINB3	PINB2	PINB1	PINB0	PINB

*/

void set_timer1 (uint8_t mode, uint8_t config )
{
	switch (mode)
	{
		case 0:	{	// Mode 0 Normal
			TCCR1A &= ~0x03;
			TCCR1B &= ~0x18;
			break;
		}
		
		case 4:	{	// Mode 4 CTC
			TCCR1A &= ~0x03;
			TCCR1B &= ~0x18;
			TCCR1B |= 0x08;
			break;
		}
		
		case 14:{	// Mode 14 Fast PWM (ICR1 Top value)
			TCCR1A &= ~0x03;
			TCCR1B &= ~0x18;
			TCCR1A |= 0x02;
			TCCR1B |= 0x18;
			break;
		}
	}
	
	
	switch (config)
	{
		case 0:	{
			TCCR1A &= ~0xC0;		// Normal port operation, OC0A disconnected.						config 0
			TCCR1A &= ~0x30;		// Normal port operation, OC0B disconnected.						config 0
			cli();
			break;
		}
		
		case 10:{
			TCCR1A |= 0x40;			//config 1	// CTC- toggle on compare match - chanel A
			TIMSK1 |= 0x02;		// OCIE1A
			
			DDRB |= 0x02;
			sei();
			break;
		}
		
		case 20:{
			TCCR1A |= 0x80;			//config 2	// fastPWM- non-inverting mode	- chanel A
			TIMSK1 |= 0x02;		// OCIE1A
			
			DDRB |= 0x02;
			sei();
			break;
		}
		
		case 01:{
			TCCR1A |= 0x10;			//config 1	// CTC- toggle on compare match - chanel B
			TIMSK1 |= 0x04;		// OCIE1B
			
			DDRB |= 0x04;
			sei();
			break;
		}
		
		case 02:{
			TCCR1A |= 0x20;			//config 2	// fastPWM- non-inverting mode	- chanel B
			TIMSK1 |= 0x04;		// OCIE1B
			
			DDRB |= 0x04;
			sei();
			break;
		}
		
		case 11:{
			TCCR1A |= 0x40;			//config 1	// CTC- toggle on compare match - chanel A
			TCCR1A |= 0x10;			//config 1	// CTC- toggle on compare match - chanel B
			TIMSK1 |= 0x06;		// OCIE1A and OCIE1B
			
			DDRB |= 0x06;
			sei();
			break;
		}
		
		case 22:{
			TCCR1A |= 0x80;				//config 2	// fastPWM- non-inverting mode	- chanel A	// // Beide Ausgänge hängen von OCR0A ab
			TCCR1A |= 0x20;				//config 2	// fastPWM- non-inverting mode	- chanel B
			TIMSK1 |= 0x06;		// OCIE1A and OCIE1B
			
			DDRB |= 0x06;
			sei();
			break;
		}
	}
}



void set_timer1_CTC_freq(uint32_t f_CLK)	// f_clk ist um den Faktor 1000 größer einzugeben, 1,25Hz --> 1250
{
	if (f_CLK <250)								//Prescaler 256   0,25Hz bis 100 Hz
	{
		TCCR1B &= ~0x07;							// timer stopped
		OCR1A = ((f_CPU/(0.001*f_CLK*2*256))-1);
	}
	
	if (f_CLK >=250 && f_CLK < 100000)			//Prescaler 256   0,25Hz bis 100 Hz
	{
		TCCR1B &= ~0x07;
		TCCR1B |= 0x04;							// set the prescaler to 256
		OCR1A = ((f_CPU/(0.001*f_CLK*2*256))-1);
	}
	
	if (f_CLK >=100000 && f_CLK < 250000)		// Prescaler 64   100Hz bis 250 Hz
	{
		TCCR1B &= ~0x07;
		TCCR1B |= 0x03;							// set the prescaler to 64		
		OCR1A = ((f_CPU/(0.001*f_CLK*2*64))-1);
	}
	
	if (f_CLK >=250000 && f_CLK < 750000)		//Prescaler 8   250Hz bis 750 Hz
	{
		TCCR1B &= ~0x07;
		TCCR1B |= 0x02;							// set the prescaler to 8
		OCR1A = ((f_CPU/(0.001*f_CLK*2*8))-1);
	}
	
	if (f_CLK >=750000 && f_CLK < 2300000)		// Prescaler 1   750Hz bis 2300 Hz
	{
		TCCR1B &= ~0x07;
		TCCR1B |= 0x01;							// no prescaling
		OCR1A = ((f_CPU/(0.001*f_CLK*2*1))-1);
	}
	
	f_CLK_global = f_CLK;								// der neue Wert wird in der globalen Variable direkt übernommen;
	
}





void set_timer1_CTC_freqchange (uint32_t freq, uint32_t acc)
{
	f_CLK_n1 = f_CLK_global;
	
	DDRD |= 0xF0;
	
	acc_ctrlreg |= 0x01;					// Freigabe für die Beschleunigung
	acc_ctrlreg |= 0x02;					// Freigabe für die Berechnung der nächsten Zwischenfrequenz
	
	if (freq >= f_CLK_global)	// Überprüfung ob eine Beschleunigung oder verzögerung gewünscht ist
	{
		acc_ctrlreg |= 0x08;	// Beschleunigung
		PORTD |=0x80;			// visualisierung des Beschleunigungsbeginns
	}
	else
	{
		acc_ctrlreg &= ~0x08;	// Verzögerung
		PORTD |=0x40;			// visualisierung des Verzögerungsbeginn
	}
	
	while((acc_ctrlreg & 0x01) == 0x01)		// Überprüfung der BEschleunigungsfreigabe
	{
		
		if ((acc_ctrlreg & 0x02) == 0x02)	// Überprüfung der Berechnungsfreigabe
		{
			
			/*****************************************************************************************************************************************/	
			
			if ((acc_ctrlreg & 0x08) == 0x08)				// Wenn Beschleunigung
			{
				f_CLK_n2 = (acc/f_CLK_n1)+f_CLK_n1;			// Berechnung des nächsten Schrittes
				f_CLK_n1 = f_CLK_n2;
				
				if (f_CLK_n2 >= freq)						// Falls die Zielfrequenz überschritten wird wird eingegriffen, das ist der letzte Inkrementierungsschritt. Siehe unten
				{
					f_CLK_n2 = freq;
					acc_ctrlreg &= ~(0x01);					// Deaktiviert den BEschleunigungsvorgang, Beschleunigung somit abgeschlossen, Schleife wird verlassen
				}	
			}
			
			else											// VErzögerung
			{
				f_CLK_n2 = -(acc/f_CLK_n1)+f_CLK_n1;		// Berechnung des nächsten Schrittes
				f_CLK_n1 = f_CLK_n2;
				
				if (f_CLK_n2 <= freq)						// Falls die Zielfrequenz überschritten wird wird eingegriffen, das ist der letzte Inkrementierungsschritt. Siehe unten
				{
					f_CLK_n2 = freq;
					acc_ctrlreg &= ~(0x01);					// Deaktiviert den BEschleunigungsvorgang, Beschleunigung somit abgeschlossen, Schleife wird verlassen
				}
			}
			/*****************************************************************************************************************************************/		
					
			if ((f_CLK_n2 - f_CLK_global) >= 1 || (f_CLK_n2 - f_CLK_global) <= -1)		// Überprüft ob eine Ganzzahldifferenz zwischen Ist- und Soll-Wert vorliegt
			{
				acc_ctrlreg |= 0x04;								
			}
			
			acc_ctrlreg &= ~(0x02);											// deaktivierung der Freigabe für die nächste Berechnung damit das Programm nicht zurück in die Berechnung springen kann
		}
		//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		
		PORTD &= ~(0x10);			// nicht zu erklärender Fehler. Wenn dieser Befehl gelöscht wird, funktioniert die Rampe nicht mehr
		
		//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	}
	
	PORTD &= ~(0xC0);				// Schaltet die visualisierungsled ab
}


ISR( TIMER1_COMPA_vect )
{
	
	
	if ((acc_ctrlreg & 0x02) == 0)			// Inkrementierung nur solange keine Freigabe für die nächste Berechnung vorliegt
	{
		
		
		if ((acc_ctrlreg & 0x04) == 0x04)		// Überlauf zur nächsten Ganzzahl wird hier überprüft
		{
			set_timer1_CTC_freq(f_CLK_n2);
			acc_ctrlreg &= ~(0x04);
			
		}
		acc_ctrlreg |= 0x02;			// Frequenzänderung stattgefunden , Freigabe für die nächste Berechnung erteilt
	}
	
}








/*

void set_timer1_CTC_freqchange (uint32_t freq, uint32_t acc)
{
	f_CLK_n1 = f_CLK_global;
	
	DDRD |= 0xF0;
	PORTD |=0x40;			// visualisierung des Beschleunigungsbeginns
	
	a =1;					// Freigabe für die Beschleunigung
	b = 1;
	
	
	while((a == 1))
	{
		
		if (b == 1)
		{
			
			f_CLK_n2 = (acc/f_CLK_n1)+f_CLK_n1;	// Berechnung des nächsten Schrittes
			f_CLK_n1 = f_CLK_n2;
			
			
			if (f_CLK_n2 >= freq)
			{
				f_CLK_n2 = freq;					// Falls es zum Überlauf kommen sollte wird eingegriffen, das ist der letzte Inkrementierungsschritt. Siehe unten
				a = 0;								// Deaktiviert den BEschleunigungsvorgang, Beschleunigung somit abgeschlossen, Schleife wird verlassen
			}
			
			differenz = f_CLK_n2 - f_CLK_global;
			
			if (differenz >= 1)
			{
				c = 1;
			}
			
			b = 0;											// deaktivierung der Freigabe für die nächste Berechnung damit das Programm nicht zurück in die Berechnung springen kann
			
		}
		
		
		//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		
		PORTD &= ~(0x10);			// nicht zu erklärender Fehler. Wenn dieser Befehl gelöscht wird, funktioniert die Rampe nicht mehr
		
		//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

	}
	
	PORTD &= ~(0x40);
}


ISR( TIMER1_COMPA_vect )
{
	
	
	if (b == 0)			// Inkrementierung nur solange keine Freigabe für die nächste Berechnung vorliegt
	{
		
		
		if (c ==1)		// Überlauf zur nächsten Ganzzahl wird hier überprüft
		{
			f_CLK_2int = f_CLK_n2;
			set_timer1_CTC_freq(f_CLK_2int);
			c = 0;
			
		}
		b = 1;			// Frequenzänderung stattgefunden , Freigabe für die nächste Berechnung erteilt
	}
	
}

*/