#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <string.h>
#include "timer.h"
#include "circular_buf.h"

#define F_CPU 16000000
#define SIZE_BUF 16



volatile unsigned char usartTxBuf[SIZE_BUF];
volatile unsigned char txBufTail = 0;
volatile unsigned char txBufHead = 0;
volatile unsigned char txCount = 0;

volatile unsigned char usartRxBuf[SIZE_BUF];
volatile unsigned char rxBufTail = 0;
volatile unsigned char rxBufHead = 0;
volatile unsigned char rxCount = 0;



void UARTInit(void) {
	UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << TXCIE0);
	UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
	UBRR0H = 0;
	UBRR0L = 103;
}

void UARTSend(uint8_t* data, size_t length) {
	for (size_t i = 0; i < length; i++) { // Æä¸ì îïóñòîøåíèÿ áóôåðà ïåðåäà÷è (÷èòàåì ôëàã).
		while (!(UCSR0A & (1 << UDRE0)));
		UDR0 = data[i];// Çàïèñûâàåì â ðåãèñòð çíà÷åíèå ïåðåìåííîé "data" äëÿ ïåðåäà÷è.
	}
}
//ïîëîæèòü ñèìâîë â áóôåð
void USART_PutChar(unsigned char sym) {
	if (((UCSR0A & (1 << UDRE0)) != 0) && (txCount == 0)) {
		UDR0 = sym;
		} else {
		if (txCount < SIZE_BUF) {
			usartTxBuf[txBufTail] = sym;
			txCount++;
			txBufTail++;
			if (txBufTail == SIZE_BUF) {
				txBufTail = 0;
			}
		}
	}
}
//âçÿòü ñèìâîë èç áóôåðà
unsigned char GetChar(void) {
	unsigned char sym = 0;
	if (txCount > 0) {
		sym = usartTxBuf[txBufHead];
		txCount--;
		txBufHead++;
		if (txBufHead == SIZE_BUF) {
			txBufHead = 0;
		}
	}
	return sym;
}
//ôóíêöèÿ çàãðóçêè ñòðîê
void USART_SendStr(const unsigned char* data) {
	while (*data) {  
		USART_PutChar(*data++);
	}
}
//ïîëó÷àåì äàííûå èç áóôåðà
void UARTReceive(uint8_t* data) {
	uint32_t timeout_ms_mb = 100;//timeout 100ms,  â íàøåì ñëó÷àå, èíîãäà ïî 1 ñåê, è äàæå ïî 4-5 ñ, åñëè áàéò ïîâðåäèëñÿ è èäåò îêîëî 1-2ñåêóíä, òî øòîðà ìîæåò ñëîìàòüñÿ
	uint32_t timeout_ms = 4;	
	uint32_t start_time = millis();//çàïîìèíàåì âðåìÿ íà÷àëà îæèäàíèÿ
	while (rxCount == 0) {		//îæèäàíèå íàëè÷èÿ äàííûõ â áóôåðå ïðè¸ìà
		if ((millis() - start_time) > timeout_ms_mb) { //åñëè âðåìÿ îæèäàíèÿ èñòåêëî 
			return 0; //âûõîäèì èç öèêëà 
		}
	}
	data[0] = usartRxBuf[rxBufHead];//ñ÷èòûâàíèå áàéòà èç áóôåðà
	rxCount--;
	rxBufHead++;
	if (rxBufHead == SIZE_BUF) {
		rxBufHead = 0;
	}
	start_time = millis();//îáíóëÿåì òàéìàóò, òàê êàê äàííûå íà÷àëè ïðèõîäèòü
	while (rxCount > 0) { //îæèäàíèå îêîí÷àíèÿ ïðè¸ìà äàííûõ
		if ((millis() - start_time) > timeout_ms) {  //åñëè âðåìÿ îæèäàíèÿ èñòåêëî
			break;  //âûõîäèì èç öèêëà îæèäàíèÿ
		}
	}
}


int main(void) {
	sei();
	UARTInit();
	timerInit();
	DDRD = 0xFF;
	uint8_t buff[] = {0x48, 0x45, 0x4C, 0x4C, 0x4F, 0x21, 0x09};
	UARTSend(buff, sizeof(buff));
	//for (int i = 0; i < 7; i++) {
	//UARTSend(buff, sizeof(buff));
	//}

	uint8_t receivedData[SIZE_BUF];
	UARTReceive(receivedData);


	UARTSend(receivedData, sizeof(receivedData));
	


	while (1) {
		//unsigned long currentTime = millis();
		// Äåëàéòå ÷òî-òî ñ òåêóùèì âðåìåíåì...
	}
	return 0;
}

ISR(USART_RX_vect) {
	if (rxCount < SIZE_BUF) {
		usartRxBuf[rxBufTail] = UDR0;
		rxBufTail++;
		if (rxBufTail == SIZE_BUF) {
			rxBufTail = 0;
		}
		rxCount++;
	}
}


////îáðàáîò÷èê ïðåðûâàíèÿ ïî çàâåðøåíèþ ïåðåäà÷è
//ISR(USART_TXC_vect) {
	//if (txCount > 0){                              //åñëè áóôåð íå ïóñòîé
		//UDR0 = usartTxBuf[txBufHead];         //çàïèñûâàåì â UDR ñèìâîë èç áóôåðà
		//txCount--;                                      //óìåíüøàåì ñ÷åò÷èê ñèìâîëîâ
		//txBufHead++;                                 //èíêðåìåíòèðóåì èíäåêñ ãîëîâû áóôåðà
		//if (txBufHead == SIZE_BUF)
		//txBufHead = 0;
	//}
	//else {
		//UCSR0B &= ~(0<<TXCIE0);
	//}
	//
	//// rx_data = UDR0; //Â íåì äàííûå èç ïðèåìíîãî áóôåðà UDR ïåðåíîñÿòñÿ â ãëîáàëüíóþ ïåðåìåííóþ rx_data
	//// rx_flag = 1;  //âûñòàâëÿåòñÿ ôëàã rx_flag, ãîâîðÿùèé î òîì, ÷òî ïðèåì çàâåðøåí
//}