// ******************************************** //
// DATALOGGER PRO MONITOROVANI VODNICH TOKU		//
// VERZE: 2.1b, 8.5.2014						//
// VYPRACOVAL: PACINEK DAVID, ID:12775			//
// V RÁMCI DIPLOMOVÉ PRÁCE NA FEKT VUT BRNO		//
// ******************************************** //

#define F_CPU 1000000UL		//Frekvence pro vypocet zpozdeni - util/delay.h
							//Musi byt zde, jinak hlasi chybu, ze ji nenalezl

#include <avr/io.h>			//Registry kontroleru
#include <stdio.h>			//Rutiny pro praci se vstupy a vystupy
#include <avr/interrupt.h>	//Funkce a makra pro obsluhu preruseni
#include <avr/sleep.h>		//Funkce spanku
#include <avr/pgmspace.h>	//Funkce pro praci s pameti
#include <util/delay.h>		//Casove funkce
#include <stdlib.h>			//Matematicke funkce
												
void port_init (void)
{
  DDRB	= 0b11100101;		//MOSI vystup MISO vstup
  PORTB = 0b00000010;		//Urovne vystupu log.0, pro SCK log. 1
  DDRC  = 0b00101100;		//PC2,3,5 vystupy, ostatni vstupy
  PORTC = 0b00000000;		//Vystupni piny v log.0, neaktivni pull-up R na vstupech
  DDRD  = 0b11011010;		//PD3,4,6,7 vystupy, ostatni vstupy
  PORTD = 0b00000000;		//Vystupni piny v log.0, neaktivni pull-up R na vstupech
}


// ******************* //
// **** RTC OBVOD **** //
// ******************* //

// Vytvoreni maker pro snadnejsi praci s RTC //

#define CLK_M	DDRB		//PB0 nastaveni orientace
#define DATA_M	DDRB		//PB1 nastaveni orientace
#define RST_M	DDRD		//PD7 nastaveni orientace

#define CLK PORTB			//PB0 port jako CLK nebo taky CE
#define DDO PORTB			//PB1 pin nastaven jako vystup dat
#define DDI PINB			//PB1 pin nastaven jako vstup dat
#define RST PORTD			//PD7 nastaven jako RST

void init_rtc ()			//Inicializace a nastaveni do vychoziho stavu			
{
   CLK_M  |= (1<<PB0);			//CLK jako vystup
   RST_M  |= (1<<PB1);			//RST jako vystup
   DATA_M |= (1<<PD7);			//DATA jako vystup
   CLK = PORTB &~ (1<<PB0);     //CLK jako vstup
   RST = PORTD &~ (1<<PD7);		//RST jako vstup
   DDO = PORTB &~ (1<<PB1);		//DATA jako vstup

}

void clk_rtc (void)	//Vytvoreni hodinoveho pulsu na vystupu CLK
{
	_delay_us (5); CLK = 1; _delay_us (5); CLK = 0; _delay_us (5);
}

unsigned char read_rtc (unsigned char adresa)	//Cteni dat z RTC
{
  unsigned char cc1, rtc_data;
  init_rtc();
  rtc_data=0;
  RST = 1;								//Aktivace linky, zahajeni prenosu
  for (cc1=0; cc1<8; cc1++)				//Prenos command bajtu
     {
       if ((adresa&0x01) == 1) DDO = 1;	//Podminka
         else DDO = 0;
       adresa>> 1;						//Posunuti o jeden bit doprava 
	   clk_rtc ();	
     }


  DATA_M = 0;                    //Nastaveni DAT jako vstup
  rtc_data = 0;
 for (cc1=0; cc1<8; cc1++)      //Cyklus pro prenos dat
     {
       rtc_data>>= 1;
       if (DDI) rtc_data |=128;

       clk_rtc ();
     }
     
  DDO = 0;                       //Ukonceni komunikace s obvodem
  RST = 0;
  return rtc_data;
}

unsigned char write_rtc (unsigned char adresa, unsigned char rtc_data) //Zapis dat do RTC
{
  unsigned char cc1;
  init_rtc();
  RST = 1;						//Zahajeni prenosu
  for (cc1=0; cc1<8; cc1++)     //Prenos command bajtu
     {
       if ((adresa&0x01) == 1) DDO = 1;	//Podminka
         else DDO = 0;
		 
       adresa>> 1;              //Posunuti o jeden bit doprava
       
       clk_rtc ();
     }
  for (cc1=0; cc1<8; cc1++)     //Cyklus pro prenos dat
     {
       if ((rtc_data&0x01) == 1) DDO = 1;
         else DDO = 0;
       rtc_data>> 1;            //Posunuti o jeden bit doprava
       
       clk_rtc ();  
     }
  DDO =0;						//Ukonceni komunikace s obvodem
  RST =0;
  
  return 0;
}
 
// ************************** //
// **** ANALOGOVÉ OBVODY **** //
// ************************** //

// Vytvoreni maker pro praci s ADC

#define ADC_ZAPNOUT 		ADCSRA |= (1<<ADEN) //Log 1 do ADEN bitu
#define ADC_VYPNOUT 		ADCSRA &= 0x7F		//Log 0 do ADEN, zbytek 1
#define ADC_START			ADCSRA |= (1<<ADSC)	//Start prevodu log 1 do ADSC

unsigned char teplota[7];			//Alokace pole pro teplotu
unsigned char hladina[7];			//Alokace pole pro hladinu
unsigned char napeti[7];			//Alokace pole pro napeti AKU

void ADC_init(void)				//Inicializacni fce
unsigned int ADC_read(void)			//Fce pro cteni ADC
void readteplota(unsigned char)		//Fce pro cteni teploty
void readhladina(unsigned char)		//Fce pro cteni hladiny
void readnapeti(unsigned char)		//Fce pro cteni napeti


//Inicializace analogovych portu, prevodni cas je 65uS //

void ADC_init(void)
{
  ADCSRA = 0x00;	//Vypnuti ADC
  ADMUX  = 0x41;	//Nastaveni ADC1 jako vstup, AVcc jako ref.
  ADCSRA = 0x82;	//Delici faktor 4, a povoleni cinosti AD
  ADC_ZAPNOUT;		//Povoleni ADC
}


// Prevod analogove merene hodnoty na digitalni //

unsigned int ADC_read(void)
{
    char i;
    unsigned int ADC_temp, ADCH_temp;	//Deklarace pomocnych pro prumerovani
    unsigned int ADC_hodnota = 0;			//Deklarace a nulovani
    
            
    for(i=0;i<5;i++)				//Pro lepsi presnost se prevod provede 5x
    {
	 	ADC_START;					//Zacatek prevodu
        while(!(ADCSRA & 0x10));	//Cekaci cyklus na dokonceni prevodu
        ADCSRA|=(1<<ADIF);			//Priznakovy bit preruseni do 1
		
        ADC_temp = ADCL;			//Cteni ADCL registru
        ADCH_temp = ADCH;			//Cteni ADCH registru      
		
		//Akumulace vysledku pro pozdejsi prumerovani
		ADC_temp +=(ADCH_temp << 5);
        ADC_hodnota += ADC_temp;      
    }

    ADC_hodnota = ADC_hodnota >> 2;				//Prumerovani

	if(ADC_hodnota > 1023) ADC_hodnota = 1023;	//Podmninka pro splneni max. hodnoty
	
    return ADC_hodnota;							//Ulozeni int hodnoty do ADC_hodnota
}


// Cteni hodnoty teploty z teplomeru pripojeneho na ADC1 //

void readteplota(unsigned char channel) //Funkce cteni teploty s parametrem channel
{
   unsigned int hodnota;
   float volt;					//Datovy typ pro volty

   ADMUX = 0x41 | channel;		//Nastaveni ADMUXU pro ADC
   hodnota = ADC_read();		//Prirazeni hodnoty do ADC_read

   volt = (float)(hodnota * 3.3)/ 1024.0;		//Vypocet digitalni hodnoty
   hodnota = (unsigned int)(volt * 1000);		//Pomocne nasobeni
	//Zapis namerenych hodnot do poli
   teplota[6] = 'C';					//Prirazeni C pro teplotu
   teplota[5] = 0xb0;					//Prirazeni ° pro teplotu
   teplota[4] = (hodnota % 10) | 0x30;	//Hodnota za desetinnou teckou
   teplota[3] = '.';					//Prirazeni desetinne tecky
   hodnota = hodnota / 10;				//Deleni 10
   teplota[2] = (hodnota % 10) | 0x30;	//Prvni cislo hodnoty
   hodnota = hodnota / 10;				//Deleni 10
   teplota[1] = (hodnota % 10) | 0x30;	//Druhe cislo hodnoty
   hodnota = hodnota / 10;				//Deleni 10
   teplota[0] = hodnota | 0x30;			//Treti cislo
}  

// Cteni hodnoty hladiny z tenzometru pripojeneho na ADC0 //

void readhladina(unsigned char channel) //Funkce cteni hladiny s parametrem channel
{
   unsigned int hodnota;
   float volt;				//Datovy typ pro volty

   ADMUX = 0x40 | channel;	//Nastaveni ADMUXU pro ADC
   hodnota = ADC_read();		//Prirazeni hodnoty do ADC_read

   volt = (float)(hodnota * 3.3)/ 1024.0;		//Vypocet digitalni hodnoty
   hodnota = (unsigned int)(volt * 1000);		//Pomocne nasobeni
//Zapis namerenych hodnot do poli
   hladina[6] = 'm';						//Prirazeni m pro hladinu
   hladina[5] = ' ';						//Mezera
   hladina[4] = (hodnota % 10) | 0x30;		//Hodnota za desetinnou teckou
   hladina = hodnota / 10;						//Deleni 10
   hladina[3] = (hodnota % 10) | 0x30;		//Hodnota za desetinnou teckou
   hladina = hodnota / 10;						//Deleni 10
   hladina[2] = (hodnota % 10) | 0x30;		//Hodnota za desetinnou teckou
   hladina[1] = '.';						//Prirazeni desetinne tecky
   hodnota = hodnota / 10;						//Deleni 10
   hladina[0] = hodnota | 0x30;				//Cislo hodnoty


// Cteni hodnoty napětí AKU na pinu ADC7 //

void readnapeti(unsigned char channel)	//Funkce cteni napeti s parametrem channel
{
   unsigned int hodnota;
   float volt;				//Datovy typ pro volty

   ADMUX = 0x47 | channel;	//Nastaveni ADMUXU pro ADC
   hodnota = ADC_read();		//Prirazeni hodnoty do ADC_read

   volt = (float)(hodnota * 3.3)/ 1024.0;		//Vypocet digitalni hodnoty
   hodnota = (unsigned int)(volt * 1000);		//Pomocne nasobeni
//Zapis namerenych hodnot do poli
   napeti[6] = 'V';						//Prirazeni V pro napeti
   napeti[5] = ' ';						//Mezera
   napeti[4] = (hodnota % 10) | 0x30;		//Hodnota za desetinnou teckou
   hodnota = hodnota / 10;						//Deleni 10
   napeti[3] = (hodnota % 10) | 0x30;		//Hodnota za desetinnou teckou
   hodnota = hodnota / 10;						//Deleni 10
   napeti[2] = (hodnota % 10) | 0x30;		//Hodnota za desetinnou teckou
   napeti[1] = '.';						//Prirazeni desetinne tecky
   hodnota = hodnota / 10;						//Deleni 10
   napeti[0] = hodnota | 0x30;				//Cislo hodnoty
}  

// ************************************************************** //
// **** Inicializace SPI rozhrani pro komunikaci s SD kartou **** //
// ************************************************************** //

// Makra //

#define SPI_SD             SPCR = 0x52	//SPE zap., MSB, SCK low, MASTER, fosc/64
#define SPI_HIGH_SPEED     SPCR = 0x50; SPSR |= (1<<SPI2X) //Dvojnasobne SCK

void spi_init(void);						//Funkce init pro SPI
unsigned char SPI_prenos(unsigned char);	//Otypovani pro prenos
unsigned char SPI_prijem(void);				//Otypovani pro prijem

void spi_init(void)		//Funkce init pro SPI
{
SPCR = 0x52;			//SPI zap., MSB, SCK low, MASTER, fosc/64
SPSR = 0x00;			//Nulovani stavoveho registru
}

unsigned char SPI_prenos(unsigned char data)	//Funkce pro prenos
{

SPDR = data;				//Zahajeni prenosu "data"

while(!(SPSR & (1<<SPIF)));	//Cekaci smycka pro dokonceni prenosu
data = SPDR;				//Zapsani dat do datoveho registru SPDR

return(data);				//Vraceni datoveho registru
}

unsigned char SPI_prijem(void)	//Funkce pro prijem
{
unsigned char data;

SPDR = 0xff;					//Nastaveni datoveho registru SPDR na 1			
while(!(SPSR & (1<<SPIF)));		//Cekaci smycka na dokonceni prijmu
data = SPDR;					//Zapsani dat do datoveho registru SPDR

return data;					//Vraceni datoveho registru
}


// ****************** //
// **** SD KARTA **** //
// ****************** //

// *********************************** //
// Castecne prevzato a upraveno z [32] //
// Kod je pripraveny pro otestovani na strane PC pomoci USART rozhrani  a take pro moznost pouziti SDHC karty//
// Rozhrani PC je mozne videt z odkazu [32] //
// Komentare jen u nejdul. prvku //

// Makra pro ovladani karty //

#define PRECHOD_IDLE            0
#define POSLANI_PRI_COND		8
#define SD_ODESLANI_OP			41   //ACMD
#define APP_CMD					55
#define CTENI_OCR				58
#define CRC_ZAP_VYP             59

#define ON     1
#define OFF    0

volatile unsigned long startBlock, totalBlocks; 
volatile unsigned char SDHC_flag, cardType, buffer[512];

unsigned char SD_init(void);										//Vraci prazdny parametr
unsigned char SD_sendCommand(unsigned char cmd, unsigned long arg);	//Poslat pozadavek
unsigned char SD_readSingleBlock(unsigned long startBlock);			//Cteni jednoho bitu
unsigned char SD_writeSingleBlock(unsigned long startBlock);		//Zapis jednoho bitu
unsigned char SD_readMultipleBlock (unsigned long startBlock, unsigned long totalBlocks);	//Cteni vice bitu
unsigned char SD_writeMultipleBlock(unsigned long startBlock, unsigned long totalBlocks);	//Zapis vice bitu
unsigned char SD_erase (unsigned long startBlock, unsigned long totalBlocks);	//Vymazani karty


// **** Inicializace SD karty v SPI modu **** //

unsigned char SD_init(void)		//Funkce_SD init
{
unsigned char i, odpoved, SD_verze;
unsigned int opakovani=0 ;

 for(i=0;i<10;i++)
      SPI_prenos(0xff);   // Nastaveni 80 pulzu pred odeslanim prvniho prikazu

SD_CS_ASSERT;
do
{
  
   odpoved = SD_sendCommand(PRECHOD_IDLE, 0); //Odesle reset a prejde do idle
   opakovani++;
   if(opakovani>0x20)	//Cyklus pro opakovani, pokud je chyba
   	  return 1;			//time out, karta nenalezena
   
} while(odpoved != 0x01);	//Cyklus pro odpoved

SD_CS_DEASSERT;
SPI_prenos (0xff);			//Log. 1 na SPI
SPI_prenos (0xff);			//Log. 1 na SPI

opakovani = 0;

// SD_verze = 2;
				
do
{
// Cyklus pro testovani napajeni SD karty
odpoved = SD_sendCommand(POSLANI_PRI_COND,0x000001AA);
opakovani++;
if(opakovani>0xfe) 
   {
	  TX_NEWLINE;	//TX prenos
	  SD_verze = 1;	
	  cardType = 1;
	  break;
   }				//Time out, problem s kartou

}while(odpoved != 0x01);

opakovani = 0;

do
{
odpoved = SD_sendCommand(APP_CMD,0);				 //CMD55 musi byt odesla pred odeslanim ACMD commandu
odpoved = SD_sendCommand(SD_ODESLANI_OP,0x40000000); //ACMD41 nastaveni

opakovani++;
if(opakovani>0xfe) 
   {
      TX_NEWLINE;
	  return 2;  //time out, inicializace karty selhala
   } 

}while(odpoved != 0x00);

opakovani = 0;
SDHC_flag = 0;

return 0;		//Vse v poradku, vracime 0
}

// **** Funkce pro odesilani prikazu do SD karty **** //

unsigned char SD_sendCommand(unsigned char cmd, unsigned long arg)
{
unsigned char odpoved, opakovani=0, status;

//SD karta akceptuje adresovaci byte nacez SDHC prijima bloky v nasobcich 512,
//to znamena, ze bloky adres musime prevest do prislusneho bajtu adresy..
//Je to vlastne ekvivalent posunutí 9x doleva

if(SDHC_flag == 0)		
if(cmd == READ_SINGLE_BLOCK     ||
   cmd == READ_MULTIPLE_BLOCKS  ||
   cmd == WRITE_SINGLE_BLOCK    ||
   cmd == WRITE_MULTIPLE_BLOCKS ||
   cmd == ERASE_BLOCK_START_ADDR|| 
   cmd == ERASE_BLOCK_END_ADDR ) 
   {
     arg = arg << 9;
   }	   

SD_CS_ASSERT;

// Odeslani prikazu, prvni dva bity jsou porad 01
SPI_prenos(cmd | 0x40); //dtto
SPI_prenos(arg>>24);
SPI_prenos(arg>>16);
SPI_prenos(arg>>8);
SPI_prenos(arg);

if(cmd == POSLANI_PRI_COND)	 //Nastaveni CRC na CMD8 (CRC=0x87) & CMD0 (CRC=0x95)
  SPI_prenos(0x87);			 //Zbyvajici prikazy, kde CRC je ignorovany v SPI
else 
  SPI_prenos(0x95); 

while((odpoved = SPI_prijem()) == 0xff) //Cekani na odpoved
   if(opakovani++ > 0xfe) break;		//Chyba prenosu

if(odpoved == 0x00 && cmd == 58)		//Testovani odpovedi od CMD58
{
  status = SPI_prijem() & 0x40;			//Prvni bajt z OCR registru
  if(status == 0x40) SDHC_flag = 1;  // Potřebná verifikace SDHC karty
  else SDHC_flag = 0;

  SPI_prijem(); // Zbyvajici tri bajty z OCR se zde ignoruji
  SPI_prijem(); 
  SPI_prijem(); 
}

SPI_prijem();	//Specialne pro CLK
SD_CS_DEASSERT;

return odpoved; //Vraci odpoved 
}


// **** Mazani specifickeho poctu bloku na SD karte **** //

unsigned char SD_erase (unsigned long startBlock, unsigned long totalBlocks)
{
unsigned char odpoved;

odpoved = SD_sendCommand(ERASE_BLOCK_START_ADDR, startBlock);	//Odeslat startovaci block adres
if(odpoved != 0x00) //Test SD statusu: 0x00 - OK (zadne nastavene flagy)
  return odpoved;

odpoved = SD_sendCommand(ERASE_BLOCK_END_ADDR,(startBlock + totalBlocks - 1)); //Odeslat posledni blok adres
if(odpoved != 0x00)
  return odpoved;

odpoved = SD_sendCommand(ERASE_SELECTED_BLOCKS, 0); //Smaze vsechny oznacene bloky
if(odpoved != 0x00)
  return odpoved;

return 0;
}

// **** Cteni jednoho bloku z SD karty **** //

unsigned char SD_readSingleBlock(unsigned long startBlock)
{
unsigned char odpoved;
unsigned int i, opakovani=0;

 odpoved = SD_sendCommand(READ_SINGLE_BLOCK, startBlock); //Cteni bloku prikazu
 
 if(odpoved != 0x00) return odpoved; //SD status: 0x00 - OK (zadny flag)

SD_CS_ASSERT;

opakovani = 0;
while(SPI_prijem() != 0xfe) // Ceka na startovaci blok 0xfe (0x11111110)
  if(opakovani++ > 0xfffe){SD_CS_DEASSERT; return 1;} //vraci hodnotu time-out

for(i=0; i<512; i++)		//cteni 512 bajtu
  buffer[i] = SPI_prijem();

SPI_prijem(); // Prijem prichoziho CRC (16-bit)
SPI_prijem();

SPI_prijem(); //extra 8 CLK pulzu
SD_CS_DEASSERT;

return 0;
}

// **** Zapis jednoho bloku na SD kartu **** //

unsigned char SD_writeSingleBlock(unsigned long startBlock)
{
unsigned char odpoved;
unsigned int i, opakovani=0;

 odpoved = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock); //Zapis prikazu
  
 if(odpoved != 0x00) return odpoved; //Status SD karty: 0x00 - OK (zadny nastaveny flag)

SD_CS_ASSERT;

SPI_prenos(0xfe);     //Odeslani startovaciho bloku 0xfe (0x11111110)

for(i=0; i<512; i++)    //Odeslani 512 bajtu dat
  SPI_prenos(buffer[i]);

SPI_prenos(0xff);     //Prenos 16-bitoveho CRC
SPI_prenos(0xff);

odpoved = SPI_prijem();

if( (odpoved & 0x1f) != 0x05) //odpoved= 0xXXX0AAA1 ; AAA='010' - data OK
{                              //AAA='101'-data chyba, CRC chyba
  SD_CS_DEASSERT;              //AAA='110'-data chyba, chyba zapisu 
  return odpoved;
}

while(!SPI_prijem()) //Cekani na dokonceni zapisu a nastaveni do IDLE
if(opakovani++ > 0xfffe){SD_CS_DEASSERT; return 1;}

SD_CS_DEASSERT;
SPI_prenos(0xff);		//8 CLK zpozdeni pred resetovanim CS linky
SD_CS_ASSERT;         //Zonovu potvrdit, zda-li CS linka je obsazena

while(!SPI_prijem()) //Cekani na dokonceni zapisu a nastaveni do IDLE
   if(opakovani++ > 0xfffe){SD_CS_DEASSERT; return 1;}
SD_CS_DEASSERT;

return 0;
}



// ************************ //
// **** USART ROZHRANI **** //
// ************************ //

// **** Inicializace **** //

#define x_baud 9600UL	//Nastaveni BaudRate
#define x_ubrr 12		//Nastaveni hodnoty UBRR

void USART_Init( void)
{
	UCSR0A = 0x00;								//Normalni rychlost, tedy vse 0
	UCSR0B=0x18;								//Prijem a vysilani log.1
	UCSR0C=0x86;								//Format dat 8 bit, 1 bit stop, asynchronni
	UBRR0L = (unsigned char)(x_ubrr);			//Ulozeni hodnoty do dolni casti UBRR
	UBRR0H = (unsigned char)(x_ubrr>>8);		//Ulozeni hodnoty do horni casti UBRR

	return;
}

// **** Obsluha preruseni pro USART - prijem dat **** //

ISR(USART0_RX_vect) 
{
	unsigned char data;							//Promenna data
	data=UDR0;									//Ulozeni prijateho znaku do UDR0

	while ( !(UCSR0A & (1<<RXC)) );				//Cekani na dokonceni prijmu
	while(!(UCSR1A & (1<<UDRE)));				//Cekani na vyprazdeni registru
	UDR1=data;									//Vyslani dat na UDR1

	return;

// **** Obsluzna funkce pro prijem a vysilani na USART **** //

unsigned char USART_prijem( void )
{
	while ( !(UCSR0A & (1<<RXC)) );				//Cekani na dokonceni prijmu
	return UDR0;								//Vraci hodnoty do UDR0
}

void USART_vysilani(unsigned char data)
{
	while(!(UCSR0A & (1<<UDRE)));				//Cyklus na vyprazdneni registru
	UDR0=data;									//Ulozeni dat do UDR0
	return;
}


// ********************************* //
// **** Ovladani USART rozhrani **** //
// ********************************* //

#define CHAR 0
#define INT  1
#define LONG 2

#define TX_NEWLINE {transmitByte(0x0d); transmitByte(0x0a);}

void uart0_init(void);
unsigned char receiveByte(void);
void transmitByte(unsigned char);
void transmitString_F(char*);
void transmitString(unsigned char*);
void transmitHex( unsigned char dataType, unsigned long data );

// ***************************************************** //
// **** FAT32  - cerpano z www.dharmanitech.com [32]**** //
// **** jedna se o obecne formatovani do FAT32 ********* //
// ***************************************************** //

//Struktura pro pristup k Master bitu
struct MBRinfo_Structure{
unsigned char	nothing[446];		// Vyplneni mezery
unsigned char	partitionData[64];	//Zazanm partiton (16x4)
unsigned int	signature;		//0xaa55
};

//Struktura pro pristup k informaci z prvniho partition
struct partitionInfo_Structure{ 				
unsigned char	status;				//0x80 - aktivace partition
unsigned char 	headStart;			//zacatek head
unsigned int	cylSectStart;		//zacatek cylinder a sector
unsigned char	type;				//partition typy
unsigned char	headEnd;			//konec head partition
unsigned int	cylSectEnd;			//koncec cylinder a sector
unsigned long	firstSector;		//Celkem sector mezi MBR a prvnim sectorem
unsigned long	sectorsTotal;		//Velikost partition sectoru
};

// Struktura pro pristup do bootovaciho sektoru dat
struct BS_Structure{
unsigned char jumpBoot[3];		// 0x009000EB
unsigned char OEMName[8];
unsigned int bytesPerSector;	//¨512
unsigned char sectorPerCluster;
unsigned int reservedSectorCount;
unsigned char numberofFATs;
unsigned int rootEntryCount;
unsigned int totalSectors_F16; //musi byt 0 pro FAT32
unsigned char mediaType;
unsigned int FATsize_F16;		//musi byt 0 pro FAT32
unsigned int sectorsPerTrack;
unsigned int numberofHeads;
unsigned long hiddenSectors;
unsigned long totalSectors_F32;
unsigned long FATsize_F32; //citac sektoru
unsigned int extFlags;
unsigned int FSversion; //0x0000 
unsigned long rootCluster; //prvni cluster z root directory (=2)
unsigned int FSinfo; 
unsigned int BackupBootSector;
unsigned char reserved[12];
unsigned char driveNumber;
unsigned char reserved1;
unsigned char bootSignature;
unsigned long volumeID;
unsigned char volumeLabel[11]; //"NO NAME "
unsigned char fileSystemType[8]; //"FAT32"
unsigned char bootData[420];
unsigned int bootEndSignature; //0xaa55
};


//Structure pro pristup FSinfo sector data
struct FSInfo_Structure
{
unsigned long leadSignature; //0x41615252
unsigned char reserved1[480];
unsigned long structureSignature; //0x61417272
unsigned long freeClusterCount; //initial: 0xffffffff
unsigned long nextFreeCluster; //initial: 0xffffffff
unsigned char reserved2[12];
unsigned long trailSignature; //0xaa550000
};

//Struktura pro pristup do adresare
struct dir_Structure{
unsigned char name[11];
unsigned char attrib;		//atributy souboru
unsigned char NTreserved;	//0
unsigned char timeTenth;	//sekundy, nastavit na 0
unsigned int createTime;	//cas byl vytvoren
unsigned int createDate;	//datum bylo vytvoreno
unsigned int lastAccessDate;
unsigned int firstClusterHI; //vyssi slovo v prvnim clusteru
unsigned int writeTime; 
unsigned int writeDate; 
unsigned int firstClusterLO; 
unsigned long fileSize; /
};

//Atributy pro adresar
#define ATTR_READ_ONLY     0x01
#define ATTR_HIDDEN        0x02
#define ATTR_SYSTEM        0x04
#define ATTR_VOLUME_ID     0x08
#define ATTR_DIRECTORY     0x10
#define ATTR_ARCHIVE       0x20
#define ATTR_LONG_NAME     0x0f


#define DIR_ENTRY_SIZE     0x32
#define EMPTY              0x00
#define DELETED            0xe5
#define GET     0
#define SET     1
#define READ	0
#define VERIFY  1
#define ADD		0
#define REMOVE	1
#define LOW		0
#define HIGH	1	
#define TOTAL_FREE   1
#define NEXT_FREE    2
#define GET_LIST     0
#define GET_FILE     1
#define DELETE		 2


#define MAX_STRING_SIZE		100	 //Definuje maximalni delku datoveho ramce


//************* externi promenne *************
volatile unsigned long firstDataSector, rootCluster, totalClusters;
volatile unsigned int  bytesPerSector, sectorPerCluster, reservedSectorCount;
unsigned long unusedSectors, appendFileSector, appendFileLocation, fileSize, appendStartCluster;

//global flag pro update FSinfo
unsigned char freeClusterCountUpdated;

//Datove retezce, kde se sbiraji data pred odeslanim na kartu
volatile unsigned char dataString[MAX_STRING_SIZE];


// -------------------------
// **** Funkce pro cteni dat z boot sectoru SD karty **** //

unsigned char getBootSectorData (void)
{
struct BS_Structure *bpb; //Mapovani bufferu na strukture
struct MBRinfo_Structure *mbr;
struct partitionInfo_Structure *partition;
unsigned long dataSectors;

unusedSectors = 0;

SD_readSingleBlock(0);
bpb = (struct BS_Structure *)buffer;

if(bpb->jumpBoot[0]!=0xE9 && bpb->jumpBoot[0]!=0xEB)   //kontrola jestli se jedna o boot sector
{
  mbr = (struct MBRinfo_Structure *) buffer;       //Jestli je to boot sector, musi to byt MBR
  
  if(mbr->signature != 0xaa55) return 1;       //Jestli to neni boot sector, neni to FAT32
  	
  partition = (struct partitionInfo_Structure *)(mbr->partitionData);//Prvnic partition
  unusedSectors = partition->firstSector; //Nevyuzite sektory, ktere jsou pro FAT32 skryte
  
  SD_readSingleBlock(partition->firstSector);//Cteni bpb sector
  bpb = (struct BS_Structure *)buffer;
  if(bpb->jumpBoot[0]!=0xE9 && bpb->jumpBoot[0]!=0xEB) return 1; 
}

bytesPerSector = bpb->bytesPerSector;

sectorPerCluster = bpb->sectorPerCluster;

reservedSectorCount = bpb->reservedSectorCount;
rootCluster = bpb->rootCluster;
firstDataSector = bpb->hiddenSectors + reservedSectorCount + (bpb->numberofFATs * bpb->FATsize_F32);

dataSectors = bpb->totalSectors_F32
              - bpb->reservedSectorCount
              - ( bpb->numberofFATs * bpb->FATsize_F32);
totalClusters = dataSectors / sectorPerCluster;

if((getSetFreeCluster (TOTAL_FREE, GET, 0)) > totalClusters)
     freeClusterCountUpdated = 0;
else
	 freeClusterCountUpdated = 1;
return 0;
}

// Spocitani prvniho sectoru adresy, ktery dava cluster

unsigned long getFirstSector(unsigned long clusterNumber)
{
  return (((clusterNumber - 2) * sectorPerCluster) + firstDataSector);
}



// **** Ziskani clusterove hodnoty z FAT32 k nalazeni dalsiho clusteru **** //

unsigned long getSetNextCluster (unsigned long clusterNumber,
                                 unsigned char get_set,
                                 unsigned long clusterEntry)
{
unsigned int FATEntryOffset;
unsigned long *FATEntryValue;
unsigned long FATEntrySector;
unsigned char retry = 0;

//Ziskani cisla sektoru z FAT
FATEntrySector = unusedSectors + reservedSectorCount + ((clusterNumber * 4) / bytesPerSector) ;

//Ziskani offsetove adresy v sectoru
FATEntryOffset = (unsigned int) ((clusterNumber * 4) % bytesPerSector);

//Cteni sectoru v bufferu
while(retry <10)
{ if(!SD_readSingleBlock(FATEntrySector)) break; retry++;}

//Ziskany adresy clusteru z bufferu
FATEntryValue = (unsigned long *) &buffer[FATEntryOffset];

if(get_set == GET)
  return ((*FATEntryValue) & 0x0fffffff);


*FATEntryValue = clusterEntry;   //Nastaveni nove hodnoty v clusteru FAT

SD_writeSingleBlock(FATEntrySector);

return (0);
}


// **** Ziskani dalsiho volneho clusteru nebo vsechny clustery v FSinfo sectoru na SD karte **** //
unsigned long getSetFreeCluster(unsigned char totOrNext, unsigned char get_set, unsigned long FSEntry)
{
struct FSInfo_Structure *FS = (struct FSInfo_Structure *) &buffer;
unsigned char error;

SD_readSingleBlock(unusedSectors + 1);

if((FS->leadSignature != 0x41615252) || (FS->structureSignature != 0x61417272) || (FS->trailSignature !=0xaa550000))
  return 0xffffffff;

 if(get_set == GET)
 {
   if(totOrNext == TOTAL_FREE)
      return(FS->freeClusterCount);
   else
      return(FS->nextFreeCluster);
 }
 else
 {
   if(totOrNext == TOTAL_FREE)
      FS->freeClusterCount = FSEntry;
   else 
	  FS->nextFreeCluster = FSEntry;
 
   error = SD_writeSingleBlock(unusedSectors + 1);	//update FSinfo
 }
 return 0xffffffff;
}


// ---------
// **** Funkce k ziskani DIR/FILE listu, nebo jednotlivych adresarovych adres, nebo vymazani specifickeho adresare  **** //
struct dir_Structure* findFiles (unsigned char flag, unsigned char *fileName)
{
unsigned long cluster, sector, firstSector, firstCluster, nextCluster;
struct dir_Structure *dir;
unsigned int i;
unsigned char j;

cluster = rootCluster; //Root cluster

while(1)
{
   firstSector = getFirstSector (cluster);

   for(sector = 0; sector < sectorPerCluster; sector++)
   {
     SD_readSingleBlock (firstSector + sector);
	

     for(i=0; i<bytesPerSector; i+=32)
     {
	    dir = (struct dir_Structure *) &buffer[i];

        if(dir->name[0] == EMPTY)	//Indikace konce souboru v adresari
		{
		  if(flag == DELETE)
		      transmitString_F(PSTR("File does not exist!"));
		  return 0;   
		}
		if((dir->name[0] != DELETED) && (dir->attrib != ATTR_LONG_NAME))
        {
          if((flag == GET_FILE) || (flag == DELETE))
          {
            for(j=0; j<11; j++)
            if(dir->name[j] != fileName[j]) break;
            if(j == 11)
			{
			  if(flag == GET_FILE)
              {
			    appendFileSector = firstSector + sector;
				appendFileLocation = i;
				appendStartCluster = (((unsigned long) dir->firstClusterHI) << 16) | dir->firstClusterLO;
				fileSize = dir->fileSize;
			    return (dir);
			  }	
			  else    //Pokud je flag tak DELETE
			  {
			     TX_NEWLINE;
				 transmitString_F(PSTR("Deleting.."));
				 TX_NEWLINE;
				 TX_NEWLINE;
				 firstCluster = (((unsigned long) dir->firstClusterHI) << 16) | dir->firstClusterLO;
                
				 dir->name[0] = DELETED;    
				 SD_writeSingleBlock (firstSector+sector);
				 			 
				 freeMemoryUpdate (ADD, dir->fileSize);

				 cluster = getSetFreeCluster (NEXT_FREE, GET, 0); 
				 if(firstCluster < cluster)
				     getSetFreeCluster (NEXT_FREE, SET, firstCluster);

			     while(1)  
			     {
			        nextCluster = getSetNextCluster (firstCluster, GET, 0);
					getSetNextCluster (firstCluster, SET, 0);
					if(nextCluster > 0x0ffffff6) 
					   {transmitString_F(PSTR("File deleted!"));return 0;}
					firstCluster = nextCluster;
			  	 } 
			  }
            }
          }
          else  //Pokud je flag tak GET_LIST
		  {
		     TX_NEWLINE;
			 for(j=0; j<11; j++)
		     {
			   if(j == 8) transmitByte(' ');
			   transmitByte (dir->name[j]);
			 }
		     transmitString_F (PSTR("   "));
		     if((dir->attrib != 0x10) && (dir->attrib != 0x08))
			 {
			     transmitString_F (PSTR("FILE" ));
		         transmitString_F (PSTR("   "));
			     displayMemory (LOW, dir->fileSize);
			 }
			 else
			   transmitString_F ((dir->attrib == 0x10)? PSTR("DIR") : PSTR("ROOT"));
		  }
       }
     }
   }

   cluster = (getSetNextCluster (cluster, GET, 0));

   if(cluster > 0x0ffffff6)
   	 return 0;
   if(cluster == 0) 
   {transmitString_F(PSTR("Error in getting cluster"));  return 0;}
 }
return 0;
}


// **** Funkce FALG=READ nez se zacne cist z SD karty a posilat na UART **** //

unsigned char readFile (unsigned char flag, unsigned char *fileName)
{
struct dir_Structure *dir;
unsigned long cluster, byteCounter = 0, fileSize, firstSector;
unsigned int k;
unsigned char j, error;

error = convertFileName (fileName); //Prevod fileName na FAT format
if(error) return 2;

dir = findFiles (GET_FILE, fileName); //Ziskani umisteni souboru
if(dir == 0) 
{
  if(flag == READ) return (1);
  else return (0);
}

if(flag == VERIFY) return (1);	//Toto jmeno souboru jiz existuje

cluster = (((unsigned long) dir->firstClusterHI) << 16) | dir->firstClusterLO;

fileSize = dir->fileSize;

TX_NEWLINE;
TX_NEWLINE;

while(1)
{
  firstSector = getFirstSector (cluster);

  for(j=0; j<sectorPerCluster; j++)
  {
    SD_readSingleBlock(firstSector + j);
    
	for(k=0; k<512; k++)
    {
      transmitByte(buffer[k]);
      if ((byteCounter++) >= fileSize ) return 0;
    }
  }
  cluster = getSetNextCluster (cluster, GET, 0);
  if(cluster == 0) {transmitString_F(PSTR("Error in getting cluster")); return 0;}
}
return 0;
}


// **** Funkce pro prevod normalniho short soboru na FAT format *** //

unsigned char convertFileName (unsigned char *fileName)
{
unsigned char fileNameFAT[11];
unsigned char j, k;

for(j=0; j<12; j++)
if(fileName[j] == '.') break;

if(j>8) {transmitString_F(PSTR("Invalid fileName..")); return 1;}

for(k=0; k<j; k++) 
  fileNameFAT[k] = fileName[k];

for(k=j; k<=7; k++) 
  fileNameFAT[k] = ' ';

j++;
for(k=8; k<11; k++)
{
  if(fileName[j] != 0)
    fileNameFAT[k] = fileName[j++];
  else
    while(k<11)
      fileNameFAT[k++] = ' ';
}

for(j=0; j<11; j++)
  if((fileNameFAT[j] >= 0x61) && (fileNameFAT[j] <= 0x7a))
    fileNameFAT[j] -= 0x20;

for(j=0; j<11; j++)
  fileName[j] = fileNameFAT[j];

return 0;
}

// ****Funkce pro vytvoreni souboru ve FAT32 formatu v korenovem adresari a prirazeni nazvu, pokdu neexistuje **** //

unsigned char writeFile (unsigned char *fileName)
{
unsigned char j,k, data, error, fileCreatedFlag = 0, start = 0, appendFile = 0, sector=0;
unsigned int i, firstClusterHigh=0, firstClusterLow=0;  //hodnoty na 0 jako ochrana pred chybami
struct dir_Structure *dir;
unsigned long cluster, nextCluster, prevCluster, firstSector, clusterCount, extraMemory;

j = readFile (VERIFY, fileName);

if(j == 1) 
{
  appendFile = 1;
  cluster = appendStartCluster;
  clusterCount=0;
  while(1)
  {
    nextCluster = getSetNextCluster (cluster, GET, 0);
    if(nextCluster == EOF) break;
	cluster = nextCluster;
	clusterCount++;
  }

  sector = (fileSize - (clusterCount * sectorPerCluster * bytesPerSector)) / bytesPerSector; //last sector number of the last cluster of the file
  start = 1;
}
else if(j == 2) 
   return 1; //Spatny nazev souboru

else
{
  cluster = getSetFreeCluster (NEXT_FREE, GET, 0);
  if(cluster > totalClusters)
     cluster = rootCluster;

  cluster = searchNextFreeCluster(cluster);
   if(cluster == 0)
   {
      TX_NEWLINE;
      transmitString_F(PSTR(" No free cluster!"));
	  return 1;
   }
  getSetNextCluster(cluster, SET, EOF);   //Posledni cluster v souboru, oznacen jako EOF
   
  firstClusterHigh = (unsigned int) ((cluster & 0xffff0000) >> 16 );
  firstClusterLow = (unsigned int) ( cluster & 0x0000ffff);
  fileSize = 0;
}

k=0;

while(1)
{
   if(start)
   {
      start = 0;
	  startBlock = getFirstSector (cluster) + sector;
	  SD_readSingleBlock (startBlock);
	  i = fileSize % bytesPerSector;
	  j = sector;
   }
   else
   {
      startBlock = getFirstSector (cluster);
	  i=0;
	  j=0;
   }
   
   
   do
   {

	 data = dataString[k++];
     buffer[i++] = data;
	 fileSize++;
     
     if(i >= 512)   // "i" nikdy nebude vetsi nez 512 a to musi byt dodrzeno
	 {				
	   i=0;
	   error = SD_writeSingleBlock (startBlock);
       j++;
	   if(j == sectorPerCluster) {j = 0; break;}
	   startBlock++; 
     }
   } while((data != '\n') && (k < MAX_STRING_SIZE)); //STOP pokud je nalezen novy charakter
   													 //nebo pokud je velikost retezecce prekrocena

   if((data == '\n') || (k >= MAX_STRING_SIZE))
   {
      for(;i<512;i++)  //Naplneni bufferu 0x00
        buffer[i]= 0x00;
   	  error = SD_writeSingleBlock (startBlock);

      break;
   } 
 
   prevCluster = cluster;

   cluster = searchNextFreeCluster(prevCluster); //Hledani volneho startovaciho clusteru

   if(cluster == 0)
   {
      TX_NEWLINE;
      transmitString_F(PSTR(" No free cluster!"));
	  return 1;
   }

   getSetNextCluster(prevCluster, SET, cluster);
   getSetNextCluster(cluster, SET, EOF);   //Posledni cluster souboru, oznacen jako EOF
}        

getSetFreeCluster (NEXT_FREE, SET, cluster); //update FSinfo

error = getDateTime_FAT();    //Ziskani aktualniho data a casu z RTC
if(error) { dateFAT = 0; timeFAT = 0;}

if(appendFile)  
{
  SD_readSingleBlock (appendFileSector);    
  dir = (struct dir_Structure *) &buffer[appendFileLocation]; 

  dir->lastAccessDate = 0;   //Datum posledniho zamitnuteho pristupu
  dir->writeTime = timeFAT;  //Zapsani noveho casu z RTC
  dir->writeDate = dateFAT;  //Zapsani noveho data z RTC
  extraMemory = fileSize - dir->fileSize;
  dir->fileSize = fileSize;
  SD_writeSingleBlock (appendFileSector);
  freeMemoryUpdate (REMOVE, extraMemory); //Update volne pameti v FSinfp

  return 0;
}

prevCluster = rootCluster; //Root cluster

while(1)
{
   firstSector = getFirstSector (prevCluster);

   for(sector = 0; sector < sectorPerCluster; sector++)
   {
     SD_readSingleBlock (firstSector + sector);
	

     for(i=0; i<bytesPerSector; i+=32)
     {
	    dir = (struct dir_Structure *) &buffer[i];

		if(fileCreatedFlag)   
           return 0;
         }

        if((dir->name[0] == EMPTY) || (dir->name[0] == DELETED))  //Hledani volneho slotu
		{
		  for(j=0; j<11; j++)
  			dir->name[j] = fileName[j];
		  dir->attrib = ATTR_ARCHIVE;	//Nastaveni atriburu na'archive'
		  dir->NTreserved = 0;			//Porad nastaveno na 0
		  dir->timeTenth = 0;			//Porad nastaveno na 0
		  dir->createTime = timeFAT; 	//_Nastaveni casu, kdy byl soubor vytvoren
		  dir->createDate = dateFAT; 	//setting date of file creation, obtained from RTC
		  dir->lastAccessDate = 0;   	//Datum posledniho nezdareneho logu
		  dir->writeTime = timeFAT;  	//Nastaveni noveho casu z RTC
		  dir->writeDate = dateFAT;  	//Nastaveni noveho data z RTC
		  dir->firstClusterHI = firstClusterHigh;
		  dir->firstClusterLO = firstClusterLow;
		  dir->fileSize = fileSize;

		  SD_writeSingleBlock (firstSector + sector);
		  fileCreatedFlag = 1;


		  freeMemoryUpdate (REMOVE, fileSize); //Update volne pameti FSinfo
	     
        }
     }
   }

   cluster = getSetNextCluster (prevCluster, GET, 0);

   if(cluster > 0x0ffffff6)
   {
      if(cluster == EOF)   
	  {  
		cluster = searchNextFreeCluster(prevCluster); //Hledani dalsiho clusteru pro pristup
		getSetNextCluster(prevCluster, SET, cluster); //Odkaz na novy cluster v Rootu
		getSetNextCluster(cluster, SET, EOF);  //Nastaveni noveho clusteru a ukonceni ROOT souboru
      } 

      else
      {	
	    transmitString_F(PSTR("End of Cluster Chain")); 
	    return 1;
      }
   }
   if(cluster == 0) {transmitString_F(PSTR("Error in getting cluster")); return 1;}
   
   prevCluster = cluster;
 }
 
 return 0;
}


// **** Funkce pro hledani dalsiho volneho clusteru v ROOT adresari **** //

unsigned long searchNextFreeCluster (unsigned long startCluster)
{
  unsigned long cluster, *value, sector;
  unsigned char i;
    
	startCluster -=  (startCluster % 128);   //Start s prvnim souborem ve FAT sektoru
    for(cluster =startCluster; cluster <totalClusters; cluster+=128) 
    {
      sector = unusedSectors + reservedSectorCount + ((cluster * 4) / bytesPerSector);
      SD_readSingleBlock(sector);
      for(i=0; i<128; i++)
      {
       	 value = (unsigned long *) &buffer[i*4];
         if(((*value) & 0x0fffffff) == 0)
            return(cluster+i);
      }  
    } 

 return 0;
}



// **** Mazani specifikaceho souboru v Rood adresari **** //

void deleteFile (unsigned char *fileName)
{
  unsigned char error;

  error = convertFileName (fileName);
  if(error) return;

  findFiles (DELETE, fileName);
}


// **** Funkce pro pro update volne pameti v FSinfo sectoru **** //
void freeMemoryUpdate (unsigned char flag, unsigned long size)
{
  unsigned long freeClusters;

  if((size % 512) == 0) size = size / 512;
  else size = (size / 512) +1;
  if((size % 8) == 0) size = size / 8;
  else size = (size / 8) +1;

  if(freeClusterCountUpdated)
  {
	freeClusters = getSetFreeCluster (TOTAL_FREE, GET, 0);
	if(flag == ADD)
  	   freeClusters = freeClusters + size;
	else  
	   freeClusters = freeClusters - size;
	getSetFreeCluster (TOTAL_FREE, SET, freeClusters);
  }
}

// **** Jednotlive funkce pro ovladani FAT32 **** //

unsigned char getBootSectorData (void);
unsigned long getFirstSector(unsigned long clusterNumber);
unsigned long getSetFreeCluster(unsigned char totOrNext, unsigned char get_set, unsigned long FSEntry);
struct dir_Structure* findFiles (unsigned char flag, unsigned char *fileName);
unsigned long getSetNextCluster (unsigned long clusterNumber,unsigned char get_set,unsigned long clusterEntry);
unsigned char readFile (unsigned char flag, unsigned char *fileName);
unsigned char convertFileName (unsigned char *fileName);
unsigned char writeFile (unsigned char *fileName);
void appendFile (void);
unsigned long searchNextFreeCluster (unsigned long startCluster);
void displayMemory (unsigned char flag, unsigned long memory);
void deleteFile (unsigned char *fileName);
void freeMemoryUpdate (unsigned char flag, unsigned long size);




// **** Makra pro sleep mode a casovac **** //

#define INTERVAL	3600 		//Interval mezi merenimi, nastaven na 36000 sekund (hodina)
#define EXT_OSC		2457.6		//Hodnota externiho oscilatoru v Hz

{

volatile unsigned char	cykl;	//Nadefinovani promenne cykl

ISR (TIMER1_OVF_vect)		//Preteceni registru TCNT1
{	
	float preruseni;
	preruseni = ((INTERVAL/EXT_OSC)*1000000)/65536 // Nastaveni hodnoty pro opakovani cyklu
	
	if(cykl==preruseni) //Pokud se cyklus rovna poctu preruseni, probud MCU
	{
	sleep_disable(); //Probuzeni
	cli();			//Zruseni externiho preruseni
	cykl=0;
	
	//Zapnuti periferii
	PORTD |= (1<<PD6)|(1<<PD4);
	PORTC |=(1<<PC2)|(1<<PC3)|(1<<PC5);
		
	}
}

// ************** //
// **** MAIN **** //
// ************** //

// ** VOLANI PEREFIRII ** //

  port_init();
  spi_init(); 
  USART_Init();
  ADC_init();
   
// Konec inicializace perfierii

//Vypnuti periferii
PORTD &= ~(1<<PD6)|(1<<PD4);
PORTC &= ~(1<<PC2)|(1<<PC3)|(1<<PC5);
	
sleep_enable;	
set_sleep_mode(SLEEP_MODE_STANDBY);
sleep_mode();

int main(void)

{
	
TCCR1B |= (1 << CS10)|(1 << CS11)|(1 << CS12); //Nastaveni externiho CLK, nabezna hrana signalu

TIMSK |= (1 << TOIE1);		//Preruseni pri preteceni

sei();						//Povoleni globalnich preruseni

while(1);					//Nekonecna smycka

{							//Zapis na SD kartu
		j=0;
		for(i=0; i<8; i++)
		{
			fileName[i] = date[j++];	//Cyklus pro nazev souboru
			if(j==2 || j==5) j++;		
		}

		fileName[8] = '.';				//Pripona souboru ve tvar scv
		fileName[9] = 'C';
		fileName[10] = 'S';
		fileName[11] = 'V';

		error = RTC_getTime();			//Chyba od RTC
    	if(error) blinkRedLED();
								
		
		//Cykly pro ziskani poli v deklaraci FAT32, vychazi z FAT32.h
		//Ukladani do vytvoreneho csv souboru
		
		for(i=0; i<10; i++) dataString[i] = date[i];	//Pole pro datum
		dataString[i++] = ',';							//Inkrementujeme

		for(j=0;j<8; j++)  dataString[i++] = time[j];	//Pole pro čas
		dataString[i++] = ',';							//Inkrementujeme
		
		readteplota(0); /								//Cteni teploty
		for(j=0;j<7; j++)  dataString[i++] = teplota[j];
		
		readhladina(0); /								//Cteni hladiny
		for(j=0;j<7; j++)  dataString[i++] = hladina[j];

		readnapeti(0); /								//Cteni napeti
		for(j=0;j<7; j++)  dataString[i++] = napeti[j];
		

		dataString[i++] = '\r';
		dataString[i] = '\n';    //Ukonceni retezce pred olanim funkce write

		error = writeFile(fileName);	//Chyba pri zapis	

}
	STOP: 
  return 0;
}



