// Deklarationen ==============================================================

// Festlegung der Quarzfrequenz

#ifndef F_CPU					
#define F_CPU 18432000UL			
#endif								


// Include von Header-Dateien

#include <avr/io.h>				// I/O-Konfiguration (intern weitere Dateien)
#include <avr/interrupt.h>		// Bibliothek zur Verwendung einer Interuptroutine
#include <stdbool.h> 			// Bibliothek fuer Bit-Variable
#include <util/delay.h>			// Definition von Delays (Wartezeiten)
#include <avr/sleep.h>

// Makros

#define SET_BIT(PORT, BIT)  ((PORT) |= (1<<BIT))	// Einzelbit auf Port SET
#define CLR_BIT(PORT, BIT)  ((PORT) &= ~(1<<BIT))	// Einzelbit auf Port RESET

// Konstanten

#define ON_TIME		30			// "Ein-Zeit" in Inkrementen zu 100 ms
#define OFF_TIME	30			// "Aus-Zeit" in Inkrementen zu 100 ms
#define VORTEILER_WERT 		90	// Faktor Vorteiler = 90 (Timerticks)
#define HUNDERTSTEL_WERT 	10	// Faktor Hundertstel = 10 (1/100 s)

// Definition der Variablen 

unsigned char vorteiler 	= VORTEILER_WERT;	// Zaehlvariable Vorteiler
unsigned char hundertstel 	= HUNDERTSTEL_WERT; // Zaehlvariable Hundertstel

bool drehen=1;				// Bitspeicher fuer Taste 1
bool motor1=0;				// Bitspeicher fuer Taste 2
bool neigen=1;				// Bitspeicher fuer Taste 3
bool motor2=0;				// Bitspeicher fuer Taste 4

bool timertick;					// Bit-Botschaft alle 0,111ms (bei Interrupt)
bool takt10ms;					// Bit-Botschaft alle 10ms
bool takt100ms;					// Bit-Botschaft alle 100ms

void motor(void);
void lese_Eingang(void);
void timer0(void);
void pwm_generator(void);


// Hauptprogramm ==============================================================

int main() 						// Start des Hauptprogramms
{	
	timer0();
	pwm_generator();
	sei();

//	SET_BIT(PORTD, PD5);		// Enable auf "High" setzten
//	SET_BIT(PORTD, PD6);		// Enable auf "High" setzten

	while(1)
	{
		//set_sleep_mode(SLEEP_MODE_IDLE);
      	//sleep_mode();

		if (takt10ms)			// alle 10ms:
		{
			takt10ms = 0;		// Botschaft "10ms" loeschen
			lese_Eingang();
		}
		if (takt100ms)			// alle 100ms: 
		{
			takt100ms = 0;		// Botschaft "100ms" loeschen
			motor();
		}
	}	
	return 0;

}								// Ende des Hauptprogramms

void pwm_generator(void)
{
	DDRB |= (1<<PB3);
	TCCR2A	|=	(1<<WGM21) |  (1<<WGM20);		//Modevorwahl Fast-PWM
	TCCR2A	|=	(1<<COM2A1) |  (0<<COM2A0);		//clear on Compare-match

	TCCR2B	|=	(1<<WGM22);								//Modevorwahl Fast-PWM
	TCCR2B	|=	(1<<CS22) |  (1<<CS21) |  (1<<CS20);	//Vorteiler N=1024
		
	TIMSK2  |=	(1<<TOIE2);						//Interrupt bei Overflow enable

	OCR2A = 100;
}

ISR (TIMER2_OVF_vect)		//Interrupt Overflow Timer2
{
	OCR2A;		//Keine Ahnung was hier stehen muss
}

void timer0(void)
{
	TCCR0A = 0;					// Timer 0 auf "Normal Mode" schalten
	TCCR0B |= (1<<CS01);		// mit Prescaler /8 betreiben
	TIMSK0 |= (1<<TOIE0);		// Overflow-Interrupt aktivieren
}

ISR (TIMER0_OVF_vect)	// Modul funktioniert!!

/* In der Interrupt-Routine sind die Softwareteiler für die Taktbotschaften 
   (10ms, 100ms) realisiert. Die Interrupts stammen von Timer 0 (Interrupt 1)

   Verwendete Variable:	vorteiler
						hunderstel

   Ausgangsvariable:	takt10ms
						takt100ms
*/
{
	timertick = 1;					// Botschaft 0,111ms senden
	--vorteiler;					// Vorteiler dekrementieren
	if (vorteiler==0)				// wenn 0 erreicht: 10ms abgelaufen
	{
		vorteiler = VORTEILER_WERT;	//    Vorteiler auf Startwert
		takt10ms = 1;				//    Botschaft 10ms senden
		--hundertstel;				//    Hunderstelzähler dekrementieren

		if (hundertstel==0)			// wenn 0 erreicht: 100ms abgelaufen
		{
			hundertstel = HUNDERTSTEL_WERT; // Teiler auf Startwert
			takt100ms = 1;			//    Botschaft 100ms senden
		}
	}
}

void lese_Eingang(void)		// Modul funktioniert!!
{
	DDRC = DDRC & 0xF0;				// Port C auf Eingabe schalten
	PORTC = 0x0F;					// Pullup-Rs eingeschaltet

	_delay_us(10);					// Wartezeit Umstellung Hardware-Signal

	drehen =! (PINC & (1 << PC0));
	motor1 =! (PINC & (1 << PC1));
	neigen =! (PINC & (1 << PC2));
	motor2 =! (PINC & (1 << PC3));

	DDRC = DDRC | 0x0F;				// Port C auf Ausgabe schalten
}

void motor(void)	// Modul funktioniert!!
{
	if(motor1)
	{
		if(drehen==0)		//dreht nach links
		{
			DDRD |= (1<<PD2) | (1<<PD3);	// PD2 und PD3 auf Ausgang schalten
			PORTD &=~ (1<<PD2);				// PD2 zur Sicherheit ausschalten
			PORTD &=~ (1<<PD3);				// PD3 ausschalten
			PORTD |= (1<<PD2);				// PD2 einschalten
		}

		if(drehen==1)		//dreht nach rechts
		{
			DDRD |= (1<<PD2) | (1<<PD3);	// PD2 und PD3 auf Ausgang schalten
			PORTD &=~ (1<<PD3);				// PD3 zur Sicherheit ausschalten
			PORTD &=~ (1<<PD2);				// PD2 ausschalten
			PORTD |= (1<<PD3);				// PD3 einschalten
		}
	}
	else
	{
		PORTD &=~ (1<<PD2);
		PORTD &=~ (1<<PD3);
	}

	if(motor2)
	{
		if(neigen==0)		// neigen nach hinten
		{
			DDRB |= (1<<PB0) | (1<<PB1);	// PD2 und PD3 auf Ausgang schalten
			PORTB &=~ (1<<PB0);				// PD2 zur Sicherheit ausschalten
			PORTB &=~ (1<<PB1);				// PD3 ausschalten
			PORTB |= (1<<PB0);				// PD2 einschalten
		}

		if(neigen==1)		//neigen nach vorne
		{
			DDRB |= (1<<PB0) | (1<<PB1);	// PD2 und PD3 auf Ausgang schalten
			PORTB &=~ (1<<PB1);				// PD3 zur Sicherheit ausschalten
			PORTB &=~ (1<<PB0);				// PD2 ausschalten
			PORTB |= (1<<PB1);				// PD3 einschalten
		}
	}
	else
	{
		PORTB &=~ (1<<PB0);
		PORTB &=~ (1<<PB1);
	}
}
