//#define F_CPU 16000000L

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>		//interrupts
#include <stdlib.h>
#include <string.h>
#include "pinout.h"
#include "print.h"
#include "adc.h"
#include "uart.h"
#include "i2cmaster.h"
#include "DS3231.h"

#define RX_INPUT_BUFFER_SIZE 92

/*README
   DIP1 aktiviert Röhren-Schaltregler
*/

volatile int counter = 0;
//char text[22] = {'F','R','o','h','e',' ',' ','W','e','i','h','n','a','c','h','t','e', 'n', ' ',' ', ' ', ' '};
char text[18] = {'1','2','3','4','5','6','7','8','9','t','s','c','a','f','e',' ', ' ', ' '};
int offset = 0;
int animationtimer = 0;
int stringlength = 22;
int duty = 125;


void check_dip_switches(void);
void check_buttons(void);
void setup(void);
void set_PWM_duty(int dutycycle);

uint8_t parse_nmea_gps(char input_string[RX_INPUT_BUFFER_SIZE], uint8_t output_buffer[3]){
    char* token = strsep(&input_string, ",");
    if(!strcmp("$GPRMC", token)){
        char* time = strsep(&input_string, ",");
        if(!strlen(time)){
            // no valid time available
            return -1;
        }

        // craft bcd values
        output_buffer[0]  = (time[0] - 48) << 4;
        output_buffer[0] |= time[1] - 48;

        output_buffer[1]  = (time[2] - 48) << 4;
        output_buffer[1] |= time[3] - 48;

        output_buffer[2]  = (time[4] - 48) << 4;
        output_buffer[2] |= time[5] - 48;

        return 0;
    }
}

int main(void){
  setup();

  while(1){
 	_delay_ms(500);
 	
 	check_dip_switches();
 	check_buttons();

    uint32_t clock = DS3231_read();
    for(uint8_t i=0; i < 6; i++){
        SR_Buffer[5-i] = number_Font[clock & 0x0F];
        clock = clock >> 4;
    }
 	print_SR_Buffer();
  }
}

void check_dip_switches() {
  if (PINB & DIP_1) {
    PORTC |=  ENABLE_TUBE_PSU;
    PORTA &= ~ENABLE_TUBE_SUPPLY;
  //  PORTB |=  STATUS_LED_B;
  } else {
    PORTC &= ~(ENABLE_TUBE_PSU);
    PORTA |=  (ENABLE_TUBE_SUPPLY);
 //   PORTB &= ~STATUS_LED_B;
  }
}

void check_buttons(){
	if((PINC & BUTTON_A)){
		 // PORTB &=  ~STATUS_LED_C;
	}
};

void setup(){
	
	DDRA =   ENABLE_TUBE_SUPPLY;

    DDRB =   STATUS_LED_B
           | STATUS_LED_C
           | MOSI
           | CLK;

    DDRC =   LATCH_SR
		   | ENABLE_SR
		   | DOT
           | ENABLE_TUBE_PSU;

    DDRD =   RESET_SR 
		   | TUBE_LED;


  //--------------------------
  //  		 SPI
  //--------------------------
    SPCR = (1 << SPE) |   //enable SPI
           (1 << MSTR) |  //SPI als Master starten
           (1 << SPR0) |  //clock-prescaler LSB
           (1 << SPR1) |  //clock-prescaler MSB
           (0 << SPIE) |  //complete transfer/ recive interrupt
           (0 << CPOL) |
           (0 << CPHA) |
           (0 << DORD);   //MSB first = 0
    SPSR = (1 << SPI2X);// | //clock- prescaler double speed

    PORTC &= ~LATCH_SR; //latch low, sonst startet SPI nicht
    PORTC |= LATCH_SR;
    PORTD |= RESET_SR;   //Setzte Reset auf HIGH (active LOW)
    PORTC &= ~(ENABLE_SR); //Aktiviert Shiftregister (active LOW)
    
    
    
  //--------------------------
  //    Externe Interrupts
  //--------------------------
  //External Interrupt Mask Register
 
  EIMSK |= (1 << INT0)  |        //Aktiviere Interrupt INT0
           (1 << INT1);          //Aktiviere Interrupt INT1

  //External Interrupt Control Register A
  EICRA |= (0 << ISC10) |        //Interrupt bei jedem Pegelwechsel auf INT1
           (1 << ISC11) |
           (1 << ISC00) |        //Interrupt bei jedem Pegelwechsel auf INT0
           (1 << ISC01);
  //Pin Change Interrupt Control Register
  PCICR |= (1 << PCIE2);        //Enabled PCINT16-23 als mögliche Signalquelle für Interrupt
  
  //Pin Change Mask Register 2
  //PCMSK2 |= (1 << PCINT18) |    //PCINT18 als Signalquelle wählen
  //            (1 << PCINT19);      //PCINT19 als Signalquelle wählen
    
   
  //--------------------------
  //  Timer + Zeitinterrupts
  //--------------------------

  //PWM-Timer
  //OC2A  set when upcounting, clear when down counting
  TCCR2A = (1<<COM1A1) 
		| (0<<COM1A0);
    
  TCCR2B=(1<<WGM20) //Wave form generartion mode
	    |(1<<WGM21) // Wave form generation mode
	    |(1<<COM2A1); //Compare Output Mode  	    
	    
  OCR2A   = duty; // Compare value 125
	    


	    


  //Timer/Counter control Register A&B
  //set normal-Mode and waveform
  TCCR1A = (0 << WGM01) |
           (0 << WGM00);
  TCCR1B = (0 << WGM02);


  ////Prescaler von 1024
  //TCCR1B |= (1 << CS02) |
  //          (0 << CS01) |
  //          (1 << CS00) ;


  //Output compare Regsiter (Setzt Zeit bei der Interrupt auslösen soll)
  OCR1A = (1 << 7) | //MSB
          (1 << 6) |
          (1 << 5) |
          (1 << 4) |
          (1 << 3) |
          (1 << 2) |
          (1 << 1) |
          (1 << 0) ; //LSB

  //TIMSK1 |= (1 << OCIE0A); //Interruptvector hinzufügen
  TIMSK1 |= (1 << ICIE1) |  	//Interrupt Counter Enabled)
			(1 << TOIE1);  	   //Timer Overflow Enabled

  uart_init();
  i2c_init();
    
	sei(); //Enable Interrupts
	//adc_setup();
	//i2c_init();
	//USART_Init(MYUBRR); 
    clear_SR_Buffer();
    


}

void set_PWM_duty(int dutycycle){
	 OCR2A = dutycycle;
 }


//Timer 1 Interrupt
ISR (TIMER1_OVF_vect)    // Timer1 ISR
{
	//PORTD ^=TUBE_LED;
	PORTB ^=STATUS_LED_C;
	TCNT1 = 63974; //63974;   // for 1 sec at 16 MHz
	animationtimer ++;
	if(animationtimer > 10){
		animationtimer= 0;
		offset++;
		PORTB ^= STATUS_LED_B;
		if(offset > 15){
			offset = 0;
		}
	}
}

//Encoder rotate
ISR(INT0_vect) {
  if (PIND & ENCODER_B) {
  //  set_PWM_duty(duty--);
  } else {
   // set_PWM_duty(duty++);
  }
}

//Encoder Button
ISR(INT1_vect) {

}


ISR(USART0_RX_vect)
{
    static char async_input_buffer[RX_INPUT_BUFFER_SIZE];
    static uint8_t async_buffer_pointer = 0;

    uint8_t data = UART_DATA_REG;
    if(!(data == '\n' || data == '\r')){
        async_input_buffer[async_buffer_pointer]=data;
        async_buffer_pointer++;
    }
    else if(async_buffer_pointer>0){
        async_input_buffer[async_buffer_pointer] = 0; // Null terminate string
        async_buffer_pointer=0;
        PORTB ^=STATUS_LED_C;
        uint8_t test[3];
        if(!parse_nmea_gps(async_input_buffer, test))
            printf("parse: %x %x %x\n\r", test[0], test[1], test[2]); 
    }
}

