using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

using System.Management;

namespace SerialPort
{
    ///-----------------------------------------------------------------------------------
    ///FrmMain :KW01-A1工程的窗体                                                          
    ///目    的:
    ///日    期:                                             
    ///编 程 者:
    ///-----------------------------------------------------------------------------------
    public partial class FrmMain : Form
    {      
        //1. 窗体类的临时变量区
        private System.IO.Ports.SerialPort UARTport;   //声明系统工具-串口对象的变量声明
        private Uart uart1;                          //声明一个自定义的Uart类型（串口操作）的变量
        private PCNode pcNode1;                      //声明一个自定义的PCNode类型的变量
          
   
        //2. 构造函数（启动窗体最先执行程序）
        public FrmMain()
        {
            //系统生成的构造函数（初始化窗体的元素）
            InitializeComponent();        
            //禁止检测跨线程调用异常(
            CheckForIllegalCrossThreadCalls = false;  
            //初始化窗体类临时变量
            UARTport = null;          //初始化“系统工具-串口对象”
            uart1 = null;             //初始化“Uart类型（串口操作）对象”
            pcNode1 = new PCNode();   //
       }
        
        //3. 加载窗体事件程序（在构造函数之后执行的程序）
        private void FrmMain_Load(object sender, EventArgs e)
        {

            string s1;
            this.tb_statue1.Text = "运行状态：FrmMain_Load开始,调用PCNode类内部函数，寻找PCNode...";

            if (uart1 != null && uart1.IsOpen) uart1.close();
            s1 = pcNode1.findPCNode();           //调用PCNode类内部函数，寻找PCNode
            uart1 = pcNode1.PCNode_Uart1;

            this.tb_statue1.Text = "运行状态：" + s1;

            lbl_PC_Node_State.Text = s1;

            //保留编程参考：绑定DataReceived事件(即串口接收中断处理函数）
            if (uart1 != null)
            {
                UARTport = uart1.port;
                UARTport.DataReceived += new System.IO.Ports. //添加串口对象变量的接收事件的响应函数
                         SerialDataReceivedEventHandler(this.UARTport_recvData);
            }
            //uart1.setReceInt(2);           //设置触发DataRecieved事件的字节数（目的是关闭该事件）
            //uart1.sendData(B1, B1.Length); //发送握手数据


            //
          

       
            rBtnTargetComm_CheckedChanged(sender, e);
            
        }

        //========================以下是本窗体的各个事件响应函数==========================
       
        //------------------------单击“检测PC节点”按钮----------------------------------
        private void btnCheckPcNode_Click(object sender, EventArgs e)
        {
            //if (_port1.IsOpen) 

            this.tb_statue1.Text = "运行状态：" + "单击“检测PC节点”按钮...";

            FrmMain_Load(sender, e);

            this.tb_statue1.Text = "运行状态：" + "单击“检测PC节点”按钮...退出";
        }

        //--------------------------单击窗口关闭“X”按钮---------------------------------
        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (uart1 == null) return;
            //如果串口未关闭，则关闭
            if (uart1.IsOpen) uart1.close(); 
        }
        
        
        //-------------------------------串口接收事件的响应函数---------------------------
        private void UARTport_recvData(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string s1 = string.Empty;
            string s2 = string.Empty;
            int i;

            s1="";
            s2="";
         
           Thread.Sleep(100);

           PublicVar.g_ReceiveByteArray = uart1.recvData();    //调用串口接收函数
           if (PublicVar.g_ReceiveByteArray.Length > 0)
           {
                   for (i = 0; i < PublicVar.g_ReceiveByteArray.Length; i++)
                   {
                       s1 =s1+" "+ Convert.ToString(PublicVar.g_ReceiveByteArray[i], 10);
                       s2=s2+"--"; 
                   }
                   this.Txt_recv2.Text = s1;

                   this.Txt_recv1.Text = s2;

               //this.Txt_recv2.Text = "Interrupt--- " + System.Text.Encoding.Default.GetString(PublicVar.g_ReceiveByteArray);
           }
        }
            
        //---------------------------Flash读取操作按钮点击事件----------------------------
        private void btnPnFlashRead_Click(object sender, EventArgs e)
        {
            // 1. 临时变量声明
            byte sector;           // 扇区号
            int offset;            // 偏移量
            byte count;            // 读取字节数

            byte[] SendByteArray = new byte[13];          // 定义发送缓冲区
            byte offset_high, offset_low;                // 定义偏移地址的高低字节

            // 2. 临时变量赋值
            sector = Convert.ToByte(tbSector1.Text);    // 将TextBox中的Text转换为Byte类型
            offset  = Convert.ToInt32(tbOffset1.Text);  // 将TextBox中的Text转换为Byte类型
            count = Convert.ToByte(tbCount1.Text);
            
            //发送检查
            if (sector < 0 || sector > 127)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash读操作扇区号设置有误，可输入范围是0~127,请重新输入";
                return;
            }
            if (offset < 0 || offset > 1023)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash读操作偏移量设置有误，可输入范围是0~1023,请重新输入";
                return;
            }
            if (offset%4!=0)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash读操作偏移量应为4的倍数，输入范围是0~1023,请重新输入";
                return;
            }
            if (count < 1 || count > 56)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash读操作读取字节数设置有误，可输入范围是1~56,请重新输入";
                return;
            }
            if ((offset + count) < 1 || (offset + count) > 1024)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash读操作偏移量与读取字节数之和不合理,合理范围是1~1024，请重新输入";
                return;
            }

            // 计算偏移地址高低位
            offset_low = (byte)(0xff & offset);
            offset_high = (byte)((0xff00 & offset) >> 8);

            //this.Txt_recv1.Text = "";
            this.Txt_recv2.Text = "";
            //this.Txt_recv1.Refresh();
            this.Txt_recv2.Refresh();

            this.tb_statue1.Text = "运行状态：" + "单击“Target Flash 读测试”按钮...";
            //this.tb_statue1.Refresh();
            try
            {
                SendByteArray[0] = (byte)'P';      //帧头
                SendByteArray[1] = 0x0A;           //帧长

                SendByteArray[2] = 0xFF;           //硬件地址
                SendByteArray[3] = 0x00;           //网段高字节
                SendByteArray[4] = 0xFF;           //网段低字节
                SendByteArray[5] = 0x00;           //网内地址高字节
                SendByteArray[6] = 0xFF;           //网内地址低字节
                SendByteArray[7] = 0x02;           //FLASH读操作
                SendByteArray[8] = sector;         //第几页
                SendByteArray[9] = offset_high;    //偏移量高字节
                SendByteArray[10] = offset_low;    //偏移量低字节
                SendByteArray[11] = count;         //读取字节数

                SendByteArray[12] = (byte)'C';     //帧尾

                //发送、接收、显示
                sendRecv(SendByteArray,2,300);
            }
            catch
            {
                //this.Txt_recv1.Text = "PCNode Flash读取操作失败！";
                this.tb_statue1.Text = "运行状态：" + "Target Flash读取操作失败！";
            }
        }
        //---------------------------Flash写入操作按钮点击事件----------------------------
        private void btnPnFlashWrite_Click(object sender, EventArgs e)
        {

            // 1. 临时变量声明
            byte sector;        //扇区号
            int offset;         //偏移量
            byte count;             //读取字节数
            int i;
         

            // 2. 临时变量赋值
 
            sector = Convert.ToByte(tbSector2.Text);  // 将TextBox中的Text转换为Byte类型
            offset = Convert.ToInt32(tbOffset2.Text);   // 将TextBox中的Text转换为Byte类型
            count = Convert.ToByte(tbCount2.Text);
            byte[] writeDataArray = System.Text.Encoding.Default.GetBytes(tbWriteData1.Text); //String转化为Byte[]


            //发送检查
            if (sector < 99 || sector > 126)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash写操作扇区号设置有误，可输入范围是99~126,请重新输入";
                return;
            }
            if (offset < 0 || offset > 1023)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash写操作偏移量设置有误，可输入范围是0~1023,请重新输入";
                return;
            }
            if (offset % 4 != 0)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash写操作偏移量应为4的倍数，输入范围是0~1023,请重新输入";
                return;
            }
            if (count < 1 || count > 45)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash写操作读取字节数设置有误，可输入范围是1~45,请重新输入";
                return;
            }
            if ((offset + count) < 1 || (offset + count) > 1024)
            {
                this.tb_statue1.Text = "运行状态：" + "target Flash写操作偏移量与读取字节数之和不合理,合理范围是1~1024，请重新输入";
                return;
            }



            byte[] SendByteArray = new byte[count +13];

            this.Txt_recv2.Text = "";
            this.Txt_recv2.Refresh();
           
            //this.tb_statue1.Refresh();

            try
            {
 
                SendByteArray[0] = (byte)'P';      //帧头

                SendByteArray[1] = (byte)(count + 10);           //帧长
                
                SendByteArray[2] = 0xFF;      //硬件地址

                SendByteArray[3] = 0x00;           //网段高字节
                SendByteArray[4] = 0xFF;           //网段低字节
                SendByteArray[5] = 0x00;           //网内地址高字节
                SendByteArray[6] = 0xFF;           //网内地址低字节
                SendByteArray[7] = 0x03;           //FLASH写操作

                SendByteArray[8] = sector;         //扇区号
                SendByteArray[9] = (byte)(offset/256);    //偏移量高字节
                SendByteArray[10] = (byte)(offset%256);    //偏移量低字节
                SendByteArray[11] = count;              //字节数 

                for (i = 12; i <= count + 11; i++)
                {
                   SendByteArray[i]=(byte)writeDataArray[i-12];
                 }

                SendByteArray[count + 12] = (byte)'C';       //帧尾
                
                //发送、接收、显示
                sendRecv(SendByteArray,2,300);
                
            }
            catch
            {
                this.tb_statue1.Text = "运行状态：" + "PCNode Flash读取操作失败！";
                //this.Txt_recv1.Text = "PCNode Flash读取操作失败！";
            } 
        
        }
       


        


        // 目标节点（Target）Flash 读取操作
        private void btnTnFlashRead_Click(object sender, EventArgs e)
        {
             // 1. 临时变量声明
            byte sector;        //扇区号
            int offset;         //偏移量
            byte n;             //读取字节数
    
    

            // 2. 临时变量赋值
            sector = Convert.ToByte(tbSector1.Text);   // 将TextBox中的Text转换为Byte类型
            offset = Convert.ToInt32(tbOffset1.Text);   // 将TextBox中的Text转换为Byte类型
            n = Convert.ToByte(tbCount1.Text);
 
            byte[] SendByteArray = new byte[14];

            //this.Txt_recv1.Text = "";
            this.Txt_recv2.Text = "";
            //this.Txt_recv1.Refresh();
            this.Txt_recv2.Refresh();

            this.tb_statue1.Text = "运行状态：" + "单击“Target Flash 读测试”按钮...";
            //this.tb_statue1.Refresh();

            try
            {

                SendByteArray[0] = (byte)'P';      //帧头

                SendByteArray[1] = (byte)(10 + 1); //帧长

                SendByteArray[2] = (byte)'B';      //PCNode转发命令操作命令

                SendByteArray[3] = (byte)0;        //目标节点地址_高字节
                SendByteArray[4] = (byte)1;        //目标节点地址_低字节

                SendByteArray[5] = (byte)1;        //帧类型

                SendByteArray[6] = (byte)'F';      //操作目标节点Flash命令
                SendByteArray[7] = (byte)'R';      //操作目标节点Flash读命令

                SendByteArray[8] = (byte)1;        //保留字节

                SendByteArray[9] = sector;         //读取的Flash扇区号

                SendByteArray[10] = (byte)(offset / 256);    //偏移量高字节
                SendByteArray[11] = (byte)(offset % 256);    //偏移量低字节

                SendByteArray[12] = n;             //读取FLash字节数 

                SendByteArray[13] = (byte)'C';     //帧尾

                //发送、接收、显示
                sendRecv(SendByteArray,3,1500);
            }
            catch
            {
                //this.Txt_recv1.Text = "";
                this.Txt_recv2.Text = "";
                this.tb_statue1.Text = "输入参数有误！";
            } 
        }

        // 目标节点（Target）Flash 写入操作
        private void btnTnFlashWrite_Click(object sender, EventArgs e)
        {
            // 1. 临时变量声明
            byte sector;        //扇区号
            int offset;         //偏移量
            byte n;             //读取字节数
            int i;
            byte len;
        

            // 2. 临时变量赋值

            sector = Convert.ToByte(tbSector2.Text);  // 将TextBox中的Text转换为Byte类型
            offset = Convert.ToInt32(tbOffset2.Text);   // 将TextBox中的Text转换为Byte类型
            n = Convert.ToByte(tbCount2.Text);
            byte[] writeDataArray = System.Text.Encoding.Default.GetBytes(tbWriteData1.Text); //String转化为Byte[]

            len = (byte)(n + 11);

            byte[] SendByteArray = new byte[len + 3];

            //this.Txt_recv1.Text = "";
            this.Txt_recv2.Text = "";
            //this.Txt_recv1.Refresh();
            this.Txt_recv2.Refresh();

            this.tb_statue1.Text = "运行状态：" + "单击“Target Flash 写测试”按钮...";
            //this.tb_statue1.Refresh();
         
            try
            {

                SendByteArray[0] = (byte)'P';      //帧头

                SendByteArray[1] = len;            //帧长

                SendByteArray[2] = (byte)'B';      //PCNode转发命令操作命令

                SendByteArray[3] = (byte)0;        //目标节点地址_高字节
                SendByteArray[4] = (byte)1;        //目标节点地址_低字节

                SendByteArray[5] = (byte)1;        //帧类型

                SendByteArray[6] = (byte)'F';      //操作目标节点Flash命令
                SendByteArray[7] = (byte)'W';      //操作目标节点Flash读命令

                SendByteArray[8] = (byte)1;        //保留字节

                SendByteArray[9] = sector;         //读取的Flash扇区号

                SendByteArray[10] = (byte)(offset / 256);    //偏移量高字节
                SendByteArray[11] = (byte)(offset % 256);    //偏移量低字节

                SendByteArray[12] = n;             //写入FLash字节数 

                for(i=13; i<=12+n; i++)
                    SendByteArray[i]=writeDataArray[i-13];

                SendByteArray[len+2] = (byte)'C';      //帧尾

                //发送、接收、显示
                sendRecv(SendByteArray,3,1500);
            }
            catch
            {
                this.tb_statue1.Text = "运行状态：" + "没有接收到Target节点返回的信息，Target节点Flash写入操作失败。";
                //this.Txt_recv1.Text = "没有接收到Target节点返回的信息，Target节点Flash写入操作失败。";
            } 
        }

        


        //-------------------------
        private void sendRecv(byte[] SendByteArray,int cnt,int time)

        {
            byte[] recvData;
            byte[] data;//用于保存有效数据的字符数组
            String str = String.Empty;
            String s1 = String.Empty;
            s1 = "";

            int i;
            this.tb_statue1.Text += "正在发送...";
            //this.tb_statue1.Refresh();
            recvData = pcNode1.PCNodeSendReturn(SendByteArray, cnt, time);
            
            
            if (recvData.Length <= 0)
            {
                this.tb_statue1.Text += "无数据返回";
                //this.tb_statue1.Refresh();
            }
            else
            {
                data = new byte[recvData.Length - 9];    //长度为接收字符数组中的有效字符数
                this.tb_statue1.Text += "有数据返回";
                //this.tb_statue1.Refresh();
                this.Txt_recv2.Text = string.Empty;

                for (i = 8; i < recvData.Length - 1; i++)
                {
                    // this.Txt_recv.Text += "-" + recvData[i].ToString("D3").ToUpper() + " ";
                    // this.Txt_recv2.Text += recvData[i] + " ";
                    data[i - 8] = recvData[i];           //有效数据字符数组
                    s1 = s1 +recvData[i].ToString("X2")+" ";
                }
                str = Encoding.Default.GetString(data);  //转换为字符串
                 this.Txt_recv2.Text = str;
                 this.Txt_recv1.Text = s1;


                  
            }
        }
        

        //---------------------------单击“清空显示框”按钮-------------------------------
        private void btnClear1_Click(object sender, EventArgs e)
        {
            this.tb_statue1.Text = "运行状态：" + "单击“清空显示框”按钮。";
            //this.tb_statue1.Refresh();
           
            //this.Txt_recv1.Text = "";
            this.Txt_recv2.Text = "";
            this.Txt_recv1.Text = "";
        }

        private void rBtnTargetComm_CheckedChanged(object sender, EventArgs e)
        {
           

            this.tb_statue1.Text = "运行状态：" + "选择“与Target通信”单选框。";
            //this.tb_statue1.Refresh();

         
        }

        private void tbWriteData1_TextChanged(object sender, EventArgs e)
        {
            tbCount2.Text = tbWriteData1.Text.Length.ToString();
        }

        private void groupBox9_Enter(object sender, EventArgs e)
        {

        }
    }
}
