#include <avr/io.h>
#define F_CPU 16000000UL
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUFLEN		50
volatile unsigned int	ticTC0;
volatile unsigned char	irx, status;
char	TxBuf[100];
char	EEPROM_Buf[100], RxBuf[BUFLEN+1];

#define STX		2
#define ETX		3
#define BAUD	57600	//bitrate
#define UBRR	F_CPU/16/BAUD-1
#define USARTRX			(status & (1<<0))		
#define SET_USARTRX		(status |= (1<<0))
#define CLR_USARTRX		(status &= ~(1<<0))
//--------------------------------------------------------------------
ISR (TIMER0_OVF_vect)
{ 
	ticTC0++; 
	if (ticTC0 == 250) {PORTB  ^= (1<<PORTB5); ticTC0 = 0;}
	TCNT0 = 131;		//2ms
}
//------------------------------------------------------------------------------
ISR (USART_RX_vect)		
{
	char	temp;
	temp = UDR0;
	if (temp == STX) {irx = 0; return;}
	if (irx < BUFLEN) RxBuf[irx++] = temp;
	if (temp == ETX) {RxBuf[irx]='\0'; SET_USARTRX;}
}
//--------------------------------------------------------------------
void InitTimerCounter_0 (void)		
{
	TCCR0B = (1<<CS02);				
	TIFR0 = 1<<TOV0;				
	TIMSK0 = 1<<TOIE0;			  	
	TCNT0 = 131;				 
}
//--------------------------------------------------------------------
void USART_Init (unsigned int ubrr)	
{
	UBRR0H = (unsigned char)(ubrr>>8);	
	UBRR0L = (unsigned char)ubrr;
	UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); 
	UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); 
}
//--------------------------------------------------------------------
void USART_Transmit (char dataout)
{
	while(!(UCSR0A & (1 << UDRE0)));
	UDR0 = dataout;
}
//------------------------------------------------------------------------------
void USART_Transmit_Text (char *text) {
	unsigned char	i;
	for (i=0; i<strlen(text); i++) 
		USART_Transmit (text[i]);
}
//-------------------------------------------------------------------------------
void EEPROM_read (unsigned int Address, unsigned int count)
{
	unsigned char	i, j;
	
	sprintf (EEPROM_Buf, "\n\r0x%03X:%04d", Address, count); 
	USART_Transmit_Text(EEPROM_Buf);
	for (i=0; i<(count/16); i++) {
		wdt_reset(); 
		sprintf (EEPROM_Buf, "\n\r0x%03X:", Address+i*0x10); USART_Transmit_Text(EEPROM_Buf);
		for (j=0; j < 16; j++) {
			sprintf (EEPROM_Buf, "%02X ",  eeprom_read_byte((uint8_t*)Address+i*16+j));
			USART_Transmit_Text(EEPROM_Buf);
		}
		EEPROM_Buf[16] = '\0';
		eeprom_read_block(EEPROM_Buf, (uint8_t*)Address+i*16, 16);
		USART_Transmit_Text(EEPROM_Buf);
	}	
}
//-------------------------------------------------------------------------------
void EEPROM_read_ASCII (unsigned int Address, unsigned char count)
{
	unsigned int	i;
	char	znak;
	
	sprintf (EEPROM_Buf, "\n\r0x%03X:%02d\n\r", Address, count); 
	USART_Transmit_Text(EEPROM_Buf);
	for (i=0; i < count; i++) {
		wdt_reset(); 
		znak = eeprom_read_byte((uint8_t*)Address+i);
		if (!isalnum(znak) && !ispunct(znak) && !isspace(znak)) znak = '.';
		USART_Transmit (znak);
	}
}
//------------------------------------------------------------------------------
int main (void) {
	unsigned char	prikaz_ok, i;
	char	prikaz[6];
	unsigned int	adr, poc;
	float	testfl;

	wdt_enable(WDTO_1S);
	DDRB |= (1<<DDB5);
	USART_Init (UBRR);
	InitTimerCounter_0();	
	sei();
	USART_Transmit_Text("\n\rTest internej pamate EEPROM");
	USART_Transmit_Text("\n\rEECLR - eeprom clear");
	USART_Transmit_Text("\n\rEE_RD_adr_count - read EE_RD00001024");
	USART_Transmit_Text("\n\rEERDA_adr_count - read ascii EERDA000034");
	USART_Transmit_Text("\n\rEEWRA_adr_text - write ascii EEWRA0000Zaklady Mikroprocesorovej Techniky");

	while(1) { 
		wdt_reset();
		if (USARTRX) {
			CLR_USARTRX; prikaz_ok = '?';
			for (i=0; i<5; i++) prikaz[i]=RxBuf[i];
			prikaz[5]='\0';
			//$02EECLR$FF$03
			if (!strcmp (prikaz, "EECLR")) {
				prikaz_ok = '+';
				sprintf(TxBuf,"\n\rEEPROM Clear 0x%02X", RxBuf[5]); 
				USART_Transmit_Text(TxBuf);
				for (adr=0; adr<1024; adr++) {
					wdt_reset();
					eeprom_update_byte ((uint8_t*)adr, RxBuf[5]);
				}
				USART_Transmit_Text("\n\rOK");
			}
			//$02EE_RD00001024$03
			if (!strcmp (prikaz, "EE_RD")) {
				prikaz_ok = '+';
				adr = (RxBuf[5]-'0')*1000 + (RxBuf[6]-'0')*100 + (RxBuf[7]-'0')*10 + RxBuf[8]-'0';
				poc = (RxBuf[9]-'0')*1000 + (RxBuf[10]-'0')*100 + (RxBuf[11]-'0')*10 + RxBuf[12]-'0';
				if (poc%0x10) poc = poc+0x10-poc%0x10; //kontrola na 16 bytov
				EEPROM_read (adr, poc);
			}
			//$02EERDA000034$03
			if (!strcmp (prikaz, "EERDA")) {
				prikaz_ok = '+';
				adr = (RxBuf[5]-'0')*1000 + (RxBuf[6]-'0')*100 + (RxBuf[7]-'0')*10 + RxBuf[8]-'0';
				poc = (RxBuf[9]-'0')*10 + RxBuf[10]-'0';
				EEPROM_read_ASCII (adr, (char)poc);	
			}
			//$02EEWRA0000Zaklady Mikroprocesorovej Techniky$03
			if (!strcmp (prikaz, "EEWRA")) {
				prikaz_ok = '+';
				adr = (RxBuf[5]-'0')*1000 + (RxBuf[6]-'0')*100 + (RxBuf[7]-'0')*10 + RxBuf[8]-'0';
				for (i=0; i<100; i++) {
					if (RxBuf[i+9] != ETX) EEPROM_Buf[i]=RxBuf[i+9];
					else break;
				}
				EEPROM_Buf[i]='\0';
				USART_Transmit_Text(EEPROM_Buf);
				eeprom_update_block (EEPROM_Buf, (uint8_t*)adr, i);
			}
			//$02EERDF0000$03
			if (!strcmp (prikaz, "EERDF")) {
				prikaz_ok = '+';
				adr = (RxBuf[5]-'0')*1000 + (RxBuf[6]-'0')*100 + (RxBuf[7]-'0')*10 + RxBuf[8]-'0';
				testfl = eeprom_read_float ((void*)adr);
				sprintf (EEPROM_Buf, "\n\r0x%03X:%f\n\r", adr, testfl);
				USART_Transmit_Text(EEPROM_Buf);
			}
			//$02EEWDF00003.14$03
			if (!strcmp (prikaz, "EEWDF")) {
				prikaz_ok = '+';
				adr = (RxBuf[5]-'0')*1000 + (RxBuf[6]-'0')*100 + (RxBuf[7]-'0')*10 + RxBuf[8]-'0';
				for (i=0; i<100; i++) {
					if (RxBuf[i+9] != ETX) EEPROM_Buf[i]=RxBuf[i+9];
					else break;
				}
				EEPROM_Buf[i]='\0';
				USART_Transmit_Text(EEPROM_Buf);
				testfl = atof(EEPROM_Buf);
				eeprom_update_float((void*)adr, testfl);
			}
			USART_Transmit(prikaz_ok);
		}
	}
}
//------------------------------------------------------------------------------

