'==========================================================================
'This Application is for customer who using Modbus protocol
'==========================================================================
'Sample Name  : Modbus Sample Software
'Purpose      : 1. Control PLC by Modbus protocol
'                 2. Control NXIO by Modbus protocol
'Environment  : WIndows XP Pro-SP2, Visual Basic 2005
'Date         : 2007/02/21 ~ 02/23 V1.0
'Programming  : Kijoon Kim  ( kjkim@ra.rockwell.com )
'Copyriht     : Rockwell Automation Korea, OEMax Business
'                 Strategic Marketing
'Revision     : 
'                
'               
'==========================================================================

'So This definition does not use.
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text
Imports Microsoft.VisualBasic

Public Class frmModbus
    '----------------------------------------------
    'Communication Buffer
    '----------------------------------------------
    Dim PLCSB() As Byte                       'PLC Buffer for Send
    Dim PLCSBB() As Byte                     'PLC Buffer for Re-Send

    Dim NXIOSB() As Byte                     'NXIO Buffer for Send
    Dim NXIOSBB() As Byte                    'NXIO Buffer for Re-Send

    Dim INVERTERSB() As Byte                'INVERTER Buffer for Send
    Dim INVERTERSBB() As Byte              'INVERTER Buffer for Re-Send

    Dim RB(4096) As Byte                      'Buffer for Receive
    Dim RB_0(4096) As Byte                   'Buffer for Receive
    Dim ANS_BUFFER(255) As Byte           'Buffer for Answer
    Dim ANS_FLAG As Integer                'Flag For checking status

    Dim Data07 As Integer = &H1111
    Dim Data07_1 As Integer = &HF
    Dim DataReceivedFlag As Boolean = False
    '----------------------------------------------
    '
    '----------------------------------------------
    Public RString(0 To 10) As String
    Public WString(0 To 1023) As String
    Public RCommand(0 To 8) As Byte
    Public WCommand(0 To 1023) As Byte

    Dim CRCTable() As Integer = { _
        0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728, 1920, 51009, 1280, 50625, 50305, 1088, _
        52225, 3264, 3456, 52545, 3840, 53185, 52865, 3648, 2560, 51905, 52097, 2880, 51457, 2496, 2176, 51265, _
        55297, 6336, 6528, 55617, 6912, 56257, 55937, 6720, 7680, 57025, 57217, 8000, 56577, 7616, 7296, 56385, _
        5120, 54465, 54657, 5440, 55041, 6080, 5760, 54849, 53761, 4800, 4992, 54081, 4352, 53697, 53377, 4160, _
        61441, 12480, 12672, 61761, 13056, 62401, 62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529, _
        15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040, 15232, 64321, 14592, 63937, 63617, 14400, _
        10240, 59585, 59777, 10560, 60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865, 60545, 11328, _
        58369, 9408, 9600, 58689, 9984, 59329, 59009, 9792, 8704, 58049, 58241, 9024, 57601, 8640, 8320, 57409, _
        40961, 24768, 24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432, 42241, 26048, 25728, 42049, _
        27648, 44225, 44417, 27968, 44801, 28608, 28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688, _
        30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448, 32640, 48961, 32000, 48577, 48257, 31808, _
        46081, 29888, 30080, 46401, 30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120, 28800, 45121, _
        20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441, 38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, _
        39937, 23744, 23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360, 39169, 22976, 22656, 38977, _
        34817, 18624, 18816, 35137, 19200, 35777, 35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905, _
        17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088, 17280, 33601, 16640, 33217, 32897, 16448 _
    }

    '----------------------------------------------
    'Member Variable
    '----------------------------------------------
    Dim m_OFFSET As Integer = 0             'Offset Value for receiving data
    Dim SCOMM_STATUS As Integer = ST_IDLE   'Send Status
    Dim RCOMM_STATUS As Integer = ST_IDLE   'Receive Status
    Dim RETRY_COUNT As Integer = 0          'Retry Count
    '----------------------------------------------
    'Init Screen
    'After loading main form, Fill the Comport
    '----------------------------------------------
    Private Sub frmModbus_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Try
            Dim i As Integer
            Dim S As String = ""

            btnOpen.Enabled = False
            btnOpen.Text = "Open"

            btnCommTest.Enabled = True
            InitVar()
            InitScreen()
            'Insert COM 1~n to ComboBox
            With cbCommList.Items
                .Clear()
                For i = 1 To 32
                    .Add("COM" + i.ToString)
                Next i
            End With
            cbCommList.Text = "COM1"
            'To prevent Thread Error in VB2005.Net. Default value is True.
            Control.CheckForIllegalCrossThreadCalls = False

        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '----------------------------------------------
    '
    '----------------------------------------------
    Private Sub InitScreen()
        Try
            Dim i As Integer = 0

            '---------------------------------------------------------------------
            'For PLC Control
            Dim arrModbusFunction() As String = {"01 - Read Coil Status", "02 - Read Input Status", _
                                                            "03 - Read Holding Register", "04 - Read Input Register", _
                                                            "05 - Force Single Coil", "06 - Preset Single Register", _
                                                            "07 - Read Exception Status", "15 - Force Multiple Coils", _
                                                            "16 - Preset Multiple Registers", "17 - Report Slave ID"}

            txtPLCSlaveAddress.Text = "255"
            For i = 0 To arrModbusFunction.Length - 1
                cbPLCFunction.Items.Add(arrModbusFunction(i))
            Next i
            txtPLCAddress.Text = "0"
            chkHex.Checked = True
            chkHexSize.Checked = True
            txtPLCDataSize.Text = "1"
            '---------------------------------------------------------------------
            'For NXIO
            Dim arrModbusFunctionNXIO() As String = {"01 - Read Coil Status", "02 - Read Input Status", _
                                                            "03 - Read Holding Register", "04 - Read Input Register", _
                                                            "05 - Force Single Coil", "06 - Preset Single Register", _
                                                            "08 - Dianostics", "15 - Force Multiple Coils", _
                                                            "16 - Preset Multiple Registers", "23 - Read/Write Mulyiple Register"}
            txtNXIOSlaveAddress.Text = "1"
            For i = 0 To arrModbusFunctionNXIO.Length - 1
                cbNXIOFunction.Items.Add(arrModbusFunctionNXIO(i))
            Next i
            txtNXIOAddress.Text = "0"
            chkHexNXIO.Checked = True
            chkHexSizeNXIO.Checked = True
            txtNXIODataSize.Text = "1"
            '---------------------------------------------------------------------
            btnChangeMode.Enabled = False
            btnChangeMode1.Enabled = False
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
    '----------------------------------------------
    '
    '----------------------------------------------
    Private Sub btnOpenPort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

    End Sub

    '----------------------------------------------
    '
    '----------------------------------------------
    Private Sub btnCommTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCommTest.Click
        Try
            'if there is no selection..
            If cbCommList.Text = "" Then
                Exit Sub
            End If

            If IsPortAvailableSP(cbCommList.Text) = True Then
                btnOpen.Enabled = True
                btnOpen.Text = "Open"
            Else
                MessageBox.Show("Communication Port Test Error", "Open Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Exit Sub
            End If
            'Fill Combobox to setting Serial Port
            FillCommParameter()
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '----------------------------------------------
    'Fill Combobox to setting Serial Port
    '----------------------------------------------
    Private Sub FillCommParameter()
        Try
            Dim arrBR() As String = {"38400", "19200", "9600", "4800", "2400", "1200"}
            Dim arrDB() As String = {"6", "7", "8"}
            Dim arrSB() As String = {"1", "2", "1.5"}
            Dim arrPB() As String = {"None", "Even", "Odd", "Mark", "Space"}
            Dim i As Integer

            cbBaudrate.Items.Clear()
            For i = 0 To arrBR.Length - 1
                cbBaudrate.Items.Add(arrBR(i))
            Next i
            cbBaudrate.Text = "9600"

            cbDatabits.Items.Clear()
            For i = 0 To arrDB.Length - 1
                cbDatabits.Items.Add(arrDB(i))
            Next i
            cbDatabits.Text = "8"

            cbStopbits.Items.Clear()
            For i = 0 To arrSB.Length - 1
                cbStopbits.Items.Add(arrSB(i))
            Next i
            cbStopbits.Text = "1"

            cbParitybits.Items.Clear()
            For i = 0 To arrPB.Length - 1
                cbParitybits.Items.Add(arrPB(i))
            Next i
            cbParitybits.Text = "None"
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '----------------------------------------------
    '
    '----------------------------------------------
    Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click
        Try
            With commModbus
                Dim P As String = ""
                If btnOpen.Text = "Open" Then
                    btnOpen.Text = "Close"
                    btnCommTest.Enabled = False
                    Try
                        .PortName = cbCommList.Text
                        .BaudRate = CInt(cbBaudrate.Text)
                        .DataBits = CInt(cbDatabits.Text)
                        Select Case cbParitybits.Text
                            Case "None"
                                .Parity = IO.Ports.Parity.None
                            Case "Even"
                                .Parity = IO.Ports.Parity.Even
                            Case "Odd"
                                .Parity = IO.Ports.Parity.Odd
                            Case "Mark"
                                .Parity = IO.Ports.Parity.Mark
                            Case "Space"
                                .Parity = IO.Ports.Parity.Space
                            Case Else
                                .Parity = IO.Ports.Parity.None
                        End Select

                        Select Case cbStopbits.Text
                            Case "1"
                                .StopBits = IO.Ports.StopBits.One
                            Case "1.5"
                                .StopBits = IO.Ports.StopBits.OnePointFive
                            Case "2"
                                .StopBits = IO.Ports.StopBits.Two
                            Case Else
                                .StopBits = IO.Ports.StopBits.One
                        End Select
                        .ReceivedBytesThreshold = 1

                        cbCommList.Enabled = False
                        cbBaudrate.Enabled = False
                        cbDatabits.Enabled = False
                        cbStopbits.Enabled = False
                        cbParitybits.Enabled = False
                        btnChangeMode.Enabled = True
                        btnChangeMode1.Enabled = True
                        .Open()
                    Catch
                        btnOpen.Enabled = False
                        btnOpen.Text = "Open"
                        MessageBox.Show("Port Open Error", "Close Error", MessageBoxButtons.OK, MessageBoxIcon.Error)

                        cbCommList.Enabled = True
                        cbBaudrate.Enabled = True
                        cbDatabits.Enabled = True
                        cbStopbits.Enabled = True
                        cbParitybits.Enabled = True
                        Exit Sub
                    End Try

                Else   ' if caption="Close"
                    cbCommList.Enabled = True
                    cbBaudrate.Enabled = True
                    cbDatabits.Enabled = True
                    cbStopbits.Enabled = True
                    cbParitybits.Enabled = True
                    btnChangeMode.Enabled = False
                    btnChangeMode1.Enabled = False
                    Try
                        If .IsOpen = True Then
                            .Close()
                        End If
                        btnOpen.Text = "Open"
                    Catch ex As Exception
                        MessageBox.Show("Port Close Error", "Close Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                        If .IsOpen = True Then
                            .Close()
                        End If
                        btnOpen.Text = "Open"
                    End Try
                End If
            End With
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '----------------------------------------------
    'Init Variable
    '----------------------------------------------
    Private Sub InitVar()


    End Sub

    '----------------------------------------------
    '
    '----------------------------------------------
    Private Sub btnEnd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnd.Click
        End
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub CalcCRC(ByRef Buffer() As Byte, ByVal L As Integer)
        Try
            Dim i As Integer
            Dim CRC As Long

            'Check Length whether it is 0
            If L <= 0 Then Exit Sub

            Buffer(L - 2) = 0
            Buffer(L - 1) = 0

            CRC = 65535

            For i = 0 To L - 3
                CRC = CLng(Int(CRC / 256)) Xor CRCTable(CInt((CRC Xor Buffer(i)) And 255))
            Next i
            '-------------------------------------------------------------------------
            Buffer(L - 2) = CByte(CRC And 255)           'CRC Low Byte
            Buffer(L - 1) = CByte((CRC And 65280) / 256) 'CRC High Byte
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Function CheckCRC(ByRef Buffer() As Byte, ByVal L As Integer) As Boolean
        Try
            Dim i As Integer
            Dim CRC As Long
            Dim XCRC(0 To 1) As Byte

            'Check Length whether it is 0
            If L <= 0 Then Exit Function

            XCRC(0) = 0     'Low
            XCRC(1) = 0     'High

            CRC = 65535

            For i = 0 To L - 3
                CRC = CLng(Int(CRC / 256)) Xor CRCTable(CInt((CRC Xor Buffer(i)) And 255))
            Next i
            '-------------------------------------------------------------------------
            XCRC(0) = CByte(CRC And 255)           'CRC Low Byte
            XCRC(1) = CByte((CRC And 65280) / 256) 'CRC High Byte

            If XCRC(0) = Buffer(L - 2) And XCRC(1) = Buffer(L - 1) Then
                Return True
            Else
                Return False
            End If
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Function

    '----------------------------------------------
    '
    '----------------------------------------------
    Private Sub commModbus_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles commModbus.DataReceived
        Try
            Dim OFS, i As Integer
            OFS = 0
            Dim S As String = ""

            With commModbus
                My.Application.DoEvents()
                'Check Data Size which in Receive Buffer
                OFS = .BytesToRead
                Do
                    .Read(RB, m_OFFSET, .BytesToRead)
                    'Add Offset Value
                    m_OFFSET = m_OFFSET + OFS
                    OFS = .BytesToRead
                Loop While (OFS > 0)

                If CheckCRC(RB, m_OFFSET) = False Then
                    ClearFlag()
                    Exit Sub
                End If

                'Copy Oroginal Data to RB_0
                ReDim RB_0(0 To m_OFFSET - 1)
                Array.ConstrainedCopy(RB, 0, RB_0, 0, m_OFFSET)
                For i = 0 To m_OFFSET - 1
                    S += Microsoft.VisualBasic.Right("00" + Hex(RB_0(i)), 2) + " "
                Next i
                txtReceivedData.Text = S
                m_OFFSET = 0
                ClearGlobalBuffer()
            End With
        Catch
            MessageBox.Show("Unknown Error Occured-Serial Port Receive", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '----------------------------------------------
    'When using VB2005 Serial Port Control, This function will check Serial Port
    '----------------------------------------------
    Private Function IsPortAvailableSP(ByVal ComPort As String) As Boolean
        With commModbus
            Try
                .PortName = ComPort
                .Open()
                .Close()
                Return True
            Catch
                ' If it gets here, then the attempt to open the Comm Port was unsuccessful.
                Return False
            End Try
        End With
    End Function

    '-------------------------------------
    'Clear Buffer
    '-------------------------------------
    Private Sub ClearGlobalBuffer()
        Array.Clear(RB, 0, RB.Length)
        Array.Clear(RB_0, 0, RB_0.Length)
    End Sub

    '-------------------------------------
    'Clear Flag
    '-------------------------------------
    Private Sub ClearFlag()
        ANS_FLAG = FLAG_NULL
    End Sub
    '-------------------------------------
    'Send Buffer Backup for preparing Re-Send
    '-------------------------------------
    Private Sub SB_Backup(ByRef Buf() As Byte)
        Try
            ReDim PLCSBB(Buf.Length - 1)
            Array.ConstrainedCopy(Buf, 0, PLCSBB, 0, PLCSBB.Length - 1)
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub btnPLCSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPLCTestSend.Click
        Try
            If commModbus.IsOpen = True Then
                ReDim PLCSB(0 To 7)
                ReDim PLCSBB(0 To 7)
                PLCSB = New Byte() {&HFF, &H1, &H0, &H0, &H0, &HA, &HA9, &HD3}

                Dim S As String = ""
                Dim i As Integer
                Array.ConstrainedCopy(PLCSB, 0, PLCSBB, 0, PLCSB.Length)
                For i = 0 To PLCSB.Length - 1
                    S += Microsoft.VisualBasic.Right("00" + Hex(PLCSBB(i)), 2) + " "
                Next i
                txtSendData.Text = S

                commModbus.Write(PLCSB, 0, PLCSB.Length)
            Else
                MessageBox.Show("Communication Port did not open", "Open Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub txtPLCSlaveAddress_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtPLCSlaveAddress.TextChanged
        Try
            If CInt(txtPLCSlaveAddress.Text) > 255 Or CInt(txtPLCSlaveAddress.Text) <= 0 Then txtPLCSlaveAddress.Text = "255"
        Catch
            MessageBox.Show("Invalid Character", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            txtPLCSlaveAddress.Text = "255"
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub txtPLCAddress_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtPLCAddress.TextChanged
        Try
            Dim S As String = ""
            If txtPLCAddress.Text = "" Then
                txtPLCAddress.Text = "0"
                Exit Sub
            End If

            Select Case chkHex.Checked
                Case True    'Hex
                    S = "&H" + txtPLCAddress.Text
                Case False    'Decimal
                    S = txtPLCAddress.Text
            End Select

            If CInt(S) > 65535 Or CInt(S) < 0 Then
                MessageBox.Show("Invalid Number", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                txtPLCAddress.Text = "0"
            End If

        Catch
            MessageBox.Show("Invalid Character", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            txtPLCAddress.Text = "0"
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub txtPLCDataSize_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtPLCDataSize.TextChanged
        Try
            Dim S As String = ""
            If txtPLCDataSize.Text = "" Then
                txtPLCDataSize.Text = "0"
                Exit Sub
            End If

            Select Case chkHexSize.Checked
                Case True    'Hex
                    S = "&H" + txtPLCAddress.Text
                Case False    'Decimal
                    S = txtPLCAddress.Text
            End Select

            If CInt(S) > 65535 Or CInt(S) < 0 Then
                MessageBox.Show("Invalid Number", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                txtPLCDataSize.Text = "0"
            End If

        Catch
            MessageBox.Show("Invalid Character", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            txtPLCDataSize.Text = "0"
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub btnPLCSend_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPLCSend.Click
        Try
            Select Case Microsoft.VisualBasic.Mid(cbPLCFunction.Text, 1, 2)
                Case "07"
                    MakePLCModbusPacket_07()

                Case "17"
                    MakePLCModbusPacket_17()

                Case "06"
                    If txtPLCSlaveAddress.Text = "" Or txtPLCAddress.Text = "" Or txtPLCDataSize.Text = "" Or cbPLCFunction.Text = "" Then
                        MessageBox.Show("Please Fill data !!", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                        Exit Sub
                    End If
                    ReDim PLCSB(0 To 7)
                    'Array.Clear(PLCSB, 0, PLCSB.Length)
                    Select Case chkContinue.Checked
                        Case True
                            tmrTimer.Enabled = True
                        Case False
                            tmrTimer.Enabled = False
                    End Select
                    MakePLCModbusPacket()

                Case Else
                    If txtPLCSlaveAddress.Text = "" Or txtPLCAddress.Text = "" Or txtPLCDataSize.Text = "" Or cbPLCFunction.Text = "" Then
                        MessageBox.Show("Please Fill data !!", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                        Exit Sub
                    End If
                    ReDim PLCSB(0 To 7)
                    'Array.Clear(PLCSB, 0, PLCSB.Length)
                    MakePLCModbusPacket()
            End Select
            commModbus.Write(PLCSB, 0, PLCSB.Length)
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub btnPLCMakePacket_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPLCMakePacket.Click
        Try
            Select Case Microsoft.VisualBasic.Mid(cbPLCFunction.Text, 1, 2)
                Case "07"
                    MakePLCModbusPacket_07()

                Case Else
                    If txtPLCSlaveAddress.Text = "" Or txtPLCAddress.Text = "" Or txtPLCDataSize.Text = "" Or cbPLCFunction.Text = "" Then
                        MessageBox.Show("Please Fill data !!", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                        Exit Sub
                    End If
                    MakePLCModbusPacket()
            End Select
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
    '-------------------------------------
    'Make Packet for 07 Read Exception Status
    '-------------------------------------
    Private Sub MakePLCModbusPacket_07()
        Try
            ReDim PLCSB(0 To 3)
            Dim S As String = ""

            'Address of Slave Device 
            PLCSB(0) = CByte(txtPLCSlaveAddress.Text)

            'Function Code
            PLCSB(1) = CByte(Microsoft.VisualBasic.Mid(cbPLCFunction.Text, 1, 2))

            'CRC
            PLCSB(2) = 0
            PLCSB(3) = 0

            CalcCRC(PLCSB, 4)
            ReDim PLCSBB(PLCSB.Length)
            Dim i As Integer
            S = ""
            Array.ConstrainedCopy(PLCSB, 0, PLCSBB, 0, PLCSB.Length)
            For i = 0 To PLCSB.Length - 1
                S += Microsoft.VisualBasic.Right("00" + Hex(PLCSBB(i)), 2) + " "
            Next i
            txtSendData.Text = S

        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    'Make Packet for 17 Read Exception Status
    '-------------------------------------
    Private Sub MakePLCModbusPacket_17()
        Try
            ReDim PLCSB(0 To 3)
            Dim S As String = ""

            'Address of Slave Device 
            PLCSB(0) = CByte(txtPLCSlaveAddress.Text)

            'Function Code
            PLCSB(1) = CByte(Microsoft.VisualBasic.Mid(cbPLCFunction.Text, 1, 2))

            'CRC
            PLCSB(2) = 0
            PLCSB(3) = 0

            CalcCRC(PLCSB, 4)
            ReDim PLCSBB(PLCSB.Length)
            Dim i As Integer
            S = ""
            Array.ConstrainedCopy(PLCSB, 0, PLCSBB, 0, PLCSB.Length)
            For i = 0 To PLCSB.Length - 1
                S += Microsoft.VisualBasic.Right("00" + Hex(PLCSBB(i)), 2) + " "
            Next i
            txtSendData.Text = S

        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    'Make Packet
    '-------------------------------------
    Private Sub MakePLCModbusPacket()
        Try
            ReDim PLCSB(0 To 7)
            Dim S As String = ""
            Dim SS As String = ""

            'Address of Slave Device 
            PLCSB(0) = CByte(txtPLCSlaveAddress.Text)

            'Function Code
            PLCSB(1) = CByte(Microsoft.VisualBasic.Mid(cbPLCFunction.Text, 1, 2))

            'Address
            Select Case chkHex.Checked
                Case True
                    S = Hex(CInt("&H" + txtPLCAddress.Text))
                Case False
                    S = Hex(CInt(txtPLCAddress.Text))
            End Select
            SS = Microsoft.VisualBasic.Right("0000" + S, 4)

            PLCSB(2) = CByte("&H" + Microsoft.VisualBasic.Mid(SS, 1, 2))
            PLCSB(3) = CByte("&H" + Microsoft.VisualBasic.Mid(SS, 3, 2))

            'Data Size
            Select Case chkHexSize.Checked
                Case True    'Hex
                    S = Hex(CInt("&H" + txtPLCDataSize.Text))
                Case False    'Decimal
                    S = Hex(CInt(txtPLCDataSize.Text))
            End Select

            SS = Microsoft.VisualBasic.Right("0000" + S, 4)

            PLCSB(4) = CByte("&H" + Microsoft.VisualBasic.Mid(SS, 1, 2))
            PLCSB(5) = CByte("&H" + Microsoft.VisualBasic.Mid(SS, 3, 2))

            'CRC
            PLCSB(6) = 0
            PLCSB(7) = 0

            CalcCRC(PLCSB, 8)

            ReDim PLCSBB(PLCSB.Length)
            Dim i As Integer
            S = ""
            Array.ConstrainedCopy(PLCSB, 0, PLCSBB, 0, PLCSB.Length)
            For i = 0 To PLCSB.Length - 1
                S += Microsoft.VisualBasic.Right("00" + Hex(PLCSBB(i)), 2) + " "
            Next i
            txtSendData.Text = S

        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub cbPLCFunction_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cbPLCFunction.Click
        Select Case Microsoft.VisualBasic.Mid(cbPLCFunction.Text, 1, 2)
            Case "07"
                txtPLCAddress.Enabled = False
                txtPLCAddress.Text = ""
                txtPLCDataSize.Enabled = False
                txtPLCDataSize.Text = ""
                chkHex.Enabled = False
                chkHexSize.Enabled = False
                btnSendFunction15.Enabled = False
                btnSendFunction16.Enabled = False
                btnPLCMakePacket.Enabled = True
                btnPLCSend.Enabled = True
            Case "17"
                txtPLCAddress.Enabled = False
                txtPLCAddress.Text = ""
                txtPLCDataSize.Enabled = False
                txtPLCDataSize.Text = ""
                chkHex.Enabled = False
                chkHexSize.Enabled = False
                btnSendFunction15.Enabled = False
                btnSendFunction16.Enabled = False
                btnPLCMakePacket.Enabled = True
                btnPLCSend.Enabled = True
            Case "15"
                txtPLCAddress.Enabled = False
                txtPLCAddress.Text = ""
                txtPLCDataSize.Enabled = False
                txtPLCDataSize.Text = ""
                chkHex.Enabled = False
                chkHexSize.Enabled = False
                btnPLCMakePacket.Enabled = False
                btnPLCSend.Enabled = False
                btnSendFunction15.Enabled = True
                btnSendFunction16.Enabled = False
            Case "16"
                txtPLCAddress.Enabled = False
                txtPLCAddress.Text = ""
                txtPLCDataSize.Enabled = False
                txtPLCDataSize.Text = ""
                chkHex.Enabled = False
                chkHexSize.Enabled = False
                btnPLCMakePacket.Enabled = False
                btnPLCSend.Enabled = False
                btnSendFunction16.Enabled = True
                btnSendFunction15.Enabled = False
            Case Else
                txtPLCAddress.Enabled = True
                txtPLCDataSize.Enabled = True
                chkHex.Enabled = True
                chkHexSize.Enabled = True
                btnSendFunction15.Enabled = False
                btnSendFunction16.Enabled = False
                btnPLCMakePacket.Enabled = True
                btnPLCSend.Enabled = True
        End Select
    End Sub

    '-------------------------------------
    'When Change Modbus Function Combobox changed,
    'Call Combobox_Click Event manually
    '-------------------------------------
    Private Sub cbPLCFunction_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbPLCFunction.SelectedIndexChanged
        Call cbPLCFunction_Click(sender, e)
    End Sub

    '-------------------------------------
    'Make and Send Function 15 Packet
    '-------------------------------------
    Private Sub btnSendFunction15_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSendFunction15.Click
        Try
            If commModbus.IsOpen = True Then
                ReDim PLCSB(0 To 10)
                ReDim PLCSBB(0 To 10)
                PLCSB = New Byte() {&HFF, &HF, &H0, &H13, &H0, &HA, &H2, &HCD, &H1, &H0, &H0}
                CalcCRC(PLCSB, PLCSB.Length)

                Dim S As String = ""
                Dim i As Integer
                Array.ConstrainedCopy(PLCSB, 0, PLCSBB, 0, PLCSB.Length)
                For i = 0 To PLCSB.Length - 1
                    S += Microsoft.VisualBasic.Right("00" + Hex(PLCSBB(i)), 2) + " "
                Next i
                txtSendData.Text = S

                commModbus.Write(PLCSB, 0, PLCSB.Length)
            Else
                MessageBox.Show("Communication Port did not open", "Open Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    'Make and Send Function 16 Packet
    '-------------------------------------
    Private Sub btnSendFunction16_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSendFunction16.Click
        Try
            If commModbus.IsOpen = True Then
                ReDim PLCSB(0 To 12)
                ReDim PLCSBB(0 To 12)
                PLCSB = New Byte() {&HFF, &H10, &H0, &H1, &H0, &H2, &H4, &H0, &HA, &H1, &H2, &H0, &H0}
                CalcCRC(PLCSB, PLCSB.Length)

                PLCSB(0) = CByte(txtPLCSlaveAddress.Text)

                Dim S As String = ""
                Dim i As Integer
                Array.ConstrainedCopy(PLCSB, 0, PLCSBB, 0, PLCSB.Length)
                For i = 0 To PLCSB.Length - 1
                    S += Microsoft.VisualBasic.Right("00" + Hex(PLCSBB(i)), 2) + " "
                Next i
                txtSendData.Text = S

                commModbus.Write(PLCSB, 0, PLCSB.Length)
            Else
                MessageBox.Show("Communication Port did not open", "Open Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    'Change Mode (NX Protocol<=>Modbus)  on Port1
    '-------------------------------------
    Private Sub btnChangeMode_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChangeMode.Click
        Try
            If commModbus.IsOpen = True Then
                Select Case btnChangeMode.Text
                    Case "To Port1 Modbus"
                        ReDim PLCSB(0 To 8)
                        'NX Protocol : F12.2==> On
                        PLCSB = New Byte() {&HFF, &HFF, &H22, &H3, &HC2, &H1C, &HFF, &H11, &H3F}
                        btnChangeMode.Text = "To Port1 NX"
                    Case "To Port1 NX"
                        ReDim PLCSB(0 To 7)
                        'NX Protocol : F12.2==> Off
                        'F12.2 ==> 0 . F12.2 Modbus Address is 0x1CC2
                        '0xFF: Slave Address, 0x5:Force Single Coil 
                        PLCSB = New Byte() {&HFF, &H5, &H1C, &HC2, &H0, &H0, &H0, &H0}
                        btnChangeMode.Text = "To Port1 Modbus"
                        CalcCRC(PLCSB, 8)

                End Select
                'DIsplay Data to Text Box
                Dim i As Integer
                Dim S As String = ""
                ReDim PLCSBB(PLCSB.Length)
                Array.ConstrainedCopy(PLCSB, 0, PLCSBB, 0, PLCSB.Length)
                For i = 0 To PLCSB.Length - 1
                    S += Microsoft.VisualBasic.Right("00" + Hex(PLCSBB(i)), 2) + " "
                Next i
                txtSendData.Text = S

                commModbus.Write(PLCSB, 0, PLCSB.Length)
            End If
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    'Change Mode (NX Protocol<=>Modbus) On Port2 
    '-------------------------------------
    Private Sub btnChangeMode1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChangeMode1.Click
        Try
            If commModbus.IsOpen = True Then
                Select Case btnChangeMode.Text
                    Case "To Port2 Modbus"
                        ReDim PLCSB(0 To 8)
                        'NX Protocol : F12.2==> On
                        PLCSB = New Byte() {&HFF, &HFF, &H22, &H3, &HC9, &H1C, &HFF, &H60, &HFD}
                        btnChangeMode.Text = "To Port2 NX"
                    Case "To Port2 NX"
                        ReDim PLCSB(0 To 7)
                        'NX Protocol : F12.2==> Off
                        'F12.9 ==> 0 . F12.9 Modbus Address is 0x1CC9
                        '0xFF: Slave Address, 0x5:Force Single Coil 
                        PLCSB = New Byte() {&HFF, &H5, &H1C, &HC9, &H0, &H0, &H0, &H0}
                        btnChangeMode.Text = "To Port2 Modbus"
                        CalcCRC(PLCSB, 8)
                End Select
                'DIsplay Data to Text Box
                Dim i As Integer
                Dim S As String = ""
                ReDim PLCSBB(PLCSB.Length)
                Array.ConstrainedCopy(PLCSB, 0, PLCSBB, 0, PLCSB.Length)
                For i = 0 To PLCSB.Length - 1
                    S += Microsoft.VisualBasic.Right("00" + Hex(PLCSBB(i)), 2) + " "
                Next i
                txtSendData.Text = S

                commModbus.Write(PLCSB, 0, PLCSB.Length)
            End If
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub tmrTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrTimer.Tick
        Try
            Data07 <<= 1
            If Data07 > &H8888 Then Data07 = &H1111
            txtPLCDataSize.Text = Hex(Data07)
            ReDim PLCSB(0 To 7)
            MakePLCModbusPacket()
            commModbus.Write(PLCSB, 0, PLCSB.Length)

            'Do
            '    My.Application.DoEvents()
            'Loop While DataReceivedFlag = False

            'Data07_1 <<= 4
            'If Data07_1 > &HF000 Then Data07_1 = &HF
            'txtPLCAddress.Text = Hex(CInt("&H" + txtPLCAddress.Text) + 1)
            'txtPLCDataSize.Text = Hex(Data07_1)
            'ReDim PLCSB(0 To 7)
            'MakePLCModbusPacket()
            'commModbus.Write(PLCSB, 0, PLCSB.Length)
            'txtPLCAddress.Text = Hex(CInt("&H" + txtPLCAddress.Text) - 1)
        Catch
            MessageBox.Show("Unknown Error Occured in Timer", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub txtReceivedData_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtReceivedData.TextChanged
        DataReceivedFlag = True
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub chkContinue_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkContinue.CheckedChanged
        Select Case chkContinue.Checked
            Case True
                tmrTimer.Enabled = True
            Case False
                tmrTimer.Enabled = False
        End Select
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub rbNXPLC_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)

    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub rbNXIO_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)

    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub btnPLCMakePacketNXIO_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNXIOMakePacket.Click
        Try
            Select Case Microsoft.VisualBasic.Mid(cbPLCFunction.Text, 1, 2)
                Case "07"
                    MakePLCModbusPacket_07()

                Case Else
                    If txtPLCSlaveAddress.Text = "" Or txtPLCAddress.Text = "" Or txtPLCDataSize.Text = "" Or cbPLCFunction.Text = "" Then
                        MessageBox.Show("Please Fill data !!", "Data Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                        Exit Sub
                    End If
                    MakePLCModbusPacket()
            End Select
        Catch
            MessageBox.Show("Unknown Error Occured", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    '-------------------------------------
    '
    '-------------------------------------
    Private Sub cbNXIOFunction_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cbNXIOFunction.Click
        Select Case Microsoft.VisualBasic.Mid(cbPLCFunction.Text, 1, 2)
            Case "08"
                txtNXIOAddress.Enabled = True
                txtNXIOAddress.Text = "1"
                txtNXIODataSize.Enabled = False
                txtNXIODataSize.Text = ""
                chkHexNXIO.Enabled = False
                chkHexSizeNXIO.Enabled = False
                btnNXIOMakePacket.Enabled = True
                btnNXIOSend.Enabled = True

                'Case "17"
                '    txtPLCAddress.Enabled = False
                '    txtPLCAddress.Text = ""
                '    txtPLCDataSize.Enabled = False
                '    txtPLCDataSize.Text = ""
                '    chkHex.Enabled = False
                '    chkHexSize.Enabled = False
                '    btnSendFunction15.Enabled = False
                '    btnSendFunction16.Enabled = False
                '    btnPLCMakePacket.Enabled = True
                '    btnPLCSend.Enabled = True
            Case "15"
                txtNXIOAddress.Enabled = False
                txtNXIOAddress.Text = ""
                txtNXIODataSize.Enabled = False
                txtNXIODataSize.Text = ""
                chkHexNXIO.Enabled = False
                chkHexSizeNXIO.Enabled = False
                btnNXIOMakePacket.Enabled = False
                btnNXIOSend.Enabled = False

                'Case "16"
                '    txtPLCAddress.Enabled = False
                '    txtPLCAddress.Text = ""
                '    txtPLCDataSize.Enabled = False
                '    txtPLCDataSize.Text = ""
                '    chkHex.Enabled = False
                '    chkHexSize.Enabled = False
                '    btnPLCMakePacket.Enabled = False
                '    btnPLCSend.Enabled = False
                '    btnSendFunction16.Enabled = True
                '    btnSendFunction15.Enabled = False
            Case Else
                txtNXIOAddress.Enabled = True
                txtNXIODataSize.Enabled = True
                chkHexNXIO.Enabled = True
                chkHexSizeNXIO.Enabled = True
                btnNXIOMakePacket.Enabled = True
                btnNXIOSend.Enabled = True
        End Select
    End Sub

    Private Sub cbNXIOFunction_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbNXIOFunction.SelectedIndexChanged
        Call cbNXIOFunction_Click(sender, e)
    End Sub

    Private Sub btnNXIOSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNXIOSend.Click

    End Sub
End Class
