// Author: Tamas Borsanyi aka Tomixworks - tomix89@centrum.sk
// Program : visual c# express 2010

#define _use_thread

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.Threading;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

public enum Mode_Coupling { AC, DC }

public struct Pos_oldsize // it changes only if manually the time is set (not if time_index is chnged)
{
    public int X; // time level for pulse width low
    public int Y; // time level for pulse width high
}

public enum Uart_error { StartBit, StopBit, Parity, None };


public struct Uart_transfers // it changes only if manually the time is set (not if time_index is chnged)
{
    public int startpos; // time level for pulse width low
    public int endpos; // time level for pulse width high
    public short value; // it can be a 9 bit data, if parity + 8 bits set
    public Uart_error errors;
    public bool drawThis;
}

namespace Logger_visualiser
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        //---------------------------------------------------------------------------------
        static int datalen = 4;

        byte[] data1 = { 0, 0, 0, 0 };
        byte[] data2 = { 0, 0, 0, 0 };
        byte[] data3 = { 0, 0, 0, 0 };
        byte[] data4 = { 0, 0, 0, 0 };

        int ampli1, ampli2, ampli3;
        int file_ampli_offset1, file_ampli_offset2, file_ampli_offset3;
        int bar_ampli_offset1 = 0, bar_ampli_offset2 = 0, bar_ampli_offset3 = 0;
        Mode_Coupling coupling1, coupling2, coupling3;
        int deci_factor;

        double[] AmpLabels_d = { 50e-3, 100e-3, 200e-3, 500e-3, 1, 2, 5 }; // per dividion
        string[] AmpLabels = { " 50mV", "100mV", "200mV", "500mV", "  1V ", "  2V ", "  5V " };

        bool fully_loaded = false;

        int postTrigLen;

        // real jump length depends on the 1/coeff -> dalenegth / picture width
        int jmp_portion = 1000; //ppm (/1000000) of data that is not taken.  10'000 = 1%  100'000 = 10%
        int rand_portion = 12; // percent (/100)

        // const double digi_mul_const = 9.8;
        // const double digi_add_const = 8.0;

        bool resizing = false;
        Pos_oldsize oldsize;

        bool makeNewEnvelope = true;
        Point[] curveCH1 = new Point[16]; // pointst of chanels
        Point[] curveCH2 = new Point[16]; // pointst of chanels
        Point[] curveCH3 = new Point[16]; // pointst of chanels

        Point[][] digiCurve = new Point[16][];

        const int max_num_uart_transfer = 25;
        Uart_transfers[][] UART_data = new Uart_transfers[2][]; // no more than "max_num_uart_transfer" are shown

        double processA = 0;
        double processB = 0;

        int Lcursor;
        int Rcursor;

        double zoomFrom = 0;
        double zoomTo = datalen;

        int origMouseDragX;

        double coeff;
        //---------------------------------------------------------------------------------
        private void Form1_Load(object sender, EventArgs e)
        {
            int n;
            Random rnd = new Random();

            Array.Resize(ref curveCH1, pictureBox2.Size.Width * 2);
            Array.Resize(ref curveCH2, pictureBox2.Size.Width * 2);
            Array.Resize(ref curveCH3, pictureBox2.Size.Width * 2);

            for (n = 0; n < 16; n++)
            {
                digiCurve[n] = new Point[pictureBox2.Width];
            }



            coeff = (double)(zoomTo - zoomFrom) / pictureBox2.Width;

            Lcursor = 0;
            Rcursor = pictureBox2.Width-1;


            toolCursor_Click(null, null);
            toolStripComboRender.SelectedIndex = 1;

            toolStripComboRxChan.SelectedIndex = 0;
            toolStripComboTxChan.SelectedIndex = 0;
            toolStripComboBaud.SelectedIndex = 7;
            toolStripComboParity.SelectedIndex = 0;
            toolStripComboNbits.SelectedIndex = 3;

            UART_data[0] = new Uart_transfers[max_num_uart_transfer];
            UART_data[1] = new Uart_transfers[max_num_uart_transfer];

            openFileDialog1.Filter = "Logger file(*.lgf)|*.lgf|All files (*.*)|*.*";
            openFileDialog1.FileName = "";
            saveFileDialog1.Filter = "Image file(*.png)|*.png|All files (*.*)|*.*";
            saveFileDialog1.FileName = "PrintScreen";
        }
        //---------------------------------------------------------------------------------
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {


            SolidBrush brush = new SolidBrush(Color.Gray);
            Rectangle rect = new Rectangle(0, 0, 0, 0);

            rect.Width = (int)(pictureBox1.Width * (zoomFrom / (double)datalen));
            rect.Height = 6;
            rect.X = 0;
            rect.Y = (int)((pictureBox1.Height - rect.Height) * 0.5);

            e.Graphics.FillRectangle(brush, rect);
            //------

            rect.Width = pictureBox1.Width;
            rect.Height = 6;
            rect.X = (int)(pictureBox1.Width * ((zoomTo - zoomFrom) / (double)datalen));
            rect.Y = (int)((pictureBox1.Height - rect.Height) * 0.5);
            e.Graphics.FillRectangle(brush, rect);
            //----active potrion-------

            rect.Width = (int)(pictureBox1.Width * ((zoomTo - zoomFrom) / (double)datalen));
            rect.Height = 6;
            rect.X = (int)(pictureBox1.Width * (zoomFrom / (double)datalen));
            rect.Y = (int)((pictureBox1.Height - rect.Height) * 0.5);

            if (rect.Width < 1) // always show at least minimum position
                rect.Width = 1;

            brush.Color = Color.Lime;
            e.Graphics.FillRectangle(brush, rect);

            //-----trigpos---------
            rect.Width = 3;
            rect.Height = 24;
            rect.X = (int)(pictureBox1.Width * ((datalen - postTrigLen) / (double)datalen) - 1);
            rect.Y = (int)((pictureBox1.Height - rect.Height) * 0.5);

            brush.Color = Color.Yellow;
            e.Graphics.FillRectangle(brush, rect);




            //   double coeff = (double)datalen / pictureBox2.Width;
            double step = (int)(coeff * (jmp_portion / 1000000.0));

            label3.Text = "step: " + step;
            label4.Text = "random: " + (int)(((step * rand_portion)) / 100.0);

        }
        //---------------------------------------------------------------------------------
        private void decodeUART(string direction, bool is_ttl)
        {
            double samprate = 48e6 / 9.0 / deci_factor;
            int baud = Convert.ToInt32(toolStripComboBaud.Text);
            double dots_per_bit = samprate / baud;
            byte numBits = Convert.ToByte(toolStripComboNbits.Text);
            int curr_sample, dly_sample;

            byte TxRx = 99;

            byte chanel_mask;

            if (toolStripComboParity.SelectedIndex > 0) // parity is an extra bit
                numBits++;
            int n;

            int samp_cntr = (int)(zoomFrom + 1); // global sample counter
            bool first_fall = false; // find first faling AKA start bit



            if (direction == "rx")
            {
                chanel_mask = (byte)(1 << ((toolStripComboRxChan.SelectedIndex) - 1));
                TxRx = 1;
            }
            else if (direction == "tx")
            {
                chanel_mask = (byte)(1 << ((toolStripComboTxChan.SelectedIndex) - 1));
                TxRx = 0;
            }
            else
                chanel_mask = 0;



            byte num_of_transfrs = 0; // no more than x are shown

            byte current_bit = 0;


            for (n = 0; n < UART_data[TxRx].Length; n++) // clearing previous session
                {
                    UART_data[TxRx][n].drawThis = false;
                    UART_data[TxRx][n].errors = Uart_error.None;
                    UART_data[TxRx][n].value = 0x00;
                }



 
                //------------ finding start bit------------------------------------------------
                while ((samp_cntr < (zoomTo - numBits * dots_per_bit)) && (num_of_transfrs < max_num_uart_transfer)) // if the lengt is not enough to be a valid UART transmisson stop decoding
                {

                    first_fall = false;

                    while ((first_fall == false) && (samp_cntr < zoomTo))
                    {

                        if (is_ttl)
                        {
                            curr_sample = data4[samp_cntr] & chanel_mask;
                            dly_sample = data4[samp_cntr-1] & chanel_mask;
                        }
                        else
                        {
                            curr_sample = (~(data4[samp_cntr])) & chanel_mask;
                            dly_sample = (~(data4[samp_cntr - 1])) & chanel_mask;
                        }

                        if ((curr_sample == 0) && (dly_sample >= 1)) //edge detect
                            {
                                first_fall = true;
                                break;
                            }

                        samp_cntr = samp_cntr + 1;
                    }

                    if (first_fall == false) // if no edge was detected, return without values
                        return;



                    UART_data[TxRx][num_of_transfrs].startpos = samp_cntr;
                    UART_data[TxRx][num_of_transfrs].drawThis = true;



                    if (is_ttl)
                        curr_sample = data4[(int)(samp_cntr + dots_per_bit * 0.5)] & chanel_mask;
                    else
                        curr_sample = (~(data4[(int)(samp_cntr + dots_per_bit * 0.5)])) & chanel_mask;


                    //------ start bit is checked here ----
                    if (curr_sample == 0) // startbit ok
                    {
                    }
                    else // false startbit
                    {
                        UART_data[TxRx][num_of_transfrs].endpos = (int)(samp_cntr + dots_per_bit * 0.5);
                        UART_data[TxRx][num_of_transfrs].errors = Uart_error.StartBit;
                        samp_cntr = (int)(samp_cntr + dots_per_bit * (1 + 1 + numBits));
                        continue;
                    }


                    //-- data length is checked there

                    // becouse after last transmission could be enough space to fit transfer in
                    // but the last transfer could be out of sampling area
                    if ((samp_cntr + dots_per_bit * (0.5 + numBits + 1)) > zoomTo)
                    {
                        UART_data[TxRx][num_of_transfrs].drawThis = false;
                        return;
                    }



                    current_bit = 0;

                    //------- bits --------------------------
                    while (current_bit < numBits)
                    {

                        if (is_ttl)
                            curr_sample = data4[(int)(samp_cntr + dots_per_bit * (1.5 + current_bit))] & chanel_mask;
                        else
                            curr_sample = (~(data4[(int)(samp_cntr + dots_per_bit * (1.5 + current_bit))])) & chanel_mask;


                        if (curr_sample > 0) //if there is data
                        {
                            UART_data[TxRx][num_of_transfrs].value |= (short)(1 << current_bit); // set it if 1 on the data
                        }
                        current_bit++;

                    }


                    UART_data[TxRx][num_of_transfrs].endpos = (int)(samp_cntr + dots_per_bit * (1.8 + numBits)); // becouse the end of the loop ends int the half of the last bit

                    // int pos = (int)(samp_cntr + dots_per_bit * (1.5 + numBits));
                    // int val = data4[(int)(samp_cntr + dots_per_bit * (1.5 + numBits))] & chanel_mask;


                    if (is_ttl)
                        curr_sample = data4[(int)(samp_cntr + dots_per_bit * (1.5 + numBits))] & chanel_mask;
                    else
                        curr_sample = (~(data4[(int)(samp_cntr + dots_per_bit * (1.5 + numBits))])) & chanel_mask;

                    // stopbit check
                    if (curr_sample >= 1) // stopbit ok // masked value can be > 1
                    {
                    }
                    else // stopbit error
                    {
                        UART_data[TxRx][num_of_transfrs].errors = Uart_error.StopBit;
                        samp_cntr = (int)(samp_cntr + dots_per_bit * (1.8 + numBits));
                        //continue;
                    }




                    // if parity is enabled  // parity check 
                    if (toolStripComboParity.SelectedIndex > 0)
                    {
                        byte par_cntd = 0;

                        // parity is the highest bit !!!!!!!!!!!!!!!!!!!
                        for (n = 0; n < numBits; n++)
                        {
                            par_cntd += (byte)((UART_data[TxRx][num_of_transfrs].value >> n) & 0x01); // data bits except parity
                        }

                        if ((toolStripComboParity.SelectedIndex & 0x01) == (par_cntd & 0x01))
                        {
                            UART_data[TxRx][num_of_transfrs].errors = Uart_error.Parity;
                        }
                    }



                    num_of_transfrs++;
                    samp_cntr = (int)(samp_cntr + dots_per_bit * (1.8 + numBits));
                }
            
           
        }
        //---------------------------------------------------------------------------------
        private void pictureBox2_Paint(object sender, PaintEventArgs e)
        {
            int n, from = 0, to = -1;

            Point[] shiftedCurve = new Point[Math.Max(curveCH3.Length, Math.Max(curveCH1.Length, curveCH2.Length))];

            Pen pen = new Pen(Color.DimGray);
            SolidBrush brush = new SolidBrush(Color.Lime);
            TextureBrush Tbrush = new TextureBrush(Properties.Resources.multidata);

            //   Array.Resize(ref curve, pictureBox2.Size.Width * 2);


            double Canvas_Width_param1 = pictureBox2.Width / 10.0;
            int Canvas_Height_param1 = pictureBox2.Height + 1;

            int Canvas_Width_param2 = pictureBox2.Width + 1;
            double Canvas_Height_param2 = pictureBox2.Height / 8.0;

            // double coeff = (double)datalen / pictureBox2.Width;


            Rectangle[] grid = new Rectangle[]  
            {
                // x,y,width height   // float is needed for a better accuracy of lines
            new Rectangle(-1,                             -1, (int)Canvas_Width_param1, Canvas_Height_param1),   
            new Rectangle((int)(Canvas_Width_param1*2.0), -1, (int)Canvas_Width_param1, Canvas_Height_param1), 
            new Rectangle((int)(Canvas_Width_param1*4.0), -1, (int)Canvas_Width_param1, Canvas_Height_param1), 
            new Rectangle((int)(Canvas_Width_param1*6.0), -1, (int)Canvas_Width_param1, Canvas_Height_param1), 
            new Rectangle((int)(Canvas_Width_param1*8.0), -1, (int)Canvas_Width_param1, Canvas_Height_param1), 

            new Rectangle(-1, -1, Canvas_Width_param2, (int)Canvas_Height_param2), 
            new Rectangle(-1, (int)(Canvas_Height_param2*2.0), Canvas_Width_param2, (int)Canvas_Height_param2), 
            new Rectangle(-1, (int)(Canvas_Height_param2*4.0), Canvas_Width_param2, (int)Canvas_Height_param2), 
            new Rectangle(-1, (int)(Canvas_Height_param2*6.0), Canvas_Width_param2, (int)Canvas_Height_param2), 
            };

            e.Graphics.DrawRectangles(pen, grid);

            DateTime begin = DateTime.Now;

            if (makeNewEnvelope)
            {
                if (rxToolStripMenuItem.Checked == true)
                {
                    decodeUART("rx", RxpolarityTTLToolStrip.Checked);
                }

                if (txToolStripMenuItem.Checked == true)
                {
                    decodeUART("tx", TxpolarityTTLToolStrip.Checked);
                }


                if (checkBoxD03.Checked)
                {
                    labelWich.Text = "Digi0";
                    labelWich.Refresh();
                    makeEnvelopeCHx(0xD0);
                    labelWich.Text = "Digi1";
                    labelWich.Refresh();
                    makeEnvelopeCHx(0xD1);
                    labelWich.Text = "Digi2";
                    labelWich.Refresh();
                    makeEnvelopeCHx(0xD2);
                    labelWich.Text = "Digi3";
                    labelWich.Refresh();
                    makeEnvelopeCHx(0xD3);
                }

                if (checkBoxD47.Checked)
                {
                    labelWich.Text = "Digi4";
                    labelWich.Refresh();
                    makeEnvelopeCHx(0xD4);
                    labelWich.Text = "Digi5";
                    labelWich.Refresh();
                    makeEnvelopeCHx(0xD5);
                    labelWich.Text = "Digi6";
                    labelWich.Refresh();
                    makeEnvelopeCHx(0xD6);
                    labelWich.Text = "Digi7";
                    labelWich.Refresh();
                    makeEnvelopeCHx(0xD7);
                }


                if (labelCH1.BackColor != Color.Transparent)
                {
                    labelWich.Text = "CH 1";
                    labelWich.Refresh();
                    makeEnvelopeCHx(1);
                }
                if (labelCH2.BackColor != Color.Transparent)
                {
                    labelWich.Text = "CH 2";
                    labelWich.Refresh();
                    makeEnvelopeCHx(2);
                }

                if (labelCH3.BackColor != Color.Transparent)
                {
                    labelWich.Text = "CH 3";
                    labelWich.Refresh();
                    makeEnvelopeCHx(3);
                }


                makeNewEnvelope = false;
                labelWich.Text = "";
            }


            if (checkBoxD03.Checked)
            {
                from = 0;
                to = 3;
            }
            if (checkBoxD47.Checked)
            {
                from = 4;
                to = 7;
            }
            if ((checkBoxD03.Checked) && (checkBoxD47.Checked))
            {
                from = 0;
                to = 7;
            }


            int buff_first;
            int buff_last;

            for (n = from; n <= to; n++)
            {

                buff_first = digiCurve[n][0].Y;
                buff_last = digiCurve[n][digiCurve[1].Length - 1].Y;

                // first and last of LOG 1 highlight is in 0 to prevebnt artefacts on the screen, and highlight 0
                digiCurve[n][0].Y = (int)(pictureBox2.Size.Height - 3 - ((pictureBox2.Size.Height / 8.0) * n));
                digiCurve[n][digiCurve[1].Length - 1].Y = (int)(pictureBox2.Size.Height - 3 - ((pictureBox2.Size.Height / 8.0) * n));

                brush.Color = Color.FromArgb(150, 0, 0, 200);
                e.Graphics.FillPolygon(brush, digiCurve[n]);


                digiCurve[8 + n][0].Y = (int)(pictureBox2.Size.Height - 3 - (pictureBox2.Size.Height / 8.0) * n);
                digiCurve[8 + n][digiCurve[1].Length - 1].Y = (int)(pictureBox2.Size.Height - 3 - (pictureBox2.Size.Height / 8.0) * n);

                // overlapping data texture
                digiCurve[n][0].Y = buff_first;
                digiCurve[n][digiCurve[1].Length - 1].Y = buff_last;

                e.Graphics.FillPolygon(Tbrush, digiCurve[8 + n]);


                // finally on top of all draw main curve
                pen.Color = Color.Cyan;
                e.Graphics.DrawLines(pen, digiCurve[n]);
            }



            if (labelCH1.BackColor != Color.Transparent)
            {
                pen.Color = Color.Fuchsia;
                brush.Color = Color.Fuchsia;

                for (n = 0; n < curveCH1.Length; n++)
                {
                    shiftedCurve[n].Y = (int)(curveCH1[n].Y - bar_ampli_offset1 * pictureBox2.Size.Height / 60.0);
                    shiftedCurve[n].X = curveCH1[n].X;
                }


                e.Graphics.FillPolygon(brush, shiftedCurve);
                e.Graphics.DrawLines(pen, shiftedCurve);
            }

            if (labelCH2.BackColor != Color.Transparent)
            {
                pen.Color = Color.Lime;
                brush.Color = Color.Lime;

                for (n = 0; n < curveCH2.Length; n++)
                {
                    shiftedCurve[n].Y = (int)(curveCH2[n].Y - bar_ampli_offset2 * pictureBox2.Size.Height / 60.0);
                    shiftedCurve[n].X = curveCH2[n].X;
                }

                e.Graphics.FillPolygon(brush, shiftedCurve);
                e.Graphics.DrawLines(pen, shiftedCurve);
            }
            if (labelCH3.BackColor != Color.Transparent)
            {
                pen.Color = Color.Yellow;
                brush.Color = Color.Yellow;

                for (n = 0; n < curveCH3.Length; n++)
                {
                    shiftedCurve[n].Y = (int)(curveCH3[n].Y - bar_ampli_offset3 * pictureBox2.Size.Height / 60.0);
                    shiftedCurve[n].X = curveCH3[n].X;
                }

                e.Graphics.FillPolygon(brush, shiftedCurve);
                e.Graphics.DrawLines(pen, shiftedCurve);
            }

            bool zoom_req = false;

            //-------uart---Rx-draw---------------------------
            if (rxToolStripMenuItem.Checked == true)
            {
                double uart_dec_chan = (toolStripComboRxChan.SelectedIndex - 1.0) / 4.0;

                if (((uart_dec_chan >=1) && (checkBoxD47.Checked)) || ((uart_dec_chan < 1) && (checkBoxD03.Checked)))
                    zoom_req |= pictureBox2_UART_draw(e, 1);
            }

            //-------uart---Tx-draw---------------------------
            if (txToolStripMenuItem.Checked == true)
            {
                double uart_dec_chan = (toolStripComboTxChan.SelectedIndex-1.0) / 4.0;

                if (((uart_dec_chan >= 1) && (checkBoxD47.Checked)) || ((uart_dec_chan < 1) && (checkBoxD03.Checked)))
                zoom_req |= pictureBox2_UART_draw(e, 0);
            }

            if (zoom_req)
            {
                labelUART.Text = "Change zoom to see (all) decoded UART";
            }
            else
            {
                labelUART.Text = "";
            }

            pen.Color = Color.Red;
            e.Graphics.DrawLine(pen, Lcursor - 1, 0, Lcursor - 1, pictureBox2.Height);
            e.Graphics.DrawLine(pen, Lcursor, 0, Lcursor, pictureBox2.Height);
            e.Graphics.DrawLine(pen, Rcursor, 0, Rcursor, pictureBox2.Height);
            e.Graphics.DrawLine(pen, Rcursor + 1, 0, Rcursor + 1, pictureBox2.Height);


            pen.Color = Color.Yellow;

            int trigpos_screen = (int)((datalen - postTrigLen - zoomFrom) / coeff);

            e.Graphics.DrawLine(pen, trigpos_screen, 0, trigpos_screen, pictureBox2.Height);
            e.Graphics.DrawLine(pen, trigpos_screen + 1, 0, trigpos_screen + 1, pictureBox2.Height);


            DateTime ending = DateTime.Now;


            label1.Text = "coeff: " + coeff;
            label2.Text = "time: " + (ending - begin).TotalMilliseconds;
        }
        //--------------------------------------------------------------------------------
        private bool pictureBox2_UART_draw(PaintEventArgs e, byte TxRx)
        {
            int n;
            bool zoom_req = false; 

            Pen pen = new Pen(Color.DimGray);
            SolidBrush brush = new SolidBrush(Color.Lime);
          
             int draw_chanel_offset=99;


             if (TxRx == 0)
                 draw_chanel_offset = toolStripComboTxChan.SelectedIndex - 1;
             else if (TxRx == 1)
                 draw_chanel_offset = toolStripComboRxChan.SelectedIndex - 1;



                pen.Color = Color.Lime;
                brush.Color = Color.FromArgb(210, 240, 250, 240);
                Font UARTFont = new Font("Courier New", 11, FontStyle.Bold);

                Point[] Uart_box = new Point[4];

                double A, B;

                A = ((UART_data[TxRx][0].startpos - zoomFrom) / coeff);
                B = ((UART_data[TxRx][0].endpos - zoomFrom) / coeff);

                if ((B - A) > 39) // if the width of the transfer is smaller than x pixels on the screen
                {


                    for (n = 0; n < max_num_uart_transfer; n++)
                    {
                        if (UART_data[TxRx][n].drawThis != true)  // draw only valid items
                            continue;

                        A = ((UART_data[TxRx][n].startpos - zoomFrom) / coeff);
                        B = ((UART_data[TxRx][n].endpos - zoomFrom) / coeff);



                        Uart_box[0].X = (int)((UART_data[TxRx][n].startpos - zoomFrom) / coeff);
                        Uart_box[0].Y = (int)(pictureBox2.Size.Height - pictureBox2.Size.Height / 42.0
                                                - (pictureBox2.Size.Height / 8.0) * draw_chanel_offset);

                        Uart_box[1].X = (int)((UART_data[TxRx][n].endpos - zoomFrom) / coeff) - 1;
                        Uart_box[1].Y = (int)(pictureBox2.Size.Height - pictureBox2.Size.Height / 42.0
                                                - (pictureBox2.Size.Height / 8.0) * draw_chanel_offset);

                        Uart_box[2].X = (int)((UART_data[TxRx][n].endpos - zoomFrom) / coeff) - 1;
                        Uart_box[2].Y = (int)(pictureBox2.Size.Height - pictureBox2.Size.Height / 11.6
                            - (pictureBox2.Size.Height / 8.0) * draw_chanel_offset);

                        Uart_box[3].X = (int)((UART_data[TxRx][n].startpos - zoomFrom) / coeff);
                        Uart_box[3].Y = (int)(pictureBox2.Size.Height - pictureBox2.Size.Height / 11.6
                            - (pictureBox2.Size.Height / 8.0) * draw_chanel_offset);


                        if (UART_data[TxRx][n].errors == Uart_error.None)
                        {
                            brush.Color = Color.FromArgb(210, 240, 250, 240);
                            e.Graphics.FillPolygon(brush, Uart_box);

                            e.Graphics.DrawString("0x" + ((byte)UART_data[TxRx][n].value).ToString("X2"), // necessery to supress parity
                           UARTFont, Brushes.Black,
                           new Point((int)((A + B) / 2.0) - 24, (int)((Uart_box[3].Y + Uart_box[1].Y) / 2.0) - 10));

                        }
                        else
                        {
                            brush.Color = Color.FromArgb(210, 240, 50, 50);
                            e.Graphics.FillPolygon(brush, Uart_box);

                            switch (UART_data[TxRx][n].errors)
                            { 
                                case Uart_error.Parity:
                                    e.Graphics.DrawString("Par", UARTFont, Brushes.Black,
                                      new Point((int)((A + B) / 2.0) - 24, (int)((Uart_box[3].Y + Uart_box[1].Y) / 2.0) - 10));
                                    break;

                                case Uart_error.StartBit:
                                    e.Graphics.DrawString("Strt", UARTFont, Brushes.Black,
                                     new Point((int)((A + B) / 2.0) - 24, (int)((Uart_box[3].Y + Uart_box[1].Y) / 2.0) - 10));
                                    break;

                                case Uart_error.StopBit:
                                    e.Graphics.DrawString("Stop", UARTFont, Brushes.Black,
                                     new Point((int)((A + B) / 2.0) - 24, (int)((Uart_box[3].Y + Uart_box[1].Y) / 2.0) - 10));
                                    break;
                            }

                          
                        }


                       


                        //separator line
                        pen.Color = Color.Black;
                        e.Graphics.DrawLine(pen, Uart_box[1], Uart_box[2]);


                       
                    }
                }
                else
                {
                    zoom_req = true;
                }

                return zoom_req;
        }
    //----------------------------------------------------------------------------------------------
        private void makeEnvelopeCHx(byte chanel)
        {
            int n;
            Point[] envelopeP = new Point[pictureBox2.Width]; // pointst of chanels
            Point[] envelopeM = new Point[pictureBox2.Width]; // pointst of chanels

#if _use_thread

            Thread elso = new Thread(() => getNegEnvelopeE(envelopeM, chanel));
            Thread masik = new Thread(() => getPosEnvelopeE(envelopeP, chanel));

            processA = 0;
            processB = 0;

            elso.Start();
            masik.Start();

            while (elso.IsAlive | masik.IsAlive)
            {
                progressBar1.Value = (int)(Math.Min(processA, processB) * 100);
            }

            progressBar1.Value = 100;

#else   
            getNegEnvelopeE(envelopeM, chanel);
            getPosEnvelopeE(envelopeP, chanel);
#endif

            switch (chanel)
            {

                case 1:

                    //creating big envelope for closed curve
                    Array.Copy(envelopeP, curveCH1, pictureBox2.Size.Width);

                    for (n = 0; n < pictureBox2.Size.Width; n++)
                    {
                        curveCH1[n + pictureBox2.Size.Width] = envelopeM[pictureBox2.Size.Width - n - 1];
                    }

                    break;




                case 2:

                    //creating big envelope for closed curve
                    Array.Copy(envelopeP, curveCH2, pictureBox2.Size.Width);

                    for (n = 0; n < pictureBox2.Size.Width; n++)
                    {
                        curveCH2[n + pictureBox2.Size.Width] = envelopeM[pictureBox2.Size.Width - n - 1];
                    }

                    break;




                case 3:

                    //creating big envelope for closed curve
                    Array.Copy(envelopeP, curveCH3, pictureBox2.Size.Width);

                    for (n = 0; n < pictureBox2.Size.Width; n++)
                    {
                        curveCH3[n + pictureBox2.Size.Width] = envelopeM[pictureBox2.Size.Width - n - 1];
                    }

                    break;
            }

            if ((chanel >= 0xD0) && (chanel <= 0xD7))
            {
                chanel = (byte)(chanel - 0xD0);

                for (n = 0; n < pictureBox2.Size.Width; n++)
                {

                    digiCurve[chanel][n].X = envelopeP[n].X;
                    digiCurve[chanel][n].Y = (int)(pictureBox2.Size.Height -
                       (envelopeP[n].Y * (pictureBox2.Size.Height / 9.8) + 3 + (pictureBox2.Size.Height / 8.0) * chanel));


                    digiCurve[8 + chanel][n].X = envelopeM[n].X;
                    digiCurve[8 + chanel][n].Y = (int)(pictureBox2.Size.Height -
                       ((envelopeP[n].Y - envelopeM[n].Y) * (pictureBox2.Size.Height / 9.8)
                       + 3 + (pictureBox2.Size.Height / 8.0) * chanel));

                }

            }
        }
        //--------------------------------------------------------------------------------
        private void getPosEnvelopeE(Point[] envelopeP, byte chanel)
        {
            int n, cntr, currindex;
            double buff, m;
            double from, to, step;
            // double coeff = (double)datalen / pictureBox2.Width;
            Random rnd = new Random(555);

            //--envelope plus
            cntr = 0;
            for (n = 0; n < pictureBox2.Size.Width; n++)
            {
                from = (n * (coeff)) + zoomFrom;
                to = (n * (coeff)) + coeff + zoomFrom;

                //  from = Math.Round(from);
                // to = Math.Round(to);
                step = (coeff * (jmp_portion / 1000000.0));

                buff = -1;

                if ((to - from) > 1)
                {
                    for (m = from; m < to; m += step)
                    {

                        currindex = (int)(m + (rnd.Next((int)(-step * rand_portion), (int)(step * rand_portion)) / 100.0));
                        //saturating
                        if (currindex < 0)
                            currindex = 0;
                        if (currindex >= datalen)
                            currindex = datalen - 1;


                        /*   if (buff < data1[currindex])
                               buff = data1[currindex];*/

                        if (buff < getPointsFromData(chanel, currindex))
                            buff = getPointsFromData(chanel, currindex);

                    }
                }
                else
                {
                    // buff = data1[(int)from]; // becouse probaby the same data will be all ower the screen  125.000058
                    buff = getPointsFromData(chanel, (int)from);

                }

                processA = (double)n / (pictureBox1.Size.Width - 1);


                envelopeP[cntr].X = (int)((cntr + 1));
                if (chanel >= 0xD0)
                {
                    //saving only the signal, not with offset, becouse we need create differtnial for changing signal
                    envelopeP[cntr++].Y = (int)buff;


                }
                else
                {
                    envelopeP[cntr++].Y = (int)((pictureBox2.Size.Height / 2.0) + // positioning to the half of the screen
                                         (pictureBox2.Size.Height / 256.0) * //  amplitude compensation of the screen
                                         (buff - 128)); // data compensated to sign
                    //                                                   - flip screen + center + sweep
                }
            }
        }
        //--------------------------------------------------------------------------------
        private byte getPointsFromData(byte chanel, int index)
        {
            switch (chanel)
            {
                case 1: return data1[index];
                case 2: return data2[index];
                case 3: return data3[index];

                case 0xD0: return (byte)(data4[index] & 0x01);
                case 0xD1: return (byte)((data4[index] & 0x02) >> 1);
                case 0xD2: return (byte)((data4[index] & 0x04) >> 2);
                case 0xD3: return (byte)((data4[index] & 0x08) >> 3);
                case 0xD4: return (byte)((data4[index] & 0x10) >> 4);
                case 0xD5: return (byte)((data4[index] & 0x20) >> 5);
                case 0xD6: return (byte)((data4[index] & 0x40) >> 6);
                case 0xD7: return (byte)((data4[index] & 0x80) >> 7);

                default: return 0;
            }
        }
        //--------------------------------------------------------------------------------
        private void getNegEnvelopeE(Point[] envelopeM, byte chanel)
        {
            int n, cntr, currindex;
            double m, from, to, step, buff;
            // double coeff = (double)datalen / pictureBox2.Width;
            Random rnd = new Random(5);


            //--envelope min
            cntr = 0;
            for (n = 0; n < pictureBox2.Size.Width; n++)
            {
                from = (n * (coeff)) + zoomFrom;
                to = (n * (coeff)) + coeff + zoomFrom;



                //  from = Math.Round(from);
                //  to = Math.Round(to);
                step = (coeff * (jmp_portion / 1000000.0));

                buff = 1000;


                if ((to - from) > 1)
                {
                    for (m = from; m < to; m += step)
                    {
                        currindex = (int)(m + (rnd.Next((int)(-step * rand_portion), (int)(step * rand_portion)) / 100.0));
                        //saturating
                        if (currindex < 0)
                            currindex = 0;
                        if (currindex >= datalen)
                            currindex = datalen - 1;


                        /*  if (buff > data1[currindex])
                              buff = data1[currindex];*/

                        if (buff > getPointsFromData(chanel, currindex))
                            buff = getPointsFromData(chanel, currindex);

                    }
                }
                else
                {
                    // buff = data1[(int)from]; // becouse probaby the same data will be all ower the screen  125.000058
                    buff = getPointsFromData(chanel, (int)from);

                }

                processB = (double)n / (pictureBox1.Size.Width - 1);

                envelopeM[cntr].X = (int)((cntr + 1));

                if (chanel >= 0xD0)
                {
                    envelopeM[cntr++].Y = (int)buff;
                }
                else
                {
                    envelopeM[cntr++].Y = (int)((pictureBox2.Size.Height / 2.0) + // positioning to the half of the screen
                                         (pictureBox2.Size.Height / 256.0) * //  amplitude compensation of the screen
                                         (buff - 128)); // data compensated to sign
                    //                                                   - flip screen + center + sweep
                }



            }
        }
        //--------------------------------------------------------------------------------
        // it is neccary becouse:
        // resize wont fire to maximize
        // resizeBegin and resizeEnd fires for moving too
        //and sizechanged fires before resizeEnd, so the flag has no effect on resizing 
        private void Form1_ResizeBegin(object sender, EventArgs e)
        {
            resizing = true;
        }
        //--------------------------------------------------------------------------------
        private void Form1_ResizeEnd(object sender, EventArgs e)
        {
            resizing = false;

            //check size if it changed, fire size changed

            if ((oldsize.X != this.Width) || (oldsize.Y != this.Height))
            {

                oldsize.X = this.Width;
                oldsize.Y = this.Height;

                Form1_SizeChanged(null, null);
            }

        }
        //--------------------------------------------------------------------------------
        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            if (pictureBox2.Size.Width > 10)
            {

                double KurzorPomer = ((pictureBox2.Size.Width + 2) * 2.0) / (curveCH1.Length);
                int n;

                if (resizing == false)
                {
                    Lcursor = (int)(Lcursor * KurzorPomer);
                    Rcursor = (int)(Rcursor * KurzorPomer);

                    makeNewEnvelope = true;
                    coeff = (double)(zoomTo - zoomFrom) / pictureBox2.Size.Width;
                    Array.Resize(ref curveCH1, pictureBox2.Size.Width * 2);
                    Array.Resize(ref curveCH2, pictureBox2.Size.Width * 2);
                    Array.Resize(ref curveCH3, pictureBox2.Size.Width * 2);


                    for (n = 0; n < 16; n++)
                    {
                        Array.Resize(ref digiCurve[n], pictureBox2.Width);
                    }



                    pictureBox1.Refresh();
                    pictureBox2.Refresh();
                    pictureBox3.Refresh();

                    label5.Text = "" + pictureBox2.Width;
                }
            }
        }
        //--------------------------------------------------------------------------------
        private void updateCursorLabelL()
        {

            if (panel2.BackColor == Color.Fuchsia)
            {
                byte currentSampleR = data1[(int)(zoomFrom + (Rcursor * coeff))];
                byte currentSampleL = data1[(int)(zoomFrom + (Lcursor * coeff))];

                label9.Text = "cur.A: " + ((((168 - file_ampli_offset1) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli1]).ToScientific() + "V";

                label12.Text = (char)0x0394 + "U: " + (
                   ((((168 - file_ampli_offset1) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli1]) -
                   ((((168 - file_ampli_offset1) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli1])
                   ).ToScientific() + "V";
            
            }
            else if (panel2.BackColor == Color.Lime)
            {
                byte currentSampleR = data2[(int)(zoomFrom + (Rcursor * coeff))];
                byte currentSampleL = data2[(int)(zoomFrom + (Lcursor * coeff))];

                                                            // 336/256
                label9.Text = "cur.A: " + ((((168 - file_ampli_offset2) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli2]).ToScientific() + "V";

                label12.Text = (char)0x0394 + "U: " + (
                   ((((168 - file_ampli_offset2) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli2]) -
                   ((((168 - file_ampli_offset2) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli2])
                   ).ToScientific() + "V";
            
            }
            else if (panel2.BackColor == Color.Yellow)
            {
                byte currentSampleR = data3[(int)(zoomFrom + (Rcursor * coeff))];
                byte currentSampleL = data3[(int)(zoomFrom + (Lcursor * coeff))];

                label9.Text = "cur.A: " + ((((168 - file_ampli_offset3) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli3]).ToScientific() + "V";

                label12.Text = (char)0x0394 + "U: " + (
                   ((((168 - file_ampli_offset3) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli3]) -
                   ((((168 - file_ampli_offset3) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli3])
                   ).ToScientific() + "V";
            }
            else
            {
                label10.Text = "";
                label9.Text = "";
            }
                                        // number of sample                 // timestep
            label6.Text = "cur.A: " + ((zoomFrom + (Lcursor * coeff)) * deci_factor / (48.0e6 / 9.0)).ToScientific()+"s";

            // delta is shown only if both cursors are present
            if (label7.Text != "")
            {
                label11.Text = (char)0x0394 + "t :" +
                  (((zoomFrom + (Rcursor * coeff)) * deci_factor / (48.0e6 / 9.0)) -
                   ((zoomFrom + (Lcursor * coeff)) * deci_factor / (48.0e6 / 9.0))).ToScientific() + "s";
            }
        }
        //--------------------------------------------------------------------------------
        private void updateCursorLabelR()
        {

            if (panel2.BackColor == Color.Fuchsia)
            {
                byte currentSampleR = data1[(int)(zoomFrom + (Rcursor * coeff))];
                byte currentSampleL = data1[(int)(zoomFrom + (Lcursor * coeff))];

                label10.Text = "cur.B: " + ((((168 - file_ampli_offset1) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli1]).ToScientific() + "V";

                label12.Text = (char)0x0394 + "U: " + (
                    ((((168 - file_ampli_offset1) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli1]) -
                    ((((168 - file_ampli_offset1) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli1])
                    ).ToScientific() + "V";

            }
            else if (panel2.BackColor == Color.Lime)
            {
                byte currentSampleR = data2[(int)(zoomFrom + (Rcursor * coeff))];
                byte currentSampleL = data2[(int)(zoomFrom + (Lcursor * coeff))];


                // 336/256
                label10.Text = "cur.B: " + ((((168 - file_ampli_offset2) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli2]).ToScientific() + "V";

                label12.Text = (char)0x0394 + "U: " + (
                    ((((168 - file_ampli_offset2) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli2]) -
                    ((((168 - file_ampli_offset2) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli2])
                    ).ToScientific() + "V";
            }
            else if (panel2.BackColor == Color.Yellow)
            {
                byte currentSampleR = data3[(int)(zoomFrom + (Rcursor * coeff))];
                byte currentSampleL = data3[(int)(zoomFrom + (Lcursor * coeff))];

                label10.Text = "cur.B: " + ((((168 - file_ampli_offset3) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli3]).ToScientific() + "V";

                label12.Text = (char)0x0394 + "U: " + (
                    ((((168 - file_ampli_offset3) / 1.3125 - currentSampleL) / 255.0 * 8.0) * AmpLabels_d[ampli3]) -
                    ((((168 - file_ampli_offset3) / 1.3125 - currentSampleR) / 255.0 * 8.0) * AmpLabels_d[ampli3])
                    ).ToScientific() + "V";

            }
            else
            {
                label10.Text = "";
                label9.Text = "";
            }

            label7.Text = "cur.B: " + ((zoomFrom + (Rcursor * coeff)) * deci_factor / (48.0e6 / 9.0)).ToScientific() + "s";


            if (label6.Text != "")
            {
                label11.Text = (char)0x0394 + "t :" +
                   (((zoomFrom + (Rcursor * coeff)) * deci_factor / (48.0e6 / 9.0)) -
                    ((zoomFrom + (Lcursor * coeff)) * deci_factor / (48.0e6 / 9.0))).ToScientific() + "s";
            }
        }
        //--------------------------------------------------------------------------------
        private void pictureBox2_MouseClick(object sender, MouseEventArgs e)
        {

            if (toolCursor.Checked == true)
            {
                if (e.Button == MouseButtons.Left)
                {
                    Lcursor = e.X;
                    pictureBox2.Refresh(); // draw the cursor

                    updateCursorLabelL();

                }


                if (e.Button == MouseButtons.Right)
                {
                    Rcursor = e.X;
                    pictureBox2.Refresh(); // draw the cursor

                    updateCursorLabelR();
                }

                if (e.Button == MouseButtons.Middle)
                {
                    if (Lcursor > Rcursor)
                    {
                        int buff = Lcursor;
                        Lcursor = Rcursor;
                        Rcursor = buff;
                    }


                    //check new coeff size, if zoom will be bigger than 0.03x stop zooming
                    double coeffbuff = (double)((zoomTo - ((pictureBox2.Size.Width - Rcursor) * coeff))
                        - (zoomFrom + (Lcursor * coeff))) / pictureBox2.Size.Width;


                    // allowed if zoom is not at limit, or if zoom out is performed at any zoom level
                    if (coeffbuff > 0.03)
                    {
                        zoomFrom += (Lcursor * coeff);
                        zoomTo -= ((pictureBox2.Size.Width - Rcursor) * coeff);

                        coeff = coeffbuff;

                        Lcursor = 0;
                        Rcursor = pictureBox2.Size.Width - 1;

                        makeNewEnvelope = true;
                        pictureBox1.Refresh(); // draw the overall positin
                        pictureBox2.Refresh(); // draw the cursor

                        showDeltatime();
                    }
                    else
                    {
                        labelUART.Text = "Zoom at limit";
                    }
                }
            }

        }
        //--------------------------------------------------------------------------------
        private void pictureBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if (toolCursor.Checked == false)
            {
                if (e.Button == MouseButtons.Left)
                {
                    origMouseDragX = e.X;
                }
            }
        }
        //--------------------------------------------------------------------------------
        private void pictureBox2_MouseMove(object sender, MouseEventArgs e)
        {

            if (e.Button != MouseButtons.None)
            {
                if (toolCursor.Checked == true)
                {
                    if (e.Button == MouseButtons.Left)
                    {
                        Lcursor = e.X;
                        pictureBox2.Refresh(); // draw the cursor only if the mouse butten is being pushed
                    }

                    if (e.Button == MouseButtons.Right)
                    {
                        Rcursor = e.X;
                        pictureBox2.Refresh(); // draw the cursor only if the mouse butten is being pushed
                    }
                }
                else // hand tool selected
                {
                    if (e.Button == MouseButtons.Left)
                    {
                        if (((zoomFrom + ((origMouseDragX - e.X) * coeff)) > 0) && ((zoomTo + ((origMouseDragX - e.X) * coeff)) < datalen))
                        {
                            zoomFrom += ((origMouseDragX - e.X) * coeff); // sign is made by  (origMouseDragX - e.X)
                            zoomTo += ((origMouseDragX - e.X) * coeff);
                        }


                        origMouseDragX = e.X;

                        coeff = (double)(zoomTo - zoomFrom) / pictureBox2.Size.Width;

                        Lcursor = 0;
                        Rcursor = pictureBox2.Size.Width-1;

                        makeNewEnvelope = true;
                        pictureBox1.Refresh(); // draw the overall positin
                        pictureBox2.Refresh(); // draw the cursor only if the mouse butten is being pushed
                    }
                }
            }
        }
        //--------------------------------------------------------------------------------
        private void pictureBox2_MouseHover(object sender, EventArgs e)
        {
            pictureBox2.Focus(); //set focus to picturebox, to enable mouse wheel
        }
        //--------------------------------------------------------------------------------
        private void pictureBox2_MouseWheel(object sender, MouseEventArgs e)
        {
            int sign = e.Delta > 0 ? 1 : -1;

            double LtoR = (e.X / (double)pictureBox2.Size.Width);
            double zoomWheelAmountL = (pictureBox2.Size.Width * 0.2 * LtoR * coeff * sign);
            double zoomWheelAmountR = (pictureBox2.Size.Width * 0.2 * (1 - LtoR) * coeff * sign);

            //check new coeff size, if zoom will be bigger than 0.03x stop zooming
            double coeffbuff = (double)((zoomTo - zoomWheelAmountR) - (zoomFrom + zoomWheelAmountL)) / pictureBox2.Size.Width;

            // allowed if zoom is not at limit, or if zoom out is performed at any zoom level
            if ((coeffbuff > 0.03) || (coeffbuff > coeff))
            {

            zoomFrom += zoomWheelAmountL;
            zoomTo -= zoomWheelAmountR;

            if (zoomFrom < 0)
                zoomFrom = 0;
            if (zoomTo > datalen)
                zoomTo = datalen;

            coeff = coeffbuff;

            Lcursor = 0;
            Rcursor = pictureBox2.Size.Width-1;

            makeNewEnvelope = true;
            pictureBox1.Refresh(); // draw the overall position
            pictureBox2.Refresh(); // draw the cursor

            showDeltatime();

            label6.Text = "";
            label7.Text = "";

            label9.Text = "";
            label10.Text = "";

            label11.Text = "";
            label12.Text = "";
            }
            else
            {
                labelUART.Text = "Zoom at limit";
            }
        }
        //--------------------------------------------------------------------------------
        private void showDeltatime()
        {
            string buff = "" + (((zoomTo - zoomFrom) / ((48.0e6 / 9.0) / deci_factor)) / 10.0).ToScientific() + "s";
            labeldt.Text = buff + "/div";
        }
        //--------------------------------------------------------------------------------
        private void toolNoZoom_Click(object sender, EventArgs e)
        {
            zoomFrom = 0;
            zoomTo = datalen;
            coeff = (double)(zoomTo - zoomFrom) / pictureBox2.Size.Width;

            Lcursor = 0;
            Rcursor = pictureBox2.Size.Width-1;

            makeNewEnvelope = true;
            pictureBox1.Refresh(); // draw the overall positin
            pictureBox2.Refresh(); // draw the cursor
            pictureBox3.Refresh(); // draw the cursor

            label6.Text = "";
            label7.Text = "";

            label9.Text = "";
            label10.Text = "";

            label11.Text = "";
            label12.Text = "";

            showDeltatime();
        }
        //--------------------------------------------------------------------------------
        private void toolHand_Click(object sender, EventArgs e)
        {
            toolHand.Image = Properties.Resources.hand_sel;
            toolCursor.Image = Properties.Resources.cursor;

            toolHand.Checked = true;
            toolCursor.Checked = false;

            pictureBox2.Cursor = Cursors.Hand;
        }
        //--------------------------------------------------------------------------------
        private void toolCursor_Click(object sender, EventArgs e)
        {
            toolHand.Image = Properties.Resources.Hand;
            toolCursor.Image = Properties.Resources.cursor_sel;

            toolHand.Checked = false;
            toolCursor.Checked = true;

            pictureBox2.Cursor = Cursors.Cross;
        }
        //--------------------------------------------------------------------------------
        private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (toolStripComboRender.SelectedIndex)
            {
                case 0: jmp_portion = 10000; //fast
                    break;
                case 1: jmp_portion = 1000;
                    break;
                case 2: jmp_portion = 100;
                    break;
                case 3: jmp_portion = 10; // ultra fine
                    break;

            }
            makeNewEnvelope = true;
            pictureBox2.Refresh();
        }
        //--------------------------------------------------------------------------------
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {

                string lines, header_read, header_orig = "TMW OSC LOG";
                byte ChanelPresent;
                byte data_offset;



                FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open);
                BinaryReader reader = new BinaryReader(fs);

                fully_loaded = false;

                lines = reader.ReadString();
                header_read = lines.Substring(0, header_orig.Length);

                if (header_read == header_orig)
                {
                    ChanelPresent = reader.ReadByte();
                    deci_factor = reader.ReadInt32();
                    datalen = reader.ReadInt32();

                    postTrigLen = reader.ReadInt32();

                    data_offset = reader.ReadByte();
                    ampli1 = reader.ReadInt32();
                    ampli2 = reader.ReadInt32();
                    ampli3 = reader.ReadInt32();


                    file_ampli_offset1 = reader.ReadInt32();
                    file_ampli_offset2 = reader.ReadInt32();
                    file_ampli_offset3 = reader.ReadInt32();

                    coupling1 = (Mode_Coupling)reader.ReadByte();
                    coupling2 = (Mode_Coupling)reader.ReadByte();
                    coupling3 = (Mode_Coupling)reader.ReadByte();

                    if ((ChanelPresent & 0x03) > 0)
                    {
                        Array.Resize(ref data1, datalen);
                        data1 = reader.ReadBytes(datalen);
                        labelCH1.BackColor = Color.Fuchsia;
                        labelCH1.Enabled = true;
                        labelCH1.Text = "CH1: " + AmpLabels[ampli1] + (coupling1 == Mode_Coupling.AC ? " AC" : " DC");
                    }
                    else
                    {
                        labelCH1.BackColor = Color.Transparent;
                        labelCH1.Enabled = false;
                    }

                    if ((ChanelPresent & 0x0C) > 0)
                    {
                        Array.Resize(ref data2, datalen);
                        data2 = reader.ReadBytes(datalen);
                        labelCH2.BackColor = Color.Lime;
                        labelCH2.Enabled = true;
                        labelCH2.Text = "CH2: " + AmpLabels[ampli2] + (coupling2 == Mode_Coupling.AC ? " AC":" DC");
                    }
                    else
                    {
                        labelCH2.BackColor = Color.Transparent;
                        labelCH2.Enabled = false;
                    }

                    if ((ChanelPresent & 0x30) > 0)
                    {
                        Array.Resize(ref data3, datalen);
                        data3 = reader.ReadBytes(datalen);
                        labelCH3.BackColor = Color.Yellow;
                        labelCH3.Enabled = true;
                        labelCH3.Text = "CH3: " + AmpLabels[ampli3] + (coupling3 == Mode_Coupling.AC ? " AC" : " DC");
                    }
                    else
                    {
                        labelCH3.BackColor = Color.Transparent;
                        labelCH3.Enabled = false;
                    }

                    if ((ChanelPresent & 0xC0) > 0)
                    {
                        Array.Resize(ref data4, datalen);
                        data4 = reader.ReadBytes(datalen);
                        labelD03.BackColor = Color.Cyan;
                        labelD47.BackColor = Color.Cyan;
                        //  labelD03.Enabled = true;
                        //   labelD47.Enabled = true;
                        checkBoxD03.Checked = true;
                        checkBoxD47.Checked = true;
                        checkBoxD03.Enabled = true;
                        checkBoxD47.Enabled = true;
                    }
                    else
                    {
                        labelD03.BackColor = Color.Transparent;
                        labelD47.BackColor = Color.Transparent;
                        // labelD03.Enabled = false;
                        //  labelD47.Enabled = false;
                        checkBoxD03.Checked = false;
                        checkBoxD47.Checked = false;
                        checkBoxD03.Enabled = false;
                        checkBoxD47.Enabled = false;
                    }


                    reader.Close();
                    fs.Close();

                    fully_loaded = true;

                    // show the new screen
                    toolNoZoom_Click(null, null);


                    int last = openFileDialog1.FileName.LastIndexOf('\\');
                    string buff = openFileDialog1.FileName.Substring(last, openFileDialog1.FileName.Length - last);

                    this.Text = "Visualiser    ..." + buff;

                }
                else
                {
                    MessageBox.Show("File not valid", "Error",
                               MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                }
            }
        }
        //--------------------------------------------------------------------------------
        private void exportToPNGToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Thread.Sleep(333); // this is needed, becouse the printscreen is so fast
                // that it takes picture with the savedialog still active

                Rectangle bounds = this.Bounds;
                using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
                {
                    using (Graphics g = Graphics.FromImage(bitmap))
                    {
                        g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
                    }
                    bitmap.Save(saveFileDialog1.FileName, ImageFormat.Png);
                }
            }
        }
        //--------------------------------------------------------------------------------
        private void pictureBox3_Paint(object sender, PaintEventArgs e)
        {
            Font SignFont = new Font("Courier New", 13, FontStyle.Bold);
            Font DigiChanelNumFont = new Font("Courier New", 9, FontStyle.Regular);

            double hcoeff = pictureBox3.Height / 8.0;

            if (checkBoxD47.Checked == true)
            {
                e.Graphics.DrawString("7", DigiChanelNumFont, Brushes.Cyan, new Point(-1, (int)(hcoeff * 1 - 20)));
                e.Graphics.DrawString("6", DigiChanelNumFont, Brushes.Cyan, new Point(-1, (int)(hcoeff * 2 - 20)));
                e.Graphics.DrawString("5", DigiChanelNumFont, Brushes.Cyan, new Point(-1, (int)(hcoeff * 3 - 20)));
                e.Graphics.DrawString("4", DigiChanelNumFont, Brushes.Cyan, new Point(-1, (int)(hcoeff * 4 - 20)));
            }

            if (checkBoxD03.Checked == true)
            {
                e.Graphics.DrawString("3", DigiChanelNumFont, Brushes.Cyan, new Point(-1, (int)(hcoeff * 5 - 20)));
                e.Graphics.DrawString("2", DigiChanelNumFont, Brushes.Cyan, new Point(-1, (int)(hcoeff * 6 - 20)));
                e.Graphics.DrawString("1", DigiChanelNumFont, Brushes.Cyan, new Point(-1, (int)(hcoeff * 7 - 20)));
                e.Graphics.DrawString("0", DigiChanelNumFont, Brushes.Cyan, new Point(-1, (int)(hcoeff * 8 - 20)));
            }



            if (labelCH1.BackColor == Color.Fuchsia)
            {
                /*
                                e.Graphics.DrawString(">", SignFont, Brushes.Fuchsia, new Point(-5, (int)(pictureBox2.Height / 2
                                    - file_ampli_offset1 - 11 - bar_ampli_offset1 * pictureBox2.Size.Height / 90.0))); // bigger than one screen(*4) becouse
                             // if the GND is the corner , the one scrren shift is not enough to shift it over the screen
                  */


                e.Graphics.DrawString(">", SignFont, Brushes.Fuchsia, new Point(-5, (int)((pictureBox2.Height * (168 - file_ampli_offset1) / 336.0)
                                        - 11 - bar_ampli_offset1 * pictureBox2.Size.Height / 60.0)));



            }

            if (labelCH2.BackColor == Color.Lime)
            {

                /*  e.Graphics.DrawString(">", SignFont, Brushes.Lime, new Point(-5, (int)(pictureBox2.Height / 2
                      - file_ampli_offset2 - 11 - bar_ampli_offset2 * pictureBox2.Size.Height / 90.0)));
                  */

                e.Graphics.DrawString(">", SignFont, Brushes.Lime, new Point(-5, (int)((pictureBox2.Height * (168 - file_ampli_offset2) / 336.0)
                    - 11 - bar_ampli_offset2 * pictureBox2.Size.Height / 60.0)));
            }

            if (labelCH3.BackColor == Color.Yellow)
            {

                e.Graphics.DrawString(">", SignFont, Brushes.Yellow, new Point(-5, (int)((pictureBox2.Height * (168 - file_ampli_offset3) / 336.0)
                    - 11 - bar_ampli_offset3 * pictureBox2.Size.Height / 60.0)));
            }
        }
        //--------------------------------------------------------------------------------
        private void labelCH1_Click(object sender, EventArgs e)
        {
            panel1.BackColor = labelCH1.BackColor;
            panel2.BackColor = labelCH1.BackColor;
            if (((Label)sender).BackColor == Color.Transparent)
                trackBar1.Enabled = false;
            else
                trackBar1.Enabled = true;

            trackBar1.Value = bar_ampli_offset1;
        }

        private void labelCH2_Click(object sender, EventArgs e)
        {
            panel1.BackColor = labelCH2.BackColor;
            panel2.BackColor = labelCH2.BackColor;
            if (((Label)sender).BackColor == Color.Transparent)
                trackBar1.Enabled = false;
            else
                trackBar1.Enabled = true;
            trackBar1.Value = bar_ampli_offset2;
        }

        private void labelCH3_Click(object sender, EventArgs e)
        {
            panel1.BackColor = labelCH3.BackColor;
            panel2.BackColor = labelCH3.BackColor;
            if (((Label)sender).BackColor == Color.Transparent)
                trackBar1.Enabled = false;
            else
                trackBar1.Enabled = true;
            trackBar1.Value = bar_ampli_offset3;
        }
        //--------------------------------------------------------------------------------
        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            if (panel1.BackColor == Color.Fuchsia)
            {
                bar_ampli_offset1 = trackBar1.Value;
                pictureBox2.Refresh();
                pictureBox3.Refresh();
            }

            if (panel1.BackColor == Color.Lime)
            {
                bar_ampli_offset2 = trackBar1.Value;
                pictureBox2.Refresh();
                pictureBox3.Refresh();
            }

            if (panel1.BackColor == Color.Yellow)
            {
                bar_ampli_offset3 = trackBar1.Value;
                pictureBox2.Refresh();
                pictureBox3.Refresh();
            }

        }
        //--------------------------------------------------------------------------------
        private void labelCHx_DoubleClick(object sender, EventArgs e)
        {
            if (fully_loaded == true)
            {
                if (((Label)sender).BackColor == Color.Transparent)
                {

                    trackBar1.Enabled = true;
                    makeNewEnvelope = true; // becouse zoom must not fit in the current mode

                    switch (((Label)sender).Name)
                    {
                        case "labelCH1":
                            ((Label)sender).BackColor = Color.Fuchsia;
                            trackBar1.Value = bar_ampli_offset1;
                            break;

                        case "labelCH2":
                            ((Label)sender).BackColor = Color.Lime;
                            trackBar1.Value = bar_ampli_offset2;
                            break;

                        case "labelCH3":
                            ((Label)sender).BackColor = Color.Yellow;
                            trackBar1.Value = bar_ampli_offset3;
                            break;
                    }


                }
                else
                {
                    ((Label)sender).BackColor = Color.Transparent;
                    trackBar1.Enabled = false;
                }


                panel1.BackColor = ((Label)sender).BackColor;
                panel2.BackColor = ((Label)sender).BackColor;
               
                pictureBox2.Refresh();
                pictureBox3.Refresh();
            }
        }
        //--------------------------------------------------------------------------------
        private void checkBoxDx_CheckedChanged(object sender, EventArgs e)
        {
            if (fully_loaded == true)
            {
                if (((CheckBox)sender).Checked == true) 
                {
                    makeNewEnvelope = true;
                }

                pictureBox2.Refresh();
                pictureBox3.Refresh();
            }
        }
        //--------------------------------------------------------------------------------
        private void toolStripComboChanSel_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (fully_loaded)
            {
            if (toolStripComboTxChan.SelectedIndex > 0)
            {
                txToolStripMenuItem.Checked = true;
            }
            else 
            {
                txToolStripMenuItem.Checked = false;
            }


            if (toolStripComboRxChan.SelectedIndex > 0)
            { 
                rxToolStripMenuItem.Checked = true;
            }
                else 
            {
                rxToolStripMenuItem.Checked = false;
            }


            if (rxToolStripMenuItem.Checked || txToolStripMenuItem.Checked)
            {
                decodeUARTToolStripMenuItem.Checked = true;
                makeNewEnvelope = true;
                pictureBox2.Refresh();
            }
            else 
            {
                decodeUARTToolStripMenuItem.Checked = false;
            }


            }


        }
        //--------------------------------------------------------------------------------
        private void decodeUARTToolStripMenuItem_Click(object sender, EventArgs e)
        {
            decodeUARTToolStripMenuItem.Checked = false;
            fully_loaded = false;
            toolStripComboTxChan.SelectedIndex = 0;
            toolStripComboRxChan.SelectedIndex = 0;

            rxToolStripMenuItem.Checked = false;
            txToolStripMenuItem.Checked = false;

            fully_loaded = true;
            pictureBox2.Refresh();
        }
        //--------------------------------------------------------------------------------
        private void toolStripUART_SelectedIndexChanged(object sender, EventArgs e)
        {
            makeNewEnvelope = true;
            pictureBox2.Refresh();
        }
        //--------------------------------------------------------------------------------
        private void TxpolarityTTLToolStrip_Click(object sender, EventArgs e)
        {
            TxpolarityTTLToolStrip.Checked = true;
            TxpolarityRSToolStrip.Checked = false;

            if (TxpolarityTTLToolStrip.Checked == true)
            {
                makeNewEnvelope = true;
                pictureBox2.Refresh();
            }
        }

        private void TxpolarityRSToolStrip_Click(object sender, EventArgs e)
        {
            TxpolarityTTLToolStrip.Checked = false;
            TxpolarityRSToolStrip.Checked = true;

            if (TxpolarityRSToolStrip.Checked == true)
            {
                makeNewEnvelope = true;
            pictureBox2.Refresh();
            }
        }

        private void RxpolarityTTLToolStrip_Click(object sender, EventArgs e)
        {
            RxpolarityTTLToolStrip.Checked = true;
            RxpolarityRSToolStrip.Checked = false;

            if (RxpolarityTTLToolStrip.Checked == true)
            {
                makeNewEnvelope = true;
                pictureBox2.Refresh();
            }
        }

        private void RxpolarityRSToolStrip_Click(object sender, EventArgs e)
        {
            RxpolarityTTLToolStrip.Checked = false;
            RxpolarityRSToolStrip.Checked = true;

            if (RxpolarityRSToolStrip.Checked == true)
            {
                makeNewEnvelope = true;
                pictureBox2.Refresh();
            }
        }
    }

    //--------------------------------------------------------------------------------
    //--------------------------------------------------------------------------------
    //--------------------------------------------------------------------------------
    public static class FormatExtensions
    {
        public static string ToEngineering(this double value)
        {
            int exp = (int)(Math.Floor(Math.Log10(value) / 3.0) * 3.0);
            double newValue = value * Math.Pow(10.0, -exp);
            if (newValue >= 1000.0)
            {
                newValue = newValue / 1000.0;
                exp = exp + 3;
            }
            if (exp == 0)
                return string.Format("{0:0.###}", newValue);
            else
                return string.Format("{0:0.###}e{1}", newValue, exp);
        }
        //--------------------------------------------------------------------------------
        public static string ToScientific(this double d)
        {
            double exponent = Math.Log10(Math.Abs(d));
            if (Math.Abs(d) >= 1)
            {
                switch ((int)Math.Floor(exponent))
                {
                    case 0:
                    case 1:
                    case 2:
                        return d.ToString("0.###") + " ";
                    case 3:
                    case 4:
                    case 5:
                        return (d / 1e3).ToString("0.###") + " k";
                    case 6:
                    case 7:
                    case 8:
                        return (d / 1e6).ToString("0.###") + " M";
                    case 9:
                    case 10:
                    case 11:
                        return (d / 1e9).ToString("0.###") + " G";
                    case 12:
                    case 13:
                    case 14:
                        return (d / 1e12).ToString("0.###") + " T";
                    case 15:
                    case 16:
                    case 17:
                        return (d / 1e15).ToString("0.###") + " P";
                    case 18:
                    case 19:
                    case 20:
                        return (d / 1e18).ToString("0.###") + " E";
                    case 21:
                    case 22:
                    case 23:
                        return (d / 1e21).ToString("0.###") + " Z";
                    default:
                        return (d / 1e24).ToString("0.###") + " Y";
                }
            }
            else if (Math.Abs(d) > 0)
            {
                switch ((int)Math.Floor(exponent))
                {
                    case -1:
                    case -2:
                    case -3:
                        return (d * 1e3).ToString("0.###") + " m";
                    case -4:
                    case -5:
                    case -6:
                        return (d * 1e6).ToString("0.###") + " μ";
                    case -7:
                    case -8:
                    case -9:
                        return (d * 1e9).ToString("0.###") + " n";
                    case -10:
                    case -11:
                    case -12:
                        return (d * 1e12).ToString("0.###") + " p";
                    case -13:
                    case -14:
                    case -15:
                        return (d * 1e15).ToString("0.###") + " f";
                    case -16:
                    case -17:
                    case -18:
                        return (d * 1e15).ToString("0.###") + " a";
                    case -19:
                    case -20:
                    case -21:
                        return (d * 1e15).ToString("0.###") + " z";
                    default:
                        return (d * 1e15).ToString("0.###") + " y";
                }
            }
            else
            {
                return "0";
            }
        }
    }
}