#include <avr/io.h>
#include <avr/interrupt.h>


unsigned int changed=0;		//Zeit geaendert

unsigned int z_std = 0;		//Zehnerstunden
unsigned int e_std = 0;		//Einerstunden
unsigned int z_min = 0;		//Zehnerminuten
unsigned int e_min = 0;		//Einerminuten
unsigned int z_sek = 0;		//Zehnersekunden
unsigned int e_sek = 0;		//Einersekunden


unsigned int w_on = 0;		// Weckfunktion an

unsigned int w_zstd = 0;		//Weckzeit Zehnerstunden
unsigned int w_estd = 0;		//Weckzeit Einerstunden
unsigned int w_zmin = 0;		//Weckzeit Zehnerminuten
unsigned int w_emin = 0;		//Weckzeit Einerminuten
//unsigned int w_zsec = 0;		//Weckzeit Zehnersekunden
//unsigned int w_esec = 0;		//Weckzeit Einersekunden

//unsigned int cb=0;

void count(unsigned int w){

	if(w==0){
		z_sek+=e_sek/10;	//Zehnersekunden berechnen

		e_min+=z_sek/6;		//Einerminuten berechnen
		z_min+=e_min/10;	//Zehnerminuten berechnen

		e_std+=z_min/6;		//Einerstunden berechnen
		z_std+=e_std/10;	//Zehnerstunden berechnen
	}else{
		w_zmin+=w_emin/10;	//Weckzeit Zehnerminuten berechnen

		w_estd+=w_zmin/6;	//Weckzeit Einerstunden berechnen
		w_zstd+=w_estd/10;	//Weckzeit Zehnerstunden berechnen
	}

}


void update(unsigned int w){

	if(w==0){
		e_sek=e_sek%10;		//Einersekunden auf 0-9
		z_sek=z_sek%6;		//Zehnersekunden auf 0-6

		e_min=e_min%10;		//Einerminuten auf 0-9
		z_min=z_min%6;		//Zehnerminuten auf0-6

		e_std=e_std%10;		//Einerstunden auf 0-9

		if((z_std==2) & (e_std>3)){	//bei 24:00 auf 00:00
			z_std = 0;
			e_std = 0;
			z_min = 0;
			e_min = 0;
			z_sek = 0;
			e_sek = 0;

		}

		PORTD = (z_sek<<4) | e_sek | (w_on<<7);
		PORTB = (z_min<<4) | e_min;
		PORTA = (z_std<<4) | e_std;

	}else{
		w_emin=w_emin%10;		//Weckzeit Einerminuten auf 0-9
		w_zmin=w_zmin%6;		//Weckzeit Zehnerminuten auf0-6

		w_estd=w_estd%10;		//Weckzeit Einerstunden auf 0-9

		if((w_zstd==2) & (w_estd>3)){ //bei 24:00 auf 00:00
			w_zstd = 0;
			w_estd = 0;
			w_zmin = 0;
			w_emin = 0;
		}

		PORTB = (w_zmin<<4) | w_emin;
		PORTA = (w_zstd<<4) | w_estd;
	}
}


ISR(TIMER1_COMPA_vect){
	unsigned int n=0;
	TCCR1B &= (0<<CS10)&(0<<CS12);	//Timer aus
	changed++;						//1 Sekunde weiter
	while(n<55){					//Warteschleife
		n++;
	}
	TCNT1H=0;  						//Zaehler auf 0
	TCNT1L=0; 						//Zaehler auf 0

	TCCR1B |= (1<<CS10)|(1<<CS12);	//Timer an
}




//    TCNT1 wird nicht zurückgesetzt.
int main(void){

	MCUCSR |= (1<<JTD);		//JTAG ausschlaten 2x
	MCUCSR |= (1<<JTD);

	OCR1AH=0x0e;
	OCR1AL=0x0f;

	TCCR1B |= (1<<CS10)|(1<<CS12);  //16 Bit Timoner

	sei();
	TIMSK |= (1<<OCIE1A);

	DDRA=0x3f;	//Stunden
	DDRB=0xff;	//Minuten
	DDRD=0xff;	//Sekunden
	DDRC=0x03;	//Eingaben und LCD Ansteuerung
	PORTC=0xfc;	// PullUp fuer PORTC 8 
	unsigned int k,k2;
	while(1){

		while(bit_is_set(PINC,2)==0){ // Uhrzeit stellen
			cli();
			TCCR1B &= (0<<CS10)&(0<<CS12);	//Timer aus
			TCNT1H=0;  						//Zaehler auf 0
			TCNT1L=0; 						//Zaehler auf 0

			if(bit_is_set(PINC,4)==0){	// Minuten hoch
				
				e_min++;
				e_sek=0;
				z_sek=0;
				count(0);
				update(0);
				//while(bit_is_set(PIND,2)==0){}
				for(k=0;k<350;k++){
					k2=0;
					while(k2<100){
						k2++;
					}
				}
			}

			if(bit_is_set(PINC,5)==0){	// Stunden hoch

				e_std++;
				e_sek=0;
				z_sek=0;
				count(0);
				update(0);
				//while(bit_is_set(PIND,2)==0){}
				for(k=0;k<350;k++){
					k2=0;
					while(k2<100){
						k2++;
					}
				}		
			}
			sei();
			TCCR1B |= (1<<CS10)|(1<<CS12);	//Timer an	
		}

		while(bit_is_set(PINC,3)==0){	// Weckzeit stellen
			update(1);
			if(bit_is_set(PINC,4)==0){	// Minuten hoch
				
				w_emin++;
				count(1);
				update(1);
				//while(bit_is_set(PIND,2)==0){}
				for(k=0;k<350;k++){
					k2=0;
					while(k2<100){
						k2++;
					}
				}
			}

			if(bit_is_set(PINC,5)==0){	// Stunden hoch

				w_estd++;
				count(1);
				update(1);
				//while(bit_is_set(PIND,2)==0){}
				for(k=0;k<350;k++){
					k2=0;
					while(k2<100){
						k2++;
					}
				}		
			}
		}


		if(bit_is_set(PINC,6)==0){  // Wecker Ein / Aus
			if(w_on==1){		//wenn Wecker an ist, mach ihn aus
				w_on=0;
				PORTD &= (0<<7);
			}else{				//wenn Wecker aus ist, mach ihn an
				w_on=1;
				PORTD |= (1<<7);
			}

			for(k=0;k<350;k++){	//kurz warten
				k2=0;
				while(k2<100){
					k2++;
				}
			}		
		}

		//  nach unten in die if-abfrage

		if((w_on==1) & (w_zstd==z_std) & (w_estd==e_std) & (w_zmin==z_min) & (w_emin==e_min)){	// wenn Wecker an ist und zeit = weckzeit:
			if(e_sek%2==0){								// Wecke
				PORTB |= 0x80;							// mich
			}else{										// uebelst
				PORTB &= 0x7f;							// auf
			}
		}		
			
		if(changed>0){				//Sekunde vergangen
			e_sek+=changed;			//Einersekunden hochzählen
			changed=0;
			count(0);	
			update(0);
		}                        
	}
}

