Public Class Main

    Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
        'quit app
        End
    End Sub

    Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'populate comm port combo box
        Dim X As Integer
        For X = 1 To 32
            cmbCommPort.Items.Add(Trim(Str(X)))
        Next

        'Sets a value indicating whether to catch calls on the wrong thread that access a control's Handle property 
        txtBaseStationACK.CheckForIllegalCrossThreadCalls = False
        txtSOP.CheckForIllegalCrossThreadCalls = False
        txtDeliveryFlags.CheckForIllegalCrossThreadCalls = False
        txtAppDataType.CheckForIllegalCrossThreadCalls = False
        txtNodeAddress.CheckForIllegalCrossThreadCalls = False
        txtReplyLength.CheckForIllegalCrossThreadCalls = False
        txtExtraByte.CheckForIllegalCrossThreadCalls = False
        txtCommand.CheckForIllegalCrossThreadCalls = False
        txtRoll.CheckForIllegalCrossThreadCalls = False
        txtPitch.CheckForIllegalCrossThreadCalls = False
        txtYaw.CheckForIllegalCrossThreadCalls = False
        txtTimerTick.CheckForIllegalCrossThreadCalls = False
        txtLQI.CheckForIllegalCrossThreadCalls = False
        txtRSSI.CheckForIllegalCrossThreadCalls = False
        txtMyCS.CheckForIllegalCrossThreadCalls = False
        txtTheirCS.CheckForIllegalCrossThreadCalls = False
        txtElapsed.CheckForIllegalCrossThreadCalls = False

    End Sub

    Private Sub SampleToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SampleToolStripMenuItem.Click
        'set error handler
        On Error GoTo ErrorHandler

        'test for comm port selection
        If cmbCommPort.Text = "" Then
            'event
            Call ReportEvent("Comm Port not selected")
            'exit
            Exit Sub
        End If

        'determine action based on menu check
        If SampleToolStripMenuItem.Checked = False Then
            'event
            Call ReportEvent("Sampling started")
            'set menu check
            SampleToolStripMenuItem.Checked = True
            'disable combo
            cmbCommPort.Enabled = False
            'disable numupdown
            NumUpDown.Enabled = False
            'zero elapsed time counter
            ElapsedTime = 0
            'zero previous time counter
            PreviousTime = 0
            'set flag
            flgFirstPass = 0
            'set serial port number
            SerialPort1.PortName() = "COM" + Trim(cmbCommPort.Text)
            'set receive threshold
            SerialPort1.ReceivedBytesThreshold = 29
            'open serial port
            SerialPort1.Open()
            'redim command byte array
            ReDim arrCommand(0 To 9)
            'dim
            Dim CommandCheckSum As Double
            'calc checksum
            CommandCheckSum = 11 + _
                                0 + _
                                (NumUpDown.Value \ 256) + _
                                (NumUpDown.Value Mod 256) + _
                                2 + _
                                0 + _
                                206
            'populate command byte array with packetized polling command for 0xCE
            arrCommand(0) = 170
            arrCommand(1) = 11
            arrCommand(2) = 0
            arrCommand(3) = (NumUpDown.Value \ 256)
            arrCommand(4) = (NumUpDown.Value Mod 256)
            arrCommand(5) = 2
            arrCommand(6) = 0
            arrCommand(7) = 206
            arrCommand(8) = CommandCheckSum \ 256
            arrCommand(9) = CommandCheckSum Mod 256
            'send command
            SerialPort1.Write(arrCommand, 0, 10)
        ElseIf SampleToolStripMenuItem.Checked = True Then
            'open serial port
            SerialPort1.Close()
            'event
            Call ReportEvent("Sampling stopped")
            'set menu check
            SampleToolStripMenuItem.Checked = False
            'set checksum indicator
            lblCheckSum.ForeColor = Color.Red
            'enable combo
            cmbCommPort.Enabled = True
            'enable numupdown
            NumUpDown.Enabled = True
        End If

        Exit Sub
ErrorHandler:
        'open serial port
        If SerialPort1.IsOpen = True Then SerialPort1.Close()
        'event
        Call ReportEvent("Sampling errored: " + Err.Description)
        'set menu check
        SampleToolStripMenuItem.Checked = False
        'set checksum indicator
        lblCheckSum.ForeColor = Color.Red
        'enable combo
        cmbCommPort.Enabled = True
        'enable numupdown
        NumUpDown.Enabled = True
        'exit
        Exit Sub
    End Sub

    Private Function ReportEvent(ByVal MyEvent As String) As Boolean
        'add event to text
        If txtEvent.Text = "" Then
            txtEvent.Text = MyEvent
        Else
            txtEvent.Text = txtEvent.Text + Chr(13) + Chr(10) + MyEvent
        End If
    End Function

    Private Function CheckSum() As Boolean
        'set error handler
        On Error GoTo ErrorHandler

        '-----calc TheirCheckSum
        'dim
        Dim X As Double
        'zero variable
        TheirCheckSum = 0
        'calc TheirCheckSum
        For X = 2 To 24
            TheirCheckSum = TheirCheckSum + CDbl(arrBytes(X))
        Next X

        'handle CheckSum rollover
        TheirCheckSum = TheirCheckSum Mod 65536

        'calc MyCheckSum
        MyCheckSum = (CDbl(arrBytes(27)) * 256) + arrBytes(28)

        'compare checksums
        If MyCheckSum = TheirCheckSum Then
            ''set checksum return
            CheckSum = True
            '-----------parse packet
            BaseStationACK = arrBytes(0)
            SOP = arrBytes(1)
            DeliveryFlags = arrBytes(2)
            AppDataType = arrBytes(3)
            NodeAddress = (CDbl(arrBytes(4)) * 256) + arrBytes(5)
            ReplyLength = arrBytes(6)
            ExtraByte = arrBytes(7)
            Command = arrBytes(8)
            'convert array of 32bit floating point values in IEEE-754 format
            arrTemp(0) = arrBytes(12)
            arrTemp(1) = arrBytes(11)
            arrTemp(2) = arrBytes(10)
            arrTemp(3) = arrBytes(9)
            Roll = BitConverter.ToSingle(arrTemp, 0)
            'scale radians to degrees
            Roll = Roll * (180 / 3.14159)
            'round
            Roll = Math.Round(Roll, 1)
            'convert array of 32bit floating point values in IEEE-754 format
            arrTemp(0) = arrBytes(16)
            arrTemp(1) = arrBytes(15)
            arrTemp(2) = arrBytes(14)
            arrTemp(3) = arrBytes(13)
            Pitch = BitConverter.ToSingle(arrTemp, 0)
            'scale radians to degrees
            Pitch = Pitch * (180 / 3.14159)
            'round
            Pitch = Math.Round(Pitch, 1)
            'convert array of 32bit floating point values in IEEE-754 format
            arrTemp(0) = arrBytes(20)
            arrTemp(1) = arrBytes(19)
            arrTemp(2) = arrBytes(18)
            arrTemp(3) = arrBytes(17)
            Yaw = BitConverter.ToSingle(arrTemp, 0)
            'scale radians to degrees
            Yaw = Yaw * (180 / 3.14159)
            'round
            Yaw = Math.Round(Yaw, 1)
            'calc timer tick and elapsed time
            TimerTick = TimerTickCalc(21)
            'signal indicators
            LQI = arrBytes(25)
            RSSI = arrBytes(26)
        Else
            'set checksum return
            CheckSum = False
        End If

        'exit
        Exit Function
ErrorHandler:
        'set checksum return
        CheckSum = False
        'exit
        Exit Function
    End Function

    Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        'set error handler
        On Error GoTo ErrorHandler

        'temporary cob job
        'there should be a better way to trap a comm event that isn't 
        'generated by the receive threshold being met
        If SerialPort1.BytesToRead = 0 Then
            'event
            ''Call ReportEvent(Trim(Str(SerialPort1.BytesToRead)))
            'exit
            Exit Sub
        End If

        'set variable
        UpperLimitOfArray = SerialPort1.BytesToRead - 1
        'prep array
        ReDim arrBytes(0 To UpperLimitOfArray)
        'get comm buffer
        SerialPort1.Read(arrBytes, 0, SerialPort1.BytesToRead)

        'test for no byte return
        If UBound(arrBytes) = -1 Then
            'set checksum indicator
            lblCheckSum.ForeColor = Color.Red
            'send command
            SerialPort1.Write(arrCommand, 0, 10)
            'exit
            Exit Sub
        End If

        'test 29 byte return and 0xAA 0xAA header
        If Not UBound(arrBytes) = 28 And Not arrBytes(0) = 170 And Not arrBytes(1) = 170 Then
            'set checksum indicator
            lblCheckSum.ForeColor = Color.Red
            'send command
            SerialPort1.Write(arrCommand, 0, 10)
            'exit
            Exit Sub
        End If

        'test checksum
        If CheckSum() = False Then
            'set checksum indicator
            lblCheckSum.ForeColor = Color.Red
            'send command
            SerialPort1.Write(arrCommand, 0, 10)
            'exit
            Exit Sub
        End If

        'set checksum indicator
        lblCheckSum.ForeColor = Color.Green

        'display data
        txtBaseStationACK.Text = BaseStationACK
        txtSOP.Text = SOP
        txtDeliveryFlags.Text = DeliveryFlags
        txtAppDataType.Text = AppDataType
        txtNodeAddress.Text = NodeAddress
        txtReplyLength.Text = ReplyLength
        txtExtraByte.Text = ExtraByte
        txtCommand.Text = Command
        txtRoll.Text = Roll
        txtPitch.Text = Pitch
        txtYaw.Text = Yaw
        txtTimerTick.Text = DisplayTimerTickCalc
        txtLQI.Text = LQI
        txtRSSI.Text = RSSI
        txtMyCS.Text = MyCheckSum
        txtTheirCS.Text = TheirCheckSum
        txtElapsed.Text = ElapsedTime

        'send command
        SerialPort1.Write(arrCommand, 0, 10)

        Exit Sub
ErrorHandler:
        'close serial port
        If SerialPort1.IsOpen = True Then SerialPort1.Close()
        'exit
        Exit Sub
    End Sub

End Class
