#define F_CPU 8000000UL
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>

#define LAMP_LIGHT 160
#define DEBUG_LED PIND2
#define BUTTON_PRESSED_ITERATIONS 2
#define BUTTON_MIN 6
#define BUTTON_MAX 7
unsigned long int min;
unsigned long int max;
unsigned long int prc;


unsigned long int ovfCount;
unsigned long int avgCount;
unsigned long int PulseCount;
//unsigned long int TCNT1_Last;
unsigned long int TCNT1_Current;
unsigned long int TCNT1_Prew;


void USART_Init( unsigned int baud )
{
	unsigned int v;
	v = (unsigned int)(F_CPU / (16UL * baud)) - 1U;
	/* Set baud rate */
	UBRRH = (unsigned char)(v>>8);
	UBRRL = (unsigned char)v;
	/* Enable Receiver and Transmitter */
	UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
	/* Set frame format: 8data, 2stop bit */
	UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}


void USART_Transmit( unsigned char data )
{
	/* Wait for empty transmit buffer */
	while ( !( UCSRA & (1<<UDRE)) )
	;
	/* Put data into buffer, sends the data */
	UDR = data;
}

void USART_Transmit_String(unsigned char * s)
{
	while (*s) USART_Transmit(*s++);
}


ISR(USART_RXC_vect)
{
	unsigned char val;
	val = UDR;
	unsigned char tmp[12];
	if (val=='a')
	{
		ultoa(avgCount,tmp,10);
		//USART_Transmit_String("avgCount=");
		USART_Transmit_String(tmp);
		USART_Transmit(13);
		return;
	};
	if (val=='m')
	{
		ultoa(max,tmp,10);
		//USART_Transmit_String("max=");
		USART_Transmit_String(tmp);
		USART_Transmit(13);
		return;
	};
	if (val=='0')
	{
		ultoa(min,tmp,10);
		//USART_Transmit_String("min=");
		USART_Transmit_String(tmp);
		USART_Transmit(13);
		return;
	};
	if (val=='p')
	{
		ultoa(prc,tmp,10);
		//USART_Transmit_String("prc=");
		USART_Transmit_String(tmp);
		USART_Transmit(13);
		return;
	};
}




//Таймер 1 відповідає за ШИМ
void init_pwm (void)
{
	TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10); //На выводе OC1A единица, когда OCR1A==TCNT1, восьмибитный ШИМ
	TCCR1B=(0<<CS12)|(1<<CS11)|(0<<CS10);		 //Дільник=8
	OCR1A=0;			//Начальная яркость нулевая
	OCR1B=0;			//Начальная яркость нулевая
}

//Таймер 0 рахує імпульси датчика
void Start_Measure()
{
	PORTD |= (1<<DEBUG_LED);	
	while (TCNT1>5){;};//Чекаэм поки головний таймер дотікає до нуля (+/-5тіків... то не важливо)
	ovfCount = 0;
	TCNT0 = 0;
	TCCR0 |= (1<<CS02) | (1<<CS01) | (1<<CS00);//Джерело імпульсів - ножка PORT(DTO)
}
ISR(TIMER0_OVF_vect)
{
	//Нарахували 256 ымпцльсыв
	TCCR0 &=~((1<<CS02) | (1<<CS01) | (1<<CS00));//Вимкнути таймер0
	TCNT1_Current = (unsigned long int)TCNT1;
	PORTD &= ~(1<<DEBUG_LED);
	PulseCount = (ovfCount * 255 * 255)+TCNT1_Current - TCNT1_Prew;
	ovfCount = 0;
	TCNT1_Prew = TCNT1_Current;
	avgCount = (avgCount + PulseCount)/2UL;
	//Обчислюєм залишок пального
	if ((min!=0) & (max!=0))
	{
		if ((avgCount<=min) | (min==max))
		{
			prc=0;
		}
		else
		{
			prc = (avgCount-min)*255UL;
			prc = prc/(max-min);
			if (prc>255)
			{
				prc=255;
			}
		}
		OCR1A=prc;			//Виставляєм положення стрiлки
		//Якщо залишилось менше 10 % то свiтиться лампочка
		if (prc<27)
		{
			OCR1B=LAMP_LIGHT;
		}
		else
		{
			OCR1B=0;
		}
	}
	else
	{
		prc=0;
		OCR1B=LAMP_LIGHT;//Світить лампочка
		OCR1A=125;//стрілка показує пів бака
	}
	
}

ISR(TIMER1_OVF_vect)
{
	ovfCount++;
}

int main(void)
{
	//Налаштування портiв вводу/виводу
	DDRB = 0x00|(1<<PINB1)|(1<<PINB2);
	DDRC = 0x00|(1<<PINC1)|(1<<PINC2)|(1<<PINC5);
	DDRD = 0x00|(1<<PIND2)|(1<<PIND5);
	PORTD = (1<<PIND4);
	PORTB = (1<<PINB6)|(1<<PINB7);
	PORTC = (1<<PINC6)|(1<<PINC0);
	//Просто почекаєм поки зарядяться конденсатори
	_delay_ms(200);
	//_delay_ms(200);
	//_delay_ms(200);
	//_delay_ms(200);
	//_delay_ms(200);

	USART_Init(9600);
	TIMSK = (1<<TOIE0)|(1<<TOIE1);//переривання по переповненню таймера 0 і таймера 1

	USART_Transmit_String("All systems ready...");
	
	//Зчитуєм калiбровочнi данi з флеш памятi

	unsigned char i = 0;
	unsigned char test;
	unsigned char minPressed;
	unsigned char maxPressed;
	
	max = eeprom_read_dword((uint32_t*)8);
	min = eeprom_read_dword((uint32_t*)12);
	avgCount = min;
	prc = eeprom_read_dword((uint32_t*)0);//Переводимо курсор памятi в нульову комiрку
	
	TCNT1_Current = 0;
	TCNT1_Prew = 0;
	//Налаштування таймерiв
	init_pwm();
	OCR1B=LAMP_LIGHT;//Світить лампочка
	OCR1A=125;//стрілка показує пів бака

	sei();
    while(1)
    {
		Start_Measure();
 		//Поточний стап порта Б
 		test=PINB;
 		if ((test & (1<<BUTTON_MIN))==0)//Якщо нажато мiн
 		{
	 		minPressed++;
	 		if (minPressed>BUTTON_PRESSED_ITERATIONS)
	 		{
		 		min = avgCount;
		 		eeprom_write_dword((uint32_t*)12, min);
		 		prc = eeprom_read_dword((uint32_t*)0);//Переводимо курсор памятi в нульову комiрку
		 		_delay_ms(200);
		 		_delay_ms(200);
		 		_delay_ms(100);
		 		minPressed = 0;
	 		}
 		} else
 		{minPressed=0;};
 		if ((test & (1<<BUTTON_MAX))==0)//Якщо нажано макс
 		{
	 		maxPressed++;
	 		if (maxPressed>BUTTON_PRESSED_ITERATIONS)
	 		{
		 		max = avgCount;
		 		eeprom_write_dword((uint32_t*)8, max);
		 		prc = eeprom_read_dword((uint32_t*)0);//Переводимо курсор памятi в нульову комiрку
		 		_delay_ms(200);
		 		_delay_ms(200);
		 		_delay_ms(100);
		 		maxPressed = 0;
	 		};
 		}
 		else
 		{maxPressed=0;};
		_delay_ms(100);
    };//while
}