/*
 * AvtoSpeed_0.0.2.c
 *
 * Created: 11.02.2017 18:39:15
 *  Author: Саубанов Ринат
 */ 

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define SEG_ON PORTB |= _BV(4)
#define SEG_OFF PORTB &=~ _BV(4)
#define DP_ON PORTB |= _BV(5)
#define DP_OFF PORTB &=~ _BV(5)
#define DIGIT_ON PORTC |= _BV(4)
#define DIGIT_OFF PORTC &=~ _BV(4)

static uint8_t SYMBOLS[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
//static uint16_t SYMBOLS[] = {};	
unsigned int speed = 0;
unsigned char TOR = 0;
unsigned long int time;
unsigned char lap = 0;
unsigned int time_lap = 0;
unsigned int time_lap8;

uint16_t getSymbol(uint8_t number)//
{
	return SYMBOLS[number];
}

uint8_t DIGIT_CLEAR()//очистка дисплея
{
	DIGIT_ON;
	PORTC |= _BV(5);
	asm ("nop");
	PORTC &=~ _BV(5);
	DIGIT_OFF;
}

uint8_t DIGIT_LAP()//выбор сегмента дисплея
{
	DIGIT_CLEAR();
	for (uint8_t i=0; i<5; i++)
	{
		PORTC |= _BV(5);
		PORTC &=~ _BV(5);
	}
}

//void printLap(uint8_t* arrayLap)//лишний код
//{
	//SEG_OFF;
	//SEG_ON;
	//PORTC = getSymbol(arrayLap[0]) | DIGIT_CLEAR();
//}

void printSpeed(uint8_t* array)//программа отвечающая за дисплей
{
	SEG_OFF;
	SEG_ON;
	PORTC = getSymbol(array[4]) | DIGIT_CLEAR();
	_delay_us(45);
	PORTC = getSymbol(array[3]) | _BV(5);
	PORTC &=~ _BV(5);
	_delay_us(65);
	PORTC = getSymbol(array[2]) | _BV(5);
	PORTC &=~ _BV(5);
	_delay_us(65);
	PORTC = getSymbol(array[1]) | _BV(5);
	PORTC &=~ _BV(5);
	_delay_us(65);
	PORTC = getSymbol(array[0]) | _BV(5);
	PORTC &=~ _BV(5);
	_delay_us(70);
}

void speedtoDiigit (uint16_t speed, uint8_t* result)//раскладываем скорость на отдельные цифры
{
	result[0] = speed%100000/10000;
	result[1] = speed%10000/1000;
	result[2] = speed%1000/100;
	result[3] = speed%100/10;
	result[4] = speed%10;
}

uint16_t readSpeed()//подсчет скоростм круга
{
	uint16_t data = 0;
	data = time_lap;
	return (uint16_t)(((float)6250/data)*3600);
}

uint16_t readSpeed_8()//подсчет конечной скорости
{
	uint16_t data = 0;
	data = time_lap8;
	return (uint16_t)(((float)50000/data)*3600);
}

void Timer1_init()
{
	TCCR1B |= _BV(CS10)|_BV(ICES1);
	TCNT1 = 57535;
	TIMSK |= _BV(TOIE1)|_BV(TICIE1);
}

void Interrupt_init()
{
	DDRD &=~ (_BV(2)|_BV(3));
	PORTD |= _BV(2)|_BV(3);
	MCUCR |= _BV(ISC11)|_BV(ISC01);
	GICR |= _BV(INT0)|_BV(INT1);
}

ISR (INT0_vect)//Key START переход в программу подсчета кругов
{
	TOR = 1;
}

ISR (INT1_vect)//Key RESET полный сброс программы
{
	TOR = 0;
	return main();
}

ISR (TIMER1_OVF_vect)//
{
	TCNT1 = 57535;
	time++;
}

ISR (TIMER1_CAPT_vect)//Time lap время круга
{
	time++;
	lap = 1;
	time_lap = time;
	time = 0;
}

int main(void)
{
	DDRC = 0x7f;
	PORTC = 0x00;
	DDRB = 0xff;
	PORTB |= _BV(4)|_BV(0);
	Timer1_init();
	Interrupt_init();
	asm("sei");
	time_lap = 0;
	while (1)
	{
		if (TOR != 1)//проверяем нажал ли спортсмен на кнопку
		{
			uint8_t array1[5];//массив для результата
			speed = readSpeed();//получаем результа круга
			speedtoDiigit(speed, array1);//раскладываем результат на отдельные цифры и записываем в массив
			printSpeed(array1);//выводим результат на дисплей
		} 
		else
		{
			lap = 0;
			time_lap8 = 0;
			DIGIT_CLEAR();//очищаем дисплей
			for(uint8_t c=0; c<8;)
			{
				if (lap != 0)//счетаем круги
				{
					time_lap8 += time_lap;
					c++;
					lap = 0;
				} 
				else
				{
					PORTC = getSymbol(c);//выводим номер круга на дисрлей
				}
			}
			while (1)//конечный результат до момента сброса
			{
				uint8_t lap_8[5];
				speed = readSpeed_8();
				speedtoDiigit(speed, lap_8);
				printSpeed(lap_8);
			}							
		}
		
	}
}