Document scris de Simpalean Nicolae la 20.11.2016    

Aceasta aplicatiea am scris-o in Visual Studio 2015,limbajul

de programare C# ,Windows Form Application si se foloseste in prezent la

o centrala electrica cu 6 generatoare electrice pentru:

 

-Afisarea puterilor generate sub forma de text, grafic si bargraf

 

-Afisarea Ordinului de Reglaj al puterii pentru reglajul frecventei, transmis

 de la Dispeceratul Energetic National (DEN),sub forma de text si sub forma de grafic

 

-Afisarea frecventei sistemului energetic sub forma de text si sub forma de grafic

 

-Calcul si afisare valori medii pe ora in curs

 

-Calcul si afisare valori de energie livrata in sistem in ora anterioara

 

-Afiseaza intr-un tabel ,in ordine cronologica , ultimele evenimente in legatura cu

 conectarea sau deconectarea generatoarelor.Aceste evenimente sunt generate in momentele

 aparitiei sau disparitiei unei puteri minime masurate.Nu exista informatii digitale folosite

 in aplicatie care sa fie folosite la generarea evenimentelor

 

-In fiecare zi creaza automat un fisier cu numele zilei in curs (ex. “20 noiembrie 2016”)in

 care se salveaza sub forma de coloane text , la intervale de 0,5s  ,data ,ora,puterile generatoarelor ,frecventa

si Ordinul de Reglaj.Un astfel de fisier are o marime de aproximativ 20Mb

 

-Salvarea datelor trebuie sa fie facuta sincron cu ora Central Europeana , deci ora PC-ului pe care

 ruleaza aplicatia trebuie sa fie decalata cu o ora in urma fata de ora Romaniei, iar la ora

 afisata in ecranul aplicatiei trebuie adaugata o ora pentru a se afisa corect ora Romaniei.Trebuie

procedat la fel si cu momentele aparitiei evenimentelor pentru a fi afisate corect

 

In imaginea de mai jos este un Print Screen cu aplicatia pornita intr-o perioada

in care functionau trei generatoare , G1 , G4 si G5

puteri


    

Test aplicatie cu marimi de intrare simulate:

simulare



    

Partea de inceput a unui fisier text cu inregistrari arata in felul urmator:

 

cap_de_tabel

 

Pentru a scrie codul sursa al programului am folosit doua clase oferite de firma Advantech , impreuna cu placa de achizitie USB4711A.Cele doua clase sunt SimpleGraph si PerformanceCounter si se pot vedea la sfarsitul codului de mai jos.

Proiectul complet , arhivat ZIP se poate descarca de AICI

 

Codul sursa al programului este urmatorul:






using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Automation.BDaq;
using System.IO;
using System.Drawing.Drawing2D;
using System.Diagnostics;

namespace AI_InstantAI
{
    public partial class InstantAIForm : Form
    {
        #region fields

        SimpleGraph m_simpleGraph;
        SimpleGraph graficOrdin;
        SimpleGraph graficFrecventa;
        public const int CHANNEL_COUNT_MAX = 16; //nr maxim de canale analogice citite
        double[] m_dataScaled = new double[CHANNEL_COUNT_MAX];
        double[] ordin_grafic = { 0 };
        double[] frecventa_grafic = { 0 };
        string secunde = "00";
        int ora = 0;
        int minut = 0;
        int secunda = 0;
        int milisecunda = 0;
        /// <summary>
        /// //////////////
        /// </summary>
        string[] eveniment = new string[5] {"","","","",""}; // siruri de caractere pentru evenimente (generator conectat/deconectat)
        int[] stare_bloc = new int[7] { 0, 0, 0, 0, 0, 0, 0 }; // starea generatoarelor (conectat/deconectat)
        int[] temporizare_la_conectare = new int[7]{ 0, 0, 0, 0, 0, 0, 0 };
        int[] temporizare_la_deconectare = new int[7] { 0, 0, 0, 0, 0, 0, 0 };
        string stare_gen_pornire = ""; // starea generatoarelor in momentul pornirii programului afisat ca text (ex. 011010)
        double Generator1 = 0;
        double Generator2 = 0;
        double Generator3 = 0;
        double Generator4 = 0;
        double Generator5 = 0;
        double Generator6 = 0;
        double totalMW = 0;
        double ordin = 0;
        double frecventa = 0;
        double suma_puteri_citite = 0;
        /// <summary>
        /// ///////
        /// </summary>
        double suma_puteri_Generator1 = 0;
        double putere_medie_Generator1 = 0;
        double energie_Generator1 = 0;
        /// <summary>
        /// /
        /// </summary>
        double suma_puteri_Generator2 = 0;
        double putere_medie_Generator2 = 0;
        double energie_Generator2 = 0;
        /// <summary>
        /// ///////////
        /// </summary>
        double suma_puteri_Generator3 = 0;
        double putere_medie_Generator3 = 0;
        double energie_Generator3 = 0;
        /// <summary>
        ///
        /// </summary>
        double suma_puteri_Generator4 = 0;
        double putere_medie_Generator4 = 0;
        double energie_Generator4 = 0;
        /// <summary>
        ///
        /// </summary>
        double suma_puteri_Generator5 = 0;
        double putere_medie_Generator5 = 0;
        double energie_Generator5 = 0;
        /// <summary>
        ///
        /// </summary>
        double suma_puteri_Generator6 = 0;
        double putere_medie_Generator6 = 0;
        double energie_Generator6 = 0;

        double suma_ordin = 0;
        double ordin_mediu_ora_curenta = 0;
        double ordin_mediu_ora_anterioara = 0;
        /// <summary>
        /// //////////
        /// </summary>
        double putereMedie = 0;
        double energie = 0;
        int numar_de_citiri = 0; // variabila care creste intr-o ora de la 0 la 7200
        /// <summary>
        /// variabile care indica valorile primare (Puteri 0-100MW , 0-200MW, ordin 0-100%,frecventa 49.8-50.2Hz)
        /// </summary>
        double Generator1_calibrat = 0;
        double Generator2_calibrat = 0;
        double Generator3_calibrat = 0;
        double Generator4_calibrat = 0;
        double Generator5_calibrat = 0;
        double Generator6_calibrat = 0;
        double ordin_calibrat = 0;
        double frecventa_calibrat = 0;
        /// <summary>
        /// variabile care se vor salva in fisier pentru trimitere la Dispeceratul Energetic National
        /// </summary>
        string Generator1_text_3_zecimale;
        string Generator2_text_3_zecimale;
        string Generator3_text_3_zecimale;
        string Generator4_text_3_zecimale;
        string Generator5_text_3_zecimale;
        string Generator6_text_3_zecimale;
        string ordin_text_3_zecimale;
        string frecventa_text_3_zecimale;
        /// <summary>
        /// variabile pentru afisare si salvare data/ora
        /// </summary>
        string luna;
        string ziua_lunii;
        string oraCurenta;
        string oraCurenta_minus10Min;
        /// <summary>
        /// variabile pentru crearea fisierului pentru inregistrari pe discul (D:)
        /// </summary>
        string nume_fisier;
        string fisier_inreg;
        /// <summary>
        /// formatare string , cap de tabel cu numele coloanelor din fisierul de inregistrari
        /// </summary>
        string cap_de_tabel = String.Format("{0,11}  {1,11}  {2,11}  {3,11}  {4,11}  {5,11}  {6,11}  {7,11}  {8,11} {9,11}", "DATA",
         "ORA", "Gen_1", "Gen_2", "Gen_3", "Gen_4", "Gen_5", "Gen_6", "Frecv.", "Ordin");
        /// <summary>
        /// variabila in care se vor scrie toate marimile masurate la intervale de 0,5 secunde si vor forma
        /// un rand complet in  fisierul cu inregistrari pentru Dispeceratul Energetic National (DEN)
        /// </summary>
        string textTotal;
        /// <summary>
        /// creare instrumente pentru desen in ecranul aplicatiei
        /// </summary>
        public System.Drawing.Graphics desen;
        public System.Drawing.Pen creion_albastru;
        public System.Drawing.Pen creion_gri;
        public System.Drawing.SolidBrush radiera;
        public System.Drawing.SolidBrush pensula_rosie;
        public System.Drawing.SolidBrush pensula_LightGray;
        public System.Drawing.SolidBrush pensula_LightBlue;
        public System.Drawing.SolidBrush pensula_Green;
        public System.Drawing.SolidBrush pensula_LightGreen;
        public System.Drawing.SolidBrush pensula_LightSkyBlue;
        public System.Drawing.SolidBrush pensula_Yellow;
        public System.Drawing.SolidBrush pensula_albastra;
        public System.Drawing.Font font_nina;
        /// <summary>
        /// creare instrumente virtuale (bargrafe) in clasa "instrum"
        /// </summary>
        public instrum instrument_1;
        public instrum instrument_2;
        public instrum instrument_3;
        public instrum instrument_4;
        public instrum instrument_5;
        public instrum instrument_6;
        public instrum instrument_7;
        public instrum instrument_8;
        public instrum instrument_9;
        #endregion

        public InstantAIForm()
        {
            InitializeComponent();
        }

        public InstantAIForm(int deviceNumber)
        {
            InitializeComponent();
            instantAiCtrl1.SelectedDevice = new DeviceInformation(deviceNumber);
        }

        private void InstantAiForm_Load(object sender, EventArgs e)
        {
            if (!instantAiCtrl1.Initialized)
            {
                MessageBox.Show(" Nu gasesc placa de achizitie!", "AI_InstantAI");
                this.Close();
                return;
            }
            /// titlul aplicatiei (apare pe bara de sus)
            this.Text = "Program Achizitie Date , By Simpalean Nicolae sectia PRAM Iernut";
            ///
            // initializare grafice ,plasate in pictureBox , de marimea pictureBox-ului
            ///
            m_simpleGraph = new SimpleGraph(pictureBox.Size, pictureBox);
            graficOrdin = new SimpleGraph(pictureBox1.Size, pictureBox1);
            graficFrecventa = new SimpleGraph(pictureBox2.Size, pictureBox2);
            //initializare timer pentru citirea datelor la intervale prestabilite
            timer_getData.Interval = trackBar.Value;
            //configurare grafice//
            ConfigureGraph_ordin();
            ConfigureGraph_frecventa();
            ConfigureGraph();
            desen = this.CreateGraphics();
            creion_albastru = new System.Drawing.Pen(System.Drawing.Color.Blue, 2);
            creion_gri = new System.Drawing.Pen(System.Drawing.Color.Red, 2);
            radiera = new System.Drawing.SolidBrush(this.BackColor);
            pensula_rosie = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
            pensula_LightGray = new System.Drawing.SolidBrush(System.Drawing.Color.LightGray);
            pensula_LightBlue = new System.Drawing.SolidBrush(System.Drawing.Color.LightBlue);
            pensula_Green = new System.Drawing.SolidBrush(System.Drawing.Color.Green);
            pensula_LightGreen = new System.Drawing.SolidBrush(System.Drawing.Color.LightGreen);
            pensula_LightSkyBlue = new System.Drawing.SolidBrush(System.Drawing.Color.LightSkyBlue);
            pensula_Yellow = new System.Drawing.SolidBrush(System.Drawing.Color.Yellow);
            pensula_albastra = new System.Drawing.SolidBrush(System.Drawing.Color.Blue);
            font_nina = new System.Drawing.Font("Nina", 10);
            /////////////////////////////////////////////////////////
            instrument_1 = new instrum();//bargraf bloc 1
            instrument_2 = new instrum();//bargraf bloc 2
            instrument_3 = new instrum();//bargraf bloc 3
            instrument_4 = new instrum();//bargraf bloc 4
            instrument_5 = new instrum();//bargraf bloc 5
            instrument_6 = new instrum();//bargraf bloc 6
            instrument_7 = new instrum();//scala puteri
            instrument_8 = new instrum();//scala ordin
            instrument_9 = new instrum();//scala frecventa
            ////////////////////////////////////////////////////
            // Initializare bargrafe cu parametri (pozitie pe ecran ,dimensiuni si valoare maxima afisata)
            // exemplu : instrument_1 este plasat la 770 pixeli fata de marginea din stanga a ecranului, 45 de pixeli fata
            //de marginea de sus a ecranului , are latimea de 30 de pixeli, inaltimea de 400 de pixeli si are o scala gradata
            // intre 0 si 100
            ////////////////////////////////////////////////////
            instrument_1.init_ins(770, 45, 30, 400, 100);
            instrument_2.init_ins(865, 45, 30, 400, 100);
            instrument_3.init_ins(945, 45, 30, 400, 100);
            instrument_4.init_ins(1040, 45, 30, 400, 100);
            instrument_5.init_ins(1125, 45, 30, 400, 200);
            instrument_6.init_ins(1220, 45, 30, 400, 200);
            instrument_7.init_ins(670, 45, 1, 400, 200);
            instrument_8.init_ins(670, 479, 1, 200, 100);
            instrument_9.init_ins(670, 716, 1, 200, 100);
            //////////////////////////////////////////////////////////////
            ///Deoarece mesajele in legatura cu momentele conectarii /deconectarii
            ///generatoarelor sunt generate doar pe baza prezentei sau absentei
            ///puterii masurate este necesara verificarea starii generatoarelor
            ///in momentul pornirii programului
            ///pentru a bloca afisarea eronata a mesajelor  din cadrul listei
            ///cu evenimente conectat/deconectat. Altfel , generatoarele
            ///care sunt deja pornite in momentul pornirii programului vor fi afisate
            ///ca si cand ar fi pornit odata cu programul,deci eronat. Solutia a fost urmatoarea:
            /// daca un generator are puterea mai mare de 0,2 MW variabila "stare_bloc" corespunzatoare
            ///va lua valoarea 1 , deci urmatoarea citire care ar putea afisa textul
            ///"Generator conectat"  va fi blocata pana la o schimbare reala a starii
            /// oricarui generator
            /// //////////////////////////////////////////////////////////////
            instantAiCtrl1.Read(0, 8, m_dataScaled);
            for(int i=0;i<6;i++)
            {
                if(m_dataScaled[i]>=0.2)
                {
                    stare_bloc[i + 1] = 1;
                    stare_gen_pornire += "1";
                }
                else
                {
                    stare_gen_pornire += "0";
                }
            }
            textBox27.Text = stare_gen_pornire;
           timer_getData.Start();
        }
        /// <summary>
        /// momentul desenarii pe ecran a instrumentelor de masura , pe evenimentul Paint al Form-ului
        /// </summary>

        private void Form1_Paint(object sender, PaintEventArgs e)
        {

            instrument_1.desenez(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
            instrument_2.desenez_stanga(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
            instrument_3.desenez(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
            instrument_4.desenez_stanga(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
            instrument_5.desenez(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
            instrument_6.desenez_stanga(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
            instrument_7.desenez(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
            instrument_8.desenez(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
            instrument_9.desenez_dreapta_zecimale(desen, creion_albastru, creion_gri, pensula_rosie, font_nina);
        }

        private void ConfigureGraph()
        {
            m_simpleGraph.XCordTimeDiv = 60000; // Intervalul afisat pe grafic este de 600 secunde sau 10 minute
            string[] X_rangeLabels = new string[2];
            Helpers.GetXCordRangeLabels(X_rangeLabels, 10, 0, TimeUnit.Second);
            //label_XCoordinateMax.Text = X_rangeLabels[0];
            //label_XCoordinateMin.Text = X_rangeLabels[1];
            ValueUnit unit = (ValueUnit)(-1); // Don't show unit in the label.
            string[] Y_CordLables = new string[3];
            Helpers.GetYCordRangeLabels(Y_CordLables, 200, 0, unit);
            //label_YCoordinateMax.Text = Y_CordLables[0];
            //label_YCoordinateMin.Text = Y_CordLables[1];
            //label_YCoordinateMiddle.Text = Y_CordLables[2];
            m_simpleGraph.YCordRangeMax = 200;
            m_simpleGraph.YCordRangeMin = 0;
            m_simpleGraph.Clear();
        }
        private void ConfigureGraph_frecventa()
        {
            graficFrecventa.XCordTimeDiv = 60000;
            string[] X_rangeLabels = new string[2];
            Helpers.GetXCordRangeLabels(X_rangeLabels, 10, 0, TimeUnit.Second);
            //label_XCoordinateMax.Text = X_rangeLabels[0];
            //label_XCoordinateMin.Text = X_rangeLabels[1];
            ValueUnit unit = (ValueUnit)(-1); // Don't show unit in the label.
            string[] Y_CordLables = new string[3];
            Helpers.GetYCordRangeLabels(Y_CordLables, 10, -10, unit);
            graficFrecventa.YCordRangeMax = 50.2;
            graficFrecventa.YCordRangeMin = 49.8;
            graficFrecventa.Clear();
        }
        private void ConfigureGraph_ordin()
        {
            graficOrdin.XCordTimeDiv = 60000;
            string[] X_rangeLabels = new string[2];
            Helpers.GetXCordRangeLabels(X_rangeLabels, 10, 0, TimeUnit.Second);
            //label_XCoordinateMax.Text = X_rangeLabels[0];
            //label_XCoordinateMin.Text = X_rangeLabels[1];
            ValueUnit unit = (ValueUnit)(-1); // Don't show unit in the label.
            string[] Y_CordLables = new string[3];
            Helpers.GetYCordRangeLabels(Y_CordLables, 100, 0, unit);
            graficOrdin.YCordRangeMax = 100;
            graficOrdin.YCordRangeMin = 0;
            graficOrdin.Clear();
        }

       //functie care scrie intr-un textBox data , ora (+1 ora) minut si secunda (-6 s) in care un generator este conectat///

         private void scrie_eveniment_Conectat(int nrBloc)
         {
              for (int i = 4; i > 0; i--)
              {
                 eveniment[i] = eveniment[i - 1];
              }
              textBox33.Text = eveniment[4];
              textBox32.Text = eveniment[3];
              textBox31.Text = eveniment[2];
            eveniment[1] = "Generator " + nrBloc + " conectat la " + DateTime.Now.AddHours(1).AddSeconds(-6).ToString();
              textBox30.Text = eveniment[1];
              stare_bloc[nrBloc] = 1;
          }

       //functie care scrie intr-un textBox data , ora (+1 ora) minut si secunda (-6 s) in care un generator este deconectat ///

          private void scrie_eveniment_Deconectat(int nrBloc)
          {
              for (int i = 4; i > 0; i--)
              {
                  eveniment[i] = eveniment[i - 1];
              }
              textBox33.Text = eveniment[4];
              textBox32.Text = eveniment[3];
              textBox31.Text = eveniment[2];
              eveniment[1] = "Generator "+nrBloc+" deconectat la " + DateTime.Now.AddHours(1).AddSeconds(-6).ToString();
              textBox30.Text = eveniment[1];
              stare_bloc[nrBloc] = 0;
          }
        private void timer_getData_Tick(object sender, EventArgs e)
        {
            PerformanceCounter performanceCounter = new PerformanceCounter();
            ErrorCode err;
            performanceCounter.Start();
            err = instantAiCtrl1.Read(0, 8, m_dataScaled);//primul canal citit (0),Numarul de canale citit (8) din simulator sau (10) din USB4711
            if (err != ErrorCode.Success)
            {
                HandleError(err);
                timer_getData.Stop();
            }
            Generator1 = m_dataScaled[0];
            Generator2 = m_dataScaled[1];
            Generator3 = m_dataScaled[2];
            Generator4 = m_dataScaled[3];
            Generator5 = m_dataScaled[4];
            Generator6 = m_dataScaled[5];
            ordin = m_dataScaled[8];
            frecventa = m_dataScaled[9];
            if (Generator1 < 0)
                Generator1 = 0;
            if (Generator2 < 0)
                Generator2 = 0;
            if (Generator3 < 0)
                Generator3 = 0;
            if (Generator4 < 0)
                Generator4 = 0;
            if (Generator5 < 0)
                Generator5 = 0;
            if (Generator6 < 0)
                Generator6 = 0;
            Generator1_calibrat = Generator1 * 11;
            Generator2_calibrat = Generator2 * 11;
            Generator3_calibrat = Generator3 * 11;
            Generator4_calibrat = Generator4 * 11;
            Generator5_calibrat = Generator5 * 22;
            Generator6_calibrat = Generator6 * 22;
            ordin_calibrat = ordin * 10;
            frecventa_calibrat = 50 + (frecventa * 0.2);

                      ///    lista cronologica evenimente  (inceput)    ///
            /// daca puterea unui blocului nu sta 6 secunde la valoare mai mare de 0.8MW se reseteaza timerul
            /// corespunzator blocului respectiv, folosit ca temporizator la conectare
            if (Generator1_calibrat <= 0.8 && stare_bloc[1] == 0) { temporizare_la_conectare[1] = 0; }
            if (Generator2_calibrat <= 0.8 && stare_bloc[2] == 0) { temporizare_la_conectare[2] = 0; }
            if (Generator3_calibrat <= 0.8 && stare_bloc[3] == 0) { temporizare_la_conectare[3] = 0; }
            if (Generator4_calibrat <= 0.8 && stare_bloc[4] == 0) { temporizare_la_conectare[4] = 0; }
            if (Generator5_calibrat <= 0.8 && stare_bloc[5] == 0) { temporizare_la_conectare[5] = 0; }
            if (Generator6_calibrat <= 0.8 && stare_bloc[6] == 0) { temporizare_la_conectare[6] = 0; }
            /// daca puterea unui bloc nu sta 6 secunde sub valoarea de 0,2MW se reseteaza timerul corespunzator
            /// blocului respectiv , folosit ca temporizator la deconectare
            if (Generator1_calibrat > 0.2 && stare_bloc[1] == 1) { temporizare_la_deconectare[1] = 0; }
            if (Generator2_calibrat > 0.2 && stare_bloc[2] == 1) { temporizare_la_deconectare[2] = 0; }
            if (Generator3_calibrat > 0.2 && stare_bloc[3] == 1) { temporizare_la_deconectare[3] = 0; }
            if (Generator4_calibrat > 0.2 && stare_bloc[4] == 1) { temporizare_la_deconectare[4] = 0; }
            if (Generator5_calibrat > 0.2 && stare_bloc[5] == 1) { temporizare_la_deconectare[5] = 0; }
            if (Generator6_calibrat > 0.2 && stare_bloc[6] == 1) { temporizare_la_deconectare[6] = 0; }
            //////////////////////////////////////////////////////////////////////////////////////////////////
            ///  daca puterea unui bloc este mai mare de 0,8MW si timerul blocului respectiv reuseste sa numere 6 secunde
            ///  (daca coboara sub 0,8MW in timp ce se cronometreaza cele 6 secunde se reseteaza) adica 12 evenimente TIC de
            ///  la TimerGetData (0,5s) va fi apelata functia "scrie_eveniment_Conectat"
            ///  iar daca puterea este stabila 6 secunde sub 0.2MW va fi apelata functia "scrie_eveniment_Deconectat"
            if (Generator1_calibrat > 0.8 && stare_bloc[1] == 0)
            {
                temporizare_la_conectare[1]++;
                if(temporizare_la_conectare[1]>12)
                scrie_eveniment_Conectat(1);
            }
                else if (Generator1_calibrat <= 0.2 && stare_bloc[1] == 1)
            {
                temporizare_la_deconectare[1]++;
                if(temporizare_la_deconectare[1]>12)
                scrie_eveniment_Deconectat(1);
            }
            if (Generator2_calibrat > 0.8 && stare_bloc[2] == 0)
            {
                temporizare_la_conectare[2]++;
                if (temporizare_la_conectare[2] > 12)
                    scrie_eveniment_Conectat(2);
            }
            else if (Generator2_calibrat <= 0.2 && stare_bloc[2] == 1)
            {
                temporizare_la_deconectare[2]++;
                if (temporizare_la_deconectare[2] > 12)
                    scrie_eveniment_Deconectat(2);
            }
            if (Generator3_calibrat > 0.8 && stare_bloc[3] == 0)
            {
                temporizare_la_conectare[3]++;
                if (temporizare_la_conectare[3] > 12)
                    scrie_eveniment_Conectat(3);
            }
            else if (Generator3_calibrat <= 0.2 && stare_bloc[3] == 1)
            {
                temporizare_la_deconectare[3]++;
                if (temporizare_la_deconectare[3] > 12)
                    scrie_eveniment_Deconectat(3);
            }
            if (Generator4_calibrat > 0.8 && stare_bloc[4] == 0)
            {
                temporizare_la_conectare[4]++;
                if (temporizare_la_conectare[4] > 12)
                    scrie_eveniment_Conectat(4);
            }
            else if (Generator4_calibrat <= 0.2 && stare_bloc[4] == 1)
            {
                temporizare_la_deconectare[4]++;
                if (temporizare_la_deconectare[4] > 12)
                    scrie_eveniment_Deconectat(4);
            }
            if (Generator5_calibrat > 0.8 && stare_bloc[5] == 0)
            {
                temporizare_la_conectare[5]++;
                if (temporizare_la_conectare[5] > 12)
                    scrie_eveniment_Conectat(5);
            }
            else if (Generator5_calibrat <= 0.2 && stare_bloc[5] == 1)
            {
                temporizare_la_deconectare[5]++;
                if (temporizare_la_deconectare[5] > 12)
                    scrie_eveniment_Deconectat(5);
            }
            if (Generator6_calibrat > 0.8 && stare_bloc[6] == 0)
            {
                temporizare_la_conectare[6]++;
                if (temporizare_la_conectare[6] > 12)
                    scrie_eveniment_Conectat(6);
            }
            else if (Generator6_calibrat <= 0.2 && stare_bloc[6] == 1)
            {
                temporizare_la_deconectare[6]++;
                if (temporizare_la_deconectare[6] > 12)
                    scrie_eveniment_Deconectat(6);
            }
            /////////lista cronologica evenimente (sfarsit) //////
            /////////////////////////////////////////////
            /// calcul suma puteri pe centrala
            ////////////////////////////////////////////
            totalMW = Generator1_calibrat + Generator2_calibrat + Generator3_calibrat + Generator4_calibrat + Generator5_calibrat + Generator6_calibrat;
            ////////////////////////////////////////////
            ///formatare marimi pentru a fi scrise in fisierul text de pe discul (D:) cu trei zecimale
            ////////////////////////////////////////////
            Generator1_text_3_zecimale = String.Format("{0:0.000}", Generator1_calibrat);
            Generator2_text_3_zecimale = String.Format("{0:0.000}", Generator2_calibrat);
            Generator3_text_3_zecimale = String.Format("{0:0.000}", Generator3_calibrat);
            Generator4_text_3_zecimale = String.Format("{0:0.000}", Generator4_calibrat);
            Generator5_text_3_zecimale = String.Format("{0:0.000}", Generator5_calibrat);
            Generator6_text_3_zecimale = String.Format("{0:0.000}", Generator6_calibrat);
            frecventa_text_3_zecimale = String.Format("{0:0.000}", frecventa_calibrat);
            ordin_text_3_zecimale = String.Format("{0:0.000}", ordin_calibrat);
            ///////////////////////////////////////////////////////////////////////////////////////////
            ///formatare si afisare marimi pentru a fi afisate pe ecran cu o singura zecimala
            ///////////////////////////////////////////////////////////////////////////////////////////
            textBox1.Text = String.Format("{0:0.0}", Generator1_calibrat);
            textBox2.Text = String.Format("{0:0.0}", Generator2_calibrat);
            textBox3.Text = String.Format("{0:0.0}", Generator3_calibrat);
            textBox4.Text = String.Format("{0:0.0}", Generator4_calibrat);
            textBox5.Text = String.Format("{0:0.0}", Generator5_calibrat);
            textBox6.Text = String.Format("{0:0.0}", Generator6_calibrat);
            textBox7.Text = String.Format("{0:0.0}", totalMW);
            textBox8.Text = String.Format("{0:0.0}", ordin_calibrat);
            textBox9.Text = String.Format("{0:0.00}", frecventa_calibrat);
            /////////////////////////////////////////////////////////////////////////////////////////
            ///inserare marimi in variabile de tip double array pentru afisare pe grafice
            /////////////////////////////////////////////////////////////////////////////////////////
            m_dataScaled[0] = Generator1_calibrat;
            m_dataScaled[1] = Generator2_calibrat;
            m_dataScaled[2] = Generator3_calibrat;
            m_dataScaled[3] = Generator4_calibrat;
            m_dataScaled[4] = Generator5_calibrat;
            m_dataScaled[5] = Generator6_calibrat;
            ordin_grafic[0] = ordin_calibrat;
            frecventa_grafic[0] = frecventa_calibrat;
            /////////////////////////////////////////////////////////////////////////////////////////
            ///stergere continut urmat de colorarea bargrafului corespunzator fiecarui generator
            ///cu culoarea corespunzatoare si lungime proportionala cu puterea masurata
            /////////////////////////////////////////////////////////////////////////////////////////

            if (Generator1_calibrat >= 0 && Generator1_calibrat <= 100)
            {
                instrument_1.sterg(desen, radiera);
                instrument_1.setval(Convert.ToInt16(Generator1_calibrat), desen, pensula_LightGray);
            }
            if (Generator2_calibrat >= 0 && Generator2_calibrat <= 100)
            {
                instrument_2.sterg(desen, radiera);
                instrument_2.setval(Convert.ToInt16(Generator2_calibrat), desen, pensula_LightBlue);
            }
            if (Generator3_calibrat >= 0 && Generator3_calibrat <= 100)
            {
                instrument_3.sterg(desen, radiera);
                instrument_3.setval(Convert.ToInt16(Generator3_calibrat), desen, pensula_Green);
            }
            if (Generator4_calibrat >= 0 && Generator4_calibrat <= 100)
                    {
               instrument_4.sterg(desen, radiera);
               instrument_4.setval(Convert.ToInt16(Generator4_calibrat), desen, pensula_LightGreen);
                    }
            if (Generator5_calibrat >= 0 && Generator5_calibrat <= 200)
            {
                instrument_5.sterg(desen, radiera);
                instrument_5.setval(Convert.ToInt16(Generator5_calibrat), desen, pensula_LightSkyBlue);
            }
            if (Generator6_calibrat >= 0 && Generator6_calibrat <= 200)
            {
                instrument_6.sterg(desen, radiera);
                instrument_6.setval(Convert.ToInt16(Generator6_calibrat), desen, pensula_Yellow);
            }
            /////////////////////////////////////////////////////////////////////////////////
            textTotal = String.Format("{0,11}  {1,11}  {2,11}  {3,11}  {4,11}  {5,11}  {6,11}  {7,11}  {8,11} {9,11}"+
           " ", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString(),
           Generator1_text_3_zecimale, Generator2_text_3_zecimale, Generator3_text_3_zecimale, Generator4_text_3_zecimale,
           Generator5_text_3_zecimale, Generator6_text_3_zecimale, frecventa_text_3_zecimale, ordin_text_3_zecimale);
            luna = DateTime.Now.Month.ToString();
            nume_fisier = DateTime.Now.ToLongDateString();
            ziua_lunii = DateTime.Now.Day.ToString();
            ora = DateTime.Now.Hour;
            minut = DateTime.Now.Minute;
            secunde = DateTime.Now.Second.ToString();
            secunda = DateTime.Now.Second;
            milisecunda = DateTime.Now.Millisecond;
            fisier_inreg = "D:\\" + nume_fisier + ".txt";
            oraCurenta = DateTime.Now.AddHours(1).ToLongTimeString();
            textBox27.Text = oraCurenta;
            oraCurenta_minus10Min = DateTime.Now.AddMinutes(50).ToLongTimeString();
            textBox28.Text = oraCurenta_minus10Min;
            ////////////////////////////////////////////////////////////////////////////////////////////////
            ///prima linie din fisierul de pe discul (D:) se scrie automat la ora 00 minut 00 decunda 00 cu
            ///capul de tabel :'Data , Ora , Gen_1 , Gen_2 , Gen_3, etc...."
            ////////////////////////////////////////////////////////////////////////////////////////////////
            if (ora == 0 && minut == 0 && secunda == 0 && milisecunda <= 500)
            {
                using (StreamWriter objectStream = new StreamWriter(fisier_inreg, true))
                {
                    objectStream.WriteLine(cap_de_tabel);
                }
            }
            textBox10.Text = numar_de_citiri.ToString();
            numar_de_citiri++;
            suma_puteri_citite = suma_puteri_citite + totalMW;
            suma_puteri_Generator1 = suma_puteri_Generator1 + Generator1_calibrat;
            suma_puteri_Generator2 = suma_puteri_Generator2 + Generator2_calibrat;
            suma_puteri_Generator3 = suma_puteri_Generator3 + Generator3_calibrat;
            suma_puteri_Generator4 = suma_puteri_Generator4 + Generator4_calibrat;
            suma_puteri_Generator5 = suma_puteri_Generator5 + Generator5_calibrat;
            suma_puteri_Generator6 = suma_puteri_Generator6 + Generator6_calibrat;
            suma_ordin = suma_ordin + ordin_calibrat;
           /////////////////////////////////////////////////////////////////////////////////
           //// in prima jumatate de secunda a orei in curs se scriu pe display energiile medii
           /// livrate ora anterioara ca rezultat al puterii medii masurate ora anterioara in
           /// 7200 de esantioane (de doua ori pe secunda)
           ////////////////////////////////////////////////////////////////////////////////
            if ((minut == 0 && secunda == 0 && milisecunda <= 500)||(numar_de_citiri>7220))
            {
                ////////////////////////////////////////
                energie_Generator1 = putere_medie_Generator1;
                energie_Generator2 = putere_medie_Generator2;
                energie_Generator3 = putere_medie_Generator3;
                energie_Generator4 = putere_medie_Generator4;
                energie_Generator5 = putere_medie_Generator5;
                energie_Generator6 = putere_medie_Generator6;
                ordin_mediu_ora_anterioara = ordin_mediu_ora_curenta;
                energie = putereMedie;
                /////////////////////////////////////////
                numar_de_citiri = 1;
                putere_medie_Generator1 = Generator1_calibrat;
                putere_medie_Generator2 = Generator2_calibrat;
                putere_medie_Generator3 = Generator3_calibrat;
                putere_medie_Generator4 = Generator4_calibrat;
                putere_medie_Generator6 = Generator6_calibrat;
                putere_medie_Generator5 = Generator5_calibrat;
                ordin_mediu_ora_curenta = ordin_calibrat;
                putereMedie = totalMW;
                textBox11.Text = String.Format("{0:0.0}", putereMedie);
                textBox12.Text = String.Format("{0:0.0}", energie);
                textBox18.Text = String.Format("{0:0.0}", putere_medie_Generator1);
                textBox24.Text = String.Format("{0:0.0}", energie_Generator1);
                textBox17.Text = String.Format("{0:0.0}", putere_medie_Generator2);
                textBox23.Text = String.Format("{0:0.0}", energie_Generator2);
                textBox16.Text = String.Format("{0:0.0}", putere_medie_Generator3);
                textBox22.Text = String.Format("{0:0.0}", energie_Generator3);
                textBox15.Text = String.Format("{0:0.0}", putere_medie_Generator4);
                textBox21.Text = String.Format("{0:0.0}", energie_Generator4);
                textBox14.Text = String.Format("{0:0.0}", putere_medie_Generator5);
                textBox20.Text = String.Format("{0:0.0}", energie_Generator5);
                textBox13.Text = String.Format("{0:0.0}", putere_medie_Generator6);
                textBox19.Text = String.Format("{0:0.0}", energie_Generator6);
                textBox25.Text = String.Format("{0:0.0}", ordin_mediu_ora_curenta);
                textBox26.Text = String.Format("{0:0.0}", ordin_mediu_ora_anterioara);
                suma_puteri_citite = totalMW;
                suma_puteri_Generator1 = Generator1_calibrat;
                suma_puteri_Generator2 = Generator2_calibrat;
                suma_puteri_Generator3 = Generator3_calibrat;
                suma_puteri_Generator4 = Generator4_calibrat;
                suma_puteri_Generator5 = Generator5_calibrat;
                suma_puteri_Generator6 = Generator6_calibrat;
                suma_ordin = ordin_calibrat;
            }
            else
            {
                putereMedie = suma_puteri_citite / numar_de_citiri;
                putere_medie_Generator1 = suma_puteri_Generator1 / numar_de_citiri;
                putere_medie_Generator2 = suma_puteri_Generator2 / numar_de_citiri;
                putere_medie_Generator3 = suma_puteri_Generator3 / numar_de_citiri;
                putere_medie_Generator4 = suma_puteri_Generator4 / numar_de_citiri;
                putere_medie_Generator5 = suma_puteri_Generator5 / numar_de_citiri;
                putere_medie_Generator6 = suma_puteri_Generator6 / numar_de_citiri;
                ordin_mediu_ora_curenta = suma_ordin / numar_de_citiri;
                textBox11.Text = String.Format("{0:0.0}", putereMedie);
                textBox18.Text = String.Format("{0:0.0}", putere_medie_Generator1);
                textBox17.Text = String.Format("{0:0.0}", putere_medie_Generator2);
                textBox16.Text = String.Format("{0:0.0}", putere_medie_Generator3);
                textBox15.Text = String.Format("{0:0.0}", putere_medie_Generator4);
                textBox14.Text = String.Format("{0:0.0}", putere_medie_Generator5);
                textBox13.Text = String.Format("{0:0.0}", putere_medie_Generator6);
                textBox25.Text = String.Format("{0:0.0}", ordin_mediu_ora_curenta);
            }
            /////////////////////////////////////////////////////////////////////////////
            /// momentul scrierii in fisierul text de pe discul (D:) a unui rand cu valori
            /////////////////////////////////////////////////////////////////////////////
            using (StreamWriter objectStream = new StreamWriter(fisier_inreg, true))
            {
                objectStream.WriteLine(textTotal);
            }
            //////////////////////////////////////////////////////////////////////////////
            ///momentul adaugarii pe cele trei grafice de pe display a punctelor corespunzatoare trendurilor
            /////////////////////////////////////////////////////////////////////////////////
            m_simpleGraph.Chart(m_dataScaled, 6, 1, 1.0 * trackBar.Value / 1000);
            graficOrdin.Chart(ordin_grafic, 1, 1, 1.0 * trackBar.Value / 1000);
            graficFrecventa.Chart(frecventa_grafic, 1, 1, 1.0 * trackBar.Value / 1000);
            /////////////////////////////////////////////////////////////////////////////////
            performanceCounter.Stop(); /// sfarsit test aparitie erori la citirea datelor
            /////////////////////////////////////////////////////////////////////////////////////
            int interval = (int)(trackBar.Value - performanceCounter.Duration * 1000 - 0.5);
            if (interval > 1)
            {
                timer_getData.Interval = interval;
            }
        }
        //////////////////////////////////////////////////////////////////////////////
        ////// modificare interval citire date pe evenimentul scroll de la trackBar
        //////////////////////////////////////////////////////////////////////////////
        private void trackBar_Scroll(object sender, EventArgs e)
        {
            m_simpleGraph.Clear();
            graficFrecventa.Clear();
            graficOrdin.Clear();
            timer_getData.Interval = trackBar.Value;
        }

        private void HandleError(ErrorCode err)
        {
            if (err != ErrorCode.Success)
            {
                MessageBox.Show("Ne pare rau! S-a intamplat ceva.Mesjul de eroare este: " + err.ToString(), "AI_InstantAI");
            }
        }
    }
    //////////////////////////////////////////////////////////////////////////////////
    /// clasa care genereaza unelte de tip ProgressBar , orientate vertical(nu este folosita in aceasta aplicatie)
    ///////////////////////////////////////////////////////////////////////////////////
    public class VerticalProgressBar : ProgressBar
    {
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.Style |= 0x04;
                return cp;
            }
        }
    }
    /// <summary>
    /// clasa cu care se genereaza instrumente de tip bargraph pentru afisare marimi pe display
    /// </summary>
    public class instrum
    {
        float x0;
        float y0;
        float w;
        float h;
        float val_max;
        public void desenez(System.Drawing.Graphics zona_des, System.Drawing.Pen creion_a, System.Drawing.Pen creion_gr, System.Drawing.SolidBrush pens_r, System.Drawing.Font font_ni)
        {
            zona_des.DrawRectangle(creion_a, x0, y0, w+1, h);//deseneaza dreptunghi
            for (int j = 0; j <= h; j += 8) // deseneaza liniute pentru gradatii la intervale de 8 pixeli
            {
                if (j % 40 == 0)// de cate ori restul impartirii la 40 a inaltimii care a mai ramas este zero
                {
                    zona_des.DrawLine(creion_gr, x0 + w + 2, y0 + j, x0 + w + 12, y0 + j);// deseneaza liniute de 12 pixeli
                    zona_des.DrawString(System.Convert.ToString(val_max - j * val_max / h), font_ni, pens_r, x0 + w + 20, y0 + j - 7);//deseneaza text valori gradatii
                }
                else // altfel
                {
                    zona_des.DrawLine(creion_gr, x0 + w + 2, y0 + j, x0 + w + 7, y0 + j); // deseneaza liniute de 7 pixeli
                }
            }
        }
        public void desenez_stanga(System.Drawing.Graphics zona_des, System.Drawing.Pen creion_a, System.Drawing.Pen creion_gr, System.Drawing.SolidBrush pens_r, System.Drawing.Font font_ni)
        {
            zona_des.DrawRectangle(creion_a, x0, y0, w+1, h);
            for (int j = 0; j <= h; j += 8)// desenez gradatii
            {
                if (j % 40 == 0)
                {
                    zona_des.DrawLine(creion_gr, x0 - 2, y0 + j, x0 - 14, y0 + j);
                }
                else
                {
                    zona_des.DrawLine(creion_gr, x0 - 2, y0 + j, x0 - 7, y0 + j);
                }
            }
        }
        /// <summary>
        /// functia care creaza bargraf cu scalare intre 49,8 si 50,2 pentru graficul frecventei
        /// </summary>
        public void desenez_dreapta_zecimale(System.Drawing.Graphics zona_des, System.Drawing.Pen creion_a, System.Drawing.Pen creion_gr, System.Drawing.SolidBrush pens_r, System.Drawing.Font font_ni)
        {
            zona_des.DrawRectangle(creion_a, x0, y0, w+1, h);
            double frecv = 50.2;
            for (int j = 0; j <= h; j += 10)// desenez gradatii
            {
                if (j % 50 == 0)
                {
                    zona_des.DrawLine(creion_gr, x0 + w + 2, y0 + j, x0 + w + 12, y0 + j);
                    zona_des.DrawString(System.Convert.ToString(frecv), font_ni, pens_r, x0 + w + 20, y0 + j - 7);
                    frecv -= 0.1;
                }
                else
                {
                    zona_des.DrawLine(creion_gr, x0 + w + 2, y0 + j, x0 + w + 7, y0 + j);
                }
            }
        }
        public void sterg(System.Drawing.Graphics zona_des, System.Drawing.SolidBrush rad)
        {
            zona_des.FillRectangle(rad, x0+1 , y0+1 , w-2 , h-2 );
        }
        public void setval(float val, System.Drawing.Graphics zona_des, System.Drawing.SolidBrush pens_r)
        {
            val = System.Convert.ToInt16(System.Convert.ToDouble(val) * (System.Convert.ToDouble(h) / System.Convert.ToDouble(val_max))); //scalare
            zona_des.FillRectangle(pens_r, x0 + 1, y0 + h - val, w - 1, val);
        }
        public void init_ins(float pozx, float pozy, float lat, float inalt, float vmax)
        {
            x0 = pozx;
            y0 = pozy;
            w = lat;
            h = inalt;
            val_max = vmax;
        }
    }
}
class SimpleGraph
{
   #region fields
   Bitmap m_bitmap;
   Size m_size;
   Control m_control;

   Double m_YCordRangeMin;
   Double m_YCordRangeMax;

   Double m_xIncByTime;
   Double[] m_drawDataBuffer;
   PointF[][] m_dataPointBuffer;

   Double m_XCordDividedRate;
   Double m_XCordTimeDiv;
   Double m_XCordTimeOffset;

   Double m_shiftCount;
   public Double ShiftCount
   {
      get { return m_shiftCount; }
      set { m_shiftCount = value; }
   }
   int m_plotCount;
   int m_dataCountCachePerPlot;
   int m_mapDataIndexPerPlot = 0;
   int m_pointCountPerScreen;
   int m_dataCountPerPlot = 0;

   OverOneScreenMode m_overOneScreenMode;

       static Pen[] m_pens = new Pen[]{
          System.Drawing.Pens.LightGray,        System.Drawing.Pens.LightBlue,     System.Drawing.Pens.Green,  System.Drawing.Pens.LightGreen,
          System.Drawing.Pens.LightSkyBlue,    System.Drawing.Pens.Yellow,      System.Drawing.Pens.DarkSeaGreen, System.Drawing.Pens.LightGreen,
          System.Drawing.Pens.NavajoWhite,System.Drawing.Pens.OrangeRed,      System.Drawing.Pens.DeepPink,     System.Drawing.Pens.MediumOrchid,
          System.Drawing.Pens.LightGray,  System.Drawing.Pens.MediumVioletRed,System.Drawing.Pens.MistyRose,    System.Drawing.Pens.PowderBlue};




   object LockObject = new object();


#endregion

   #region ctor and dtor
   public SimpleGraph(Size bmSize, Control control)
   {
      m_control = control;
      m_size = bmSize;
      m_bitmap = new Bitmap(bmSize.Width, bmSize.Height);
      m_overOneScreenMode = OverOneScreenMode.BeginScreen;
      m_control.Paint += new PaintEventHandler(ControlOnPaint);


   }

   #endregion

   #region properties

   public Double XCordTimeDiv
   {
      get
      {
         return m_XCordTimeDiv;
      }
      set
      {
         m_XCordTimeDiv = value;
         Div(m_XCordTimeDiv);
      }
   }

   public Double XCordTimeOffset
   {
      get
      {
         return m_XCordTimeOffset;
      }
      set
      {
         m_XCordTimeOffset = value;
         Shift(m_XCordTimeOffset);
      }
   }

   public Double YCordRangeMin
   {
      get
      {
         return m_YCordRangeMin;
      }
      set
      {
         m_YCordRangeMin = value;
      }
   }

   public Double YCordRangeMax
   {
      get
      {
         return m_YCordRangeMax;
      }
      set
      {
         m_YCordRangeMax = value;
      }
   }

   public Pen[] Pens
   {
      get
      {
         return m_pens;
      }
   }

   public OverOneScreenMode OverOneScreenMode
   {
      get
      {
         return m_overOneScreenMode;
      }
      set
      {
         m_overOneScreenMode = value;
      }
   }
   #endregion

   #region methods

   public void Clear()
   {
      m_xIncByTime = 0;
      m_plotCount = 0;
      m_mapDataIndexPerPlot = 0;
      m_pointCountPerScreen = 0;
      m_dataCountPerPlot = 0;
      m_dataCountCachePerPlot = 0;
      m_shiftCount = 0;
      m_control.Invalidate();
   }

   public void Shift(double shiftTime)
   {
      m_mapDataIndexPerPlot = 0;
      m_XCordTimeOffset = shiftTime;
      Draw();
   }

   public void Div(double DivValue)
   {
      m_mapDataIndexPerPlot = 0;
      m_XCordTimeDiv = DivValue;
      Draw();
   }

   private void Draw()
   {
      CalcDrawParams(m_xIncByTime, m_dataCountPerPlot);
      MapDataPoints();
      m_control.Invalidate();
   }

   public void Chart(Double[] data, int plotCount, int dataCountPerPlot, double xIncBySec)
   {
      m_xIncByTime = xIncBySec;
      m_dataCountPerPlot = dataCountPerPlot;
      //to be fit for variational for plotCount
      if (null == m_drawDataBuffer || plotCount != m_plotCount)
      {
         m_drawDataBuffer = new double[plotCount * (m_size.Width * 4 + 1)];
         m_dataPointBuffer = new PointF[plotCount][];
         for (int i = 0; i < plotCount; i++)
         {
            m_dataPointBuffer[i] = new PointF[m_size.Width * 4 + 1];
         }
         m_dataCountCachePerPlot = 0;
         m_plotCount = plotCount;
      }

      CalcDrawParams(xIncBySec, m_dataCountPerPlot);
      SaveData(data, m_plotCount, dataCountPerPlot);
      MapDataPoints();
      m_control.Invalidate();
   }

   private void CalcDrawParams(double XIncBySec, int dataCountPerPlot)
   {
      lock (LockObject)
      {
         double transXIncBySec = XIncBySec;
         Double XcoordinateDivBase = m_size.Width * XIncBySec * 100.0;//ms
         if (XIncBySec * 10 * 1000 <= 1)//us
         {
            transXIncBySec = transXIncBySec * 1000;
            XcoordinateDivBase = XcoordinateDivBase * 1000.0;
            if (XIncBySec * 10 * 1000 * 1000 <= 1)//ns
            {
               transXIncBySec = transXIncBySec * 1000;
               XcoordinateDivBase = XcoordinateDivBase * 1000.0;
            }
         }

         m_shiftCount = (int)(m_XCordTimeOffset * 1.0 / (transXIncBySec * 1000));

         m_XCordDividedRate = XcoordinateDivBase / m_XCordTimeDiv;
         m_pointCountPerScreen = (int)Math.Ceiling(m_size.Width * m_XCordTimeDiv / XcoordinateDivBase) + 1;
      }
   }

   private void SaveData(Double[] data, int plotCount, int dataCountPerPlot)
   {
      if (dataCountPerPlot * m_plotCount > m_drawDataBuffer.Length)
      {
         m_drawDataBuffer = new Double[(dataCountPerPlot + 1) * m_plotCount];
      }

      if (dataCountPerPlot >= m_pointCountPerScreen)
      {
         m_mapDataIndexPerPlot = (m_dataCountPerPlot - m_pointCountPerScreen - 1);
         Array.Copy(data, 0, m_drawDataBuffer, 0, plotCount * dataCountPerPlot);
         m_dataCountCachePerPlot = dataCountPerPlot;
      }
      else
      {
         if (m_dataCountCachePerPlot + dataCountPerPlot <= m_pointCountPerScreen)
         {
            Array.Copy(data, 0, m_drawDataBuffer, m_dataCountCachePerPlot * plotCount, plotCount * dataCountPerPlot);
            m_dataCountCachePerPlot += dataCountPerPlot;
         }
         else
         {
            int overflowCount = plotCount * (m_dataCountCachePerPlot + dataCountPerPlot - m_pointCountPerScreen);
            Array.Copy(m_drawDataBuffer, overflowCount, m_drawDataBuffer, 0, plotCount * m_dataCountCachePerPlot - overflowCount);
            Array.Copy(data, 0, m_drawDataBuffer, plotCount * m_dataCountCachePerPlot - overflowCount, plotCount * dataCountPerPlot);
            m_dataCountCachePerPlot = m_pointCountPerScreen;
            m_mapDataIndexPerPlot = 0;
         }
      }
   }

   private void MapDataPoints( )
   {
      Double YCordDividedRate = 1.0 * (m_size.Height - 1) / (m_YCordRangeMax - m_YCordRangeMin);
      int count = (int)(m_dataCountCachePerPlot - m_shiftCount - m_mapDataIndexPerPlot);
      int drawPoint = count > m_pointCountPerScreen ? m_pointCountPerScreen : count;

      int mapDataIndexPerPlot = m_mapDataIndexPerPlot; //get the copy of m_mapDataIndexPerPlot to avoid the value is changed during handling
      for (int offset = mapDataIndexPerPlot; offset < mapDataIndexPerPlot + drawPoint; offset++)
      {

         for (int i = 0; i < m_plotCount; i++)
         {
            m_dataPointBuffer[i][offset - mapDataIndexPerPlot].Y = (float)Math.Ceiling(YCordDividedRate *
               (m_YCordRangeMax - m_drawDataBuffer[(int)(m_plotCount * (offset + m_shiftCount) + i)]));
            m_dataPointBuffer[i][offset - mapDataIndexPerPlot].X = (float)Math.Round((offset - mapDataIndexPerPlot) * m_XCordDividedRate);
         }
      }
   }

   private void PaintTo(Graphics g)
   {
      g.Clear(Color.Black);
      for (int i = 1; i < 10; i++)
      {
         g.DrawLine(System.Drawing.Pens.DarkGreen,
            new Point((int)(1.0 * i * m_size.Width / 10), 0),
            new Point((int)(1.0 * i * m_size.Width / 10), (m_size.Height)));
         g.DrawLine(System.Drawing.Pens.DarkGreen,
            new Point(0, (int)(1.0 * i * m_size.Height / 10)),
            new Point(m_size.Width, (int)(1.0 * i * m_size.Height / 10)));
      }

      //draw sample data on bitmap.
      if (m_dataCountCachePerPlot > 0)
      {
         Pen plotPen ;
         int count = (int)(m_dataCountCachePerPlot - m_shiftCount - m_mapDataIndexPerPlot);
         int countDrawnPerPlot = count > m_pointCountPerScreen ? m_pointCountPerScreen : count;
         if (0 == countDrawnPerPlot)
         {
            return;
         }
         PointF[] drawData = new PointF[countDrawnPerPlot];
         for (int plotNumber = 0; plotNumber < m_plotCount; plotNumber++)
         {
            plotPen = (plotNumber >= 0 && plotNumber < 16) ? m_pens[plotNumber] : System.Drawing.Pens.Black;
            Array.Copy(m_dataPointBuffer[plotNumber],drawData,countDrawnPerPlot);
            if (countDrawnPerPlot > 1)
            {
               g.DrawLines(plotPen, drawData);
            }
            else
            {
               g.DrawLine(plotPen, drawData[0], drawData[0]);
            }
         }
      }
   }

   private void ControlOnPaint(object sender, PaintEventArgs e)
   {
      PaintTo(Graphics.FromImage(m_bitmap));
      e.Graphics.DrawImage(m_bitmap, new Point(0, 0));
   }
   #endregion
}

static class Helpers
{
   public static void GetXCordRangeLabels(string[]ranges,Double rangeMax, Double rangeMin, TimeUnit unit)
   {
      string[] tUnit = { "ns", "us", "ms","Min" };
      int i;
      for (i = (int)unit; i < (int)TimeUnit.Second && !(rangeMax < 1000); ++i)
      {
         rangeMin /= 1000;
         rangeMax /= 1000;
      }
      ranges[0] = rangeMax.ToString() + " " + tUnit[i];
      ranges[1] = rangeMin.ToString() + " " + tUnit[i];
   }

   public static void GetYCordRangeLabels(string[]ranges,Double rangeMax, Double rangeMin, ValueUnit unit)
   {
      string[] sUnit = { "kV", "V", "mV", "uV", "KA", "A" ,"mA" ,"uA" ,"C" ,""};
      int index = (int)unit;
      if (-1 == index)//No unit
      {
         index = sUnit.Length - 1;
      }
      ranges[0] = rangeMax.ToString() + sUnit[index];
      ranges[1] = rangeMin.ToString() + sUnit[index];
      ranges[2] = (rangeMax == -rangeMin) ? "0" : "";
   }

   public static void GetYCordRangeLabels(string[]ranges,Double rangeMax, Double rangeMin, FrequencyUnit unit)
   {
      string[] sUnit = { "Hz", "k", "M", "" };
      int index = (int)unit;
      if (-1 == index)//No unit
      {
         index = sUnit.Length - 1;
      }
      ranges[0] = rangeMax.ToString() + sUnit[index];
      ranges[1] = rangeMin.ToString() + sUnit[index];
      ranges[2] = (rangeMax == -rangeMin) ? "0" : "";
   }
}
public class PerformanceCounter
{
   public long StartTime;  // start time, in cpu ticks
   public long StopTime;   // stop time, in cpu ticks
   public long CPUFreq;    // CPU frequency, ticks per second

   public PerformanceCounter()
   {
      if (QueryPerformanceFrequency(out CPUFreq) == false)
      {
         throw new Win32Exception(); // high-performance counter not supported
      }
   }
   public void Start()
   {
      QueryPerformanceCounter(out StartTime);
   }
   public void Stop()
   {
      QueryPerformanceCounter(out StopTime);
   }
   public double Duration      // Returns the duration of the timer (in seconds)
   {
      get { return (double)(StopTime - StartTime) / (double)CPUFreq; }
   }

   [SuppressUnmanagedCodeSecurity]
   [DllImport("Kernel32.dll")]
   public static extern bool QueryPerformanceFrequency(out long freq);

   [SuppressUnmanagedCodeSecurity]
   [DllImport("Kernel32.dll")]
   public static extern bool QueryPerformanceCounter(out long count);
}