using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Security.Permissions;
using Microsoft.Win32;
using System.Threading;
using System.IO.Ports;



namespace SensorWIM
{

   
    public partial class Form1 : Form
    {
        string dataReceived = string.Empty;
        byte[] buffer = new byte[10];
        int[] ChartLimits = new int[2];
        tMeas Meas = new tMeas();
        sFrame UsbFrame;                                    //Struktura ramce pro USB komunikaci

        public Form1()
        {
            InitializeComponent();
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void radioButton4_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void radioButton6_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            UsbFrame.Data = new byte[10];
        }

        private void button2_Click(object sender, EventArgs e)
        {
            
        }

        //Nacteni dostupnych portu z registru WIN------------------------------------------------------
        private void btnLoadPort_Click(object sender, EventArgs e)
        {
            String[] Ports = new String[50];
            int NrOfPorts;
            RegistryKey reg = Registry.LocalMachine.OpenSubKey("HARDWARE\\DEVICEMAP\\SERIALCOMM");

            cbCommPort.Items.Clear();                                                   //Vymazani seznamu dostupnych portu
            cbCommPort.Text = "";                                                       
            if (reg != null)                                                            //Pokud byly nalezeny v PC nejake ser.porty
            {
                if ((NrOfPorts = reg.ValueCount) > 0)
                {
                    Ports = reg.GetValueNames();                                        //ziskan seznam dostupnych portu z registru

                    for (int i = 0; i < NrOfPorts; i++)                                 //Postupne pridam jednotlive porty do seznamu pro vyber kom.ser.portu
                    {
                        cbCommPort.Items.Add(reg.GetValue(Ports[i].ToString()));
                    }
                    cbCommPort.SelectedIndex = 0;                                       //oznaceni defaultne prvniho ser.portu v seznamu
                   
                }   
                else                                                                    //Pokud nejsou nalezeny zadne dostupne ser.porty
                {
                    btnConnect.Enabled = false;                                         //je zakazano tlacitko pro pripojeni k ser.portu
                    MessageBox.Show("Not COM Port Found...", "Cannot find the Port");   //vypsana informace, ze nebyl nalezen zadny port
                }
            }
            else                                                                        //pokud neni nalezen dany klic
            {
                btnConnect.Enabled = false;                                             //opet zakazano pripojeni k ser.portu
                MessageBox.Show("Not COM Port Found...", "Cannot find registryKey");    //vypsana informace o chybe
            }
        }

        private void radioButton3_CheckedChanged(object sender, EventArgs e)
        {

        }

        //Pripojeni k vybranemu ser.portu s nastavenymi parametry komunikace------------------
        private void btnConnect_Click(object sender, EventArgs e)
        {
            String PortConfig;

            //Connect
            if ((btnConnect.Enabled == true)&&(btnConnect.Text == "Connect"))           //jestli jsou splneny podminky pro pripojeni (vybran port a nastaveny parametry komunikace)
            {                                                                           //a port jiz nebyl pripojen

                //Comm port                                                             //Nastaveni komunikacniho portu / cislo portu
                if (cbCommPort.Text != "")                                              //Pokud byl vybran port
                    serialPort1.PortName = cbCommPort.Text;                             //nastaveni portu pro otevreni
                //baudrate
                if (cbBaudrate.Text != "")                                              //pokud byla nastavena rychlost komunikace
                    serialPort1.BaudRate = int.Parse(cbBaudrate.Text);                  //ulozena do konfigurace
                else
                    btnConnect.Enabled = false;                                         //pokud nebyla vybrana, je zakazano tlacitko pro otevreni portu

                //Parity
                if (btnConnect.Enabled == true)                                         //jestli je tlacitko stale povoleno
                {                                                                       //dojde k nastaveni pozadovane parity pro komunikaci
                    if (rbParityEven.Checked == true)                                   //Licha parita
                        serialPort1.Parity = System.IO.Ports.Parity.Even;
                    else if (rbParityOdd.Checked == true)
                        serialPort1.Parity = System.IO.Ports.Parity.Odd;                //Suda parita
                    else if (rbParityNone.Checked == true)
                        serialPort1.Parity = System.IO.Ports.Parity.None;               //Bez parity
                    else
                        btnConnect.Enabled = false;                                     //Pokud v poli jina hodnota, zakazani tlacitka a konec
                }

                //Data bits
                if (btnConnect.Enabled == true)                                         //Nastaveni poctu datovych bitu pro komunikaci
                {
                    if (rbData8.Checked == true)
                        serialPort1.DataBits = 8;                                       // 8 datovych bitu
                    else if (rbData7.Checked == true)
                        serialPort1.DataBits = 7;                                       // 7 datovych bitu
                    else if (rbData6.Checked == true)
                        serialPort1.DataBits = 6;                                       // 6 datovych bitu
                    else if (rbData5.Checked == true)
                        serialPort1.DataBits = 5;                                       // 5 datovych bitu
                    else
                        btnConnect.Enabled = false;                                     //pokud zvolena jina hodnota, zakazani tlacitka a konec
                }

                //stop bits
                if (btnConnect.Enabled == true)                                         //Nastaveni poctu stop bitu        
                {
                    if (rbStop1.Checked == true)                                        // 1 stop bit
                        serialPort1.StopBits = System.IO.Ports.StopBits.One;
                    else if (rbStop2.Checked == true)                                   // 2 stop bity
                        serialPort1.StopBits = System.IO.Ports.StopBits.Two;
                    else
                        btnConnect.Enabled = false;                                     //Pokud vybrana jina hodnota, zakazani tlacitka a konec
                }

                //Set timeouts
                serialPort1.ReadTimeout = 500;                                          // nastaveni max. zpozdeni pro cteni
                serialPort1.WriteTimeout = 500;                                         // nastaveni max. zpozdeni pro zapis

                //save settings and show on form                                        //Do stavoveho radku vypisi aktualni nastaveni portu pro komunikaci / zde ulozim konfiguraci
                PortConfig = (serialPort1.PortName.ToString() + " " + serialPort1.Parity.ToString() + " " + serialPort1.DataBits.ToString() + " " + serialPort1.StopBits.ToString());

                //Configuration is done, now connection
                //ConState = 1;
                btnConnect.Text = "Disconnect";                                         //Na tlacitku pro pripojeni se zmeni text na odpojeni
                statusStrip1.Items.Clear();                                             //smazani stavoveho radku

                serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort1_DataReceived);   //nastaveni fce, ktera se bude volat pri prichodu dat
                
                // Try to open selected serial port
                try
                {
                    serialPort1.Open();                                                 //nyni zkusim otevrit port
                }
                catch                                                                   //pokud nastaven chyba
                {
                    statusStrip1.Items.Add("Cannot open port " + serialPort1.PortName.ToString());      //do stavoveho radku vypisi, ze nelze otevrit dany port
                    btnConnect.Enabled = false;                                         //a zakazu tlacitko pro pripojeni / dokud nezmenim port
                    btnConnect.Text = "Connect";                                        //na tlacitku se prepise text zpet na pripojeni
                }

                //Serial port opened
                if(serialPort1.IsOpen)                                                  //Pokud se podari seriovy port otevrit
                {
                     statusStrip1.Items.Add("Connected: " + PortConfig);                    //vypisu na stavovy radek parametry komunikace otevreneho portu
                     
                     chart1.Series[0].Points.Clear();                                    //vymazani dat z grafu (ukazka v grafu, pripadne stary graf)
                     ChartLimits[0] = 0;                                                    //Minimum / svisla osa grafu
                     ChartLimits[1] = 0;                                                    //Maximum / svisla osa grafu

                     groupBox2.Enabled = false;                                             //po pripojeni zakazu menit parametry komunikace / datove bity, parita, stop bity
                     groupBox3.Enabled = false;
                     groupBox4.Enabled = false;
                     FrameInit();
                     tmrMeas.Enabled = true;

                }

            }

            //Disconnect
            else                                                                        //Pokud jiz byl port pripojen, vyuziva se tlacitko pro odpojeni portu
            {
                tmrMeas.Enabled = true;
                btnConnect.Text = "Connect";                                            //prepisi odpojeni zpet na pripojeni
              //  readThread.Join();
                if(serialPort1.IsOpen)                                                  //overim, zda je dany port skutecne otevreny
                    serialPort1.Close();                                                //posleze jej uzavru
                statusStrip1.Items.Clear();                                             //vymazu data ze stavoveho radku
                statusStrip1.Items.Add("Disconnected ");                                //a zobrazim informaci, ze je port odpojen..

                groupBox2.Enabled = true;                                               //opet povolim nastavovani parametru pro seriovy port / datove bity, parita, stop bity
                groupBox3.Enabled = true;
                groupBox4.Enabled = true;
            }

        }

        //Funkce, ktera se vola pri prijeti dat na portu-------------------------------------------------
        void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                while (serialPort1.BytesToRead > 0)
                {
                    buffer[0] = (byte)serialPort1.ReadByte();
                    // serialPort1.Read(buffer, 0, 20);                                         //po zavolani funkce dorazily data, zkusim precist dva byty a ulozit do zasobniku (odesilam jen 2 dat.byty)
                    //dataReceived = serialPort1.ReadExisting();
                    this.Invoke(new EventHandler(ProcByte));                             //nastaveni zavolani funkce spojene s prijmem dat
                    //this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { message });

                }
            }
            catch
            { }
        }

        //Funkce pro rozlozeni ramce do struktury a nastaveni priznaku dokonceneho zpracovani-------
        private void ProcByte(object sender, EventArgs e)
        {
            byte RecByte = buffer[0];

            if (UsbFrame.State != ConstRxUSB.USB_RX_PROCCESS)
            {
                switch (UsbFrame.State)
                {
                    case ConstRxUSB.USB_RX_IDLE:
                        {
                            if (RecByte == ConstRxUSB.PREAMBLE)
                            {
                                UsbFrame.Preamble = RecByte;
                                UsbFrame.State = ConstRxUSB.USB_RX_PREAM;
                                UsbFrame.CompCRC = 0;
                            }
                            break;
                        }
                    case ConstRxUSB.USB_RX_PREAM:
                        {
                            if (RecByte < ConstRxUSB.CMD_COUNT)
                            {
                                UsbFrame.Cmd = RecByte;
                                UsbFrame.CompCRC = RecByte;
                                UsbFrame.State = ConstRxUSB.USB_RX_CMD;
                            }
                            else
                                UsbFrame.State = ConstRxUSB.USB_RX_IDLE;
                            break;
                        }
                    case ConstRxUSB.USB_RX_CMD:
                        {
                            if (RecByte < ConstRxUSB.MAX_DATA_COUNT)
                            {
                                UsbFrame.CompCRC ^= RecByte;
                                UsbFrame.Count = RecByte;
                                if (UsbFrame.Count > 0)
                                {
                                    UsbFrame.State = ConstRxUSB.USB_RX_COUNT;
                                    UsbFrame.tCount = RecByte;
                                }
                                else
                                {
                                    UsbFrame.State = ConstRxUSB.USB_RX_IDLE;
                                }
                            }
                            else
                                UsbFrame.State = ConstRxUSB.USB_RX_IDLE;
                            break;
                        }
                    case ConstRxUSB.USB_RX_COUNT:
                        {
                            UsbFrame.CompCRC ^= RecByte;
                            UsbFrame.Data[UsbFrame.Count - UsbFrame.tCount--] = RecByte;
                            if (UsbFrame.tCount == 0)
                                UsbFrame.State = ConstRxUSB.USB_RX_DATA;
                            break;
                        }
                    case ConstRxUSB.USB_RX_DATA:
                        {
                            if (UsbFrame.CompCRC == RecByte)
                            {
                                UsbFrame.CRC = RecByte;
                                UsbFrame.State = ConstRxUSB.USB_RX_CRC;
                            }
                            break;
                        }
                    case ConstRxUSB.USB_RX_CRC:
                        {
                            if (RecByte == '\n')
                            {
                                //zpracovani a inicializace pro prijem noveho ramce
                                UsbFrame.State = ConstRxUSB.USB_RX_PROCCESS;
                                this.Invoke(new EventHandler(DisplayText));
                                //UsbFrame.State = ConstRxUSB.USB_RX_PROCCESS;        //nyni se zpracovava, nebude se prijimat novy ramec
                                
                            }
                            break;
                        }
                    case ConstRxUSB.USB_RX_PROCCESS:
                        {
                            //nedelam nic, jen stav, kdy se nemuze prijimat dalsi ramec

                            break;
                        }
                    default:
                        {
                            FrameInit();
                            break;
                        }
                }
            }

        }

        //Funkce pro smazani vsech hodnot ze struktury---------------------------------------------
        public void FrameInit()
        {
            UsbFrame.State = ConstRxUSB.USB_RX_IDLE;
            UsbFrame.Preamble = 0;
            UsbFrame.Cmd = 0;
            UsbFrame.Count = 0;
            UsbFrame.CRC = 0;
            UsbFrame.CompCRC = 0;
        }

        //Funkce spojena s prectenim dat ze serioveho portu / jedno cislo z A/D prevodniku----------------
        //private void DisplayText(object sender, EventArgs e)
        private void DisplayText(object sender, EventArgs e)
        {
            int iADCNum;
            double ADCNum=0.0;
            float test=0;
            

            //vypis cisla do textboxu a jeho automaticky posun
            if (UsbFrame.Cmd == 1)              //OPTO
            {
                iADCNum = UsbFrame.Data[1];                                                 //nactu MSB prijateho 2Bytoveho cisla z A/D prevodniku
                iADCNum = iADCNum << 8;                                                     //Posunu v 16bitovem cisle o 8 bitu doleva
                iADCNum |= UsbFrame.Data[0];                                                //nactu spodni byte a ulozim ho na spravnou pozici v 2bytove hodnote ADCNum
                ADCNum = (double)iADCNum;
            }
            else if (UsbFrame.Cmd == 2)         //teplota
            {
                unsafe
                {
                    byte* pByte = (byte*)&test;
                    *pByte++ = UsbFrame.Data[0];
                    *pByte++ = UsbFrame.Data[1];
                    *pByte++ = UsbFrame.Data[2];
                    *pByte = UsbFrame.Data[3];
                    ADCNum = (double)test;
                }
            }
            FrameInit();
            
            //predelat na float, pak dale zustane stejny kod
            Meas.AddValue(System.Convert.ToInt32(ADCNum));                                                  //pridam hodnotu do bufferu pro pripadne mereni prumerne hodnoty a smerodatne odchylky
            txtData.AppendText(Math.Round(ADCNum,2).ToString() + '\n');                           //Pridani aktualne ziskane hodnoty do vypisu zmerenych hodnot
            //txtData.Focus();
            //txtData.SelectionStart = txtData.Text.Length - 1;
            txtData.ScrollToCaret();                                                //zobrazi posledni pridane hodnoty do listu / automaticky posune na konec

            //chart1.Series.Add("Trendline");
            chart1.Series[0].Points.AddY(ADCNum);                                   //pridani zmerene hodnoty do grafu
            //chart1.ChartAreas[0].AxisY.IntervalAutoMode = System.Windows.Forms.DataVisualization.Charting.IntervalAutoMode.FixedCount;

            //Settings of the chart's limits
            //first meas.?
            if((ChartLimits[0]==ChartLimits[1])&&(ChartLimits[0]==0))               //Pokud jsou prvni merena data            
            {

                ChartLimits[0] = System.Convert.ToInt16(ADCNum - 100);                                          //nastavi se graf tak, aby zobrazoval osu o +- 100
                ChartLimits[1] = System.Convert.ToInt16(ADCNum-1) + 101;
            }
            //Next meas.?
            else                                                                    //pokud jiz probehlo drive mereni a v grafu jiz nejake hodnoty jsou
            {
                if (ADCNum < (ChartLimits[0]+20))                                   //Pokud je minimalni hodnota na grafu mensi o mene nez 20
                    ChartLimits[0] = System.Convert.ToInt16(ADCNum) - 100;                                  //Nastavim novou minimalni hodnotu / minimum 
                if (ADCNum > (ChartLimits[1] - 20))                                 //podobne pokud je aktualni hodnota mensi o mene nez 20, nebo dokonce vetsi nez aktualni horni mez grafu
                    ChartLimits[1] = System.Convert.ToInt16(ADCNum) + 100;
            }
            //chart1.ChartAreas[0].AxisY.Maximum = ChartLimits[1];
            //chart1.ChartAreas[0].AxisY.Minimum = ChartLimits[0];          

            chart1.ChartAreas[0].AxisY.Maximum = Math.Round(ChartLimits[1] / 100.0)*100.0 ;     //zaokrouhleni hodnot na grafu
            chart1.ChartAreas[0].AxisY.Minimum = Math.Round(ChartLimits[0] / 100.0) * 100.0;   

            //Start measurement, if checked (mean value, std.dev.)
            if (cbEnableMeas.Checked)                                               //Pokud bylo uzivatelem zatrzeno i vyhodnoceni prumeru a smerodatne odchylku mereni
            {
                Meas.Measure();                                                     //Provedeni vypoctu prumerne hodnoty a smer.odchylky
                lblMeanValue.Text = Math.Round(Meas.GetMeanValue(), 2).ToString();                 //vypise prumernou merenou hodnotu
                lblStdDev.Text = Math.Round(Meas.GetStdValue(), 2).ToString();       //vypise odchylku od prumerne hodnoty
            }
        }

        //pri kliknuti na panel pro zmenu rychlosti komunikace--------------------------------
        private void cbBaudrate_SelectedIndexChanged(object sender, EventArgs e)
        {
            if ((cbBaudrate.Text != "") && (cbCommPort.Text != ""))                 //pokud byla vybrana rychlost a soucasne byl jiz zvoleny ser.port
                btnConnect.Enabled = true;                                          //dojde k povoleni tlacitka pro pripojeni k portu
            else
                btnConnect.Enabled = false;                                         //jinak je tlacitko zakazano
        }

        //pri kliknuti na panel pro vyber portu-----------------------------------------------
        private void cbCommPort_SelectedIndexChanged(object sender, EventArgs e)
        {
            if ((cbBaudrate.Text != "") && (cbCommPort.Text != ""))                 //pokud byla vybrana rychlost a soucasne byl jiz zvoleny ser.port
                btnConnect.Enabled = true;                                          //dojde k povoleni tlacitka pro pripojeni k portu
            else
                btnConnect.Enabled = false;                                         //jinak je tlacitko zakazano
        }

        //Funkce volana pri zavirani okna formulare-------------------------------------------
        private void Form1_closing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen)                                                 //Pokud zustane otevren port
                serialPort1.Close();                                                //je automaticky zavren
        }

        //Funkce pro smazani dosavadnich namerenych udaju a nove mereni / graf i data---------
        private void btnClearTxt_Click(object sender, EventArgs e)
        {
            Meas.ClearBuff();                                                       //Odstraneni veskerych namerenych dat z mericiho bufferu
            lblMeanValue.Text = "####";                                             //Na formulari se zobrazi text ####
            lblStdDev.Text = "####";
            txtData.Clear();                                                        //odstraneni dat z listu
            ChartLimits[0] = 0;                                                     //Minimum / limit pro svislou osu na grafu
            ChartLimits[1] = 0;                                                     //Maximum / limit pro svislou osu na grafu
            chart1.Series[0].Points.Clear();                                        //Vymazani dat ze zasobniku pro graf
        }

        private void label4_Click(object sender, EventArgs e)
        {

        }

        private void groupBox7_Enter(object sender, EventArgs e)
        {

        }

        //Spusteni vyhodnoceni prumerne hodnoty a smerodatne odchylky------------------------
        private void cbEnableMeas_CheckedChanged(object sender, EventArgs e)
        {
            if (cbEnableMeas.Checked == true)                                       //pokud bylo prave spusteno mereni
            {
                lblMeanValue.ForeColor = Color.Red;                                 //zobrazi se zmerene hodnoty cervene
                lblStdDev.ForeColor = Color.Red;

                //Nacteni hodnot z txt-listu
               /* for (int i = 0; i < txtData.Lines.Length-1; i++)
                {
                    Meas.AddValue(txtData.Text.
                }*/
            }
            else                                                                    //Pokud naopak bylo mereni prave zastaveno
            {
                lblMeanValue.ForeColor = Color.Black;                               //barva textu hodnot bude cerna a nebude se nadale vyhodnocovat prumer a odchylka
                lblStdDev.ForeColor = Color.Black;
            }
        }

        //funkce pro simulovani mereni hodnot pro otestovani---------------------------------
        private void btnAddValue_Click(object sender, EventArgs e)
        {
            Random _r = new Random();
            int tPos;

            Meas.AddValue( _r.Next(0,65535));                                       //pridani nove nahodne hodnoty v rozmezi 0-65535
            tPos=Meas.GetPos();                                                     //aktualni pozice v poli merenych hodnot
            txtData.Clear();                                                        //vymazani listboxu
            for(int i=0; i<tPos;i++)                                                //pro vsechny dosavadni pozice
            {
                txtData.Text = txtData.Text + Meas.GetValue(i).ToString()+'\n';     //nacteni hodnot a pridani do listboxu
            }
            if (cbEnableMeas.Checked)                                               //pokud bylo povoleno mereni prumeru a odchylky
            {
                Meas.Measure();                                                     //Provedeni vypoctu prumerne hodnoty a smer.odchylky
                lblMeanValue.Text = Meas.GetMeanValue().ToString();                 //vypise prumernou merenou hodnotu
                lblStdDev.Text = Math.Round(Meas.GetStdValue(),2).ToString();       //vypise odchylku od prumerne hodnoty
            }
        }

        //Testovani / Odeslani prikazu do prevodnikove karty--------------------------------
        private void btnSendCmd_Click(object sender, EventArgs e)
        {
            byte[] MyBuff = new byte[10];
            string s=txtSendUART.Text.ToString();

            if (serialPort1.IsOpen)
            {
                /*
                MyBuff[0] = System.Convert.ToByte(s);
                serialPort1.Write(MyBuff, 0, 1);
                 */
                MyBuff[0] = 0xff;
                MyBuff[1] = 0x01;
                MyBuff[2] = 0x00;
                MyBuff[3] = (byte)(MyBuff[1] ^ MyBuff[2]);
                MyBuff[4] = 0x0a;
                serialPort1.Write(MyBuff, 0, 5);
            }


        }

        private void tmrSendTick(object sender, EventArgs e)
        {
            byte[] MyBuff = new byte[10];
            byte index = 0;

            if (cbEnableMeas.Checked == true)
            {
                if (serialPort1.IsOpen)
                {
                    MyBuff[index++] = 0xff;
                    if (rbADCValue.Checked == true)
                    {
                        MyBuff[index++] = 0x01;                         //prikaz 1
                        MyBuff[index++] = 0x01;                         //Pocet datovych bytu
                        MyBuff[index++] = (byte)nmrChannel.Value;       //zvoleny kanal
                        MyBuff[index++] = (byte)(MyBuff[1] ^ MyBuff[2] ^ MyBuff[3]);  //CRC
                    }
                    if (rbTemp.Checked == true)
                    {
                        MyBuff[index++] = 0x02;                         //Prikaz 2
                        MyBuff[index++] = 0x00;                         //Pocet datovych bytu
                        MyBuff[index++] = (byte)(MyBuff[1] ^ MyBuff[2]);  //CRC
                    }                                       
                    MyBuff[index] = 0x0a;                               //Zakoncovaci znak
                    serialPort1.Write(MyBuff, 0, index+1);              //Odeslani do prevodnikove karty
                }
            }
        }

        private void rbADCValue_CheckedChanged(object sender, EventArgs e)
        {
            nmrChannel.Enabled = (rbADCValue.Checked == true) ? true : false;
            Meas.ClearBuff();                                                       //Odstraneni veskerych namerenych dat z mericiho bufferu
            lblMeanValue.Text = "####";                                             //Na formulari se zobrazi text ####
            lblStdDev.Text = "####";
            txtData.Clear();                                                        //odstraneni dat z listu
            ChartLimits[0] = 0;                                                     //Minimum / limit pro svislou osu na grafu
            ChartLimits[1] = 0;                                                     //Maximum / limit pro svislou osu na grafu
            chart1.Series[0].Points.Clear();                                        //Vymazani dat ze zasobniku pro graf
        }

        private void rbTemp_CheckedChanged(object sender, EventArgs e)
        {
            nmrChannel.Enabled = (rbADCValue.Checked == true) ? true : false;
            Meas.ClearBuff();                                                       //Odstraneni veskerych namerenych dat z mericiho bufferu
            lblMeanValue.Text = "####";                                             //Na formulari se zobrazi text ####
            lblStdDev.Text = "####";
            txtData.Clear();                                                        //odstraneni dat z listu
            ChartLimits[0] = 0;                                                     //Minimum / limit pro svislou osu na grafu
            ChartLimits[1] = 0;                                                     //Maximum / limit pro svislou osu na grafu
            chart1.Series[0].Points.Clear();                                        //Vymazani dat ze zasobniku pro graf
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            tmrMeas.Interval = (int)nmrMeasPeriode.Value;
        }




    }

    //---------------------------------------MERENI - trida---------------------------------------
    //trida slouzici k ulozeni a zpracovani prijatych hodnot z prevodnikove karty
    class tMeas
    {
        //Konstruktor tridy--------------------------------------------
        public tMeas()
        {
            //inicializace jednotlivych prvku
            MeanValue = 0;                                          //Nulova prumerna hodnota
            StdDev = 0;                                             //Nulova odchylka
            Pos = 0;                                                //Pozice nastavena na nulu
            BuffFull = false;                                       //Vymazan priznak plneho bufferu a prepisovani starych hodnot od zacatku
            for (int i = 0; i < 1000; i++)                          //Inicializace pole pro mereni / vymazani hodnot
            {
                BuffMeas[i] = 0;
            }
        }

        //privatni promenne tridy-------------------------------------
        private double[] BuffMeas = new double[1000];                     //zasobnik pro merene hodnoty
        private int Pos;                                            //Aktualni pozice, kam se v mericim zasobniku uklada nova hodnota
        private bool BuffFull;                                      //Priznak, ze je buffer plny a prepisuje se vzdy nejstarsi hodnota
        private double MeanValue;                                   //Prumerna hodnota mereni
        private double StdDev;                                      //Odchylka mereni od prumerne hodnoty

        //prida aktualni zmerenou hodnotu do bufferu------------------
        public void AddValue(double ADCValue)
        {
            //Zarazeni prvku do pole
            if (Pos > 999)                                          //pokud je jiz plny buffer
            {
                Pos = 0;                                            //bude se prepisovat od zacatku / nejstarsi hodnoty
                BuffFull = true;                                    //nastaveni priznaku, ze je jiz buffer zaplneny
            }
            BuffMeas[Pos++] = ADCValue;                             //ulozeni hodnoty na aktualni pozici v bufferu

        }

        //vraci aktualni pozici v bufferu------------------------------
        public int GetPos()
        {
            return Pos;
        }

        //ziskani hodnoty ulozene na indexu v bufferu-----------------
        public double GetValue(int Index)
        {
            return BuffMeas[Index];
        }

        //vraci priznak, zda jiz byl zaplnen buffer-------------------
        public bool GetBuffFull()
        {
            return BuffFull;
        }

        //funkce pro spusteni mereni prumeru a odchylky--------------
        public void Measure()
        {
            CompMeanValue();                                        //mereni prumerne hodnoty z merenych hodnot
            CompStdValue();                                         //mereni smerodatne hodnoty z merenych hodnot
        }

        //Funkce pro urceni prumerne hodnoty-------------------------
        private void CompMeanValue()
        {
            double suma = 0;
            int MaxIndex = 0;   

            //Vypocet stredni hodnoty..
            if (BuffFull == true)                                   //zjisteni, zda se bude pocitat hodnota z celeho bufferu / jiz byl zaplnen
                MaxIndex = 1000;
            else                                                    //nebo pouze z prvnich 'Pos' hodnot
                MaxIndex = Pos;

            for (int i = 0; i < MaxIndex; i++)                      //smycka pro vypocet sumy merenych hodnot
            {
                suma += BuffMeas[i];
            }

            MeanValue = (suma / MaxIndex);                          //vydeleni poctem mereni / prumer/ a ulozeni do prvku MeanValue
        }

        //funkce vraci aktualni prumernou hodnotu z mereni-----------
        public double GetMeanValue()
        {
            return MeanValue;
        }

        //Funkce pro vypocet smerodatne odchylky mereni--------------
        private void CompStdValue()
        {
            int MaxIndex = 0;
            double Pom,Temp, MeanValue;

            //Urceni dosavadniho poctu vzorku
            if (BuffFull == true)                                   //zjisteni, zda se bude pocitat hodnota z celeho bufferu / jiz byl zaplnen
                MaxIndex = 1000;
            else
                MaxIndex = Pos;                                     //nebo pouze z prvnich 'Pos' hodnot

            if (Pos > 1)                                            //pro vypocet odchylky nutne, aby byly zmereny minimalne dve hodnoty
            {
                //Ziskani vypocteneho prumeru
                MeanValue = GetMeanValue();                         //Nacteni aktualni prumerne hodnoty

                //vypocet jednotlivych rozdilu namerenych hodnot od prumeru na druhou
                Temp = 0;
                for (int i = 0; i < MaxIndex; i++)
                {
                    Temp += Math.Pow((BuffMeas[i] - MeanValue), 2.0);
                }

                //vypocet aktualni stredni hodnoty
                Pom = 1.0 / (Pos - 1.0);
                StdDev =  Pom* Math.Sqrt(Temp);                     //celkova smerodatna odchylka ulozena do prvku StdDev
            }
            else                                                    //Pokud jen jedna hodnota, odchylka je nulova
                StdDev = 0;
        }

        //Vraci aktualni smerodatnou odchylku mereni od prumeru-----
        public double GetStdValue()
        {
            return StdDev;
        }

        //Funkce pro vymazani mericiho bufferu pro nove mereni------
        public void ClearBuff()
        {
            MeanValue = 0;                                          //Nulova prumerna hodnota
            StdDev = 0;                                             //Smerodatna odchylka nulova
            Pos = 0;                                                //Pozice v bufferu / nastaveno na prvni pozici
            BuffFull = false;                                       //buffer je prazdny
            for (int i = 0; i < 1000; i++)                          //vymazani vsech hodnot z bufferu
            {
                BuffMeas[i] = 0;
            }
        }
    }


 //Struktura pro komunikaci USB--------------------------------------
    struct sFrame
    {
        public byte State;                                                 //Stav stavoveho automatu pro prijem prikazu
        public byte Preamble;                                              //Preambule
        public byte Cmd;                                                   //Cislo prikazu
        public byte Count;                                                 //Pocet datovych bytu
        public byte tCount;                                                //docasna promenna pro urceni aktualni pozice v poli
        public byte[] Data;                                                //Pole datovych bytu
        public byte CRC;                                                   //Prijaty kontrolni soucet
        public byte CompCRC;                                               //Vypocteny kontrolni soucet
    };

 //Struktura / konstanty pro USB--------------------------------------
    static class ConstRxUSB
    {
        public const byte USB_RX_IDLE = 0;                              //klidovy stav
        public const byte USB_RX_PREAM = 1;                             //prijata preambule
        public const byte USB_RX_CMD = 2;                               //prijat prikaz
        public const byte USB_RX_COUNT = 3;                             //prijat pocet dat.bytu
        public const byte USB_RX_DATA = 4;                              //prijata data
        public const byte USB_RX_CRC = 5;                               //prijat CRC
        public const byte USB_RX_PROCCESS = 6;                          //prijat zakoncovaci znak a zpracovani prikazu
        
        //konstanty souvisejici s komunikaci USB
        public const byte PREAMBLE = 255;                               //Preambule
        public const byte CMD_COUNT = 5;                                //maximalni hodnota prikazu
        public const byte MAX_DATA_COUNT = 10;                          //maximalni pocet datovych bytu

    }

}
