void dalsi(void)		//posune buffer zprav, kontrola konce bufferu
	{vyriz++;
	if (vyriz>=ZPRAV) vyriz=0;
	return;}

uint8_t dalsi2(uint8_t a)		//posune buffer zprav, kontrola konce bufferu
	{a++;
	if (a>=ZPRAV) a=0;
	return a;}

uint8_t konecbuf(uint8_t a,uint8_t b)		//kontrola konce bufferu zprav
	{uint16_t i=a+b;
	if (i>=ZPRAV) i=i-ZPRAV;
	a=(uint8_t)i;
	return a;}





ISR(USART_RX_vect)
	{
	//*pt=UDR;
	buffer[doruc]=UDR0;

/*	switch (*pt)		//zde lze nejrychleji reagovat na prichozi znaky
		{case 10:
		 case 13:		 
		 case ';':{*pt=0;
				doruc++;if (doruc>=ZPRAV) doruc=0;
				pt=buffer[doruc];break;}
		case 27:{pt=buffer[doruc];UDR=13;break;}
		case 8:{if(!(pt==buffer[doruc]))pt--;break;}
		//case 'w':{OCR1AL++;break;}
		//case 'q':{Vpwm--;break;}
		//case 'p':{UDR='p';break;}
	//	case 'w':{OCR1AL=255;break;}
	//	case 's':{OCR1AL=0;break;}
		default:pt++;
		}*/		
doruc++;if (doruc>=ZPRAV) doruc=0;		//cyklicky buffer zprav
	}




void smycka(void)
	{	uint8_t i,celazprava,cislo;
		PRIKAZ((*f));
		uint8_t vyriztmp=vyriz;

	do
	{	celazprava=0;
		i=vyriz;
		//kontrola zda je v bufferu cela zprava:
		while(i!=doruc){if (buffer[i]==ODDELOVAC){ celazprava=1;break;}i=dalsi2(i);}
		if (celazprava)		//pokud je, zpracuj
		{
				cislo=indexP(PRIKAZU,(MERP*)&povel);
				memcpy_P(&f,(PGM_VOID_P)&povel[cislo].fce,sizeof(f));

				if(!(f()))
				TransmitStr("\n\r");
	
			while(buffer[vyriz]!=ODDELOVAC) dalsi();
			if (buffer[vyriz]==ODDELOVAC) dalsi();
			};
	} while (celazprava);		//opakuj dokud v bufferu byly cele zpravy

	if (logovatSD==2){logovatSD=1;} else
	if (logovatSD)
		while(vyriztmp!=vyriz)
			{
				sd_raw_write(delkalogSD,(uint8_t*)&buffer[vyriztmp],1);
				delkalogSD++;
				vyriztmp=dalsi2(vyriztmp);
			}

	return;}

uint8_t zapnilogSD(void){
	if (!sd_raw_init()) return 0;
	delkalogSD=SD_LOG_ZACATEK+sizeof(delkalogSD);
	logovatSD=2;
	return 1;}

uint8_t vypnilogSD(void){
	sd_raw_write(SD_LOG_ZACATEK,(uint8_t*)&delkalogSD,sizeof(delkalogSD));
	logovatSD=0;
	return 1;}

uint8_t nactilogSD(void){
	if (!sd_raw_init()) return 0;
	offset_t i=SD_LOG_ZACATEK+sizeof(delkalogSD);
	sd_raw_read(SD_LOG_ZACATEK,(uint8_t*)&delkalogSD,sizeof(delkalogSD));

	cli();
	uint8_t j=0;
	while(i<delkalogSD)
	{
	sd_raw_read(i,(uint8_t*)&buffer[doruc],1);
	doruc++;if (doruc>=ZPRAV) doruc=0;
	i++;j++;
	if (j==20) {j=0;smycka();}
	}

	smycka();
	sei();
	return 1;}

void USART_Transmit( unsigned char data )
	{
	while ( !( UCSR0A & (1<<UDRE0)) );
	//while ( !( PIND & (1<<PIN2)) );
	UDR0 = data;
	}

void TransmitNm(uint8_t* p,uint8_t bytes)
	{uint8_t i;
	for(i=0;i<bytes;i++){
	while ( !( UCSR0A & (1<<UDRE0)) );
	//while ( !( PIND & (1<<PIN2)) );
	UDR0 = *p++;
	}
	}


void TransmitStr(const char *data )
	{while(*data){
		while ( !( UCSR0A & (1<<UDRE0)) );
	//	while ( !( PIND & (1<<PIN2)) );
		UDR0 = *data;
		data++;
	}}


void TransmitStrP(PGM_P p )
   {char c;
	while ((c = pgm_read_byte(p++)))
		{
		while ( !( UCSR0A & (1<<UDRE0)) );
	//	while ( !( PIND & (1<<PIN2)) );
		UDR0=c;
		}
	}

/*
uint8_t indexm(uint8_t prikazu,MER* p){
	uint8_t i,j;
//	for(j=0;j<PRIKAZUM;j++){			//projdi vsechny prikazy
	for(j=0;j<prikazu;j++){			//projdi vsechny prikazy
		//zere znaky dokud plati shoda bufferu a daneho prikazu:
		for(i=0;(p[j].nazev[i]==buffer[konecbuf(vyriz,i)]);i++){	
				}

		//pokud je dalsi znak v bufferu oddelovac a prikaz skoncil=>uspech
		if((buffer[konecbuf(vyriz,i)]==ODDELOVAC) & (p[j].nazev[i]==0))
		{vyriz=konecbuf(vyriz,i);return j;}
		//pokud je dalsi znak v bufferu carka a prikaz skoncil=>uspech
		if((buffer[konecbuf(vyriz,i)]==',')&(p[j].nazev[i]==0))
		{vyriz=konecbuf(vyriz+1,i);return j;}
		}

	return 0;}   //0 spusti chybu-nenalezen prikaz
*/
#define DELKABUF 20
uint8_t indexP(uint8_t prikazu,MERP* p){
	uint8_t i,j;
	char prbuf[DELKABUF];

	for(i=0;i<DELKABUF;i++){
		prbuf[i]=buffer[konecbuf(vyriz,i)];
		if (prbuf[i]==ODDELOVAC){prbuf[i]=0;break;}
		if (prbuf[i]==' '){prbuf[i]=0;i++;break;}
		if (prbuf[i]==','){prbuf[i]=0;i++;break;}
		};

	PGM_P pt;
	for(j=0;j<prikazu;j++){			//projdi vsechny prikazy
		//srovna prijaty prikaz se seznamem prikazu
		memcpy_P(&pt,(PGM_VOID_P)&p[j].nazev,sizeof(PGM_P));
	//	TransmitStrP(pt);TransmitStr(":");TransmitStr(prbuf);TransmitStr("- ");

			int porovna=0;
			porovna=strcmp_P(prbuf,pt);
		if(porovna==0)
			{vyriz=konecbuf(vyriz,i);return j;};  //vrati cislo nalezeneho prikazu
		}

	return 0;}   //0 spusti chybu-nenalezen prikaz


void TransmitData(uint8_t* p,uint8_t bytes)
	{
	switch(vystup_komunikace)
		{case POCETBYTU:vystup_bytu+=bytes;break;
		 case SDCARD:if (sd_raw_write(SD_offset_zapis,p,bytes)) SD_offset_zapis+=bytes;break;
		 default:TransmitNm(p,bytes);
		 };
	}

uint8_t nastavSD(void){
	vystup_komunikace=POCETBYTU;
	vystup_bytu=0;
			uint8_t i=0;void (*f)(void);
			//prochazi a posila vsechny vybrane data k odeslani
			while(kodeslani[i]){
				//povelm[kodeslani[i]].fce();
				memcpy_P(&f,(PGM_VOID_P)&povelm[kodeslani[i]].fce,sizeof(f));
				f();i++;
				}

	vystup_komunikace=SDCARD;
	return 1;};

uint8_t uloz_nastaveniSD(void){
	if (sd_raw_init()){
		SD_offset_cteni=SD_MERENI_ZACATEK+sizeof(SD_offset_zapis);
		sd_raw_write(SD_offset_cteni,&vystup_bytu,sizeof(vystup_bytu));
		uint8_t i;
		SD_offset_cteni+=sizeof(vystup_bytu);
		for(i=0;kodeslani[i]!=0;i++) sd_raw_write(SD_offset_cteni+i,&kodeslani[i],sizeof(uint8_t));
		sd_raw_write(SD_offset_cteni+i,&kodeslani[i],sizeof(uint8_t));
		SD_offset_cteni+=i+1;
		SD_offset_zapis=SD_offset_cteni;
		
		uloz_delku_mereniSD();
		return 1;}
	return 0;};

uint8_t uloz_delku_mereniSD(void){
	if(sd_raw_init()){
		sd_raw_write(SD_MERENI_ZACATEK,(uint8_t*)&SD_offset_zapis,sizeof(SD_offset_zapis));
		TransmitStr("uloz delku mereni\n");
		return 1;}
	return 0;};

uint8_t zapnicteniSD(void){
	if (!sd_raw_init()) return 0;

	cteniSD=1;
	vystup_komunikace=SERIAL;

	SD_offset_cteni=SD_MERENI_ZACATEK;
	
	sd_raw_read(SD_offset_cteni,(uint8_t*)&SD_offset_zapis,sizeof(SD_offset_zapis));
	SD_offset_cteni+=sizeof(SD_offset_zapis);
	
	sd_raw_read(SD_offset_cteni,&vystup_bytu,sizeof(vystup_bytu));
	SD_offset_cteni+=sizeof(vystup_bytu);
	
	uint8_t i;
	for(i=0;i<PRIKAZUM;i++)
	{sd_raw_read(SD_offset_cteni+i,&kodeslani[i],sizeof(uint8_t));
	if (kodeslani[i]==0) break;
	}
	kodeslani[i]=0;
	SD_offset_cteni+=i+1;

	return 1;}
