#include <avr/io.h>
#include <avr/interrupt.h>

#include "common.h"
#include "dcftime.h"
#include "display.h"
#include "utils.h"

#define BRIGHTNESS 8
#define KEY_PRESS_THRESHOLD 100
#define MAX_DISPLAY_MODE 2




int main(void) {
	TCCR1B |= _BV(WGM12) | _BV(CS11) | _BV(CS10) ; // CTC Mode for Timer 1 (16Bit) with prescale of 64
	OCR1A   = 250;                                 // Dataload 250 
	TIMSK   = _BV(OCIE1A);

	// LED PINs as output
	LEDS_DDR = _BV(LEDS_LED1) | _BV(LEDS_LED2) | _BV(LEDS_LED3);

	// Display PINs as output
	D_DDR = _BV(D_CLK) | _BV(D_STR) | _BV(D_D1) | _BV(D_D2) | _BV(D_D3) | _BV(D_D4);

	// All pins low
	D_PORT = 0;

	// DCF PIN as Input
	DCF_DDR &= ~_BV(DCF_INPUT);

	// KEY PORTS as Input
	KEYS_DDR  &= ~( _BV(KEYS_KEY1) | _BV(KEYS_KEY2) | _BV(KEYS_KEY3) | _BV(KEYS_KEY4) );
	KEYS_PORT |= _BV(KEYS_KEY1) | _BV(KEYS_KEY2) | _BV(KEYS_KEY3) | _BV(KEYS_KEY4);

	// Switch LEDs off
	LEDS_PORT &= ~( _BV(LEDS_LED1) | _BV(LEDS_LED2) | _BV(LEDS_LED3) );

	/* show display check */
	checkUpDisplay();

    /* initialize DCF77 */
    dcf_init();
	/* enable interrupts */
	sei();
	while(1){
	}
    return(0);
}

SIGNAL(TIMER1_COMPA_vect) {
	static uint8_t counter = 0;
	static uint8_t brightnessCounter = 0;
	static uint8_t ticker  = 0;
	static uint8_t data[] = {0,0,0,0};
	static uint8_t displayMode = 0;
	static uint8_t displayDateMode = 0;
	static uint8_t displaySwitchCounter =0;
	static uint8_t keyOnePressed = 0, keyTwoPressed = 0, keyThreePressed = 0;
	static uint8_t keyOneCounter = 0, keyTwoCounter = 0, keyThreeCounter = 0;
    static dcf_datetime datetime = { .is_valid=False }; /** takes the current time and date */
	ticker++;

	if((KEYS_PIN & _BV(KEYS_KEY1)) == 0 ){
		if(keyOneCounter < KEY_PRESS_THRESHOLD) {
			keyOneCounter++; 
		}
	}
	else{
		if(keyOneCounter != 0){
			keyOneCounter--;
		}	
	}


	if((KEYS_PIN & _BV(KEYS_KEY3)) == 0 ){
		if(keyThreeCounter < KEY_PRESS_THRESHOLD) {
			keyThreeCounter++; 
		}
	}
	else{
		if(keyThreeCounter != 0){
			keyThreeCounter--;
		}	
	}

	keyOnePressed   = keyOneCounter   + 50 >= KEY_PRESS_THRESHOLD;
	keyTwoPressed   = keyTwoCounter   + 50 >= KEY_PRESS_THRESHOLD;
	keyThreePressed = keyThreeCounter + 50 >= KEY_PRESS_THRESHOLD;


	if( counter == 4 ){
		counter=0;
        dcf_signal(DCF_PIN & _BV(DCF_INPUT));
	}
	else{
		counter++;
	}
	if(ticker == 250){
		ticker = 0;
		datetime = dcf_current_datetime();
		if(keyOnePressed & !(keyTwoCounter ||  keyThreePressed)){
			if(displayMode > 0){
				displayMode--;
			}
			else{
				displayMode = MAX_DISPLAY_MODE;
			}
		}
		if(keyThreePressed & !(keyOneCounter ||  keyTwoPressed)){
			if(displayMode < MAX_DISPLAY_MODE){
				displayMode++;
			}
			else{
				displayMode = 0;
			}
		}
		switch(displayMode){
				case 0: 
					convertTime((uint8_t)datetime.time.hour, (uint8_t)datetime.time.minute, (uint8_t)datetime.time.second,data);
					displayDateMode = 0;
					displaySwitchCounter = 0;
					break;
				case 1: 
					convertTime((uint8_t)datetime.date.dayofmonth, (uint8_t)datetime.date.month, (uint8_t)datetime.date.year,data);
					displayDateMode = 0;
					displaySwitchCounter = 0;
					break;
				case 2:
					data[0] = (uint8_t)datetime.time.hour;
					data[1] = (uint8_t)datetime.time.minute;
					data[2] = (uint8_t)datetime.time.second,data;
					if(displaySwitchCounter	== 20 ){
						displaySwitchCounter = 0;
						if(displayDateMode == 3){
							displayDateMode = 0;
						}
						else{
							displayDateMode++;
						}
					}
					else{
						displaySwitchCounter++;
					}
					switch(displayDateMode){
						case 0:	data[3] = 63;
								break;
						case 1: data[3] = datetime.date.dayofmonth;
								break;
						case 2: data[3] = datetime.date.month;
								break;
						case 3: data[3] = datetime.date.year;
								break;
					}
					break;
		}
	}
	if( datetime.is_valid ){
		if(brightnessCounter == BRIGHTNESS){
			ShowNumber(data[0], data[1], data[2], data[3]);
		}
		else{
			ShowNumber(0,0,0,0);
		}
	}
	else{
		waitForSignal(500);
	}
	if(brightnessCounter == BRIGHTNESS){
		brightnessCounter = 0;
		LEDS_PORT |= (( (DCF_PIN & _BV(DCF_INPUT)) >> DCF_INPUT) <<  LEDS_LED2);
	}
	else{
		LEDS_PORT &= ~( _BV(LEDS_LED1) | _BV(LEDS_LED2) | _BV(LEDS_LED3) );
		brightnessCounter++;
	}
}

// vim:ts=4 
