#include "main.h"

__C_task void main(void)
{
  uint8_t i;
  //uint8_t tmp8;

  /* Disable comaparator */
  ACSR = 1<<ACD;

  /* Init LED */
  LED_DDR = LED_1 | LED_2;
  LED_OFF(LED_1);
  LED_OFF(LED_2);

  /* Init 7 segment LED indicators */
  INDCTR_SEGMENT_DDR = 0xFF; // segment pins to output
  INDCTR_SEGMENT_PORT = 0x00; // off all segment

  INDCTR_COMMON_DDR = INDCTR_COMMON_ALL; // common pins to output
  INDCTR_COMMON_PORT = ~INDCTR_COMMON_ALL; // off all indikators

  for(i=0; i<INDCTR_NUMS; i++) {
    Display[i] = IndctrNums[i];
  }

  Flag.needDot = 0;

  /* Timer0 every 4 ms switch showing LED */
  TCCR0 = TIM0_PRESCALER;
  TCNT0 = TIM0_CNT; // load timer
  TIMSK |= 1<<TOIE0; // enable TIM0_OVF interrupt

  /* Timer0 every 4 ms switch showing LED */
  TCCR0 = TIM0_PRESCALER;
  TCNT0 = TIM0_CNT; // load timer
  TIMSK |= 1<<TOIE0; // enable TIM0_OVF interrupt

  /* ADC init */
  resultADC = 0;
  ADMUX = (1<<REFS0) | (1<<ADLAR); // Vref = AVcc, channel ADC0, Left adjusted result
  ADCSR = 1<<ADEN | 1<<ADPS2 | 1<<ADPS1; // enable ADC, prescaler = 64

  /* I2C init */
  TWI_MasterInit(100);

  __enable_interrupt();

  /* Init Scheduler and TDelay */
  RTOS_Init();

  // Tasks for sheduler
  RTOS_SetTask(startADC,0,50);
  RTOS_SetTask(getTime,0,500);
  
  /* Get time */

  while(1) {
    if (1 == Flag.newTime) {
      Flag.newTime = 0;

      Display[0] = IndctrNums[(0x0F & (Clock.hours>>4))];
      Display[1] = IndctrNums[(0x0F & Clock.hours)];
      Display[2] = IndctrNums[(0x0F & (Clock.minutes>>4))];
      Display[3] = IndctrNums[(0x0F & Clock.minutes)];
    }

    if (1 == Flag.newBTN) {
      Flag.newBTN = 0;
      
      btn_t btn = getBTN();
      if (btn == btn_1) {
        LED_ON(LED_1);
      } else if (btn == btn_2) {
        LED_ON(LED_2);
      } else if (btn == btn_3) {
        LED_OFF(LED_1);
      } else if (btn == btn_4) {
        LED_OFF(LED_2);
      } else if (btn == btn_5) {
        LED_ON(LED_1);
        LED_ON(LED_2);
      } else if (btn == btn_6) {
        LED_OFF(LED_1);
        LED_OFF(LED_2);
      }
    }

    tdelay_ms(10); // sleep and rotate dispatcher
  } // end of while(1)
} // end of main()

/**
 *  S u b r o u t i n e s
 */

static void startADC(void) {
  // enable interrupt and start conversion
  ADCSR |= ((1<<ADSC) | (1<<ADIE));
}

static btn_t getBTN(void) {
  uint8_t btn_code = resultADC;
  if (btn_code > 0xED) {
    return btn_no;
  } else if (btn_code > 0xD8) {
    return btn_1;
  } else if (btn_code > 0xD0) {
    return btn_2;
  } else if (btn_code > 0xC5) {
    return btn_3;
  } else if (btn_code > 0xB4) {
    return btn_4;
  } else if (btn_code > 0x94) {
    return btn_5;
  } else if (btn_code > 0x3F) {
    return btn_6;
  } else {
    return btn_7;
  }
}

static void getTime(void) {
  static uint8_t old_sec;

  /*устанавливаем указатель DS1307 на нулевой адрес*/
  twi_buf[0] = (DS1307_ADR<<1)|0; //адресный пакет
  twi_buf[1] = 0;                 //адрес регистра   
  TWI_SendData(twi_buf, 2);

  /*считываем время с DS1307*/
  twi_buf[0] = (DS1307_ADR<<1)|1;
  TWI_SendData(twi_buf, 5);

  /*переписываем данные буфера драйвера в свой буфер*/
  TWI_GetData(twi_buf, 5);

  Clock.seconds = twi_buf[1];
  Clock.minutes = twi_buf[2];
  Clock.hours = twi_buf[3];

  if (old_sec != Clock.seconds) {
    Flag.needDot = 1;
    old_sec = Clock.seconds;
  } else {
    Flag.needDot = 0;
  }
  Flag.newTime = 1;
}

static void setTime(void) {
   /*подготавливаем сообщение*/
  twi_buf[0] = (DS1307_ADR<<1)|0; //адресный пакет
  twi_buf[1] = 0;                 //адрес регистра
  twi_buf[2] = Clock.seconds;     //значение секунд 
  twi_buf[3] = Clock.minutes;     //значение минут 
  twi_buf[4] = Clock.hours;       //значение часов

  /*отправляем его*/
  TWI_SendData(twi_buf, 5);
}


/**
 *  I n t e r r u p t   h a n d l e r s
 */

#pragma vector=TIMER0_OVF_vect
__interrupt void TIMER0_OVF_ISR(void) {
  static uint8_t indicator = 0;

  TCNT0 = TIM0_CNT; // reload timer

  INDCTR_COMMON_PORT &= ~INDCTR_COMMON_ALL; // off all indikators

  switch (indicator) {
  case 0:
    INDCTR_SEGMENT_PORT = Display[0];
    INDCTR_COMMON_PORT |= 0x01;
    indicator = 1;
    break;

  case 1:
    if (1 == Flag.needDot) {
      INDCTR_SEGMENT_PORT = Display[1] | Sym_dot;
    } else {
      INDCTR_SEGMENT_PORT = Display[1];
    }
    INDCTR_COMMON_PORT |= 0x02;
    indicator = 2;
    break;

  case 2:
    INDCTR_SEGMENT_PORT = Display[2];
    INDCTR_COMMON_PORT |= 0x04;
    indicator = 3;
    break;

  case 3:
    INDCTR_SEGMENT_PORT = Display[3];
    INDCTR_COMMON_PORT |= 0x08;

  default:
    indicator = 0;
    break;
  }
}

#pragma vector=ADC_vect
__interrupt void ADC_ISR(void) {
  resultADC = ADCH;
  ADCSR &= ~(1<<ADIE); // disable interrupt
  Flag.newBTN = 1;
}
