/**
 * \file timer.c
 * \brief Последовательный вывод
 * \date 18 авг. 2015 г.
 * \author: ARV
 */
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include "config.h"
#include "timer.h"
#include "led.h"

//extern config_t config;

/// счетчик задержки для автоповтора опроса датчиков
static volatile uint16_t repeat_delay;

/// счетчик задержки между автоопросами температуры
static volatile uint16_t wait_conversion;

/// счетчик задержки для ухода в powerdown
static volatile uint16_t wait_powerdown;

static uint8_t police_blink_delay[5]={2,2,2,2,2};	// массив задердек таймера для полицейской мигалки

static uint8_t array_pos=0;
static uint8_t curent_array_delay=0;


ISR(TIMER2_OVF_vect){
	// прерывание переполнения таймера2
	// 8000000/1024/255=30гц
}

ISR(TIMER1_OVF_vect){
// прерывание по переполнению таймера1, используется для отсчета задержек в основной программе (1гц)
	TCNT1=TIMER1_PRESCALE;

	if(repeat_delay) repeat_delay--;
	if(wait_conversion) wait_conversion--;
	if(wait_powerdown) wait_powerdown--;
}

/** Инициализируем таймер2 для отсчета времени на через которое будем измерять температуру
 * @param нет
 * @return нет
 */
void timer2_init(void){
	// настраиваем таймер2
	TCNT2 = 0;
	//TCCR2 = 0;											/// Normal port operation, OC2A/OC2B disconnected, Normal Mode
	TCCR2 = _BV(CS20) | _BV(CS21) | _BV(CS22);				/// clkI/1024
	//ASSR |=_BV(AS2);										/// Asynchronous Timer/Counter2 for powerdown
	TIMSK |= _BV(TOIE2);									/// Timer/Counter2 Overflow Interrupt Enable
	//while (ASSR & (1<<TCN2UB | 1<<OCR2UB | TCR2UB)){}		// проверяем есть ли хоть один бит флаговый
	// Начинаем считать переменные, присаиваем начальные значения (первый элемент массива и его значение)
	// сохраняем во инкрементируемую переменную текущую задердку из текущей ячейки массива
	array_pos=0;
	curent_array_delay=police_blink_delay[array_pos];
}

/** Останавливаем таймер2 для отсчета времени powerdown
 * @param нет
 * @return нет
 */
void timer2_stop(void){
	// настраиваем таймер2
	TCNT2 = 0;
	TCCR2 = 0;												/// Normal port operation, OC2A/OC2B disconnected, Normal Mode
	TIMSK &= ~_BV(TOIE2);									/// Timer/Counter2 Overflow Interrupt Disable
	//while (ASSR & (1<<TCN2UB | 1<<OCR2UB | TCR2UB)){}		// проверяем есть ли хоть один бит флаговый
}

/** Инициализируем таймер2 для отсчета времени на через которое будем выходить из powerdown
 * @param measuring_time время в секундах через которое производить измерение температуры
 * @return нет
 */
void timer1_init(void){
	// настраиваем таймер 16-bit Timer/Counter1
	TCNT1 = TIMER1_PRESCALE;
	TCCR1A = 0;													/// Normal port operation, OC1A/OC1B disconnected, Normal Mode
	TCCR1B |= _BV(CS12) | _BV(CS10);							/// clkI/O/1024 (From prescaler)
	TIMSK |= _BV(TOIE1);										/// Timer/Counter1, Overflow Interrupt Enable

	reset_timer(DELAY_AUTOSEND);
	reset_timer(DELAY_REPEAT);
	reset_timer(DELAY_POWERDONW);
}

uint8_t time_is_over(delay_t t){
	switch(t){
	case DELAY_REPEAT:							/// Обабатываем задержку измерения температуры
		ATOMIC_BLOCK(ATOMIC_RESTORESTATE){		/// атомарно выдергиваем значение переменной со счетчиком зедержки
			return repeat_delay == 0;			/// возвращаем 1 - если repeat_delay=0, иначе возвращаем 0.
		}
		break;
	case DELAY_AUTOSEND:						/// Обабатываем задержку отправки температуры
		ATOMIC_BLOCK(ATOMIC_RESTORESTATE){		/// атомарно выдергиваем значение переменной со счетчиком зедержки
			return wait_conversion == 0;		/// возвращаем 1 - если wait_conversion=0, иначе возвращаем 0.
		}
		break;
	case DELAY_POWERDONW:						/// Обабатываем задержку ухода в powerdown
		ATOMIC_BLOCK(ATOMIC_RESTORESTATE){		/// атомарно выдергиваем значение переменной со счетчиком зедержки
			return wait_powerdown == 0;		/// возвращаем 1 - если wait_conversion=0, иначе возвращаем 0.
		}
		break;
	}
return 0;
}

void reset_timer(delay_t t){
	switch(t){
	case DELAY_REPEAT:
		ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
			repeat_delay = 5;
		}
		break;
	case DELAY_AUTOSEND:
		ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
			wait_conversion = config.delay_termo;
		}
		break;
	case DELAY_POWERDONW:
		ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
			wait_powerdown = 5;
		}
		break;
	}
}
