using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;

namespace UART_Prg
{
    public partial class Form1 : Form
    {
        //Переменные и объекты COM
        SerialPort port = new SerialPort();
        string[] ports;
        bool isOpen = false;

        //
        byte[] inBuf = new byte[540];
        byte[] outBuf = new byte[540];

        //
        Int32 ee_size = 0;
        Int32 fl_size = 0;
        Int32 fl_psize = 0;
        Int32 data_ofset = 0;

        //
        byte[] wr_arr;
        byte[] rd_arr;


        //Объекты и переменные для fileDialog
        OpenFileDialog openFile = new OpenFileDialog();
        SaveFileDialog saveFile = new SaveFileDialog();
        string filePath; //Строка адреса файла

        //Часы
        DateTime startTime = new DateTime();
        DateTime stopTime = new DateTime();

        public Form1()
        {
            InitializeComponent();

            //Получаем список доступных COM портов
            ports = SerialPort.GetPortNames();

            for (int i = 0; i < ports.Length; i++)
            {
                PortCB.Items.Add(ports[i]);
            }
        }

        //Открытие файла
        void open_file()
        {
            string rd;
            int f_size = 0;

            if (openFile.ShowDialog() == DialogResult.OK)
            {
                //Get the path of specified file
                filePath = openFile.FileName;

                if (filePath.Substring(filePath.Length - 4) == ".hex")
                {

                    StreamReader read = new StreamReader(filePath);
                    Int32 offset = 0, bofs = 0;
                    Int32 curr_offset;
                    string rds;
                    f_size = 0;

                    //Рассчитываем количество байт в HEX файле
                    while ((rds = read.ReadLine()) != null)
                    {

                        curr_offset = Convert.ToInt32(strToByte(rds.Substring(5, 2)) |
                                      (strToByte(rds.Substring(3, 2)) << 8));
                        if (rds.Substring(7, 2) == "00" && (curr_offset > offset))
                        {
                            offset = curr_offset;
                            bofs = Convert.ToInt32(strToByte(rds.Substring(1, 2)));
                        }
                    }

                    read.Close();

                    //Рассчитываем размер массива для открываемого файла
                    f_size = offset + bofs;
                    if ((f_size % 16) > 0) f_size = f_size + (16 - (f_size % 16));

                    read.Close();
                    read.Dispose();

                    //Конвертируем HEX
                    wr_arr = new byte[f_size];

                    for (Int32 i = 0; i < wr_arr.Length; i++)
                    {
                        wr_arr[i] = 0xFF;
                    }

                    StreamReader reader = new StreamReader(filePath);

                    while ((rd = reader.ReadLine()) != null)
                    {
                        if (rd.Substring(7, 2) == "00")
                        {
                            byte str_size = strToByte(rd.Substring(1, 2));
                            Int32 arr_offset = (strToByte(rd.Substring(5, 2)) | (strToByte(rd.Substring(3, 2)) << 8));
                            rd = rd.Substring(9, str_size * 2);

                            for (Int32 h = 0; h < str_size; h++)
                            {
                                wr_arr[arr_offset + h] = strToByte(rd.Substring(h * 2, 2));
                            }
                        }
                    }
                }

                //Если BIN или любой двоичный файл
                else
                {

                    //Рассчитываем размер файла
                    FileInfo fli = new FileInfo(filePath);

                    f_size = Convert.ToInt32(fli.Length);
                    if ((f_size % 16) > 0) f_size = f_size + (16 - (f_size % 16));

                    //Задаём размерность массиву
                    wr_arr = new byte[f_size];

                    //Заполняем массив 0xFF значениями
                    for (Int32 i = 0; i < wr_arr.Length; i++)
                    {
                        wr_arr[i] = 0xFF;
                    }

                    FileStream fs = File.OpenRead(filePath);
                    fs.Read(wr_arr, 0, f_size);
                    fs.Close();

                    
                }
            }

            //Очищаем нужный textBox и выводим в него файл
            HexTB.Clear();
            print_array(wr_arr);

            File.Delete("temp.txt");
        }

        void save_file()
        {
            if (rd_arr != null) //Если массив не пустой
            {
                if (saveFile.ShowDialog() == DialogResult.OK)
                {
                    //Get the path of specified file
                    filePath = saveFile.FileName;

                    //Обрезаем лишние 0xFF с конца массива
                    Int32 index = 0;
                    byte ff;
                    do
                    {
                        ff = rd_arr[(rd_arr.Length - 1) - index];
                        if (ff == 0xFF) { index++; }
                    }
                    while (ff == 0xFF);

                    if (index == 0) { File.WriteAllBytes(filePath, rd_arr); }
                    else
                    {
                        byte[] temp_arr = new byte[rd_arr.Length - index];
                        for (int x = 0; x < temp_arr.Length; x++)
                        {
                            temp_arr[x] = rd_arr[x];
                        }
                        File.WriteAllBytes(filePath, temp_arr);
                    }
                }
            }
        }

        //Сравнение записанного
        void verify()
        {
            if (rd_arr != null && wr_arr != null)
            {
                Int32 fl_error = 0;

                if (rd_arr.Length >= wr_arr.Length)
                {
                    //Сравниваем массив EEPROM
                    for (int k = 0; k < wr_arr.Length; k++)
                    {
                        if (wr_arr[k] != rd_arr[k]) fl_error++;
                    }
                }
                else
                {
                    MessageBox.Show("Файл для сравнения не загружен или превышает размер чипа", "Внимание!");
                    fl_error = wr_arr.Length;
                }
                //Если есть ошибки
                if (fl_error > 0)
                {
                    MessageBox.Show("Ошибок FLASH " + Convert.ToString(fl_error), "Есть ошибки!");
                }
                //Иначе
                else
                {
                    MessageBox.Show("Ошибок FLASH не обнаружено.", "Поздравляю");
                }
            }
            else
            {
                MessageBox.Show("Сначала прочитайте память.", "Внимание!");
            }
        }

        //Перевод строки в byte
        static byte strToByte(string data)
        {
            byte temp = 0;
            switch (data[1])
            {
                case '0': { temp = 0x00; break; }
                case '1': { temp = 0x01; break; }
                case '2': { temp = 0x02; break; }
                case '3': { temp = 0x03; break; }
                case '4': { temp = 0x04; break; }
                case '5': { temp = 0x05; break; }
                case '6': { temp = 0x06; break; }
                case '7': { temp = 0x07; break; }
                case '8': { temp = 0x08; break; }
                case '9': { temp = 0x09; break; }
                case 'a': { temp = 0x0A; break; }
                case 'A': { temp = 0x0A; break; }
                case 'b': { temp = 0x0B; break; }
                case 'B': { temp = 0x0B; break; }
                case 'c': { temp = 0x0C; break; }
                case 'C': { temp = 0x0C; break; }
                case 'd': { temp = 0x0D; break; }
                case 'D': { temp = 0x0D; break; }
                case 'e': { temp = 0x0E; break; }
                case 'E': { temp = 0x0E; break; }
                case 'f': { temp = 0x0F; break; }
                case 'F': { temp = 0x0F; break; }
                default: { temp = 0x0F; break; }
            }
            switch (data[0])
            {
                case '0': { temp |= 0x00; break; }
                case '1': { temp |= 0x10; break; }
                case '2': { temp |= 0x20; break; }
                case '3': { temp |= 0x30; break; }
                case '4': { temp |= 0x40; break; }
                case '5': { temp |= 0x50; break; }
                case '6': { temp |= 0x60; break; }
                case '7': { temp |= 0x70; break; }
                case '8': { temp |= 0x80; break; }
                case '9': { temp |= 0x90; break; }
                case 'a': { temp |= 0xA0; break; }
                case 'A': { temp |= 0xA0; break; }
                case 'b': { temp |= 0xB0; break; }
                case 'B': { temp |= 0xB0; break; }
                case 'c': { temp |= 0xC0; break; }
                case 'C': { temp |= 0xC0; break; }
                case 'd': { temp |= 0xD0; break; }
                case 'D': { temp |= 0xD0; break; }
                case 'e': { temp |= 0xE0; break; }
                case 'E': { temp |= 0xE0; break; }
                case 'f': { temp |= 0xF0; break; }
                case 'F': { temp |= 0xF0; break; }
                default: { temp |= 0xF0; break; }
            }
            return temp;
        }

        //Перевод байта в строку (HEX без "0x") 
        static string hbyteToString(byte data)
        {
            string result = null;

            switch (data & 0xF0)
            {
                case 0x00: { result += "0"; break; }
                case 0x10: { result += "1"; break; }
                case 0x20: { result += "2"; break; }
                case 0x30: { result += "3"; break; }
                case 0x40: { result += "4"; break; }
                case 0x50: { result += "5"; break; }
                case 0x60: { result += "6"; break; }
                case 0x70: { result += "7"; break; }
                case 0x80: { result += "8"; break; }
                case 0x90: { result += "9"; break; }
                case 0xA0: { result += "A"; break; }
                case 0xB0: { result += "B"; break; }
                case 0xC0: { result += "C"; break; }
                case 0xD0: { result += "D"; break; }
                case 0xE0: { result += "E"; break; }
                case 0xF0: { result += "F"; break; }
            }

            switch (data & 0x0F)
            {
                case 0x00: { result += "0"; break; }
                case 0x01: { result += "1"; break; }
                case 0x02: { result += "2"; break; }
                case 0x03: { result += "3"; break; }
                case 0x04: { result += "4"; break; }
                case 0x05: { result += "5"; break; }
                case 0x06: { result += "6"; break; }
                case 0x07: { result += "7"; break; }
                case 0x08: { result += "8"; break; }
                case 0x09: { result += "9"; break; }
                case 0x0A: { result += "A"; break; }
                case 0x0B: { result += "B"; break; }
                case 0x0C: { result += "C"; break; }
                case 0x0D: { result += "D"; break; }
                case 0x0E: { result += "E"; break; }
                case 0x0F: { result += "F"; break; }
            }

            return result;
        }

        //Вывод массива в TextBox
        private void print_array(byte[] arr)
        {
            string rd;

            StreamWriter sw = new StreamWriter("temp.txt");
            string tmp;

            tmp = "OFFSET   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n";
            sw.WriteLine(tmp);

            for (Int32 m = 0; m < arr.Length; m += 16)
            {
                tmp = "0";
                tmp += hbyteToString(Convert.ToByte(m >> 16 & 0xFF));
                tmp += hbyteToString(Convert.ToByte(m >> 8 & 0xFF));
                tmp += hbyteToString(Convert.ToByte(m & 0xFF)) + "  ";

                for (Int32 n = 0; n < 16; n++)
                {
                    tmp += hbyteToString(arr[m + n]) + " ";
                }

                sw.WriteLine(tmp);
            }
            sw.Close();

            rd = File.ReadAllText("temp.txt");

            if (HexTB.InvokeRequired) HexTB.Invoke((MethodInvoker)delegate
            { HexTB.Text = rd; });
            else HexTB.Text = rd;

            File.Delete("temp.txt");
        }

        //Кнопка сканирования портов
        private void ScanBTN_Click(object sender, EventArgs e)
        {
            PortCB.Items.Clear();

            //Получаем список доступных COM портов
            ports = SerialPort.GetPortNames();

            for (int i = 0; i < ports.Length; i++)
            {
                PortCB.Items.Add(ports[i]);
            }
        }

        //Кнопка Open PORT
        private void OpebBTN_Click(object sender, EventArgs e)
        {
            String portNum = PortCB.Text;
            int baude = Convert.ToInt32(BaudeCB.Text);

            if (isOpen == false)
            {
                try
                {
                    if (PortCB.Text == null) MessageBox.Show("Не выбран номер COM порта");
                    else
                    {
                        // настройки порта
                        port.PortName = portNum;
                        port.BaudRate = baude;
                        port.DataBits = 8;
                        port.Parity = Parity.None;
                        port.StopBits = StopBits.One;

                        port.ReadTimeout = 1000;
                        port.WriteTimeout = 1000;
                        port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                        port.Open();
                        port.DtrEnable = false;

                        isOpen = true;
                        OpenBTN.BackColor = Color.LightGreen;
                        OpenBTN.Text = "Close";
                        ConsoleTB.Text = "COM порт открыт";
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Ошибка открытия COM порта");
                }
            }
            else
            {
                port.Close();
                isOpen = false;
                OpenBTN.BackColor = Color.LightGray;
                OpenBTN.Text = "Open";
                ConsoleTB.Text = "COM порт закрыт";
            }
        }

        //
        private void CheckBTN_Click(object sender, EventArgs e)
        {
            if (isOpen)
            {
                outBuf[0] = 0xFE;
                outBuf[1] = 0x01;
                outBuf[2] = 0xCC;
                outBuf[3] = 0x00;
                port.Write(outBuf, 0, 4);
            }
        }


        //----------------------------------------------------------------------------------------//
        //-------------------------------Событие по приёму пакета---------------------------------//
        //----------------------------------------------------------------------------------------//
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            while (port.BytesToRead < 3) ;  //Ждём первые три байта из порта (заголовок)          
            port.Read(inBuf, 0, 3);        //Читаем их в массив


            if (inBuf[0] != 0xFE)          //Если первый байт не маркер начала пакета
            {
                ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = "Ошибка входящего пакета"; });
                Thread.Sleep(1000);                    //Ожидаем приход всего пакета
                port.Read(inBuf, 0, port.BytesToRead); //Вычитываем остатки пакета
                return;                                //Выходим нафиг из функции
            }
            while (port.BytesToRead < Convert.ToInt32(inBuf[1])) ; //Иначе рассчитываем длину остатка пакета
            port.Read(inBuf, 3, Convert.ToInt32(inBuf[1]));        //Ждём, пока он дойдёт весь и дочитываем его
            frame_processor();                                     //Идём в функцию обработки
        }

        //Функция обработки пакетов
        private void frame_processor()
        {
            switch (inBuf[2])
            {
                case 0xCC:
                    {
                        ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = "Программатор подключен"; });
                        break;
                    }
                case 0xE0: //Read I2C EEPROM
                    {
                        int tmp = Convert.ToInt32(inBuf[1]);

                        for (int i = 0; i < tmp; i++)
                        {
                            rd_arr[data_ofset + i] = inBuf[i + 3];
                        }
                        data_ofset += tmp;

                        ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = Convert.ToString(data_ofset) + " байт прочитано"; });

                        if (data_ofset >= ee_size)
                        {
                            print_array(rd_arr);
                            ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = "Чтение завершено\r\n"; });
                            stopTime = DateTime.Now;
                            int opMin = stopTime.Subtract(startTime).Minutes;
                            int opSec = stopTime.Subtract(startTime).Seconds;
                            string opStr = "Прошло " + Convert.ToString(opMin) + " м, " + Convert.ToString(opSec) + " cек";
                            ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text += opStr; });

                            outBuf[0] = 0xFE;
                            outBuf[1] = 0x01;
                            outBuf[2] = 0x3D;
                            outBuf[3] = 0x00;
                            port.Write(outBuf, 0, 4);
                            return;
                        }
                        else
                        {
                            outBuf[0] = 0xFE;
                            outBuf[1] = 0x01;
                            outBuf[2] = 0x3D;
                            outBuf[3] = 0x00;
                            port.Write(outBuf, 0, 4);
                        }
                        break;
                    }
                case 0xE2: //Write I2C EEPROM
                    {
                        if(data_ofset >= wr_arr.Length)
                        {
                            ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = "Запись завершена\r\n"; });
                            stopTime = DateTime.Now;
                            int opMin = stopTime.Subtract(startTime).Minutes;
                            int opSec = stopTime.Subtract(startTime).Seconds;
                            string opStr = "Прошло " + Convert.ToString(opMin) + " м, " + Convert.ToString(opSec) + " cек";
                            ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text += opStr; });
                            return;
                        }

                        outBuf[0] = 0xFE;
                        outBuf[1] = 0x22;
                        outBuf[2] = 0xE2;
                        outBuf[3] = Convert.ToByte((data_ofset >> 8) & 0xFF);
                        outBuf[4] = Convert.ToByte(data_ofset & 0xFF);

                        for(int i = 0; i < 32; i++)
                        {
                            outBuf[i + 5] = wr_arr[i + data_ofset];
                        }
                        port.Write(outBuf, 0, 37);
                        data_ofset += 32;
                        ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = Convert.ToString(data_ofset) + " байт записано"; });
                        break;
                    }
                //****************************************SPI FLASH*******************************************
                case 0xF0:
                    {
                        FlIdTB.Invoke((MethodInvoker)delegate { FlIdTB.Text = hbyteToString(inBuf[5]) + " " + 
                            hbyteToString(inBuf[3]) + hbyteToString(inBuf[4]);
                        });
                        break;
                    }
                case 0xF1:
                    {
                        FlHsregTB.Invoke((MethodInvoker)delegate { FlHsregTB.Text = hbyteToString(inBuf[4]); });
                        FlLsregTB.Invoke((MethodInvoker)delegate { FlLsregTB.Text = hbyteToString(inBuf[3]); });
                        break;
                    }
                case 0xF2: //Read SPI Flash
                    {
                        int tmp = Convert.ToInt32(inBuf[1]);

                        for (int i = 0; i < tmp; i++)
                        {
                            rd_arr[data_ofset + i] = inBuf[i + 3];
                        }
                        data_ofset += tmp;

                        ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = Convert.ToString(data_ofset) + " байт прочитано"; });

                        if (data_ofset >= fl_size)
                        {
                            stopTime = DateTime.Now;
                            int opMin = stopTime.Subtract(startTime).Minutes;
                            int opSec = stopTime.Subtract(startTime).Seconds;
                            string opStr = "Прошло " + Convert.ToString(opMin) + " м, " + Convert.ToString(opSec) + " cек\r\n";
                            ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = opStr; });

                            print_array(rd_arr);

                            ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text += "Чтение завершено\r\n"; });
                            outBuf[0] = 0xFE;
                            outBuf[1] = 0x01;
                            outBuf[2] = 0x3D;
                            outBuf[3] = 0x00;
                            port.Write(outBuf, 0, 4);

                            return;
                        }
                        else
                        {
                            outBuf[0] = 0xFE;
                            outBuf[1] = 0x01;
                            outBuf[2] = 0x3D;
                            outBuf[3] = 0x00;
                            port.Write(outBuf, 0, 4);
                        }
                        break;
                    }
                case 0xF3:
                    {
                        ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = "Запись SREG завершена"; });
                        break;
                    }
                case 0xF4:
                    {
                        ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = "Стирание завершено"; });
                        break;
                    }
                case 0xF6:
                    {
                        if(data_ofset >= wr_arr.Length)
                        {
                            ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = "Запись завершена\r\n"; });
                            stopTime = DateTime.Now;
                            int opMin = stopTime.Subtract(startTime).Minutes;
                            int opSec = stopTime.Subtract(startTime).Seconds;
                            string opStr = "Прошло " + Convert.ToString(opMin) + " м, " + Convert.ToString(opSec) + " cек";
                            ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text += opStr; });
                            return;
                        }

                        outBuf[1] = 0xFE;
                        outBuf[1] = 128;
                        outBuf[2] = 0xF6;

                        for (int i = 0; i < 128; i++) outBuf[i + 3] = wr_arr[i + data_ofset];

                        data_ofset += 128;

                        ConsoleTB.Invoke((MethodInvoker)delegate { ConsoleTB.Text = Convert.ToString(data_ofset) + " байт записано"; });
                        port.Write(outBuf, 0, 131);

                        break;
                    }
            }
        }

        //I2C EEPROM Model ComboBox
        private void EesizeCB_SelectedIndexChanged(object sender, EventArgs e)
        {
            ee_size = Convert.ToInt32(EesizeCB.Text.Substring(3)) * 1024 / 8;
        }

        //I2C EEPROM Open button
        private void I2cOpBTN_Click(object sender, EventArgs e)
        {
            open_file();
        }

        //Кнопка READ I2C EEPROM
        private void I2cRdBTN_Click(object sender, EventArgs e)
        {
            if(EesizeCB.Text != "" && isOpen == true)
            {
                startTime = DateTime.Now;
                data_ofset = 0;
                rd_arr = new byte[ee_size];

                outBuf[0] = 0xFE;
                outBuf[1] = 0x02;
                outBuf[2] = 0xE0;
                outBuf[3] = Convert.ToByte(ee_size >> 8);
                outBuf[4] = Convert.ToByte(ee_size & 0xFF);
                port.Write(outBuf, 0, 5);
            }
            else
            {
                MessageBox.Show("Не выбрана модель EEPROM\r\nили закрыт COM порт!");
            }
        }

        //Кнопка WRITE I2C EEPROM
        private void I2cWrBTN_Click(object sender, EventArgs e)
        {
            if (EesizeCB.Text != "" && isOpen == true && outBuf != null)
            {
                startTime = DateTime.Now;
                int new_size = wr_arr.Length;
                

                if ((new_size % 32) > 0) 
				{
					byte[] temp_arr;
					new_size = new_size + (32 - (new_size % 32));
					temp_arr = new byte[new_size];

					for (int i = 0; i < new_size; i++) temp_arr[i] = 0xFF;           //Заполняем 0xFF
					for (int i = 0; i < wr_arr.Length; i++) temp_arr[i] = wr_arr[i]; //Копируем wr_arr в temp_arr

					wr_arr = new byte[new_size];
					for (int i = 0; i < new_size; i++) wr_arr[i] = temp_arr[i];      //Переписываем обратно
				}
                data_ofset = 0;

                outBuf[0] = 0xFE;
                outBuf[1] = 0x02;
                outBuf[2] = 0xE1;
                outBuf[3] = Convert.ToByte(ee_size >> 8);
                outBuf[4] = Convert.ToByte(ee_size & 0xFF);
                port.Write(outBuf, 0, 5);
            }
            else
            {
                MessageBox.Show("Не выбрана модель EEPROM\r\nили закрыт COM порт!");
            }
        }

        //Кнопка SAVE I2C EEPROM
        private void I2cSvBTN_Click(object sender, EventArgs e)
        {
            save_file();
        }

        private void I2cVrfBTN_Click(object sender, EventArgs e)
        {
            verify();
        }

        //******************************SPI FLASH 25xxx********************************

        //Окно выбора модели
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch(FlModelCB.Text)
            {
                case "W25Q20":
                    {
                        fl_size = 262144;
                        fl_psize = 256;
                        break;
                    }
                case "W25Q40":
                    {
                        fl_size = 524288;
                        fl_psize = 256;
                        break;
                    }
                case "W25Q80":
                    {
                        fl_size = 1048576;
                        fl_psize = 256;
                        break;
                    }
                case "W25Q16":
                    {
                        fl_size = 2097152;
                        fl_psize = 256;
                        break;
                    }
                case "W25Q32":
                    {
                        fl_size = 4194304;
                        fl_psize = 256;
                        break;
                    }
                case "W25Q64":
                    {
                        fl_size = 8388608;
                        fl_psize = 256;
                        break;
                    }
            }
        }

        //Кнопка Save SPI Flash
        private void FlSaveBTN_Click(object sender, EventArgs e)
        {
            save_file();
        }

        private void FlOpenBTN_Click(object sender, EventArgs e)
        {
            open_file();
        }

        //Чтение SPI FLASH
        private void FlRdBTN_Click(object sender, EventArgs e)
        {
            if (FlModelCB.Text != "")
            {
                startTime = DateTime.Now;

                data_ofset = 0;
                rd_arr = new byte[fl_size];

                outBuf[0] = 0xFE;
                outBuf[1] = 0x03;
                outBuf[2] = 0xF2;
                outBuf[3] = Convert.ToByte(fl_size >> 16);
                outBuf[4] = Convert.ToByte((fl_size >> 8) & 0xFF);
                outBuf[5] = Convert.ToByte(fl_size & 0xFF);
                port.Write(outBuf, 0, 6);
            }
        }

        //GET ID SPI FLASH
        private void FlGidBTN_Click(object sender, EventArgs e)
        {
            if(FlModelCB.Text != "")
            {
                outBuf[0] = 0xFE;
                outBuf[1] = 0x01;
                outBuf[2] = 0xF0;
                outBuf[3] = 0x00;
                port.Write(outBuf, 0, 4);
            }
        }

        private void FlRsregBTN_Click(object sender, EventArgs e)
        {
            if (FlModelCB.Text != "")
            {
                outBuf[0] = 0xFE;
                outBuf[1] = 0x01;
                outBuf[2] = 0xF1;
                outBuf[3] = 0x00;
                port.Write(outBuf, 0, 4);
            }
        }

        //WRITE SREG
        private void FlWsregBTN_Click(object sender, EventArgs e)
        {
            if(FlHsregTB.Text != "" && FlLsregTB.Text != "" && isOpen)
            {
                outBuf[0] = 0xFE;
                outBuf[1] = 0x02;
                outBuf[2] = 0xF3;
                outBuf[3] = strToByte(FlHsregTB.Text);
                outBuf[4] = strToByte(FlLsregTB.Text);
                port.Write(outBuf, 0, 5);
            }
        }

        //ERASE
        private void FlErBTN_Click(object sender, EventArgs e)
        {
            if (isOpen)
            {
                outBuf[0] = 0xFE;
                outBuf[1] = 0x01;
                outBuf[2] = 0xF4;
                outBuf[3] = 0x00;
                port.Write(outBuf, 0, 4);
            }
        }

        //Кнопка WRITE SPI FLASH
        private void FlWrBTN_Click(object sender, EventArgs e)
        {
            if(isOpen && FlModelCB.Text != "" && wr_arr != null)
            {
                startTime = DateTime.Now;
                data_ofset = 0;

                int new_size = wr_arr.Length;

                if ((new_size % fl_psize) > 0)
                {
                    byte[] temp_arr;
                    new_size = new_size + (fl_psize - (new_size % fl_psize));
                    temp_arr = new byte[new_size];

                    for (int i = 0; i < new_size; i++) temp_arr[i] = 0xFF;           //Заполняем 0xFF
                    for (int i = 0; i < wr_arr.Length; i++) temp_arr[i] = wr_arr[i]; //Копируем wr_arr в temp_arr

                    wr_arr = new byte[new_size];
                    for (int i = 0; i < new_size; i++) wr_arr[i] = temp_arr[i];      //Переписываем обратно
                }

                outBuf[0] = 0xFE;
                outBuf[1] = 0x02;
                outBuf[2] = 0xF5;
                outBuf[3] = Convert.ToByte(fl_psize >> 8);
                outBuf[4] = Convert.ToByte(fl_size & 0xFF);
                port.Write(outBuf, 0, 5);
            }
        }

        private void FlVrfBTN_Click(object sender, EventArgs e)
        {
            verify();
        }
    }
}
