//#######################################
// Last saved: 04-03-2006
//#######################################

//--------------------------------------------------------------------------
//--INCLUDE Dateien---------------------------------------------------------
//--------------------------------------------------------------------------

#include <avr/io.h>
#include <stdint.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include "usb.h"				//muss im selben Ordner sein


#if defined(__AVR_AT90S8535__) || defined(__AVR_AT90S8515__) || \
      defined(__AVR_AT90S4434__) || defined(__AVR_AT90S4414__) || \
      defined(__AVR_ATmega163__)
#  define OC1 PD5
#  define DDROC DDRD
#  define OCR OCR1A
#else
#  error "Don't know what kind of MCU you are compiling for"
#endif

#if defined(COM11)
#  define XCOM11 COM11
#elif defined(COM1A1)
#  define XCOM11 COM1A1
#else
#  error "need either COM1A1 or COM11"
#endif

//--------------------------------------------------------------------------
//--Globale Variablen-------------------------------------------------------
//--------------------------------------------------------------------------

int8_t wert_icr1h, wert_icr1l;					//fuer Speicherung des Inhaltes von ICR1H/ICR1L 
volatile uint8_t messzyklus_finish; 			//fuer Synchronisation

//--------------------------------------------------------------------------
//--Definitionen------------------------------------------------------------
//--------------------------------------------------------------------------

#define		CK_Select_BitMsk	((1<<CS12)|(1<<CS11)|(1<<CS10))
#define		CK_0008_Select		(1<<CS11)
#define		OC1_HIGH			((1<<COM1A1)|(1<<COM1A0))			//damit OC1 (PD5) -> HIGH
#define		OC1_LOW				(1<<COM1A0)							//für OC1 -> LOW (&= ~)


#define		CK		3.686400			//systemtakt [Hz] mit JTAG-ICE
//#define		CK		8.0					//systemtakt [Hz]
#define 	Tper	15000.				//Gesamtperiode [µs]
#define		Env		200.				//Hüllkurve auf High 200[µs]
#define		PSF		8.					//Prescaler

#define		COMP1A ((Env*CK)/(PSF)+.5)		//Berechnung für CompareWert1A (Huellkurvendauer)
#define		COMP1B ((Tper*CK)/(PSF)+.5)		//Berechnung für CompareWert1B (Messperiode)

#define		ungueltig 0xffff				//Messbereichsüberschreitung

//--------------------------------------------------------------------------
//--SIGNAL------------------------------------------------------------------
//--------------------------------------------------------------------------

SIGNAL (SIG_OUTPUT_COMPARE1A)
	{
		PORTD |= (1<<PD4);				//PD4 = 1
		PORTD &= ~(1<<PD5);				//Pin PD5=0
	}

SIGNAL (SIG_OUTPUT_COMPARE1B)
	{
		messzyklus_finish = 1;				//Compare-Wert ist erreicht -> Messzyklus ist fertig -> ICP kann beginnen
	}

SIGNAL (SIG_INPUT_CAPTURE1)
	{
	}

//--------------------------------------------------------------------------
//--Unterprogramm INIT_IO---------------------------------------------------
//--------------------------------------------------------------------------

void init_io (void)
{
	DDRA = 0x00;										//Status LED
	DDRB = 0x00;										//USB Daten
	DDRC = 0x00;										//USB Kommunikatin und MUX
	DDRD = 0x00;										//OC1 und ICP
	
	DDRA |= (1<<PA0);															//für Status-LED
	DDRC |= (1<<PC5)|(1<<PC4)|(1<<PC3)|(1<<PC2)|(1<<PC1)|(1<<PC0);			//als Ausgang für USB Kommunikation und MUX
	DDRD |= (1<<PD5)|(1<<PD4);				   	     							//als Ausgang für OC1 (PD5-Hk) und (PD4 inv. Hk)
}


//--------------------------------------------------------------------------
//--Unterprogramm INIT_TIMER_WERTE------------------------------------------
//--------------------------------------------------------------------------

void init_timer_werte (void)
	{
		cli();														//disable IRQ
		
		TIMSK = 0x00;
		TIMSK |= (1<<OCIE1A)|(1<<OCIE1B)|(1<<TICIE1);				//OCIE1A/B (COMPARE), TICIE1 (ICP) setzen
		
		OCR1B  = COMP1B;											//=  15ms bei 8MHz, wird berechnet
		OCR1A  = COMP1A;											//= 0,2ms bei 8MHz, wird berechnet
		
		ICR1 = 0x0000;
		
		TCCR1A = 0x00;
		TCCR1B = 0x00;
		
		//TCCR1B |= (1<<ICES1);					//test mit der steigenden flanke -> falsche messung
		
		sei();														//enable IRQ
	}	

//--------------------------------------------------------------------------
//--Unterprogramm MESSZYKLUS_START------------------------------------------
//--------------------------------------------------------------------------

void messzyklus_start (void)
	{
		TCNT1L = 0x00;
		TCNT1H = 0x00;
		
		ICR1 = ungueltig;
		
		PORTD &= ~(1<<PD4);					//PD4 = 0
		PORTD |= (1<<PD5);						//Pin PD5=1 fuer die Dauer der Huellkurve
		
		TCCR1B |= CK_0008_Select;
	}

//--------------------------------------------------------------------------
//--Unterprogramm READ_ICP--------------------------------------------------
//--------------------------------------------------------------------------

void read_icp (void)
	{
	
	 	if (ICR1 != ungueltig)				//abfrage ob ICR ungleich 0xffff ist
		{
			
			wert_icr1l = ICR1L;
			wert_icr1h = ICR1H;
			
		}
			
		else
		{
			wert_icr1l = 0x00;
			wert_icr1h = 0x00;
			
		}
			
	}

//--------------------------------------------------------------------------
//--Hauptprogramm ----------------------------------------------------------
//--------------------------------------------------------------------------

int main (void)
{
	#define CHANNEL_BIT_MSK	0x0F				//für MUX-Auswahl
	unsigned char channel=0,channel_temp;
	

init_io();

init_timer_werte();

	while (1)
	{	
		
		// Kanal einstellen
		
		channel = channel 	&  CHANNEL_BIT_MSK;				
		channel_temp = PORTC;
		channel_temp = channel_temp & ~CHANNEL_BIT_MSK;
		channel_temp = channel_temp | channel;
		PORTC = channel_temp;
		
		
		//	Messzyklus starten
		
		messzyklus_start();				 // Timer 1 setzen, Ausgang (PD5) auf HIGH, PD4 auf LOW
	
		while (messzyklus_finish ==0)   // warten auf interrupt SIG_OUTPUT_COMPARE1B
		{
		};
		
		
		
		//Warten auf Flag messzyklus_finish==1)
		read_icp();				//daten abholen
		
		//usb_write_data();			//senden
		
		//Kanal weiterschalten
		channel++;
		
		
	};

return 0;

}
