// Atmega 8, intern 8 Mhz, Isr Timer 1 1ms

#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <util/delay.h>

//////////////////////////////////////////////////////////////////////////
// Zeitperioden
//Wartzeit_R1 abwarten, wenn abgelaufen einschalten und Einschaltzeit_MS abwarten, Wartzeit_R1 abwarten ...

uint16_t Einschaltzeit_MS = 3000; // Einschaltzeit - Wie lange der aktuelle Pin jeweils High ist

uint16_t pausezeiten_MS_Register_1[8] = {1000,500,3000,500,7000,100,200,800};	//  Ausschaltzeit - Wie lange der aktuelle Pin jeweils Low ist
uint16_t pausezeiten_MS_Register_2[8] = {500,10,2000,500,8000,500,200,500};
	
uint32_t wartezeit_MS_Register_1;	// Aktuelle Zeit die abzuwarten ist
uint32_t wartezeit_MS_Register_2;

uint8_t ausgaberegister_R1 = 0x00;	// Aktueller Registerzustand
uint8_t ausgaberegister_R2 = 0x00;

volatile bool zeitAbgelaufen_R1 = true;	// wahr wenn Zeit (Einschaltzeit, Ausschaltzeit) abgelaufen
volatile bool zeitAbgelaufen_R2 = true;

int8_t runde_R1 = 0;			// Aktueller zu schaltender Pin, pausezeiten_MS_ zähler
int8_t runde_R2 = 0;


bool pinIstAn_R1 = false;		// Pinzustand
bool pinIstAn_R2 = false;


//////////////////////////////////////////////////////////////////////////
// Timer 1
volatile uint32_t Millisekunde = 0;
volatile uint16_t Sekunde = 0;


void ausgabeStarten(volatile bool *zeitAbgelaufen, uint8_t * ausgaberegister, uint16_t *pausezeiten_MS, uint32_t *wartezeit_MS, int8_t *runde, bool *pinIstAn)
{
	
	if (*zeitAbgelaufen == true) // & runde != 8
	{
		*zeitAbgelaufen = false;
		
		if ( *pinIstAn == false) // Zeit aus wartezeit_MS abwarten, Pin low
		{
			*ausgaberegister = 0x00;
			*pinIstAn = true;
			
			Ausgaberegister(ausgaberegister_R1);
			Ausgaberegister(ausgaberegister_R2);
			
			*wartezeit_MS = Millisekunde + pausezeiten_MS[*runde];
			
		}
		
		else // Zeit aus Einschaltzeit_MS abwarten, Pin high
		{
			*pinIstAn = false;
			
			*ausgaberegister = 0x00;
			*ausgaberegister |= ( 1 << *runde);
			if (*runde != 8) *runde += 1;
			
			Ausgaberegister(ausgaberegister_R1);
			Ausgaberegister(ausgaberegister_R2);
			
			*wartezeit_MS = Millisekunde + Einschaltzeit_MS;
		}
		
	}
}

int main(void)
{
	
	//////////////////////////////////////////////////////////////////////////
	// Timer 1 
	TCCR1B =  ( 1 << CS10) | ( 1 << CS11) | ( 1 << WGM12); // Prescaler 64, CTC Top Ocr1A
	OCR1A = 124;  // ( 8000000 / 64 / 1000) = 125
	TIMSK = ( 1 << OCIE1A); // Output Compare A Match Interrupt Enable  Einmal pro Millisekunde
	

	Millisekunde = 0;
	sei();
    while(1)
    {
		ausgabeStarten(&zeitAbgelaufen_R1, &ausgaberegister_R1, &pausezeiten_MS_Register_1, &wartezeit_MS_Register_1, &runde_R1, &pinIstAn_R1);
		ausgabeStarten(&zeitAbgelaufen_R2, &ausgaberegister_R2, &pausezeiten_MS_Register_2, &wartezeit_MS_Register_2, &runde_R2, &pinIstAn_R2);
		
		if (runde_R1 == 8) && (runde_R2 == 8)
		{
			runde_R1 = 0; runde_R2 = 0;
			Millisekunde = 0;
		}
		
    }
}
ISR(TIMER1_COMPA_vect)
{
	Millisekunde++;
	
	if (Millisekunde >= wartezeit_MS_Register_1) 
	{	
		zeitAbgelaufen_R1 = true;
	}
	
	if (Millisekunde >= wartezeit_MS_Register_2)
	{
		zeitAbgelaufen_R2 = true;
	}
	
}