/*************************************************************************
   ADCONVERTOR
   Diplomová práce 2010 - Martin Hlúpik ID:77697


   *******************************************************************
   komunikace s MDC3202 s použitím kanálu B pri SPI data

   PB2 linka CS pro výběr ADC
   PB0 SCLK pro B kanal
   PC4 data output MOSI
   PC5 data input MISO
   PE3 LED0
   PE0 LED1
   PG6 LED2
   PG4 LED4
   PF0 Switch 0
   PF2 Switch 1
   PD0 Ethernet reset                     Output   High when not driven by ethernet
   PE2 Ethernet chip select               Output   High when not driven by ethernet
   void BitWrPortI( int port, char * portshadow, int value, int bitcode );

************************************************************************/
#class auto
#define TCPCONFIG 1
#define MAX_TCP_SOCKET_BUFFERS 3
#define DIP_ADRESS  "10.10.6.100"           //Výchozí IP adresa
#define DIP_GATE  "10.10.6.1"               //Výchozí brána
#define DIP_MASK  "255.255.255.0"           //Výchozí Maska sítě
#define DS0 3     									//port E bit 3   LED0
#define DS1 0     									//port E bit 0   LED1
#define DS2 6     									//port G bit 6   LED2
#define DS3 4     									//port G bit 4   LED4
#define LED1_ON BitWrPortI(PEDR, &PEDRShadow, 0, 3)
#define LED1_OFF BitWrPortI(PEDR, &PEDRShadow, 1, 3)
#define LED2_ON BitWrPortI(PEDR, &PEDRShadow, 0, 0)
#define LED2_OFF BitWrPortI(PEDR, &PEDRShadow, 1, 0)
#define LED3_ON BitWrPortI(PGDR, &PGDRShadow, 0, 6)
#define LED3_OFF BitWrPortI(PGDR, &PGDRShadow, 1, 6)
#define LED4_ON BitWrPortI(PGDR, &PGDRShadow, 0, 4)
#define LED4_OFF BitWrPortI(PGDR, &PGDRShadow, 1, 4)
#define SW1 BitRdPortI(PFDR, 0)               //Definice pinu vstupu SW1
#define SW2 BitRdPortI(PFDR, 2)               //Definice pinu vstupu SW2

#define SN 12345										//Seriové číslo
#define SPI_SER_B                            //use serial port B
#define SPI_CLK_DIVISOR 100                  //divisor for the appropriate Timer A register
#define SPI_MASTER_CS_PORT PBDR              //CS port from master to Slave
#define SPI_MASTER_CS_SHADOW PBDRShadow      //shadow register for CS (Master only)
#define SPI_MASTER_CS_BIT 2                  //CS  bit number

#define MCP3202_CS_PORT       PBDR            //nastaveni portu na kterem je pripojen MCP3202
#define MCP3202_CS_PORTSHADOW PBDRShadow      //nastaveni shadow registru
#define MCP3202_CS_BIT           2            //nastaveni CS pinu portu

#define RATIO_CH1  3.424       //Default prevodovy pomer analogove casti kanal1
#define RATIO_CH2  3.324       //Default prevodovy pomer analogove casti kanal2
#define REFERENCE 3.246         //Default velikost referen4niho napeti prevodniku MCP3202


#define LOG_SIZE 128					//Definice velikosti paměti pro dataloge

#define CS_ENABLE  BitWrPortI ( MCP3202_CS_PORT, &MCP3202_CS_PORTSHADOW, 0, MCP3202_CS_BIT )     //Definice signálu CS enable
#define CS_DISABLE BitWrPortI ( MCP3202_CS_PORT, &MCP3202_CS_PORTSHADOW, 1, MCP3202_CS_BIT )     //Definice signálu CS disable

#define HTTP_PORT 80           //Definice HTTP Portu
  //////////////Seriová linka/////////////
#define CINBUFSIZE  1          //Definice velikosti vstupního bufferu pro Seriovou komunikaci RS232
#define COUTBUFSIZE 127        //Definice velikosti výstupního bufferu pro Seriovou komunikaci RS232
#define _232BAUD 115200L       //Definice výchozí komunikační rychlosti RS232
//////////////Seriová linka/////////////
////////////////////MODBUS TCP Config////////////////
/**
 *  Port Number    Purpose
 *  -----------    -------
 *      80         HTTP
 *     502         Modbus
 */

#define MODBUS_PORT 502				//Definice výchozího portu pro MODBUS TCP

#define LSTN_STATE      0     // naslouchání
#define ESTB_STATE      1     // kontrola zda je spojení vytvořeno
#define RECV_STATE      2     // čekání na data
#define SEND_STATE      3     // posílání dat
#define CLSE_STATE      4     // uzavření socketu
#define CLWT_STATE      5     // čekání na uzavření socketu
#define ABRT_STATE      6     // chyba zavírání - abort

#ifndef UNIT_IDENTIFIER				//nastavení default čísla Modbus stanice
#define UNIT_IDENTIFIER 1
#endif

#use "spi.lib"								//Použití knihovny spi.lib

#define USE_RABBITWEB 1				//Definice výchozího nastavení TCP/IP
/********************************
 * Konec konfigurace            *
 ********************************/
#memmap xmem
#use "dcrtcp.lib"
#use "http.lib"

/* Deklarace proměnných*/
   int i;										//Deklarace pomocné proměnné
   int datach[5];						//Deklarace pomocné proměnné
   char low[5],high[5];			//Deklarace pomocné proměnné
   char  buffer[100],ansbuffer[32],serbuffer[200]; //Deklarace polí pro buffer
   struct tm  rtc;					//Deklarace struktury pro hodiny reálného času
   float tempscan_ms,tempscan_sec;	//Deklarace pomocné proměnné pro měření délky cyklu
   tcp_Socket socket;
   tcp_Socket socket_HTTP;
   float data[3];						//Deklarace pole pro data

bbram   longword ip_adr;		//Deklarace proměnné pro uložení IP adresy
   int count[3];						//Deklarace ukazatele naplnění zásobníku filtru kanálů
   const char ser_header[] = "Day.Month.Year;Hour:Minute:Second;Channel 1;Channel 2;Filter 1;Filter2";

   struct{
   int state;              // current state of the state machine
   int iface;              // interface number for this interface
   tcp_Socket s;           // TCP socket structure
   char buff[128];         // buffer for reading and writing data
   int bytes;              // count of number of bytes in the buffer
   unsigned long timer;    // timer to check for timeouts
      } socks;

bbram   struct{						//Deklarace struktury dat pro dataloger
   short int day;
   short int month;
   unsigned int year;
   short int hour;
   short int minute;
   short int second;
   float ch1;
   float ch2;
   float fch1;
   float fch2;
   } data_log[LOG_SIZE];

// Nacteni zhtml stránek
#ximport "pages/monitor.zhtml"  monitor_zhtml
#ximport "pages/setfiltr.zhtml"     admin_zhtml
#ximport "pages/setAD.zhtml"     setAD_zhtml
#ximport "pages/setcom.zhtml"    setcom_zhtml
#ximport "pages/setime.zhtml"    setime_zhtml
#ximport "pages/data.zhtml"    data_zhtml
#ximport "pages/logo.gif" logo_gif

//Tabulka MIME Typu
SSPEC_MIMETABLE_START
   SSPEC_MIME_FUNC(".zhtml", "text/html", zhtml_handler),
   SSPEC_MIME(".html", "text/html"),
   SSPEC_MIME(".gif", "image/gif")
SSPEC_MIMETABLE_END

//Tabulka Zdroju
SSPEC_RESOURCETABLE_START
   SSPEC_RESOURCE_XMEMFILE("/index.zhtml", monitor_zhtml),
   SSPEC_RESOURCE_XMEMFILE("/admin/sfiltr.zhtml", admin_zhtml),     //admin
   SSPEC_RESOURCE_XMEMFILE("/admin/setAD.zhtml", setAD_zhtml),			//admin
   SSPEC_RESOURCE_XMEMFILE("/admin/setcom.zhtml", setcom_zhtml),		//admin
   SSPEC_RESOURCE_XMEMFILE("/admin/setime.zhtml", setime_zhtml),		//admin
   SSPEC_RESOURCE_XMEMFILE("/data.zhtml", data_zhtml),
   SSPEC_RESOURCE_XMEMFILE("/logo.gif", logo_gif)
SSPEC_RESOURCETABLE_END
//Definice grupy admin
#web_groups admin
//Deklarace proměnných použitých na html stránkách
float realvolt[3];								//Pole reálně zmeřených napětí: [1] kanál1;[2] kanál2
#web realvolt groups=all(ro)
float filtered[3];								//Pole filtrovaných napětí:[1] kanál1;[2] kanál2
#web filtered groups=all(ro)

float scan;
#web scan groups=all(ro)					//Proměnná Scan pro měření min vzorkovací periody
float frequency;
#web frequency groups=all(ro)			//Proměnná frequency pro měření max vzorkovací frekvence

/* Deklace proměných RTC*/
short int edit_month, edit_day, edit_year, edit_hour, edit_minute, edit_second;
#web edit_second ((0 <= $edit_second) && ($edit_second <= 60)) groups=all(ro),admin	//Ověření povoleného rozsahu zadávaných hodnot
#web edit_minute ((0 <= $edit_minute) && ($edit_minute <= 60)) groups=all(ro),admin	//Ověření povoleného rozsahu zadávaných hodnot
#web edit_hour ((0 <= $edit_hour) && ($edit_hour <= 24)) groups=all(ro),admin				//Ověření povoleného rozsahu zadávaných hodnot
#web edit_day ((0 < $edit_day) && ($edit_day <= 31)) groups=all(ro),admin					//Ověření povoleného rozsahu zadávaných hodnot
#web edit_month ((1 < $edit_month) && ($edit_month <= 12)) groups=all(ro),admin   //Ověření povoleného rozsahu zadávaných hodnot
#web edit_year ((2009 < $edit_year) && ($edit_year <= 2999)) groups=all(ro),admin //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnných nastavení převodového poměru A/D převodníku Kanál1
bbram float vratio_ch1,eratio_ch1;
#web vratio_ch1 groups=all(ro)
#web eratio_ch1 ((0 < $eratio_ch1) && ($eratio_ch1<= 10)) groups=all(ro),admin //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnných nastavení převodového poměru A/D převodníku Kanál2
bbram float vratio_ch2,eratio_ch2;
#web vratio_ch2 groups=all(ro)
#web eratio_ch2 ((0 < $eratio_ch2) && ($eratio_ch2<= 10)) groups=all(ro),admin //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnných nastavení převodového poměru A/D převodníku Referenční napětí
bbram float vreference,ereference;
#web vreference groups=all(ro)
#web ereference ((0 < $ereference) && ($ereference<= 10)) groups=all(ro),admin //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnné pro uložení Modbus adresy modulu
bbram unsigned int vunit_identifier,eunit_identifier;
#web vunit_identifier groups=all(ro)
#web eunit_identifier ((0 < $eunit_identifier) && ($eunit_identifier<= 256)) groups=all(ro),admin //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnné pro uložení Modbus portu
bbram unsigned int vmodbus_port,emodbus_port;
#web vmodbus_port groups=all(ro)
#web emodbus_port ((0 < $emodbus_port) && ($emodbus_port<= 2048)) groups=all(ro),admin //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnné pro uložení periody vzorkování na seriový port
bbram float ewrite_period,vwrite_period;
#web vwrite_period
#web ewrite_period ((0.01 <= $ewrite_period) && ($ewrite_period<= 32000)) //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnné pro uložení periody zápisu do datalogeru
bbram float lwrite_period;
#web lwrite_period ((0.01 <= $lwrite_period) && ($lwrite_period<= 32000)) //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnné kalibračního napětí
float ekalib_ch1,ekalib_ch2;
#web ekalib_ch1 ((0 < $ekalib_ch1) && ($ekalib_ch1<= 10)) groups=all(ro),admin //Ověření povoleného rozsahu zadávaných hodnot
#web ekalib_ch2 ((0 < $ekalib_ch2) && ($ekalib_ch2<= 10)) groups=all(ro),admin //Ověření povoleného rozsahu zadávaných hodnot
//Deklarace proměnné kumunikační rychlosti RS232
bbram long baud;
#web baud groups=all(ro),admin
//Deklarace proměnných webového rozhraní
bbram short int time_changed,ad_param_changed,com_changed,filtr_changed,com_init,calib_month,calib_day;
//Deklarace proměnné paměti datumu kalibrace
bbram unsigned int calib_year;

bbram short int log_changed,datastackfull,log_start,log_clear,ip_changed;
bbram unsigned int datastacksize,log_size,row,row_pointer;
#web time_changed groups=all(ro),admin	//Příznak editace času z webového rozhraní
#web log_changed
#web ad_param_changed groups=all(ro),admin //Příznak editace parametů A/D převodníku z webového rozhraní
#web com_changed groups=all(ro),admin			//Příznak editace parametů komunikace
#web ip_changed groups=all(ro),admin			//Příznak editace parametů IP adresy
#web filtr_changed groups=all(ro),admin		//Příznak editace parametů nastvení filtru
#web data_log															//Pamět dat datalogeru
#web row																	//Ukazatel na řádek záznamu v datalogeru
#web datastackfull												//Příznak naplnění zásobníku datalogeru
#web datastacksize												//Velikost zásobníku datalogeru
#web log_start														//Příznaku spuštění záznamu dat do datalogeru
#web log_clear														//Příznaku vymazání záznamu dat v datalogeru
#web log_size															//Proměnná velikosti zásobníku datalogeru
#web row_pointer													//Ukazatel na pole záznamu v datalogeru
#web calib_day														//Proměnná den kalibrace
#web calib_month													//Proměnná měsíc kalibrace
#web calib_year

bbram unsigned int sample_web[3];					//Paměť vzorků pro filtr
bbram unsigned int samples_web1, samples_web2;	//Paměť vzorků pro filtr z webrozhraní
#web samples_web1 ((0 < $samples_web1) && ($samples_web1 <= 9999)) groups=all(ro),admin	//Ověření povoleného rozsahu zadávaných hodnot
#web samples_web2 ((0 < $samples_web2) && ($samples_web2 <= 9999)) groups=all(ro),admin	//Ověření povoleného rozsahu zadávaných hodnot
//Příznak stavu modbus komunikace
bbram short int modbus_activ;
#web modbus_activ
//Příznak stavu RS232 komunikace
bbram short int serial_activ;
#web serial_activ
//Proměnné nastavení TCP/IP
bbram char ip_adress[16],ip_gate[16],ip_mask[16];
#web ip_adress
#web ip_gate
#web ip_mask
//Příznak RESET do výchozího nastavení
short int reset;
#web reset
//Příznak povelu kalibrace
short int kalib_ch1,kalib_ch2;
#web kalib_ch1;
#web kalib_ch2;
///////////////////////Konec deklarace///////////////////////////




////////////////////// Funkce čtení TCP/IP konfigurace//////////////
void eth_config_read (void) {

      if( !ifconfig( IF_DEFAULT, IFG_IPADDR, &ip_adr, IFS_END));
      inet_ntoa( ip_adress, ip_adr);
      if( !ifconfig( IF_DEFAULT, IFG_NETMASK, &ip_adr, IFS_END));
   	inet_ntoa( ip_mask, ip_adr);

      if( !ifconfig( IF_DEFAULT, IFG_ROUTER_DEFAULT, &ip_adr, IFS_END));
   	inet_ntoa( ip_gate, ip_adr);
       }

////////////////////// Funkce zápisu TCP/IP konfigurace//////////////
void eth_config_write (void)
{
     if (isaddr(ip_adress)!=0)
     {
     ifconfig(IF_DEFAULT,
              IFS_DOWN,
              IFS_IPADDR, aton(ip_adress),
              IFS_NETMASK, aton(ip_mask),
              IFS_ROUTER_SET, aton(ip_gate),
              IFS_UP,
              IFS_END);
    }



}
////////////////////// Funkce čtení hodin reálného času//////////////
void realtime_read(void)
{
   if (time_changed==1){
   tm_rd(&rtc);
   edit_second=rtc.tm_sec;
   edit_minute=rtc.tm_min;
   edit_hour=rtc.tm_hour;
   edit_day=rtc.tm_mday;
   edit_month=rtc.tm_mon;
   edit_year=rtc.tm_year+1900;
   }

}
////////////////////// Funkce zápisu hodin reálného času//////////////
void realtime_write(void)
{
   if (time_changed==0){

   rtc.tm_sec  = (char)edit_second;
   rtc.tm_min  = (char)edit_minute;
   rtc.tm_hour = (char)edit_hour;
   rtc.tm_mday = (char)edit_day;
   rtc.tm_mon  = (char)edit_month;
   rtc.tm_year = (char)(edit_year-1900);
   tm_wr(&rtc);
   SEC_TIMER = mktime(&rtc);
   time_changed=1;
   }

}
////////////////////// Inicializace web rozhranní ///////////////////
void web_init(void)
{
   int userid;

   http_set_path("/", "index.zhtml");

   sspec_addrule("/admin", "Admin", admin, admin, SERVER_ANY,
                 SERVER_AUTH_BASIC, NULL);

   userid = sauth_adduser("admin", "1", SERVER_ANY);
   sauth_setusermask(userid, admin, NULL);
}
/////////////////// Funkce obnovy dat web rozhraní
void web(void)
{
   http_handler();
   sample_web[1]=samples_web1;
   sample_web[2]=samples_web2;
}
//////////////// Inicializace hardwarové konfigurace ///////////////////////
void boardInit(void)
{  /*
   PB2 linka CS pro výběr ADC
   PB0 SCLK pro B kanal
   PC4 data output MOSI
   PC5 data input MISO
   PE3 LED0
   PE0 LED1
   PG6 LED2
   PG4 LED4
   PF0 Switch 0
   PF2 Switch 1
   PD0 Ethernet reset                     Output   High when not driven by ethernet
   PE2 Ethernet chip select               Output   High when not driven by ethernet
   void BitWrPortI( int port, char * portshadow, int value, int bitcode );
   */
//configure Port B
  WrPortI(PBDDR, &PBDDRShadow, 0xFF);
//configure Port E
   WrPortI(PECR, &PECRShadow, PECRShadow&0x00);       //clear all bits to pclk/2
   WrPortI(PEFR, &PEFRShadow, PECRShadow&0x00);       //clear all bits to normal function
   WrPortI(PEDR, &PEDRShadow, 0x9);                //set bits 3,0 jako vystup - output high
   WrPortI(PEDDR, &PEDDRShadow, PEDDRShadow|0x9);     //set bits 3,0 to output
//configure Port G
   WrPortI(PGCR, &PGCRShadow, 0x00);//clear all bits for pclk/2
   WrPortI(PGFR, &PGFRShadow, 0x00);                  //clear all bits for normal function
   WrPortI(PGDCR, &PGDCRShadow, PGDCRShadow|0x50);    //set bits 6, 4 drive open drain    01010000
   WrPortI(PGDR, &PGDRShadow, PGDCRShadow|0x50);      //set bit 6,4 output high           01010000
   WrPortI(PGDDR, &PGDDRShadow, 0x50);                //set bits 6,4 to output and     C4=11000100

}


//////////////////Čtení aktuální hodnoty A/D převodníku /////////////////////////////////////////////////////////
float MCP3202Read ( float RefVoltage, int Channel )
/* Vstupní proměnná 
RefVoltage - velikost referenčního napětí
Channel - číslo kanálu čtení

Návratová hodnota
Volts - změřené napětí převedené na volty
*/
            {
               unsigned int i, j,adc_sample;
               auto float Volts;
               auto char adc_reading[4];


               if ( Channel == 1 )                                //Čtení kanálu 1
                  {
                  for(i = 0;i < 10;i++) CS_ENABLE;               //Prodleva pro CS signál
                     SPIWrRd ( "\x01\xA0\x00",adc_reading, 3 ) ; //Zápis řídícího slova čtení kanálu 1
                     CS_DISABLE;                                 //Uvolnění CS

                  }
               else if ( Channel == 2 )                          //Čtení kanálu 2
                  {
                  for(i = 0;i < 10;i++) CS_ENABLE;               //Prodleva pro CS signál
                     SPIWrRd ( "\x01\xE0\x00",adc_reading, 3 ) ; //Zápis řídícího slova  čtení kanálu 2
                     CS_DISABLE;                                 //Uvolnění CS

                  }
                 adc_sample=((adc_reading[1]&0x0f)* 0xff)+adc_reading[2]  ; //spojení horního a dolního bytu přijatého slova
                 Volts = (adc_sample*RefVoltage/4095);											//Přepočet na napětí
                  return Volts;
            }
////FILTR/////////////////////////////////////////////////////////////////////

float filter (int chanel)
/* 
Vstupní proměnná  
chanel - číslo kanálu pro filtraci

Návratová hodnota
ret_data - výstup filtru
*/
{
float ret_data;

if (sample_web[chanel]>=count[chanel])
   {
   data[chanel]+=realvolt[chanel];
   ++count[chanel];
   return filtered[chanel];
   }
else
   {
    ret_data = data[chanel]/count[chanel];
    count[chanel]=0;
    data[chanel] = 0.0;
    return ret_data;

    }
}
 ////Ošetření povelu změny parametrů z web rozhraní/////////////////////////////////////////
void parametrs_change(void)
{
 //Ošetření změny parametrů A/D převodníku
 if (ad_param_changed==0){	
  vratio_ch1=eratio_ch1;		//Převzetí editované hodnoty z web rozhranní
  vratio_ch2=eratio_ch2;		//Převzetí editované hodnoty z web rozhranní
  vreference=ereference;		//Převzetí editované hodnoty z web rozhranní
  ad_param_changed=1;				//Příznak provedení změny parametrů

  }
  //Ošetření změny parametrů komunikace
  if (com_changed==0){									
  vunit_identifier=eunit_identifier;		//Převzetí editované hodnoty z web rozhranní
  vmodbus_port=emodbus_port;						//Převzetí editované hodnoty z web rozhranní
  vwrite_period=ewrite_period;					//Převzetí editované hodnoty z web rozhranní
  com_init=0;														//Příznak provedení změny parametrů
  com_changed=1;												//Příznak provedení změny parametrů
  }
  //Ošetření změny parametrů TCP/IP
  if (ip_changed==0){										
  eth_config_write();
  eth_config_read();
  ip_changed=1;
  }
  //Ošetření povelu kalibrace kanálu 1
  if (kalib_ch1==0){									
  vratio_ch1=(ekalib_ch1)/(MCP3202Read ( vreference, 1 ));
  eratio_ch1=vratio_ch1;
  kalib_ch1=1;
  calib_year=rtc.tm_year+1900;
  calib_month=rtc.tm_mon;
  calib_day=rtc.tm_mday;
  }
  //Ošetření povelu kalibrace kanálu 2
  if (kalib_ch2==0){
  vratio_ch2=(ekalib_ch2)/(MCP3202Read ( vreference, 2 ));
  eratio_ch2=vratio_ch2;
  kalib_ch2=1;
  calib_year=rtc.tm_year+1900;
  calib_month=rtc.tm_mon;
  calib_day=rtc.tm_mday;
  }


}
////DEKODER MODUS RAMCE A SESTAVENÍ ODPOVĚDI/////////////////////////////////////////////////////////////////
void decoder2(void)
{
      int exception;
      exception=0;
      //////////////////MODBUS/////////////
        /*Struktura Requestu>
            buffer[0]=xx;       //byte 0: transaction identifier
            buffer[1]=xx;       //byte 1: transaction identifier
            buffer[2]=0x00;            //byte 2: protocol identifier
            buffer[3]=0x00;            //byte 3: protocol identifier
            buffer[4]=0x00;            //byte 4: length field (upper byte)
            buffer[5]=0x06;            //byte 5: length field (lower byte)
            buffer[6]=0x01;            //byte 6: Unit identifier (Slave address)
            buffer[7]=0x03;            //byte 7: MODBUS Function code
            buffer[8]=0x00;            //byte 8: Starting address Hi
            buffer[9]=0x01;           //byte 9: Starting address Lo
            buffer[10]=0x00;            //byte 10: Numbers of Registers Hi
            buffer[11]=0x01;            //byte 11: Numbers of Registers Lo
            */

            if (buffer[6]==vunit_identifier)
            {
            buffer[socks.bytes+1]=0;

            datach[1]=(int) (realvolt[1]*1000);
            high[1]=(char)(datach[1]>>8);
            low[1]=(char)(datach[1]&0xFF);

            datach[2]=(int) (realvolt[2]*1000);
            high[2]=(char)(datach[2]>>8);
            low[2]=(char)(datach[2]&0xFF);

            datach[3]=(int) (filtered[1]*1000);
            high[3]=(char)(datach[3]>>8);
            low[3]=(char)(datach[3]&0xFF);

            datach[4]=(int) (filtered[2]*1000);
            high[4]=(char)(datach[4]>>8);
            low[4]=(char)(datach[4]&0xFF);

            ansbuffer[0]=buffer[0];       //byte 0: transaction identifier
            ansbuffer[1]=buffer[1];       //byte 1: transaction identifier
            ansbuffer[2]=0x00;            //byte 2: protocol identifier
            ansbuffer[3]=0x00;            //byte 3: protocol identifier
            ansbuffer[4]=0x00;            //byte 4: length field (upper byte)
            ansbuffer[5]=buffer[11]*2+3;            //byte 5: length field (lower byte)
            ansbuffer[6]=vunit_identifier;            //byte 6: Unit identifier (Slave address)
            ansbuffer[8]=buffer[11]*2;            //byte 8: Byte count of response
               switch  (buffer[7])                   //byte 7: MODBUS Function code
               {
                     case 4:
                     ansbuffer[7]=buffer[7];
                      break;
                     default:
                     ansbuffer[7]=buffer[7]+0x80;              //Exception code 01 Illegal function
                     ansbuffer[8]=0x01;
                     exception=1;
                }

               switch  (buffer[9])
                  {
                     case 0:
                           ansbuffer[9]=high[1];            //byte 9: Data 0. byte  HiByte 0.Wordu
                           ansbuffer[10]=low[1];            //byte 10: Data 1. byte LoByte 0.Wordu

                           break;
                     case 1:
                           ansbuffer[9]=high[2];            //byte 9: Data 0. byte  HiByte 1.Wordu
                           ansbuffer[10]=low[2];            //byte 10: Data 1. byte LoByte 1.Wordu

                           break;
                     case 2:
                           ansbuffer[9]=high[3];            //byte 9: Data 0. byte  HiByte 2.Wordu
                           ansbuffer[10]=low[3];            //byte 10: Data 1. byte LoByte 2.Wordu

                           break;
                     case 3:
                           ansbuffer[9]=high[4];            //byte 9: Data 0. byte  HiByte 3.Wordu
                           ansbuffer[10]=low[4];            //byte 10: Data 1. byte LoByte 3.Wordu

                           break;
                  	case 4:
                           ansbuffer[9]=(char)(SN>>8);            //byte 9: Data 0. byte  HiByte Serial Number
                           ansbuffer[10]=(char)(SN&0xFF);            //byte 10: Data 1. byte LoByte Serial Number

                           break;
                  	case 5:
                           ansbuffer[9]=(char)(calib_month>>8);            //byte 9: Data 0. byte  HiByte Serial Number
                           ansbuffer[10]=(char)(calib_month&0xFF);            //byte 10: Data 1. byte LoByte Serial Number

                           break;
                  	case 6:
                           ansbuffer[9]=(char)(calib_year>>8);            //byte 9: Data 0. byte  HiByte Serial Number
                           ansbuffer[10]=(char)(calib_year&0xFF);            //byte 10: Data 1. byte LoByte Serial Number

                           break;
                  	case 7:
                           ansbuffer[9]=(char)(calib_day>>8);            //byte 9: Data 0. byte  HiByte Serial Number
                           ansbuffer[10]=(char)(calib_day&0xFF);            //byte 10: Data 1. byte LoByte Serial Number

                           break;
                   default:
                           ansbuffer[7]= buffer[7]+0x80;            //Exception code 02 Ilegal data address
                           ansbuffer[8]=0x02;


                  }
             if (exception==1)
             {
             ansbuffer[8]=0x02;
             socks.bytes=9;
             }
             else
             {
             socks.bytes=11;
             }
           }
           else
           {
           socks.state = ABRT_STATE;
           }
}

////DATA LOGER - ZÁZNAM DAT DO PAMĚTI/////////////////////////////////////////////////////////////////
void dataloger(void)
{
     costate {

                       if (log_start==1)
                       {
                       data_log[row].day=edit_day;
                       data_log[row].month=edit_month;
                       data_log[row].year=edit_year;
                       data_log[row].hour=edit_hour;
                       data_log[row].minute=edit_minute;
                       data_log[row].second=edit_second;
                       data_log[row].ch1=realvolt[1];
                       data_log[row].ch2=realvolt[2];
                       data_log[row].fch1=filtered[1];
                       data_log[row].fch2=filtered[2];
                       row++;

	                       if (row==LOG_SIZE)
	                       {
                          row=0;
	                       datastackfull=1;
                          }

                       waitfor(DelayMs((unsigned long)(lwrite_period*1000)));				
	                       if (datastackfull==1)
	                          {
	                          row_pointer=LOG_SIZE;
	                          }else
	                          {
	                          row_pointer=row+1;
	                          }
             				}
             }
					costate{
               	if (log_clear==1)
                   	{
                      row=0;
                      datastackfull=0;
                      log_clear=0;
                      row_pointer=row;
                     }
                   }

}
////MODBUS INTERFACE MANAGEMENT MODBUS ZPRÁVY/////////////////////////////////////////////////////////////////
void modbus2(void)
{
      switch (socks.state) {
            // Listen on the socket
            case LSTN_STATE:
               // Note that the iface number is passed to tcp_extlisten()
               if (tcp_extlisten(&socks.s, socks.iface,
                                 vmodbus_port, 0, 0, NULL, 0, 0, 0)) {
                  socks.state = ESTB_STATE;

               }
               else {
                  socks.state = CLSE_STATE;
 		               }
               break;
            // Check if a connection has been established
            case ESTB_STATE:
               if (sock_established(&socks.s) ||
                   sock_bytesready(&socks.s) >= 0) {
                  socks.state = RECV_STATE;
               }
               break;
            // Check if data has been received.  If so, read it out.
            case RECV_STATE:
               // Read any incoming data
               socks.bytes = sock_fastread(&socks.s,
                                                  buffer,
                                                  sizeof(buffer));
               if (socks.bytes == -1) {

                  socks.state = CLSE_STATE;

               }
               // Check if we received any data
               if (socks.bytes > 0) {

                  socks.state = SEND_STATE;        // send the data back

               }
               break;
            // Echo back any received data
            case SEND_STATE:

               decoder2();                // Dekódování MODBUS zprávy

               socks.bytes = sock_fastwrite(&socks.s,
                                                   ansbuffer,
                                                   11);

               if (socks.bytes == -1) {
                  socks.state = CLSE_STATE;
                  }

               if (socks.bytes > 0) {
                  socks.state = RECV_STATE;
                  }
               break;

            case CLSE_STATE:
               sock_close(&socks.s);
               socks.state = CLWT_STATE;

               break;

            case CLWT_STATE:
               if (!sock_alive(&socks.s)) {

                  socks.state = LSTN_STATE;

               }
               break;

            case ABRT_STATE:
               sock_abort(&socks.s);     // abort the socket
               socks.state = LSTN_STATE; // try to listen again

               break;
         }

         tcp_tick(NULL);



}
////RESET NA DEFAULT NASTAVENÍ/////////////////////////////////////////////////////////////////
void default_reset()
{
   vratio_ch1=RATIO_CH1;
   eratio_ch1=RATIO_CH1;
   vratio_ch2=RATIO_CH2;
   eratio_ch2=RATIO_CH2;
   vreference=REFERENCE;
   ereference=REFERENCE;
   vunit_identifier=UNIT_IDENTIFIER;
   eunit_identifier=UNIT_IDENTIFIER;
   vmodbus_port=MODBUS_PORT;
   emodbus_port=MODBUS_PORT;
   samples_web1=1;
   samples_web2=1;
   modbus_activ = 1;
   serial_activ = 1;
   vwrite_period=1;
   lwrite_period=1;
	 log_size=LOG_SIZE;
	 log_start=0;
	 row_pointer=0;
	 row=0;
	 datastackfull=0;
	 datastacksize=LOG_SIZE;

   baud=_232BAUD;

   ifconfig(IF_DEFAULT,
				IFS_DOWN,
              IFS_IPADDR, aton(DIP_ADRESS),//aton(ip_adress),
              IFS_NETMASK, aton(DIP_MASK),
              IFS_ROUTER_SET, aton(DIP_GATE),
              IFS_UP,
              IFS_END);
    eth_config_read();
    reset=0;
}

////INICIALIZACE PROMĚNNÝCH/////////////////////////////////////////////////////////////////
void var_init()
{

   count[1]=0;
   count[2]=0;
   data[1]=0;
   data[2]=0;
   filtered[1]=0;
   filtered[2]=0;
   ekalib_ch1=0;
   ekalib_ch2=0;
   time_changed=1;
   ip_changed=1;

   log_clear=0;
   log_size=LOG_SIZE;

   com_init=0;
      for(i = 0;i < 5;i++)
   {
   datach[i]=0;
   high[i]=0;
   low[i]=0;
   }
   tempscan_ms=MS_TIMER;      //paměť hodnoty ms timeru
   tempscan_sec=SEC_TIMER;    //paměť hodnoty s timeru

   datastacksize=LOG_SIZE;
   eth_config_write();

      socks.state = LSTN_STATE;
      socks.iface = 0;
      memset(socks.buff, 0, sizeof(socks.buff));
      socks.bytes = 0;

}
////SERIOVÁ LINKA RS-232/////////////////////////////////////////////////////////////////
void ser_com(void)
{
   int test,delka;
   char CR,LF;

   if (com_init==0)
   {
   serCopen(baud); //Otevření COM portu
   serCwrFlush();		//Vypráznění bufferu zápisu com portu
	 serCrdFlush();		//Vypráznění bufferu čtení com portu
   serCputs(ser_header);	//Zápis hlavičky dat
   serCputc (0x0D);				//Zápis CR
   serCputc (0x0A);				//Zápis LF
   com_init=1;
   }

   CR=0x0D;
   LF=0x0A;
/*Postupné vysílání dat na seriový port*/
   costate {

   itoa(rtc.tm_mday,serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));
   delka=strlen(serbuffer);
    wfd cof_serCputc ('.');
   itoa(rtc.tm_mon,serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));
    wfd cof_serCputc ('.');
   itoa(rtc.tm_year+1900,serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));
    wfd cof_serCputc (';');
      itoa(rtc.tm_hour,serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));
    wfd cof_serCputc (':');
      itoa(rtc.tm_min,serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));
    wfd cof_serCputc (':');
      itoa(rtc.tm_sec,serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));
    wfd cof_serCputc (';');
   itoa(((int) (realvolt[1]*1000)),serbuffer);


   wfd cof_serCwrite (serbuffer,strlen(serbuffer));


    wfd cof_serCputc (';');
     itoa(((int) (realvolt[2]*1000)),serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));

    wfd cof_serCputc (';');

      itoa(((int) (filtered[1]*1000)),serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));

    wfd cof_serCputc (';');
     itoa(((int) (filtered[2]*1000)),serbuffer);
    wfd cof_serCwrite (serbuffer,strlen(serbuffer));

    wfd cof_serCputc (CR);

    wfd cof_serCputc (LF);
    }


}
/////////////////////////////////////////////////////////////////////
////   HLAVNÍ PROGRAM                                            ////
/////////////////////////////////////////////////////////////////////
void main()
{
   sock_init();
   boardInit();      //Inicializace a konfigurace I/O portů
   SPIinit();        //Inicializace SPI
   http_init();
   web_init();
   var_init();        //Inicializace proměnných
   realtime_read();     //Čtení hodin reálného času
   eth_config_read();  //Čtení akt.nastavení ethernetového nastavení

   while(1)
   {

          if ((reset==1)|(SW1==0))
           {
          default_reset();
          eth_config_write();
           }


           costate {
             realvolt[1]=vratio_ch1*((MCP3202Read(vreference,1)+MCP3202Read(vreference,1)+MCP3202Read(vreference,1))/3) ;//Průměrování 3 hodnot po sobě
             realvolt[2]=vratio_ch2*((MCP3202Read(vreference,2)+MCP3202Read(vreference,2)+MCP3202Read(vreference,2))/3) ;//Průměrování 3 hodnot po sobě
             scan=(float)((MS_TIMER-tempscan_ms)/1000)+(SEC_TIMER-tempscan_sec);//Měření periody scanu
     			 tempscan_ms=MS_TIMER;   //Pamět ms_timeru
             tempscan_sec=SEC_TIMER;  //Pamět s_timeru

             if (scan!=0)
             {
             frequency=1/scan;	//Výpočet frekvence skenování f=1/T
             }
                    }
           costate{
               	filtered[1]=filter(1);
               	}
           costate{
               	filtered[2]=filter(2);
                  }
                    costate{
                      if (modbus_activ)
                      {
                       LED1_ON;
                       modbus2();
                       LED1_OFF;
                      }
                       }
                    costate{
                       LED2_ON;
                       web();
                       LED2_OFF;
                        }
                     costate {
                       LED4_ON;
                       realtime_read();
                       realtime_write();
                       parametrs_change();
                       LED4_OFF;
                       }
                     costate {

                     if (serial_activ)
                     {
                     LED3_ON;
	                   ser_com();
	                   waitfor(DelayMs((unsigned long)(vwrite_period*1000)));            
                     LED3_OFF;
                     }
                     }
	                  costate
                     {
                     dataloger();
                     }



   }




}