/*########################################################################
##									##
##			BINARY		 CLOCK				##
##									##
##	Autor:		Marco Lierfeld					##
## 	Dokumentation:	http://www-users.rwth-aachen.de/\		##
##				marcodanielpascal.lierfeld/wordpress/	##
##									##
########################################################################*/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>

typedef unsigned char	u8;
typedef signed short	s16;

#define	XTAL		1e6		// 1MHz = 1 * 10^6

#define KEY_PIN		PINC
// for mode
#define KEY0		0
// for HOUR:
#define KEY1		1
// for MINUTE:
#define KEY2		2

#define REPEAT_MASK	(1<<KEY0^1<<KEY1^1<<KEY2)	// repeat: key1, key2
#define REPEAT_START	10			// after 500ms
#define REPEAT_NEXT	4			// every 200ms

#define TIME_GLOW	2
#define TIME_SHOW	60
#define TIME_DARK	110

#define HOURS PORTD
#define MINS PORTB
#define SECS PORTA
#define BUT_PORT PINC
#define BUT_MODE PC0
#define BUT_HOUR PC1
#define BUT_MIN  PC2
#define DCF_SIG PA7			// PIN where to show reception of DCF signal

// die verschiedenen Modi
#define MODE_DISPLAY_TIME	0x00	// normaler Modus
#define MODE_SET_ALARM_1	0x01	// Alarmzeit 1 setzen
#define MODE_SET_ALARM_2	0x02	// Alarmzeit 2 setzen
#define MODE_SET_TIME		0x03	// falls DCF-Empfang nicht klappt, Zeit manuell setzen
#define MODE_RINGING		0x04	// Spezialmodus: Kann über Tasten nicht erreicht werden
					// 	-> nur aktiv, wenn der Wecker klingelt

#define LED_ALARM_1		PC4	// LED für Alarm 1
#define LED_ALARM_2		PC3	// LED für Alarm 2
#define PRT_SND			PC5	// Soundausgang

#define DCF_PIN			PD2	// Pin an dem DCF-Modul angeschlossen ist
#define EXT_INT			PD3	// zweiter externer Interrupt (hier nicht genutzt)

volatile u8 key_state;				// debounced and inverted key state:
					// bit = 1: key pressed
volatile u8 key_press;			// key press detect

volatile u8 key_rpt;				// key long press and repeat

volatile u8 hours_1st = 0, hours_2nd = 0;
volatile u8 minutes_1st = 0, minutes_2nd = 0;
volatile u8 seconds_1st = 0, seconds_2nd = 0;

volatile u8 alarm1_active = 0, alarm2_active = 0;
volatile u8 alarm1_hour_1st = 0, alarm1_hour_2nd = 0;
volatile u8 alarm1_min_1st = 0, alarm1_min_2nd = 0;
volatile u8 alarm2_hour_1st = 0, alarm2_hour_2nd = 0;
volatile u8 alarm2_min_1st = 0, alarm2_min_2nd = 0;
volatile u8 alarm_flicker = 1, alarm_count = 0;
volatile u8 actual_mode = MODE_DISPLAY_TIME;

volatile unsigned char timecount = 0;
volatile unsigned short breakcount = 0;
volatile unsigned char dcf_active = 0;
volatile unsigned char array_count = 0;
volatile unsigned char dcf_array [60];
volatile unsigned char dcf_min_l_old = 0;
volatile unsigned char dcf_min_h_old = 0;
volatile unsigned char dcf_std_l_old = 0;
volatile unsigned char dcf_std_h_old = 0;

u8 EEMEM eeAl1HR1, eeAl1HR2, eeAl1MN1, eeAl1MN2;
u8 EEMEM eeAl2HR1, eeAl2HR2, eeAl2MN1, eeAl2MN2;

void dcf77_init (void) {
	//Timer init
	TCCR1B = (1<<CS11) | (1<<CS10);	//Pre 64 -> 0,032768s (3,05 bei '0'; 6,1) -> 16MHz mit 1MHz ;)
	TIMSK |= (1<<TOIE1);
	//externer Interrupt
	MCUCR = (1<<ISC01)|(1<<ISC00);	// interrupt on rising edge (inverted signal)
	GICR |= (1<<INT0);
	TCNT1 = -512;
}

unsigned char plausibilitaetscheck (	unsigned char std_h_new, unsigned char std_l_new,
					unsigned char min_h_new, unsigned char min_l_new, 
					unsigned char std_h_old, unsigned char std_l_old,
					unsigned char min_h_old, unsigned char min_l_old) {
	unsigned char min_l_old_x = min_l_old;		//Hochzählen der zuletzt empfangenen Zeit um eine Minute
	unsigned char min_h_old_x = min_h_old;		//Vergleich der hochgezählten Zeit mit der neu empfangenen
	unsigned char std_l_old_x = std_l_old;		//wenn sie gleich sind, kann Zeit übernommen werden
	unsigned char std_h_old_x = std_h_old;		//sonst wird alte Zeit verworfen und durch neue ersetzt,
							//allerdings wird sie nicht auf die Anzeigen übernommen
	min_l_old_x++;
	if (min_l_old_x > 9) {
		min_l_old_x = 0;
		min_h_old_x++;
		if (min_h_old_x == 6) {
			min_h_old_x = 0;
			std_l_old_x++;
			if (std_l_old_x > 9) {
				std_l_old_x = 0;
				std_h_old_x++;
			}
			if (std_h_old_x == 2){
				if (std_l_old_x == 4) {
					std_h_old_x = 0;
					std_l_old_x = 0;
				}
			}
		}	
	}
	if (std_h_old_x == std_h_new) {
		if (std_l_old_x == std_l_new) {
			if (min_h_old_x == min_h_new) {
				if (min_l_old_x == min_l_new) {
					return 1;
				}
			}
		}
	}
	return 0;
}

void dcf77_exec (void) {

	unsigned short minute = 0;
	unsigned short stunde = 0;
	unsigned char parity = 0;
	unsigned char dcf_min_l = 0;
	unsigned char dcf_min_h = 0;
	unsigned char dcf_std_l = 0;
	unsigned char dcf_std_h = 0;
	
	//Stunden
	
	if (dcf_array [29] == '1') {	//stunde 1
		stunde = 1;
		parity++;
	}
	if (dcf_array [30] == '1') {	//stunde 2
		stunde += 2;
		parity++;
	}
	if (dcf_array [31] == '1') {	//stunde 4
		stunde += 4;
		parity++;
	}
	if (dcf_array [32] == '1') {	//stunde 8
		stunde += 8;
		parity++;
	}
	if (dcf_array [33] == '1') {	//stunde 10
		stunde += 10;
		parity++;
	}
	if (dcf_array [34] == '1') {	//stunde 20
		stunde += 20;
		parity++;
	}
	
	if (dcf_array [35] == '1') {	//Prüfbit ok ?
		if (parity == 1 || parity == 3 || parity == 5) {
			parity = 0;
		}
		else {
			return;
		}
	}
	else {							//Prüfbit ok ?
		if (parity == 0 || parity == 2 || parity == 4 || parity == 6) {
			parity = 0;
		}
		else {
			return;
		}
	}
	
	dcf_std_h = stunde / 10;
	dcf_std_l = stunde % 10;
	
	//Minuten
	
	if (dcf_array [21] == '1') {	//minute 1
		minute = 1;
		parity++;
	}
	if (dcf_array [22] == '1') {	//minute 2
		minute += 2;
		parity++;
	}
	if (dcf_array [23] == '1') {	//minute 4
		minute += 4;
		parity++;
	}
	if (dcf_array [24] == '1') {	//minute 8
		minute += 8;
		parity++;
	}
	if (dcf_array [25] == '1') {	//minute 10
		minute += 10;
		parity++;
	}
	if (dcf_array [26] == '1') {	//minute 20
		minute += 20;
		parity++;
	}
	if (dcf_array [27] == '1') {	//minute 40
		minute += 40;
		parity++;
	}
	
	if (dcf_array [28] == '1') {	//Prüfbit ok ?
		if (parity == 1 || parity == 3 || parity == 5 || parity == 7) {
			parity = 0;
		}
		else {
			return;
		}
	}
	else {							//Prüfbit ok ?
		if (parity == 0 || parity == 2 || parity == 4 || parity == 6) {
			parity = 0;
		}
		else {
			return;
		}
	}
	
	dcf_min_h = minute / 10;
	dcf_min_l = minute % 10;
	

	if (plausibilitaetscheck (	dcf_std_h, dcf_std_l, dcf_min_h, dcf_min_l, 
								dcf_std_h_old, dcf_std_l_old, dcf_min_h_old, dcf_min_l_old)) {
		minutes_2nd = dcf_min_l;	//wenn der check ok ist, kann Zeit auf Anzeige übernommen werden
		minutes_1st = dcf_min_h;
		hours_2nd = dcf_std_l;
		hours_1st = dcf_std_h;		
		seconds_2nd = 0;		//Rücksetzen der Sekunden, da neue Minute gerade erst beginnt
		seconds_1st = 0;
		GICR &= ~(1<<INT0);		// kein weiterer Empfang nach
		TIMSK &= ~(1<<TOIE1);		// erfolgreichem Sync
	}
	
	dcf_min_l_old = dcf_min_l;		//sichern der aktuellen Zeitdaten
	dcf_min_h_old = dcf_min_h;
	dcf_std_l_old = dcf_std_l;
	dcf_std_h_old = dcf_std_h;

	
}

ISR(INT0_vect){					//Beginn eines Zeitsignals
	TCNT1 = -512;				//Rücksetzen des "Auszähltimers"
	dcf_active = 1;	
	SECS |= (1<<DCF_SIG);
	GICR &= ~(1<<INT0);			//deaktivieren des externen Interrupts, wenn
}						//Signal komplett, wird er wieder aktiviert

ISR(TIMER1_OVF_vect){
	TCNT1 = -512;
	if (dcf_active) {
		if (breakcount > 46) {		//Signalpause (58. Bit) ?
			if (array_count >= 58)	//array voll ?
				dcf77_exec ();
			breakcount = 0;
			array_count = 0;
			GICR |= (1<<INT0);		//aktivieren des ext. Int.
			return;
		}	
		breakcount = 0;
		if (PIND & (1<<PD2)){		//noch H-Pegel
			timecount++;		//auszählen des H-Pegels
		} else  {			//jetzt L-Pegel
			SECS &= ~(1<<DCF_SIG);
			if (timecount <= 4)
				dcf_array [array_count] = '0';
			if (timecount > 4)
				dcf_array [array_count] = '1';
			array_count++;
			dcf_active = 0;
			timecount = 0;			
			GICR |= (1<<INT0);
		}
	}
	else
		breakcount++;			//gerade kein Signal, also auszählen der Pause
}

ISR(TIMER0_OVF_vect) //SIGNAL (SIG_OVERFLOW0)			// every 10ms
{
	static u8 ct0, ct1, rpt;
	u8 i;

	TCNT0 = (u8)(s16)-(XTAL / 1024 * 10e-3 + 0.5);	// preload for 50ms

	i = key_state ^ ~KEY_PIN;		// key changed ?
	ct0 = ~( ct0 & i );			// reset or count ct0
	ct1 = ct0 ^ (ct1 & i);			// reset or count ct1
	i &= ct0 & ct1;				// count until roll over ?
	key_state ^= i;				// then toggle debounced state
	key_press |= key_state & i;		// 0->1: key press detect

	if( (key_state & REPEAT_MASK) == 0 )	// check repeat function
		rpt = REPEAT_START;		// start delay
	if( --rpt == 0 ){
		rpt = REPEAT_NEXT;			// repeat delay
		key_rpt |= key_state & REPEAT_MASK;
	}
}

ISR(TIMER2_OVF_vect){
	TCNT2 = -32;	// 1s: Prescaler 1024, resonator freq. 32.768kHz
	 
	seconds_2nd++;
	if (seconds_2nd >= 10){
		seconds_1st++;
		seconds_2nd = 0;
		if (seconds_1st >= 6){
			minutes_2nd++;
			seconds_1st = 0;
			if (minutes_2nd >= 10){
				minutes_1st++;
				minutes_2nd = 0;
				if (minutes_1st >= 6){
					hours_2nd++;
					minutes_1st = 0;
					if (hours_2nd >= 10){
						hours_1st++;
						hours_2nd = 0;
					}
					if (hours_1st >= 2 && hours_2nd >= 4){
						hours_1st = 0;
						hours_2nd = 0;
					}
				}
			}
		}
	}
	if (alarm1_active == 1){
		if (hours_1st == alarm1_hour_1st && hours_2nd == alarm1_hour_2nd){
			if (minutes_1st == alarm1_min_1st && minutes_2nd == alarm1_min_2nd){
				if (seconds_1st == 0 && seconds_2nd == 0){
					actual_mode = MODE_RINGING;
				}
			}
		}
	}
	if (alarm2_active == 1){
		if (hours_1st == alarm2_hour_1st && hours_2nd == alarm2_hour_2nd){
			if (minutes_1st == alarm2_min_1st && minutes_2nd == alarm2_min_2nd){
				if (seconds_1st == 0 && seconds_2nd == 0){
					actual_mode = MODE_RINGING;
				}
			}
		}
	}
	
	if (actual_mode == MODE_RINGING){
		alarm_count++;
	} else if (actual_mode == MODE_SET_ALARM_1){
		if (alarm_flicker <= 1){
			PORTC &= ~(1<<LED_ALARM_1);
		} else if (alarm_flicker >= 2){
			PORTC |= (1<<LED_ALARM_1);
			if (alarm1_active == 0){
				alarm_flicker = 0;
			} else if (alarm1_active == 1 && alarm_flicker >= 4){
				alarm_flicker = 0;
			}
		}
		alarm_flicker++;	
	} else if (actual_mode == MODE_SET_ALARM_2){
		if (alarm_flicker <= 1){
			PORTC &= ~(1<<LED_ALARM_2);			
		} else if (alarm_flicker >= 2){
			PORTC |= (1<<LED_ALARM_2);
			if (alarm2_active == 0){
				alarm_flicker = 0;
			} else if (alarm2_active == 1 && alarm_flicker >= 4){
				alarm_flicker = 0;
			}
		}
		alarm_flicker++;	
	} else if (actual_mode == MODE_SET_TIME){
		if (alarm_flicker <= 1){
			PORTC &= ~((1<<LED_ALARM_1)|(1<<LED_ALARM_2));
			alarm_flicker++;
		} else {
			PORTC |= (1<<LED_ALARM_1)|(1<<LED_ALARM_2);
			alarm_flicker = 0;
		}
	}
	
	if (minutes_1st == 5 && minutes_2nd == 8){
		if (seconds_1st == 3 && seconds_2nd == 0){
			if ( (hours_1st == 0 && ( hours_2nd == 2 || hours_2nd == 5 || hours_2nd == 8 ) ) ||
			     (hours_1st == 1 && ( hours_2nd == 1 || hours_2nd == 4 || hours_2nd == 7 ) ) ||
			     (hours_1st == 2 && ( hours_2nd == 0 || hours_2nd == 3 ) ) ){
				GICR |= (1<<INT0);
				TIMSK |= (1<<TOIE1);
				TCNT1 = -512;
			}
		}
	}		 
}


u8 get_key_press( u8 key_mask )
{
	cli();				// read and clear atomic !
	key_mask &= key_press;		// read key(s)
	key_press ^= key_mask;		// clear key(s)
	sei();
	return key_mask;
}


u8 get_key_rpt( u8 key_mask )
{
	cli();				// read and clear atomic !
	key_mask &= key_rpt;		// read key(s)
	key_rpt ^= key_mask;		// clear key(s)
	sei();
	return key_mask;
}


u8 get_key_short( u8 key_mask )
{
	cli();				// read key state and key press atomic !
	return get_key_press( ~key_state & key_mask );
}


u8 get_key_long( u8 key_mask )
{
	return get_key_press( get_key_rpt( key_mask ));
}


int main( void ){
	
	u8 x;
	u8 flicker = 0, beeper = 0;	
	u8 time_modified = 0;
		
	// get alarm time 1 from EEPROM
	alarm1_hour_1st = eeprom_read_byte(&eeAl1HR1);
	alarm1_hour_2nd = eeprom_read_byte(&eeAl1HR2);
	alarm1_min_1st = eeprom_read_byte(&eeAl1MN1);
	alarm1_min_2nd = eeprom_read_byte(&eeAl1MN2);
	
	// get alarm time 2 from EEPROM
	alarm2_hour_1st = eeprom_read_byte(&eeAl2HR1);
	alarm2_hour_2nd = eeprom_read_byte(&eeAl2HR2);
	alarm2_min_1st = eeprom_read_byte(&eeAl2MN1);
	alarm2_min_2nd = eeprom_read_byte(&eeAl2MN2);

	DDRA = 0xff;
	DDRB = 0xff;
	// alle außer LED-Pins und dem Soundanschluss sind Input
	DDRC = (1<<LED_ALARM_1)|(1<<LED_ALARM_2)|(1<<PRT_SND);
	// PD2, PD3 are used for external interrupts
	DDRD = ~((1<<DCF_PIN)|(1<<EXT_INT));
	
	PORTA = 0x00;
	PORTB = 0x00;
	PORTC = 0x00;
	PORTD = 0x00;

	for (x=0; x<7; x++){
		SECS = (1<<x);
		_delay_ms(500);
	}
	SECS = 0x00;
	
	for (x=0; x<7; x++){
		MINS = (1<<x);
		_delay_ms(500);
	}
	MINS = 0x00;
	
	for (x=4; x<8; x++){
		HOURS = (1<<x);
		_delay_ms(500);
	}
	for (x=0; x<2; x++){
		HOURS = (1<<x);
		_delay_ms(500);
	}	
	HOURS = 0x00;
	
	TCCR0 = 1<<CS02^1<<CS00;			// divide by 1024
	TIMSK = 1<<TOIE0;				// enable timer interrupt
	ASSR |= 1<<AS2;					// use external crystal
	TCCR2 = (1<<CS22)|(1<<CS21)|(1<<CS20);		// divide by 1024
	TIMSK |= (1<<TOIE2);				// enable timer interrupt
	TCNT2 = -32;					// count up to 1s 
		
	sei();
	
	dcf77_init();

	for(;;){	// main loop
		flicker++;
		
		if (actual_mode == MODE_RINGING){			
			if (flicker < TIME_GLOW){	// let not activated leds glow
				HOURS = (~((hours_2nd<<4)|(hours_1st)))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = ~((minutes_1st<<4)|(minutes_2nd));
				SECS = (~((seconds_1st<<4)|(seconds_2nd))) & (~(1<<DCF_SIG));
			} else if (flicker >= TIME_GLOW && flicker < TIME_SHOW){	// activate leds to display time
				HOURS = ((hours_2nd<<4)|(hours_1st))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = (minutes_1st<<4)|(minutes_2nd);
				SECS = ((seconds_1st<<4)|(seconds_2nd)) & (~(1<<DCF_SIG));
			} else if (flicker >= TIME_SHOW && flicker < TIME_DARK){	// save power ;)
				HOURS = 0x00;
				MINS = 0x00;
				SECS &= (1<<DCF_SIG);	// alle aus, nur DCF_SIG nicht ändern
			} else if (flicker >= TIME_DARK){
				flicker = 0;
			}
			
			if (beeper < 3){
				PORTC |= (1<<PRT_SND);
			} else if (beeper >= 3 && beeper < 6){
				PORTC &= ~(1<<PRT_SND);
			} else {
				beeper = 0;
			}
			beeper++;
			
			if (alarm1_active == 1){
				PORTC |= (1<<LED_ALARM_1);
			} else {
				PORTC &= ~(1<<LED_ALARM_1);
			}
			if (alarm2_active == 1){
				PORTC |= (1<<LED_ALARM_2);
			} else {
				PORTC &= ~(1<<LED_ALARM_2);
			}

			if( get_key_short( (1<<BUT_HOUR)|(1<<BUT_MIN)|(1<<BUT_MODE) ) || alarm_count >= 120){	// any key deactivates alarm
				alarm_count = 0;
				actual_mode = MODE_DISPLAY_TIME;
			}
		} // if (actual_mode == MODE_RINGING)
		else if (actual_mode == MODE_DISPLAY_TIME){			
			if (flicker < TIME_GLOW){	// let not activated leds glow
				HOURS = (~((hours_2nd<<4)|(hours_1st)))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = ~((minutes_1st<<4)|(minutes_2nd));
				SECS = (~((seconds_1st<<4)|(seconds_2nd))) & (~(1<<DCF_SIG));
			} else if (flicker >= TIME_GLOW && flicker < TIME_SHOW){	// activate leds to display time
				HOURS = ((hours_2nd<<4)|(hours_1st))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = (minutes_1st<<4)|(minutes_2nd);
				SECS = ((seconds_1st<<4)|(seconds_2nd)) & (~(1<<DCF_SIG));
			} else if (flicker >= TIME_SHOW && flicker < TIME_DARK){	// save power ;)
				HOURS = 0x00;
				MINS = 0x00;
				SECS &= (1<<DCF_SIG);	// alle aus, nur DCF_SIG nicht ändern
			} else if (flicker >= TIME_DARK){
				flicker = 0;
			}
			
			if (alarm1_active == 1){
				PORTC |= (1<<LED_ALARM_1);
			} else {
				PORTC &= ~(1<<LED_ALARM_1);
			}
			if (alarm2_active == 1){
				PORTC |= (1<<LED_ALARM_2);
			} else {
				PORTC &= ~(1<<LED_ALARM_2);
			}

			if( get_key_short( 1<<BUT_HOUR)){	// activate alarm 1
				if (alarm1_active == 0){
					alarm1_active = 1;
				} else {
					alarm1_active = 0;
				}
			}
			
			if( get_key_short( 1<<BUT_MIN)){	// activate alarm 2
				if (alarm2_active == 0){
					alarm2_active = 1;
				} else {
					alarm2_active = 0;
				}
			}
			
			if (get_key_short( 1<<BUT_MODE )){
				PORTC &= ~((1<<LED_ALARM_1)|(1<<LED_ALARM_2));
				actual_mode = MODE_SET_ALARM_1;
			}
			
		} // if (actual_mode == MODE_DISPLAY_TIME)
		else if (actual_mode == MODE_SET_ALARM_1){
			if (flicker < TIME_GLOW){	// let not activated leds glow
				HOURS = (~((alarm1_hour_2nd<<4)|(alarm1_hour_1st)))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = ~((alarm1_min_1st<<4)|(alarm1_min_2nd));
				SECS = (0x00) & (~(1<<DCF_SIG));
			} else if (flicker >= TIME_GLOW && flicker < TIME_SHOW){	// activate leds to display time
				HOURS = ((alarm1_hour_2nd<<4)|(alarm1_hour_1st))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = ((alarm1_min_1st<<4)|(alarm1_min_2nd));
				SECS = (0x00) & (~(1<<DCF_SIG));
			} else if (flicker > TIME_SHOW && flicker < TIME_DARK){	// save power ;)
				HOURS = 0x00;
				MINS = 0x00;
				SECS &= (1<<DCF_SIG);	// alle aus, nur DCF_SIG nicht ändern
			} else if (flicker >= TIME_DARK){
				flicker = 0;
			}
		
			// short press
			if( get_key_short( 1<<BUT_HOUR)){
				alarm1_hour_2nd++;				
				if (alarm1_hour_2nd >= 10){
					alarm1_hour_1st++;
					alarm1_hour_2nd = 0;
				}
				if (alarm1_hour_1st >= 2 && alarm1_hour_2nd >= 4){
					alarm1_hour_1st = 0;
					alarm1_hour_2nd = 0;
				}
				time_modified = 1;
			}

			// short press
			if( get_key_short( 1<<BUT_MIN)){
				alarm1_min_2nd++;				
				if (alarm1_min_2nd >= 10){
					alarm1_min_1st++;
					alarm1_min_2nd = 0;
					if (alarm1_min_1st >= 6){
						alarm1_min_1st = 0;					
					} 
				}
				time_modified = 1;
			}
			
			if (get_key_short( 1<<BUT_MODE )){
				if (time_modified){
					// write alarm time 1 to EEPROM
					eeprom_write_byte(&eeAl1HR1, alarm1_hour_1st);
					eeprom_write_byte(&eeAl1HR2, alarm1_hour_2nd);
					eeprom_write_byte(&eeAl1MN1, alarm1_min_1st);
					eeprom_write_byte(&eeAl1MN2, alarm1_min_2nd);
					time_modified = 0;
				}
				PORTC &= ~(1<<LED_ALARM_1);
				actual_mode = MODE_SET_ALARM_2;				
			}
		} // if (actual_mode == MODE_SET_ALARM_1)
		else if (actual_mode == MODE_SET_ALARM_2){			
			if (flicker < TIME_GLOW){	// let not activated leds glow
				HOURS = (~((alarm2_hour_2nd<<4)|(alarm2_hour_1st)))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = ~((alarm2_min_1st<<4)|(alarm2_min_2nd));
				SECS = (0x00) & (~(1<<DCF_SIG));
			} else if (flicker >= TIME_GLOW && flicker < TIME_SHOW){	// activate leds to display time
				HOURS = ((alarm2_hour_2nd<<4)|(alarm2_hour_1st))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = ((alarm2_min_1st<<4)|(alarm2_min_2nd));
				SECS = (0x00) & (~(1<<DCF_SIG));
			} else if (flicker > TIME_SHOW && flicker < TIME_DARK){	// save power ;)
				HOURS = 0x00;
				MINS = 0x00;
				SECS &= (1<<DCF_SIG);	// alle aus, nur DCF_SIG nicht ändern
			} else if (flicker >= TIME_DARK){
				flicker = 0;
			}
		
			// short press
			if( get_key_short( 1<<BUT_HOUR)){
				alarm2_hour_2nd++;				
				if (alarm2_hour_2nd >= 10){
					alarm2_hour_1st++;
					alarm2_hour_2nd = 0;
				}
				if (alarm2_hour_1st >= 2 && alarm2_hour_2nd >= 4){
					alarm2_hour_1st = 0;
					alarm2_hour_2nd = 0;
				}
				time_modified = 1;
			}

			// short press
			if( get_key_short( 1<<BUT_MIN)){
				alarm2_min_2nd++;				
				if (alarm2_min_2nd >= 10){
					alarm2_min_1st++;
					alarm2_min_2nd = 0;
					if (alarm2_min_1st >= 6){
						alarm2_min_1st = 0;					
					} 
				}
				time_modified = 1;
			}
			
			if (get_key_short( 1<<BUT_MODE )){
				if (time_modified){
					// write alarm time 2 to EEPROM
					eeprom_write_byte(&eeAl2HR1, alarm2_hour_1st);
					eeprom_write_byte(&eeAl2HR2, alarm2_hour_2nd);
					eeprom_write_byte(&eeAl2MN1, alarm2_min_1st);
					eeprom_write_byte(&eeAl2MN2, alarm2_min_2nd);
					time_modified = 0;
				}
				PORTC &= ~(1<<LED_ALARM_2);
				actual_mode = MODE_SET_TIME;
			}
		} // if (actual_mode == MODE_SET_ALARM_2)
		else if (actual_mode == MODE_SET_TIME){
			if (flicker < TIME_GLOW){	// let not activated leds glow
				HOURS = (~((hours_2nd<<4)|(hours_1st)))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = ~((minutes_1st<<4)|(minutes_2nd));
				SECS = (~((seconds_1st<<4)|(seconds_2nd))) & (~(1<<DCF_SIG));
			} else if (flicker >= TIME_GLOW && flicker < TIME_SHOW){	// activate leds to display time
				HOURS = ((hours_2nd<<4)|(hours_1st))&(~(1<<DCF_PIN)|(1<<EXT_INT));
				MINS = (minutes_1st<<4)|(minutes_2nd);
				SECS = ((seconds_1st<<4)|(seconds_2nd)) & (~(1<<DCF_SIG));
			} else if (flicker > TIME_SHOW && flicker < TIME_DARK){	// save power ;)
				HOURS = 0x00;
				MINS = 0x00;
				SECS &= (1<<DCF_SIG);	// alle aus, nur DCF_SIG nicht ändern
			} else if (flicker >= TIME_DARK){
				flicker = 0;
			}
			
			// short press
			if( get_key_short( 1<<BUT_HOUR)){
				hours_2nd++;
				seconds_1st = 0;
				seconds_2nd = 0;
				if (hours_2nd >= 10){
					hours_1st++;
					hours_2nd = 0;
				}
				if (hours_1st >= 2 && hours_2nd >= 4){
					hours_1st = 0;
					hours_2nd = 0;
				}
			}
				
			// short press
			if( get_key_short( 1<<BUT_MIN)){
				minutes_2nd++;
				seconds_1st = 0;
				seconds_2nd = 0;
				if (minutes_2nd >= 10){
					minutes_1st++;
					minutes_2nd = 0;
					if (minutes_1st >= 6){
						minutes_1st = 0;
					} 
				}
			}
		
			if (get_key_short( 1<<BUT_MODE )){
				PORTC &= ~((1<<LED_ALARM_1)|(1<<LED_ALARM_2));
				actual_mode = MODE_DISPLAY_TIME;
			}
		}
	}// for(;;)
}

