Call me back | My basket | Checkout | Add to email list

     You are here: Website » Knowledge base

« back to website

SerialDataFormat / ExampleVBDecoder

VB6 serial decoder source

Note: this code can be freely used, but is supplied without warrantee or support

'<CSCC>
'--------------------------------------------------------------------------------
'    Component  : RtSerialProcessor
'    Project    : Serial Processer
'
'    Description: decode serial data over serial port
'
'    Copyright  : Race Technology Ltd, UK
'--------------------------------------------------------------------------------
'</CSCC>

Option Explicit

'defined type of errors that can be occur while processing
Enum RtMessageError
    DataOk = 0
    ChecksumError = 1
    InsufficientData = 2
    UnknownMessageType = 3
End Enum

'use for map hardware channels with internal variable reference
Enum InternalVariableReference
    TIMES_ = 1
    ACCELLONG_ = 2
    ACCELLONGFLAG_ = 3
    ACCELLAT_ = 4
    ACCELVECT_ = 5
    ACCEL_Z_ = 6
    BRAKE_FLAG_ = 7
    RPM_ = 10
    GPSSPEED_ = 15
    WHEELSPEED_ = 16
    DISTANCE_ = 17
    POWERATWHEELS_ = 20
    TORQUEATWHEELS_ = 21
    GEAR_ = 22
    POSXM_ = 30
    POSYM_ = 31
    CTIME_ = 40
    CTIMERATE_ = 41
    TRACKHEADING_ = 50
    CHANGEINHEADING_ = 51
    CORNERRADIUS_ = 52
    BICYCLELEANANGLE_ = 53
    LAPTIMES_ = 60
    SECTORTIMES_ = 61
    TRACKBEACON_ = 62
    GYROYAWRATE_ = 70
    GYROYAW_ = 71
    GYROPITCHRATE_ = 72
    GYROPITCH_ = 73
    GYROROLLRATE_ = 74
    GYROROLL_ = 75
    GYROSLIPANGLE_ = 80
    BUFFERSIZE_ = 90
    SERIALDATACOUNT_ = 91
    VIDEOFRAME_ = 100
    DL1_ANAL0_ = 200
    DL1_ANAL1_ = 201
    DL1_ANAL2_ = 202
    DL1_ANAL3_ = 203
    DL1_ANAL4_ = 204
    DL1_ANAL5_ = 205
    DL1_ANAL6_ = 206
    DL1_ANAL7_ = 207
    DL1_ANAL8_ = 208
    DL1_ANAL9_ = 209
    DL1_ANAL10_ = 210
    DL1_ANAL11_ = 211
    DL1_ANAL12_ = 212
    DL1_ANAL13_ = 213
    DL1_ANAL14_ = 214
    DL1_ANAL15_ = 215
    DL1_ANAL16_ = 216
    DL1_ANAL17_ = 217
    DL1_ANAL18_ = 218
    DL1_ANAL19_ = 219
    DL1_ANAL20_ = 220
    DL1_ANAL21_ = 221
    DL1_ANAL22_ = 222
    DL1_ANAL23_ = 223
    DL1_ANAL24_ = 224
    DL1_ANAL25_ = 225
    DL1_ANAL26_ = 226
    DL1_ANAL27_ = 227
    DL1_ANAL28_ = 228
    DL1_ANAL29_ = 229
    DL1_ANAL30_ = 230
    DL1_ANAL31_ = 231
    DL1_FREQ1_ = 300
    DL1_FREQ2_ = 301
    DL1_FREQ3_ = 302
    DL1_FREQ4_ = 303
    FREQ1_HIGHPERIOD_ = 304
    FREQ1_LOWPERIOD_ = 305
    FREQ1_PULSEPOSITION_ = 306
    FREQ2_HIGHPERIOD_ = 307
    FREQ2_LOWPERIOD_ = 308
    FREQ2_PULSEPOSITION_ = 309
    FREQ3_HIGHPERIOD_ = 310
    FREQ3_LOWPERIOD_ = 311
    FREQ3_PULSEPOSITION_ = 312
    FREQ4_HIGHPERIOD_ = 313
    FREQ4_LOWPERIOD_ = 314
    FREQ4_PULSEPOSITION_ = 315
    FREQ1_PULSE_COUNT_ = 316
    FREQ2_PULSE_COUNT_ = 317
    FREQ3_PULSE_COUNT_ = 318
    FREQ4_PULSE_COUNT_ = 319
    GPSALTITUDE_ = 400
    GPSLATACCEL_ = 401
    GPSLONGACCEL_ = 402
    GPSHEADING_ = 403
    GPSGRADIENT_ = 404
    GPSMSTIME_ = 405
    GPSPOSITIONACC_ = 406
    GPSSPEEDACC_ = 407
    GPSHEADINGACC_ = 408
    GPSGRADIENTACC_ = 409
    GPSALTACC_ = 410
    ACTUALGPSSATCOUNT_ = 411
    WEIGHTEDGPSSATCOUNT_ = 412
    GPSVELSOURCE_ = 413
    GPSRAWVEL_ = 414
    GPSRAWLONGITUDE_ = 415
    GPSRAWLATITUDE_ = 416
    GPSRTKPITCH_ = 430
    GPSRTKYAW_ = 431
    GPSRTKBASELINE_ = 450
    GPSRTKBASELINEACC_ = 451
    GPSDATACOUNT_ = 500
    ECU_FIRST_TEMP_ = 1000
    ECU_FIRST_FREQ_ = 1500
    ECU_FIRST_PERC_ = 2000
    ECU_FIRST_TIME_ = 2500
    ECU_FIRST_ANGLE_ = 3000
    ECU_FIRST_PRESSURE_ = 3500
    ECU_FIRST_MISC_ = 4000
    DEBUG_VAR_FP_0_ = 5050
    DEBUG_VAR_FP_1_ = 5051
    DEBUG_VAR_FP_2_ = 5052
    DEBUG_VAR_FP_3_ = 5053
    DEBUG_VAR_FP_4_ = 5054
    DEBUG_VAR_FP_5_ = 5055
    DEBUG_VAR_FP_6_ = 5056
    DEBUG_VAR_FP_7_ = 5057
    DEBUG_VAR_FP_8_ = 5058
    DEBUG_VAR_FP_9_ = 5059
    DEBUG_VAR_FP_A_ = 5060
    DEBUG_VAR_FP_B_ = 5061
    DEBUG_VAR_FP_C_ = 5062
    DEBUG_VAR_FP_D_ = 5063
    DEBUG_VAR_FP_E_ = 5064
    DEBUG_VAR_FP_F_ = 5065
    DEBUG_VAR_U32_0_ = 5066
    DEBUG_VAR_U32_1_ = 5067
    DEBUG_VAR_U32_2_ = 5068
    DEBUG_VAR_U32_3_ = 5069
    DEBUG_VAR_U32_4_ = 5070
    DEBUG_VAR_U32_5_ = 5071
    DEBUG_VAR_U32_6_ = 5072
    DEBUG_VAR_U32_7_ = 5073
    DEBUG_VAR_S32_0_ = 5074
    DEBUG_VAR_S32_1_ = 5075
    DEBUG_VAR_S32_2_ = 5076
    DEBUG_VAR_S32_3_ = 5077
    DEBUG_VAR_S32_4_ = 5078
    DEBUG_VAR_S32_5_ = 5079
    DEBUG_VAR_S32_6_ = 5080
    DEBUG_VAR_S32_7_ = 5081
    USER_VAR_1_ = 6001
    USER_VAR_2_ = 6002
    USER_VAR_3_ = 6003
    USER_VAR_4_ = 6004
    USER_VAR_5_ = 6005
    USER_VAR_6_ = 6006
    USER_VAR_7_ = 6007
    USER_VAR_8_ = 6008
    USER_VAR_9_ = 6009
    USER_VAR_10_ = 6010
    USER_VAR_11_ = 6011
    USER_VAR_12_ = 6012
    USER_VAR_13_ = 6013
    USER_VAR_14_ = 6014
    USER_VAR_15_ = 6015
    USER_VAR_16_ = 6016
    USER_VAR_17_ = 6017
    USER_VAR_18_ = 6018
    USER_VAR_19_ = 6019
    USER_VAR_20_ = 6020
    USER_VAR_21_ = 6021
    USER_VAR_22_ = 6022
    USER_VAR_23_ = 6023
    USER_VAR_24_ = 6024
    USER_VAR_25_ = 6025
    NODATA_ = MAXVARS
End Enum

'hardware channels used
Enum HardwareChannels
    ENCSERIALHARDC = 1 'Encrypted serial number channel
    STARTSTOPHARDC = 2 'Run Informtion Input
    GPSRAWDATA = 3 'Raw GPS Data Input
    SECTORTIMEHARDC = 4 'New Sector Time
    MARKERHARDC = 5 'New Lap Marker
    LOGGERSERIALNUMBERC = 6 'Logger Storage Channel
    GPSTIMEMSWEEKC = 7 'GPS Time Storage Channel
    ACCELSHARDC = 8 'Accelerations
    TIMEHARDC = 9 'Time Stamp
    GPSPOSHARDC = 10 'GPS Positional Data
    GPSSPEEDHARDC = 11 'GPS Raw Speed Data
    BEACONHARDC = 12 'Beacon Pulse Present
    FREQ0HARDC = 14 'Frequency 1
    FREQ1HARDC = 15 'Frequency 2
    FREQ2HARDC = 16 'Frequency 3
    FREQ3HARDC = 17 'Frequency 4
    RPMHARDC = 18 'RPM
    SERIALDATAHARDC = 19 'Serial Data Input
    ADC0HARDC = 20 'Analogue 1
    ADC1HARDC = 21 'Analogue 2
    ADC2HARDC = 22 'Analogue 3
    ADC3HARDC = 23 'Analogue 4
    ADC4HARDC = 24 'Analogue 5
    ADC5HARDC = 25 'Analogue 6
    ADC6HARDC = 26 'Analogue 7
    ADC7HARDC = 27 'Analogue 8
    ADC8HARDC = 28 'Analogue 9
    ADC9HARDC = 29 'Analogue 10
    ADC10HARDC = 30 'Analogue 11
    ADC11HARDC = 31 'Analogue 12
    ADC12HARDC = 32 'Analogue 13
    ADC13HARDC = 33 'Analogue 14
    ADC14HARDC = 34 'Analogue 15
    ADC15HARDC = 35 'Analogue 16
    ADC16HARDC = 36 'Analogue 17
    ADC17HARDC = 37 'Analogue 18
    ADC18HARDC = 38 'Analogue 19
    ADC19HARDC = 39 'Analogue 20
    ADC20HARDC = 40 'Analogue 21
    ADC21HARDC = 41 'Analogue 22
    ADC22HARDC = 42 'Analogue 23
    ADC23HARDC = 43 'Analogue 24
    ADC24HARDC = 44 'Analogue 25
    ADC25HARDC = 45 'Analogue 26
    ADC26HARDC = 46 'Analogue 27
    ADC27HARDC = 47 'Analogue 28
    ADC28HARDC = 48 'Analogue 29
    ADC29HARDC = 49 'Analogue 30
    ADC30HARDC = 50 'Analogue 31
    ADC31HARDC = 51 'Analogue 32
    PROCESSEDSPEEDHARDC__OLD = 30
    GPSDATEHARDC = 55 'Date Storage Channel
    GPSHEADINGHARDC = 56 'GPS Course Data
    GPSALTHARDC = 57 'GPS Altitude and Speed Accuracy
    EXTENDED_FREQ0HARDC = 58 'Extended Frequency 1
    EXTENDED_FREQ1HARDC = 59 'Extended Frequency 2
    EXTENDED_FREQ2HARDC = 60 'Extended Frequency 3
    EXTENDED_FREQ3HARDC = 61 'Extended Frequency 4
    EXTENDED_RPMHARDC = 62 'Extended RPM
    PROCESSEDSPEEDHARDC = 64 'Processed Speed Data
    HARDC_ECU_MODULETYPE = 71 'Auxillery Input Module Number
    HARDC_ECU_TEMP = 72 'External Temperature Channel
    HARDC_ECU_FREQ = 73 'External Frequency Channel
    HARDC_ECU_PERC = 74 'External Percentage Channel
    HARDC_ECU_TIME = 75 'External Time Channel
    PROCESSEDDISTANCEHARDC = 78 'Pre Calculated Distance Data Channel
    YAWGYROHARDC = 79 'Yaw Rates Channel
    HARDC_GPSYAW = 80 'Calculated Yaw Channel
    HARDC_PITCH_RATE = 81 'Pitch Rate Channel
    HARDC_PITCH = 82 'Pitch Angle Channel
    HARDC_ROLL_RATE = 83 'Roll Rate Channel
    HARDC_ROLL = 84 'Roll Angle Channel
    GPSGRADIENTHARDC = 85 'Gradient Channel
    HARDC_PULSE0 = 86 'Pulse Count 1
    HARDC_PULSE1 = 87 'Pulse Count 2
    HARDC_PULSE2 = 88 'Pulse Count 3
    HARDC_PULSE3 = 89 'Pulse Count 4
    HARDC_BASELINERTK = 90 'Baseline Channel
    HARDC_Z_ACCEL = 92 'Z Acceleration
    HARDC_ECU_ANGLE = 93 'External Angle Channel
    HARDC_ECU_PRESSURE = 94 'External Pressure Channel
    HARDC_ECU_MISC = 95 'External Miscellaneous Channel
    HARDC_VIDEO_INDEX = 104 'Video frame index
    HARDC_DEBUG_VAR_FP_0 = &HD0 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_1 = &HD1 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_2 = &HD2 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_3 = &HD3 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_4 = &HD4 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_5 = &HD5 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_6 = &HD6 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_7 = &HD7 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_8 = &HD8 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_9 = &HD9 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_A = &HDA 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_B = &HDB 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_C = &HDC 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_D = &HDD 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_E = &HDE 'Debug Channel (Float)
    HARDC_DEBUG_VAR_FP_F = &HDF 'Debug Channel (Float)
    HARDC_DEBUG_VAR_U32_0 = &HE0 'Debug Channel (U32)
    HARDC_DEBUG_VAR_U32_1 = &HE1 'Debug Channel (U32)
    HARDC_DEBUG_VAR_U32_2 = &HE2 'Debug Channel (U32)
    HARDC_DEBUG_VAR_U32_3 = &HE3 'Debug Channel (U32)
    HARDC_DEBUG_VAR_U32_4 = &HE4 'Debug Channel (U32)
    HARDC_DEBUG_VAR_U32_5 = &HE5 'Debug Channel (U32)
    HARDC_DEBUG_VAR_U32_6 = &HE6 'Debug Channel (U32)
    HARDC_DEBUG_VAR_U32_7 = &HE7 'Debug Channel (U32)
    HARDC_DEBUG_VAR_S32_0 = &HF0 'Debug Channel (U32)
    HARDC_DEBUG_VAR_S32_1 = &HF1 'Debug Channel (U32)
    HARDC_DEBUG_VAR_S32_2 = &HF2 'Debug Channel (U32)
    HARDC_DEBUG_VAR_S32_3 = &HF3 'Debug Channel (U32)
    HARDC_DEBUG_VAR_S32_4 = &HF4 'Debug Channel (U32)
    HARDC_DEBUG_VAR_S32_5 = &HF5 'Debug Channel (U32)
    HARDC_DEBUG_VAR_S32_6 = &HF6 'Debug Channel (U32)
    HARDC_DEBUG_VAR_S32_7 = &HF7 'Debug Channel (U32)
    GPSPULSEHARDC = 13 'GPS pulse present
End Enum

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       SerialNumber
' Description:       return version of the serial decorder
'
' Parameters :       no parameters
'--------------------------------------------------------------------------------
'</CSCM>
Public Function SerialNumber() As String
    SerialNumber = App.ProductName & " v" & App.Major & "." & App.Minor & "." & App.Revision
End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       ExtractNextRTMessage
' Description:       decode all serial data
'
' Parameters :       RawRunData() (Byte)
'                    RawSample (Long)
'                    LengthOfRawArray (Long)
'                    ReturnedFloatValues() (Double)
'                    ReturnedChannels() (Long)
'                    NumReturnedFloatChannels (Long)
'                    ReturnedByteValues() (Byte)
'                    NumberOfBytesReturned (Long)
'                    BytesReturned (Boolean)
'                    HardwareChannel (Long)
'                    ErrorState (RtMessageError)
'                    ReturnDataValues (Boolean)
'--------------------------------------------------------------------------------
'</CSCM>
Public Sub ExtractNextRTMessage(ByRef RawRunData() As Byte, _
                                ByRef RawSample As Long, _
                                ByVal LengthOfRawArray As Long, _
                                ByRef ReturnedFloatValues() As Double, _
                                ByRef ReturnedChannels() As Long, _
                                ByRef NumReturnedFloatChannels As Long, _
                                ByRef ReturnedByteValues() As Byte, _
                                ByRef NumberOfBytesReturned As Long, _
                                ByRef BytesReturned As Boolean, _
                                ByRef HardwareChannel As Long, _
                                ByRef ErrorState As RtMessageError, _
                                ByRef ReturnDataValues As Boolean)
    'RawRunData() as byte   ____this is the main raw data input array
    'RawSample As Long    ___the next index to the raw data input array
    'LengthOfRawArray As Long   ___this is the last element of the data array
    'ReturnedFloatValues() As Double  ___these are the returned float values
    'ReturnedChannels() As Long   ___these are the channels associated with the results array
    'NumReturnedFloatChannels As Long ___this is the number of valid results
    'ReturnedByteValues() As Double   ___this is the returned byte values
    'BytesReturned As Boolean ___this is the number of bytes that are returned
    'HardwareChannel As Long  ___this is the hardware channel that the data was extracted from
    'ErrorState As RtMessageError ___this is the error state
    Dim ByteCounter As Long

    If LengthOfRawArray <= RawSample Then
        ErrorState = InsufficientData
        Exit Sub
    End If

    Dim ChecksumResult As RtMessageError
    NumReturnedFloatChannels = 0
    HardwareChannel = RawRunData(RawSample)
    Dim LengthofRawData As Long
    Dim Exponent As Single

    'decode serial data according to hardware channels
    'Debug.Print RawSample
    Select Case HardwareChannel 'channel0 is adc channel 0

        Case TIMEHARDC 'AJD - no serial data?
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, U24CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                Dim NewTimeIndex As Long
                DecodeU24 RawRunData, RawSample + 1, NewTimeIndex
                NumReturnedFloatChannels = 1
                ReturnedFloatValues(0) = NewTimeIndex / 100
                ReturnedChannels(0) = TIMES_
                BytesReturned = False
                RawSample = RawSample + U24CHANNELLENGTH
            End If

        Case STARTSTOPHARDC 'Run Informtion Input(data logger start stop information)
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, STARTSTOPCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim ReturnedString As String
                    ReturnedString = GetStartStopInfo(RawRunData, RawSample)
                    BytesReturned = True
                    NumberOfBytesReturned = Len(ReturnedString) - 1

                    For ByteCounter = 0 To NumberOfBytesReturned
                        ReturnedByteValues(ByteCounter) = Asc(Mid(ReturnedString, ByteCounter + 1, 1))
                    Next

                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = CLng(&H100) * CLng(RawRunData(RawSample + 8)) + CLng(RawRunData(RawSample + 9))
                    ReturnedChannels(0) = BUFFERSIZE_
                    RawSample = RawSample + STARTSTOPCHANNELLENGTH
                Else
                    RawSample = RawSample + STARTSTOPCHANNELLENGTH
                End If
            End If

        Case MARKERHARDC 'this channel defines a new marker on the track
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, MARKERCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    RawSample = RawSample + MARKERCHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = 0
                    ReturnedChannels(0) = NODATA_
                    BytesReturned = False
                Else
                    RawSample = RawSample + MARKERCHANNELLENGTH
                End If
            End If

        Case SECTORTIMEHARDC 'hardware channel for sector time
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, SECTORTIMECHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = 0
                    ReturnedChannels(0) = NODATA_
                    BytesReturned = False
                    RawSample = RawSample + SECTORTIMECHANNELLENGTH
                Else
                    RawSample = RawSample + SECTORTIMECHANNELLENGTH
                End If
            End If

        Case GPSPULSEHARDC 'GPS pulse present
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, DIGITALCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim DigOutput As Single
                    DecodeDigital RawRunData, RawSample + 1, DigOutput
                    RawSample = RawSample + DIGITALCHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = DigOutput
                    ReturnedChannels(0) = NODATA_
                    BytesReturned = False
                Else
                    RawSample = RawSample + DIGITALCHANNELLENGTH
                End If
            End If

        Case GPSTIMEMSWEEKC 'GPS Time Storage Channel
            'AJD - no interpolation, is it required?
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, U32CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim GpsTimeInMs As Double
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = ExtractU32MsbFirst(RawRunData, RawSample + 1)
                    RawSample = RawSample + U32CHANNELLENGTH
                    ReturnedChannels(0) = GPSMSTIME_
                    BytesReturned = False
                Else
                    RawSample = RawSample + U32CHANNELLENGTH
                End If
            End If

        Case GPSSPEEDHARDC 'GPS Raw Speed Data
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSSPEEDCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim GpsSpeedOutput As Single, GpsSpeedAccuracyOutput As Single
                    DecodeGpsSpeed RawRunData, RawSample + 1, GpsSpeedOutput, GpsSpeedAccuracyOutput
                    RawSample = RawSample + GPSSPEEDCHANNELLENGTH
                    NumReturnedFloatChannels = 3
                    ReturnedFloatValues(0) = GpsSpeedOutput * 3.6 'the factor of 3.6 goes from m/s to kph
                    ReturnedFloatValues(1) = GpsSpeedAccuracyOutput
                    ReturnedFloatValues(2) = GpsSpeedOutput * 3.6
                    ReturnedChannels(0) = GPSSPEED_
                    ReturnedChannels(1) = GPSSPEEDACC_
                    ReturnedChannels(2) = GPSRAWVEL_
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSSPEEDCHANNELLENGTH
                End If

            ElseIf ErrorState = ChecksumError Then
                'Debug.Print "CK error"
            End If

        Case GPSPOSHARDC 'GPS Positional Data
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSPOSCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim Longitude As Double, Latitude As Double, PosAcc As Single
                    Dim XPos As Double, YPos As Double
                    DecodeGpsPosition RawRunData, RawSample + 1, Longitude, Latitude, PosAcc
                    NumReturnedFloatChannels = 5
                    ReturnedFloatValues(0) = Longitude
                    ReturnedFloatValues(1) = Latitude
                    ReturnedFloatValues(2) = PosAcc
                    ReturnedFloatValues(3) = Longitude / 180 * PI
                    ReturnedFloatValues(4) = Latitude / 180 * PI
                    ReturnedChannels(0) = POSXM_
                    ReturnedChannels(1) = POSYM_
                    ReturnedChannels(2) = GPSPOSITIONACC_
                    ReturnedChannels(3) = GPSRAWLONGITUDE_
                    ReturnedChannels(4) = GPSRAWLATITUDE_
                    RawSample = RawSample + GPSPOSCHANNELLENGTH
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSPOSCHANNELLENGTH
                End If
            End If

        Case GPSALTHARDC 'GPS Altitude and Speed Accuracy
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSALTLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim Altitude As Single, AltAcc As Single
                    DecodeGpsAltitude RawRunData, RawSample + 1, Altitude, AltAcc
                    RawSample = RawSample + GPSALTLENGTH
                    NumReturnedFloatChannels = 2
                    ReturnedFloatValues(0) = Altitude
                    ReturnedFloatValues(1) = AltAcc
                    ReturnedChannels(0) = GPSALTITUDE_
                    ReturnedChannels(1) = GPSALTACC_
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSALTLENGTH
                End If
            End If

        Case GPSGRADIENTHARDC 'Gradient Channel-this was added to support the brakebox
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSGRADIENTCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim Gradient As Single, GradientAcc As Single
                    DecodeGpsGradient RawRunData, RawSample + 1, Gradient, GradientAcc
                    RawSample = RawSample + GPSGRADIENTCHANNELLENGTH
                    NumReturnedFloatChannels = 2
                    ReturnedFloatValues(0) = Gradient
                    ReturnedFloatValues(1) = GradientAcc
                    ReturnedChannels(0) = GPSGRADIENT_
                    ReturnedChannels(1) = GPSGRADIENTACC_
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSGRADIENTCHANNELLENGTH
                End If
            End If

        Case GPSHEADINGHARDC 'GPS Course Data
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSHEADINGLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim Heading As Single, HeadAcc As Single
                    DecodeGpsHeading RawRunData, RawSample + 1, Heading, HeadAcc
                    RawSample = RawSample + GPSHEADINGLENGTH
                    NumReturnedFloatChannels = 2
                    ReturnedFloatValues(0) = Heading
                    ReturnedFloatValues(1) = HeadAcc
                    ReturnedChannels(0) = GPSHEADING_
                    ReturnedChannels(1) = GPSHEADINGACC_
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSHEADINGLENGTH
                End If
            End If

        Case HARDC_GPSYAW 'Calculated Yaw Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSYAWLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = (&H7F And CLng(RawRunData(RawSample + 1))) * CDbl(256) / 100 + RawRunData(RawSample + 2) / 100

                    If ((CByte(&H80) And CByte(RawRunData(RawSample + 1))) > 0) Then ReturnedFloatValues(0) = -(CDbl(256) * 128 / 100) + ReturnedFloatValues(0)
                    ReturnedFloatValues(0) = ReturnedFloatValues(0) / 180 * PI
                    ReturnedChannels(0) = GPSRTKYAW_
                    RawSample = RawSample + GPSYAWLENGTH
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSYAWLENGTH
                End If
            End If

        Case HARDC_PITCH 'Pitch Rate Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSPITCHLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = (&H7F And CDbl(RawRunData(RawSample + 1))) * CDbl(256) / 100 + RawRunData(RawSample + 2) / 100

                    If ((CByte(&H80) And CByte(RawRunData(RawSample + 1))) > 0) Then ReturnedFloatValues(0) = -(CDbl(256) * 128 / 100) + ReturnedFloatValues(0)
                    ReturnedFloatValues(0) = ReturnedFloatValues(0) / 180 * PI
                    ReturnedChannels(0) = GPSRTKPITCH_
                    RawSample = RawSample + GPSPITCHLENGTH
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSPITCHLENGTH
                End If
            End If

        Case GPSDATEHARDC 'Date Storage Channel-GPS time etc..
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSDATELENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    NumReturnedFloatChannels = 6
                    Dim Second As Long, Minute As Long, Hour As Long, Day As Long, Month As Long, Year As Long
                    DecodeGpsGmtTimeDate RawRunData, RawSample, Second, Minute, Hour, Day, Month, Year
                    RawSample = RawSample + GPSDATELENGTH
                    ReturnedFloatValues(0) = Second
                    ReturnedFloatValues(1) = Minute
                    ReturnedFloatValues(2) = Hour
                    ReturnedFloatValues(3) = Day
                    ReturnedFloatValues(4) = Month
                    ReturnedFloatValues(5) = Year
                    ReturnedChannels(0) = NODATA_
                    ReturnedChannels(1) = NODATA_
                    ReturnedChannels(2) = NODATA_
                    ReturnedChannels(3) = NODATA_
                    ReturnedChannels(4) = NODATA_
                    ReturnedChannels(5) = NODATA_
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSDATELENGTH
                End If
            End If

        Case LOGGERSERIALNUMBERC ' Logger Storage Channel-logger boot version,firmware version
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, LOGGERSERIALNUMBERCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim LoggerSerialNumber As Long
                    Dim BootVersion As Long
                    Dim FirmVersion As Long
                    DecodeLoggerSerialNumber RawRunData, RawSample + 1, LoggerSerialNumber, BootVersion, FirmVersion
                    RawSample = RawSample + LOGGERSERIALNUMBERCHANNELLENGTH
                    NumReturnedFloatChannels = 3
                    ReturnedFloatValues(0) = LoggerSerialNumber
                    ReturnedFloatValues(1) = BootVersion
                    ReturnedFloatValues(2) = FirmVersion
                    ReturnedChannels(0) = NODATA_
                    ReturnedChannels(1) = NODATA_
                    ReturnedChannels(2) = NODATA_
                    BytesReturned = False
                Else
                    RawSample = RawSample + LOGGERSERIALNUMBERCHANNELLENGTH
                End If
            End If

        Case ENCSERIALHARDC ' Encrypted serial number channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ENCSERIALHARDCLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim DateWhenLogged As Long
                    Dim SerialNumber As Long
                    DecodeEncodedLoggerSerialNumber RawRunData, RawSample + 1, LoggerSerialNumber, DateWhenLogged
                    RawSample = RawSample + ENCSERIALHARDCLENGTH
                    NumReturnedFloatChannels = 2
                    ReturnedFloatValues(0) = LoggerSerialNumber
                    ReturnedFloatValues(1) = DateWhenLogged
                    ReturnedChannels(0) = NODATA_
                    ReturnedChannels(1) = NODATA_
                    BytesReturned = False
                Else
                    RawSample = RawSample + ENCSERIALHARDCLENGTH
                End If
            End If

        Case ADC0HARDC To ADC31HARDC 'ADC hardware channels(Analogue 1 to 32)
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ADCCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim AnalogueOutput As Single
                    DecodeAdc RawRunData, RawSample + 1, AnalogueOutput
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = AnalogueOutput
                    ReturnedChannels(0) = FindAnalogueChannel(RawRunData(RawSample))
                    RawSample = RawSample + ADCCHANNELLENGTH
                    BytesReturned = False
                Else
                    RawSample = RawSample + ADCCHANNELLENGTH
                End If

            Else
                'this is to cover us for the old AX22 which had processed speed on the wrong channel!
                ErrorState = CheckCheckSumDL1(RawRunData, RawSample, PROCESSEDSPEEDCHANNELLENGTH, LengthOfRawArray)

                If ErrorState = DataOk Then 'if no check sum errors
                    If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                        Dim ProcessedSpeed2 As Single
                        DecodeProcessedSpeed RawRunData, RawSample + 1, ProcessedSpeed2
                        RawSample = RawSample + PROCESSEDSPEEDCHANNELLENGTH
                        NumReturnedFloatChannels = 1
                        ReturnedFloatValues(0) = ProcessedSpeed2
                        ReturnedChannels(0) = GPSSPEED_
                        BytesReturned = False
                    Else
                        RawSample = RawSample + PROCESSEDSPEEDCHANNELLENGTH
                    End If
                End If
            End If

        Case PROCESSEDSPEEDHARDC 'Processed Speed Data
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, PROCESSEDSPEEDCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim ProcessedSpeed As Single
                    DecodeProcessedSpeed RawRunData, RawSample + 1, ProcessedSpeed
                    RawSample = RawSample + PROCESSEDSPEEDCHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = ProcessedSpeed
                    ReturnedChannels(0) = GPSSPEED_
                    BytesReturned = False
                Else
                    RawSample = RawSample + PROCESSEDSPEEDCHANNELLENGTH
                End If
            End If

        Case PROCESSEDDISTANCEHARDC 'Pre Calculated Distance Data Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, PROCESSEDDISTANCECHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim ProcessedDistance As Single
                    DecodeProcessedDistance RawRunData, RawSample + 1, ProcessedDistance
                    RawSample = RawSample + PROCESSEDDISTANCECHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = ProcessedDistance
                    ReturnedChannels(0) = DISTANCE_
                    BytesReturned = False
                Else
                    RawSample = RawSample + PROCESSEDDISTANCECHANNELLENGTH
                End If
            End If

            '--------------------------------------------IMU rate measurements--------------------------------------------------
        Case YAWGYROHARDC 'Yaw Rates Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, YAWGYROCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim YawRate As Single
                    ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 1)) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = -((ReturnedFloatValues(0) - 32768) / 100 / 180 * PI)
                    ReturnedChannels(0) = GYROYAWRATE_
                    RawSample = RawSample + YAWGYROCHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + YAWGYROCHANNELLENGTH
                End If
            End If

        Case HARDC_PITCH_RATE 'Pitch Rate Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSPITCHRATELENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 1)) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = -((ReturnedFloatValues(0) - 32768) / 100 / 180 * PI)
                    ReturnedChannels(0) = GYROPITCHRATE_
                    RawSample = RawSample + GPSPITCHRATELENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSPITCHRATELENGTH
                End If
            End If

        Case HARDC_ROLL_RATE 'Roll Rate Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, GPSROLLRATELENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 1)) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = -((ReturnedFloatValues(0) - 32768) / 100 / 180 * PI)
                    ReturnedChannels(0) = GYROROLLRATE_
                    RawSample = RawSample + GPSROLLRATELENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + GPSROLLRATELENGTH
                End If
            End If

        Case ACCELSHARDC 'hardware channnel for acceleration
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ACCELCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim LongAccel As Single, LatAccel As Single
                    DecodeAccelerometer RawRunData, RawSample + 1, LongAccel, LatAccel
                    RawSample = RawSample + ACCELCHANNELLENGTH
                    NumReturnedFloatChannels = 2
                    ReturnedFloatValues(0) = LongAccel
                    ReturnedFloatValues(1) = LatAccel
                    ReturnedChannels(0) = ACCELLONG_
                    ReturnedChannels(1) = ACCELLAT_
                    BytesReturned = False
                Else
                    RawSample = RawSample + ACCELCHANNELLENGTH
                End If
            End If

        Case HARDC_Z_ACCEL 'hardware channel for acceleration along Z axis
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ZACCELCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim ZAccel As Single
                    DecodeZAccelerometer RawRunData, RawSample + 1, ZAccel
                    RawSample = RawSample + ZACCELCHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = ZAccel
                    ReturnedChannels(0) = ACCEL_Z_
                    BytesReturned = False
                Else
                    RawSample = RawSample + ZACCELCHANNELLENGTH
                End If
            End If

        Case BEACONHARDC 'Beacon Pulse Present
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, DIGITALCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim BeaconOutput As Single
                    DecodeDigital RawRunData, RawSample + 1, BeaconOutput
                    RawSample = RawSample + DIGITALCHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = BeaconOutput
                    ReturnedChannels(0) = TRACKBEACON_
                    BytesReturned = False
                Else
                    RawSample = RawSample + DIGITALCHANNELLENGTH
                End If
            End If

        Case FREQ0HARDC To FREQ3HARDC, RPMHARDC ' frequency and RPM hardware channels
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, FREQCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim Frequency As Single
                    DecodeFreq RawRunData, RawSample + 1, Frequency
                    RawSample = RawSample + FREQCHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = Frequency
                    ReturnedChannels(0) = FindFrequencyChannel(HardwareChannel)
                    BytesReturned = False
                Else
                    RawSample = RawSample + FREQCHANNELLENGTH
                End If
            End If

        Case EXTENDED_FREQ0HARDC To EXTENDED_FREQ3HARDC, EXTENDED_RPMHARDC ' extended frequency and RPM hardware channels
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, EXTENDEDFREQCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim HighPeriod As Single, LowPeriod As Single, PulsePosition As Single
                    DecodeExtendedFreq RawRunData, RawSample + 1, HighPeriod, LowPeriod, PulsePosition
                    Dim HighPeriodChan As Long, LowPeriodChan As Long, PulsePositionChan As Long
                    RawSample = RawSample + EXTENDEDFREQCHANNELLENGTH
                    NumReturnedFloatChannels = 3
                    ReturnedFloatValues(0) = HighPeriod
                    ReturnedFloatValues(1) = LowPeriod
                    ReturnedFloatValues(2) = PulsePosition
                    FindExtendedFrequencyChannel RawRunData(RawSample), ReturnedChannels(0), ReturnedChannels(1), ReturnedChannels(2)
                    BytesReturned = False
                Else
                    RawSample = RawSample + EXTENDEDFREQCHANNELLENGTH
                End If
            End If

        Case HARDC_PULSE0 To HARDC_PULSE3 'hardware channels for pulse count
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, PULSECOUNTLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim PulseCount As Double
                    PulseCount = CDbl(RawRunData(RawSample + 1)) * CDbl(65536) + CDbl(RawRunData(RawSample + 2)) * CDbl(256) + CDbl(RawRunData(RawSample + 3))
                    NumReturnedFloatChannels = 1
                    ReturnedChannels(0) = FindPulseChannel(HardwareChannel)
                    ReturnedFloatValues(0) = PulseCount
                    BytesReturned = False
                    RawSample = RawSample + PULSECOUNTLENGTH
                Else
                    RawSample = RawSample + PULSECOUNTLENGTH
                End If
            End If

        Case HARDC_BASELINERTK 'Baseline Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, BASELINERTKLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    'Dim PulseCount As Double
                    NumReturnedFloatChannels = 2
                    ReturnedChannels(0) = GPSRTKBASELINE_
                    ReturnedChannels(1) = GPSRTKBASELINEACC_
                    ReturnedFloatValues(0) = CDbl((RawRunData(RawSample + 1)) * CDbl(256) + CDbl(RawRunData(RawSample + 2))) / 1000
                    ReturnedFloatValues(1) = CDbl((RawRunData(RawSample + 3)) * CDbl(256) + CDbl(RawRunData(RawSample + 4))) / 10000
                    RawSample = RawSample + BASELINERTKLENGTH
                    BytesReturned = False
                Else
                    RawSample = RawSample + BASELINERTKLENGTH
                End If
            End If

        Case HARDC_VIDEO_INDEX 'Video frame index
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, VIDEOINDEXCHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                    ReturnedChannels(0) = VIDEOFRAME_
                    ReturnedFloatValues(0) = CLng(RawRunData(RawSample + 4)) * 2 ^ 24 + CLng(RawRunData(RawSample + 3)) * 2 ^ 16 + CLng(RawRunData(RawSample + 2)) * 2 ^ 8 + CLng(RawRunData(RawSample + 1))
                    RawSample = RawSample + VIDEOINDEXCHANNELLENGTH
                Else
                    RawSample = RawSample + VIDEOINDEXCHANNELLENGTH
                End If
            End If

        Case SERIALDATAHARDC 'Serial Data Input
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, RawRunData(RawSample + 1) + 3, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    Dim SerialData() As Byte

                    If RawRunData(RawSample + 1) > 0 Then
                        GetSerialData RawRunData, RawSample + 1, SerialData
                        NumReturnedFloatChannels = 0
                        BytesReturned = True
                        NumberOfBytesReturned = RawRunData(RawSample + 1)

                        For ByteCounter = 0 To 100
                            ReturnedByteValues(ByteCounter) = 0
                        Next ByteCounter

                        For ByteCounter = 0 To NumberOfBytesReturned - 1
                            ReturnedByteValues(NumberOfBytesReturned - ByteCounter - 1) = RawRunData(RawSample + 2 + ByteCounter)
                        Next ByteCounter

                    Else
                        NumReturnedFloatChannels = 0
                        BytesReturned = False
                    End If

                    RawSample = RawSample + RawRunData(RawSample + 1) + 3
                Else
                    RawSample = RawSample + RawRunData(RawSample + 1) + 3
                End If
            End If

        Case GPSRAWDATA 'Raw GPS Data Input
            LengthofRawData = RawRunData(RawSample + 1) + 3
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, LengthofRawData, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    NumReturnedFloatChannels = 0
                    BytesReturned = True
                    NumberOfBytesReturned = RawRunData(RawSample + 1)

                    For ByteCounter = 0 To NumberOfBytesReturned - 1
                        ReturnedByteValues(ByteCounter) = RawRunData(RawSample + 2 + ByteCounter)
                    Next ByteCounter

                    RawSample = RawSample + LengthofRawData
                Else
                    RawSample = RawSample + LengthofRawData
                End If
            End If

        Case HARDC_DEBUG_VAR_FP_0, HARDC_DEBUG_VAR_FP_1, HARDC_DEBUG_VAR_FP_2, HARDC_DEBUG_VAR_FP_3, HARDC_DEBUG_VAR_FP_4, HARDC_DEBUG_VAR_FP_5, HARDC_DEBUG_VAR_FP_6, HARDC_DEBUG_VAR_FP_7, HARDC_DEBUG_VAR_FP_8, HARDC_DEBUG_VAR_FP_9, HARDC_DEBUG_VAR_FP_A, HARDC_DEBUG_VAR_FP_B, HARDC_DEBUG_VAR_FP_C, HARDC_DEBUG_VAR_FP_D, HARDC_DEBUG_VAR_FP_E, HARDC_DEBUG_VAR_FP_F 'Debug Channels (Float)
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, DEBUGVAR_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = PicFpToDecSingle(RawRunData, RawSample + 1)
                    ReturnedChannels(0) = RawRunData(RawSample) - HARDC_DEBUG_VAR_FP_0 + DEBUG_VAR_FP_0_
                    RawSample = RawSample + DEBUGVAR_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + DEBUGVAR_CHANNELLENGTH
                End If
            End If

        Case HARDC_DEBUG_VAR_U32_0, HARDC_DEBUG_VAR_U32_1, HARDC_DEBUG_VAR_U32_2, HARDC_DEBUG_VAR_U32_3, HARDC_DEBUG_VAR_U32_4, HARDC_DEBUG_VAR_U32_5, HARDC_DEBUG_VAR_U32_6, HARDC_DEBUG_VAR_U32_7 'Debug Channel (U32)
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, DEBUGVAR_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = ExtractU32LsbFirst(RawRunData, RawSample + 1)
                    ReturnedChannels(0) = RawRunData(RawSample) - HARDC_DEBUG_VAR_U32_0 + DEBUG_VAR_U32_0_
                    RawSample = RawSample + DEBUGVAR_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + DEBUGVAR_CHANNELLENGTH
                End If
            End If

        Case HARDC_DEBUG_VAR_S32_0, HARDC_DEBUG_VAR_S32_1, HARDC_DEBUG_VAR_S32_2, HARDC_DEBUG_VAR_S32_3, HARDC_DEBUG_VAR_S32_4, HARDC_DEBUG_VAR_S32_5, HARDC_DEBUG_VAR_S32_6, HARDC_DEBUG_VAR_S32_7 'Debug Channel (S32)
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, DEBUGVAR_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = ExtractI32LsbFirst(RawRunData, RawSample + 1)
                    ReturnedChannels(0) = RawRunData(RawSample) - HARDC_DEBUG_VAR_S32_0 + DEBUG_VAR_S32_0_
                    RawSample = RawSample + DEBUGVAR_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + DEBUGVAR_CHANNELLENGTH
                End If
            End If

        Case HARDC_ECU_MODULETYPE 'Auxillery Input Module Number
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ECU_MODULETYPE_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    RawSample = RawSample + ECU_MODULETYPE_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    ReturnedFloatValues(0) = 0
                    ReturnedChannels(0) = NODATA_
                    BytesReturned = False
                Else
                    RawSample = RawSample + ECU_MODULETYPE_CHANNELLENGTH
                End If
            End If

        Case HARDC_ECU_TEMP 'External Temperature Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ECU_TEMP_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 3) And &H107F) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = IIf((RawRunData(RawSample + 3) And &H80) <> 0, ReturnedFloatValues(0) - (2 ^ 15), ReturnedFloatValues(0))
                    ReturnedFloatValues(0) = ReturnedFloatValues(0) * 0.1
                    ReturnedChannels(0) = RawRunData(RawSample + 1) + ECU_FIRST_TEMP_ - 1
                    RawSample = RawSample + ECU_TEMP_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + ECU_TEMP_CHANNELLENGTH
                End If
            End If

        Case HARDC_ECU_FREQ 'External Frequency Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ECU_FREQ_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 3)) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = ReturnedFloatValues(0) * 0.1
                    ReturnedChannels(0) = RawRunData(RawSample + 1) + ECU_FIRST_FREQ_ - 1
                    RawSample = RawSample + ECU_FREQ_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + ECU_FREQ_CHANNELLENGTH
                End If
            End If

        Case HARDC_ECU_PERC 'External Percentage Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ECU_PERC_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 3) And &H107F) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = IIf((RawRunData(RawSample + 3) And &H80) <> 0, ReturnedFloatValues(0) - (2 ^ 15), ReturnedFloatValues(0))
                    'ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 3)) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = ReturnedFloatValues(0) * 0.1
                    ReturnedChannels(0) = RawRunData(RawSample + 1) + ECU_FIRST_PERC_ - 1
                    RawSample = RawSample + ECU_PERC_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + ECU_PERC_CHANNELLENGTH
                End If
            End If

        Case HARDC_ECU_TIME 'External Time Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ECU_TIME_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedChannels(0) = RawRunData(RawSample + 1) + ECU_FIRST_TIME_ - 1
                    Dim Multiplier As Byte
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                    Exponent = CLng(RawRunData(RawSample + 2)) And &H807F

                    If (RawRunData(RawSample + 2) And &H8080) Then Exponent = Exponent - 128
                    If Exponent < 20 And Exponent > -20 Then
                        ReturnedFloatValues(0) = CSng((RawRunData(RawSample + 4)) * CSng(&H100) + CSng(RawRunData(RawSample + 3)))
                        ReturnedFloatValues(0) = ReturnedFloatValues(0) * 10 ^ Exponent
                        ReturnedFloatValues(0) = ReturnedFloatValues(0) / 1000 'convert mS to S
                    Else
                        ReturnedFloatValues(0) = 0
                    End If

                    RawSample = RawSample + ECU_TIME_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + ECU_TIME_CHANNELLENGTH
                End If
            End If

        Case HARDC_ECU_ANGLE 'External Angle Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ECU_ANGLE_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 3) And &H107F) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = IIf((RawRunData(RawSample + 3) And &H80) <> 0, ReturnedFloatValues(0) - (2 ^ 15), ReturnedFloatValues(0))
                    ReturnedFloatValues(0) = ReturnedFloatValues(0) * 0.1 'convert from 1/10th of a degree to degrees
                    ReturnedFloatValues(0) = ReturnedFloatValues(0) / 180 * PI 'convert to rads
                    ReturnedChannels(0) = RawRunData(RawSample + 1) + ECU_FIRST_ANGLE_ - 1
                    RawSample = RawSample + ECU_ANGLE_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + ECU_ANGLE_CHANNELLENGTH
                End If
            End If

        Case HARDC_ECU_PRESSURE 'External Pressure Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ECU_PRESSURE_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedChannels(0) = RawRunData(RawSample + 1) + ECU_FIRST_PRESSURE_ - 1
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                    Exponent = CLng(RawRunData(RawSample + 2)) And &H807F

                    If (RawRunData(RawSample + 2) And &H8080) Then Exponent = 128 - Exponent
                    If Exponent < 20 And Exponent > -20 Then
                        ReturnedFloatValues(0) = CSng((RawRunData(RawSample + 4)) * CSng(&H100) + CSng(RawRunData(RawSample + 3)))
                        ReturnedFloatValues(0) = ReturnedFloatValues(0) * 10 ^ Exponent
                        ReturnedFloatValues(0) = ReturnedFloatValues(0) * 100 'this converts from millibar to Pa
                    Else
                        ReturnedFloatValues(0) = 0
                    End If

                    RawSample = RawSample + ECU_PRESSURE_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + ECU_PRESSURE_CHANNELLENGTH
                End If
            End If

        Case HARDC_ECU_MISC 'External Miscellaneous Channel
            ErrorState = CheckCheckSumDL1(RawRunData, RawSample, ECU_MISC_CHANNELLENGTH, LengthOfRawArray)

            If ErrorState = DataOk Then 'if no check sum errors
                If ReturnDataValues Then 'if data should be decoded(TRUE) or not(FALSE)
                    ReturnedFloatValues(0) = CSng(RawRunData(RawSample + 3)) * CSng(&H100) + CSng(RawRunData(RawSample + 2))
                    ReturnedFloatValues(0) = ReturnedFloatValues(0) * 0.01
                    ReturnedChannels(0) = RawRunData(RawSample + 1) + ECU_FIRST_MISC_ - 1
                    RawSample = RawSample + ECU_MISC_CHANNELLENGTH
                    NumReturnedFloatChannels = 1
                    BytesReturned = False
                Else
                    RawSample = RawSample + ECU_MISC_CHANNELLENGTH
                End If
            End If

        Case Else
            RawSample = RawSample + 1
            ErrorState = UnknownMessageType
    End Select

    If ErrorState = ChecksumError Then
        RawSample = RawSample + 1

        If SHOWCHECKERRORS Then Debug.Print "Ck Err: " & HardwareChannel
    End If

End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       CheckCheckSumDL1
' Description:       calculate and Compare checksum with raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    DataLength (Long)
'                    LastArrayElement (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Private Function CheckCheckSumDL1(ByRef RawData() As Byte, _
                                  ByVal Offset As Long, _
                                  ByVal DataLength As Long, _
                                  ByVal LastArrayElement As Long) As RtMessageError
    Dim Checksum As Long
    Checksum = 0
    Dim DataCounter As Long

    If (Offset + DataLength - 2) < LastArrayElement Then

        For DataCounter = 0 To DataLength - 2
            Checksum = Checksum + RawData(Offset + DataCounter)
            Checksum = Checksum And &HFF
        Next

        'If Checksum And &HFF = RawData(Offset + DataLength - 1) Then
        If Checksum = RawData(Offset + DataLength - 1) Then
            CheckCheckSumDL1 = DataOk
            'Debug.Print ".";
        Else
            CheckCheckSumDL1 = ChecksumError '
            '       Debug.Print "E"
            'Debug.Print ">>" & "check error @ " & Offset
        End If

    Else
        CheckCheckSumDL1 = InsufficientData
    End If

End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeU24
' Description:       decode 24 bit unsigned number
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    U24 (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Public Sub DecodeU24(ByRef RawData() As Byte, _
                     ByVal Offset As Long, _
                     ByRef U24 As Long)
    U24 = CLng(RawData(Offset)) * CLng(&H10000) + CLng(RawData(Offset + 1)) * CLng(&H100) + CLng(RawData(Offset + 2))
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeAdc
' Description:       decode ADC channel
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    Voltage (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeAdc(ByRef RawData() As Byte, _
                      ByVal Offset As Long, _
                      ByRef Voltage As Single)
    Voltage = CDbl(RawData(Offset)) * CDbl(&H100) / 1000 + CDbl(RawData(Offset + 1)) / 1000
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeAccelerometer
' Description:       decode acceleration from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    Longitudinal (Single)
'                    Lateral (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeAccelerometer(ByRef RawData() As Byte, _
                                ByVal Offset As Long, _
                                ByRef Longitudinal As Single, _
                                ByRef Lateral As Single)
    Lateral = CDbl(RawData(Offset) And &H7F) + (CDbl(RawData(Offset + 1)) / CDbl(&H100))

    If (RawData(Offset) And &H80) Then
        Lateral = Lateral
    Else
        Lateral = -Lateral
    End If

    Longitudinal = CDbl(RawData(Offset + 2) And &H7F) + (CDbl(RawData(Offset + 3)) / CDbl(&H100))

    If (RawData(Offset + 2) And &H80) Then
        Longitudinal = Longitudinal
    Else
        Longitudinal = -Longitudinal
    End If

End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeZAccelerometer
' Description:       decode acceleration along the Z axis
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    Zacceleration (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeZAccelerometer(ByRef RawData() As Byte, _
                                 ByVal Offset As Long, _
                                 ByRef Zacceleration As Single)
    Zacceleration = CDbl(RawData(Offset) And &H7F) + (CDbl(RawData(Offset + 1)) / CDbl(&H100))

    If (RawData(Offset) And &H80) Then
        Zacceleration = -Zacceleration
    Else
        Zacceleration = Zacceleration
    End If

End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeGpsAltitude
' Description:       decode GPS altitude from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    GpsAlt (Single)
'                    GPSALTACC (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeGpsAltitude(ByRef RawData() As Byte, _
                              ByVal Offset As Long, _
                              ByRef GpsAlt As Single, _
                              ByRef GPSALTACC As Single)
    GpsAlt = ExtractI32MsbFirst(RawData, Offset) / 1000 'convert from mm to m
    GPSALTACC = ExtractI32MsbFirst(RawData, Offset + 4) / 1000 'convert from mm to m
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeGpsHeading
' Description:       decode GPS heading from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    GpsHead (Single)
'                    GpsHeadAcc (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeGpsHeading(ByRef RawData() As Byte, _
                             ByVal Offset As Long, _
                             ByRef GpsHead As Single, _
                             ByRef GpsHeadAcc As Single)
    GpsHead = ExtractI32MsbFirst(RawData, Offset) * 0.00001 / 180 * PI 'convert from ublox units to rads
    GpsHeadAcc = ExtractU32MsbFirst(RawData, Offset + 4) * 0.00001 / 180 * PI 'convert from ublox units to rads
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeGpsPosition
' Description:       decode GPS position as longitude and latitude
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    GpsLong (Double)
'                    GpsLat (Double)
'                    PositionalAcc (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeGpsPosition(ByRef RawData() As Byte, _
                              ByVal Offset As Long, _
                              ByRef GpsLong As Double, _
                              ByRef GpsLat As Double, _
                              ByRef PositionalAcc As Single)
    GpsLong = ExtractI32MsbFirst(RawData, Offset) * 0.0000001
    GpsLat = ExtractI32MsbFirst(RawData, Offset + 4) * 0.0000001
    PositionalAcc = ExtractU32MsbFirst(RawData, Offset + 8) / 1000
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeGpsSpeed
' Description:       return GPS speed and acceleration from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    GpsSpeed (Single)
'                    GPSSPEEDACC (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeGpsSpeed(ByRef RawData() As Byte, _
                           ByVal Offset As Long, _
                           ByRef GpsSpeed As Single, _
                           ByRef GPSSPEEDACC As Single)
    GpsSpeed = ExtractU32MsbFirst(RawData, Offset) / 100
    GPSSPEEDACC = ExtractU32MsbFirst(RawData, Offset + 4) / 100
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeDigital
' Description:       return digital status from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    DigitalState (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeDigital(ByRef RawData() As Byte, _
                          ByVal Offset As Long, _
                          ByRef DigitalState As Single)

    If RawData(Offset) = 1 Then
        DigitalState = 1
    Else
        DigitalState = 0
    End If

End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeFreq
' Description:       return frequency from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    Frequency (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeFreq(ByRef RawData() As Byte, _
                       ByVal Offset As Long, _
                       ByRef Frequency As Single)
    Const TickPeriod As Single = 1.66666666666667E-07
    Frequency = CDbl(RawData(Offset)) * CDbl(&H10000) + CDbl(RawData(Offset + 1)) * CDbl(&H100) + CDbl(RawData(Offset + 2))
    Frequency = Frequency * TickPeriod

    If Frequency > 0 Then Frequency = 1 / Frequency
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeExtendedFreq
' Description:       decode extended data from frequency
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    HighPeriod (Single)
'                    LowPeriod (Single)
'                    PulsePosition (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeExtendedFreq(ByRef RawData() As Byte, _
                               ByVal Offset As Long, _
                               ByRef HighPeriod As Single, _
                               ByRef LowPeriod As Single, _
                               ByRef PulsePosition As Single)
    Const TickPeriod As Single = 1.66666666666667E-07
    PulsePosition = (CDbl(RawData(Offset)) * CDbl(&H10000) + CDbl(RawData(Offset + 1)) * CDbl(&H100) + CDbl(RawData(Offset + 2))) * TickPeriod
    LowPeriod = (CDbl(RawData(Offset + 3)) * CDbl(&H10000) + CDbl(RawData(Offset + 4)) * CDbl(&H100) + CDbl(RawData(Offset + 5))) * TickPeriod
    HighPeriod = (CDbl(RawData(Offset + 6)) * CDbl(&H10000) + CDbl(RawData(Offset + 7)) * CDbl(&H100) + CDbl(RawData(Offset + 8))) * TickPeriod
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeTimeStamp
' Description:       return offset time from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    TimeOffset (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeTimeStamp(ByRef RawData() As Byte, _
                            ByVal Offset As Long, _
                            ByRef TimeOffset As Single)
    Const TickPeriod As Single = 1.66666666666667E-07
    TimeOffset = CDbl(RawData(Offset)) * CDbl(&H10000) + CDbl(RawData(Offset + 1)) * CDbl(&H100) + CDbl(RawData(Offset + 2))
    TimeOffset = TimeOffset * TickPeriod
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeProcessedSpeed
' Description:       return GPS Speed from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    GPSSPEED_ (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeProcessedSpeed(ByRef RawData() As Byte, _
                                 ByVal Offset As Long, _
                                 ByRef GPSSPEED_ As Single)
    GPSSPEED_ = CDbl(RawData(Offset)) * CDbl(&H10000) + CDbl(RawData(Offset + 1)) * CDbl(&H100) + CDbl(RawData(Offset + 2))
    GPSSPEED_ = GPSSPEED_ * 0.001379060159
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       GetSerialData
' Description:       [type_description_here]
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    SerialData() (Byte)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub GetSerialData(ByRef RawData() As Byte, _
                          ByVal Offset As Long, _
                          ByRef SerialData() As Byte)
    ReDim SerialData(RawData(Offset) - 1) As Byte
    Dim ByteCounter As Long

    For ByteCounter = 0 To RawData(Offset) - 1
        SerialData(RawData(Offset) - 1 - ByteCounter) = RawData(Offset + 1 + ByteCounter)
    Next ByteCounter

End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       ExtractU32MsbFirst
' Description:       extract MSB from 32 bit unsign integer
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Public Function ExtractU32MsbFirst(ByRef RawData() As Byte, _
                                   ByVal Offset As Long) As Double
    ExtractU32MsbFirst = CDbl(RawData(Offset)) * 2 ^ 24 + CDbl(RawData(Offset + 1)) * 2 ^ 16 + CDbl(RawData(Offset + 2)) * 2 ^ 8 + CDbl(RawData(Offset + 3))
End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeLoggerSerialNumber
' Description:       return dada logger firmware and boot version from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    SerialNumber (Long)
'                    BootVersion (Long)
'                    Firmware (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeLoggerSerialNumber(ByRef RawData() As Byte, _
                                     ByVal Offset As Long, _
                                     ByRef SerialNumber As Long, _
                                     ByRef BootVersion As Long, _
                                     ByRef Firmware As Long)
    'Channel, serial number MSB? , serial number LSB?, software version,bootloader version, checksum.
    SerialNumber = CDbl(RawData(Offset) And &H3F) * CDbl(&H100) + CDbl(RawData(Offset + 1))
    Firmware = RawData(Offset + 2)
    BootVersion = RawData(Offset + 3)
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       PicFpToDecSingle
' Description:       [type_description_here]
'
' Parameters :       ByteData() (Byte)
'                    Offset (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Public Function PicFpToDecSingle(ByRef ByteData() As Byte, _
                                 ByVal Offset As Long) As Double
    '<EhHeader>
    On Error Resume Next
    '</EhHeader>
    Dim c As Long
    Dim b(3) As Byte
    Dim d(7) As Byte
    Dim s As Boolean
    s = ByteData(Offset) And &H80
    b(0) = ByteData(Offset)
    b(1) = ByteData(Offset + 1)
    b(2) = ByteData(Offset + 2)
    b(3) = ByteData(Offset + 3)
    d(6) = Int((b(0) And &H78) / 8#)
    d(5) = (b(0) And &H7) * 32 + Int((b(1) And &HF8) / 8#)
    d(4) = (b(1) And &H7) * 32 + Int((b(2) And &HF8) / 8#)
    d(3) = (b(2) And &H7) * 32
    c = b(3) + 896
    d(6) = d(6) + ((c And &HF) * 16)

    If s Then d(7) = &H80
    d(7) = d(7) + Int(c / 16#)
    Dim Answer As Double
    RtlMoveMemory Answer, d(0), 8
    PicFpToDecSingle = Answer
End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       ExtractU32LsbFirst
' Description:       extract LSB from 32 bit unsign integer
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Public Function ExtractU32LsbFirst(ByRef RawData() As Byte, _
                                   ByVal Offset As Long) As Double
    ExtractU32LsbFirst = CDbl(RawData(Offset + 3)) * 2 ^ 24 + CDbl(RawData(Offset + 2)) * 2 ^ 16 + CDbl(RawData(Offset + 1)) * 2 ^ 8 + CDbl(RawData(Offset + 0))
End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       ExtractI32LsbFirst
' Description:       extract LSB from 32 bit sign integer
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Public Function ExtractI32LsbFirst(ByRef RawData() As Byte, _
                                   ByVal Offset As Long) As Double
    ExtractI32LsbFirst = CDbl(RawData(Offset + 3) And &H7F) * CDbl(2 ^ 24) + CDbl(RawData(Offset + 2)) * CDbl(2 ^ 16) + CDbl(RawData(Offset + 1)) * CDbl(2 ^ 8) + CDbl(RawData(Offset + 0))
    ExtractI32LsbFirst = IIf((RawData(Offset + 3) And &H80) <> 0, -(2 ^ 31) + ExtractI32LsbFirst, ExtractI32LsbFirst)
End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       ExtractI32MsbFirst
' Description:       extract MSB from 32 bit integer
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Public Function ExtractI32MsbFirst(ByRef RawData() As Byte, _
                                   ByVal Offset As Long) As Double
    ExtractI32MsbFirst = CDbl(RawData(Offset + 0) And &H7F) * CDbl(2 ^ 24) + CDbl(RawData(Offset + 1)) * CDbl(2 ^ 16) + CDbl(RawData(Offset + 2)) * CDbl(2 ^ 8) + CDbl(RawData(Offset + 3))
    ExtractI32MsbFirst = IIf((RawData(Offset + 0) And &H80) <> 0, -(2 ^ 31) + ExtractI32MsbFirst, ExtractI32MsbFirst)
End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeGpsGmtTimeDate
' Description:       return GMT time as year, month, day, hour, minute, second from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    Second (Long)
'                    Minute (Long)
'                    Hour (Long)
'                    Day (Long)
'                    Month (Long)
'                    Year (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeGpsGmtTimeDate(ByRef RawData() As Byte, _
                                 ByVal Offset As Long, _
                                 ByRef Second As Long, _
                                 ByRef Minute As Long, _
                                 ByRef Hour As Long, _
                                 ByRef Day As Long, _
                                 ByRef Month As Long, _
                                 ByRef Year As Long)
    'Dim Offet As Integer
    Second = RawData(Offset + 1)
    Minute = RawData(Offset + 2)
    Hour = RawData(Offset + 3)
    Day = RawData(Offset + 4)
    Month = RawData(Offset + 5)
    Year = CLng(RawData(Offset + 6)) * CLng(&H100) + RawData(Offset + 7)
    'Offset = RawData(Offset + 7)
    'TimeDateString = Hour & ":" & Minute & ":" & Second & "    " & Day & "/" & Month & "/" & Year & " GMT"
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       FindFrequencyChannel
' Description:       return internal variable reference for frequency channel
'
' Parameters :       FreqChan (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Function FindFrequencyChannel(ByVal FreqChan As Long) As Long

    Select Case FreqChan

        Case FREQ0HARDC
            FindFrequencyChannel = DL1_FREQ2_

        Case FREQ1HARDC
            FindFrequencyChannel = DL1_FREQ3_

        Case FREQ2HARDC
            FindFrequencyChannel = DL1_FREQ4_

        Case FREQ3HARDC
            FindFrequencyChannel = DL1_FREQ1_

        Case RPMHARDC
            FindFrequencyChannel = RPM_
    End Select

End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       FindPulseChannel
' Description:       return pulse channel from internal variable reference for given frequency channel
'
' Parameters :       FreqChan (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Function FindPulseChannel(ByVal FreqChan As Long) As Long

    Select Case FreqChan

        Case HARDC_PULSE0
            FindPulseChannel = FREQ2_PULSE_COUNT_

        Case HARDC_PULSE1
            FindPulseChannel = FREQ3_PULSE_COUNT_

        Case HARDC_PULSE2
            FindPulseChannel = FREQ4_PULSE_COUNT_

        Case HARDC_PULSE3
            FindPulseChannel = FREQ1_PULSE_COUNT_
    End Select

End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       FindExtendedFrequencyChannel
' Description:       return internal variable reference for hardware frequency channel
'
' Parameters :       HardwareFreqChan (Long)
'                    HighPeriodSoftChn (Long)
'                    LowPeriodSoftChn (Long)
'                    PulsePositionSoftChn (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Function FindExtendedFrequencyChannel(ByVal HardwareFreqChan As Long, ByRef HighPeriodSoftChn As Long, ByRef LowPeriodSoftChn As Long, ByRef PulsePositionSoftChn As Long) As Long

    Select Case HardwareFreqChan

        Case EXTENDED_FREQ0HARDC
            HighPeriodSoftChn = FREQ2_HIGHPERIOD_
            LowPeriodSoftChn = FREQ2_LOWPERIOD_
            PulsePositionSoftChn = FREQ2_PULSEPOSITION_

        Case EXTENDED_FREQ1HARDC
            HighPeriodSoftChn = FREQ3_HIGHPERIOD_
            LowPeriodSoftChn = FREQ3_LOWPERIOD_
            PulsePositionSoftChn = FREQ3_PULSEPOSITION_

        Case EXTENDED_FREQ2HARDC
            HighPeriodSoftChn = FREQ4_HIGHPERIOD_
            LowPeriodSoftChn = FREQ4_LOWPERIOD_
            PulsePositionSoftChn = FREQ4_PULSEPOSITION_

        Case EXTENDED_FREQ3HARDC
            HighPeriodSoftChn = FREQ1_HIGHPERIOD_
            LowPeriodSoftChn = FREQ1_LOWPERIOD_
            PulsePositionSoftChn = FREQ1_PULSEPOSITION_
    End Select

End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       FindAnalogueChannel
' Description:       return internal variable reference for ADC channel
'
' Parameters :       AnalgChan (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Function FindAnalogueChannel(ByVal AnalgChan As Long) As Long

    Select Case AnalgChan

        Case ADC0HARDC
            FindAnalogueChannel = DL1_ANAL7_

        Case ADC1HARDC
            FindAnalogueChannel = DL1_ANAL5_

        Case ADC2HARDC
            FindAnalogueChannel = DL1_ANAL6_

        Case ADC3HARDC
            FindAnalogueChannel = DL1_ANAL4_

        Case ADC4HARDC
            FindAnalogueChannel = DL1_ANAL3_

        Case ADC5HARDC
            FindAnalogueChannel = DL1_ANAL1_

        Case ADC6HARDC
            FindAnalogueChannel = DL1_ANAL2_

        Case ADC7HARDC
            FindAnalogueChannel = DL1_ANAL0_

        Case ADC8HARDC
            FindAnalogueChannel = DL1_ANAL15_

        Case ADC9HARDC
            FindAnalogueChannel = DL1_ANAL13_

        Case ADC10HARDC
            FindAnalogueChannel = DL1_ANAL14_

        Case ADC11HARDC
            FindAnalogueChannel = DL1_ANAL12_

        Case ADC12HARDC
            FindAnalogueChannel = DL1_ANAL11_

        Case ADC13HARDC
            FindAnalogueChannel = DL1_ANAL9_

        Case ADC14HARDC
            FindAnalogueChannel = DL1_ANAL10_

        Case ADC15HARDC
            FindAnalogueChannel = DL1_ANAL8_

        Case ADC16HARDC
            FindAnalogueChannel = DL1_ANAL16_

        Case ADC17HARDC
            FindAnalogueChannel = DL1_ANAL17_

        Case ADC18HARDC
            FindAnalogueChannel = DL1_ANAL18_

        Case ADC19HARDC
            FindAnalogueChannel = DL1_ANAL19_

        Case ADC20HARDC
            FindAnalogueChannel = DL1_ANAL20_

        Case ADC21HARDC
            FindAnalogueChannel = DL1_ANAL21_

        Case ADC22HARDC
            FindAnalogueChannel = DL1_ANAL22_

        Case ADC23HARDC
            FindAnalogueChannel = DL1_ANAL23_

        Case ADC24HARDC
            FindAnalogueChannel = DL1_ANAL24_

        Case ADC25HARDC
            FindAnalogueChannel = DL1_ANAL25_

        Case ADC26HARDC
            FindAnalogueChannel = DL1_ANAL26_

        Case ADC27HARDC
            FindAnalogueChannel = DL1_ANAL27_

        Case ADC28HARDC
            FindAnalogueChannel = DL1_ANAL28_

        Case ADC29HARDC
            FindAnalogueChannel = DL1_ANAL29_

        Case ADC30HARDC
            FindAnalogueChannel = DL1_ANAL30_

        Case ADC31HARDC
            FindAnalogueChannel = DL1_ANAL31_

        Case Else
            FindAnalogueChannel = NODATA_
    End Select

End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       GetStartStopInfo
' Description:       return dala log start and stop information
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'--------------------------------------------------------------------------------
'</CSCM>
Private Function GetStartStopInfo(ByRef RawData() As Byte, _
                                  ByVal Offset As Long) As String
    Dim s As String
    Offset = Offset + 1

    Select Case RawData(Offset)

        Case 1
            s = " Logging started by button press. "

        Case 2
            s = " Logging started automatically. "

            Select Case RawData(Offset + 5)

                Case 1 To 8
                    s = s & "Autostart based on analogue voltage. "

                Case 15
                    s = s & "Autostart based on lateral acceleration."

                Case 16
                    s = s & "Autostart based on longitudinal acceleration. "
            End Select

        Case 3
            s = " Logging started by pretrigger. "
    End Select

    Select Case RawData(Offset + 1)

        Case 1
            s = s & "Logging stopped by button press. "

        Case 2
            s = s & "Logging stopped automatically. "

            Select Case RawData(Offset + 6)

                Case 1 - 8
                    s = s & "Autostop based on analogue voltage. "

                Case 15
                    s = s & "Autostop based on lateral acceleration."

                Case 16
                    s = s & "Autostop based on longitudinal acceleration. "
            End Select

        Case 3
            s = s & "Logging stopped by posttrigger. "

        Case 4
            s = s & "Logging stopped by low battery. "

        Case 5
            s = s & "Logging stopped by slow CF card. "

        Case 6
            s = s & "Logging stopped by GSM command. "

        Case 7
            s = s & "Logging stopped by full CF card. "
    End Select

    GetStartStopInfo = s
End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeYawGyroData
' Description:       calculate Yaw rate from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    YawRate (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeYawGyroData(ByRef RawData() As Byte, _
                              ByVal Offset As Long, _
                              ByRef YawRate As Single)
    YawRate = CSng(RawData(Offset + 1)) * CSng(&H100) + CSng(RawData(Offset + 2))
    YawRate = -((YawRate - 32768) / 100 / 180 * PI)
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeGpsGradient
' Description:       calculate GPS gradient and gradient acceleration from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    GpsGradient (Single)
'                    GpsGradientAcc (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeGpsGradient(ByRef RawData() As Byte, _
                              ByVal Offset As Long, _
                              ByRef GpsGradient As Single, _
                              ByRef GpsGradientAcc As Single)
    GpsGradient = ExtractI32MsbFirst(RawData, Offset) * 0.00001 / 180 * PI 'convert from ublox units to rads
    GpsGradientAcc = ExtractU32MsbFirst(RawData, Offset + 4) * 0.00001 / 180 * PI 'convert from ublox units to rads
    'rescale so it goes from -pi to pi, instead of 0 to 2*pi
    GpsGradient = Constrain(GpsGradient, -PI, PI)
End Sub

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       Constrain
' Description:       A modifed modulo type function, used here to limit angles
'
' Parameters :       InputVar (Double)
'                    Lower (Double)
'                    Upper (Double)
'--------------------------------------------------------------------------------
'</CSCM>
Public Function Constrain(ByVal InputVar As Double, _
                          Lower As Double, _
                          Upper As Double) As Double

    If Lower > Upper Then
        InputVar = Lower
    Else
        InputVar = InputVar - (Int(InputVar / (Upper - Lower)) * (Upper - Lower))
        While InputVar < Lower
            InputVar = InputVar + (Upper - Lower)
        Wend
        While InputVar > Upper
            InputVar = InputVar - (Upper - Lower)
        Wend
    End If

    Constrain = InputVar
End Function

'<CSCM>
'--------------------------------------------------------------------------------
' Project    :       Serial Processer
' Procedure  :       DecodeProcessedDistance
' Description:       calculate GPS distance from raw data
'
' Parameters :       RawData() (Byte)
'                    Offset (Long)
'                    GPSDISTANCE_ (Single)
'--------------------------------------------------------------------------------
'</CSCM>
Private Sub DecodeProcessedDistance(ByRef RawData() As Byte, _
                                    ByVal Offset As Long, _
                                    ByRef GPSDISTANCE_ As Single)
    GPSDISTANCE_ = CSng(RawData(Offset)) * CSng(&H1000000) + CSng(RawData(Offset + 1)) * CSng(&H10000) + CSng(RawData(Offset + 2)) * CSng(&H100) + CSng(RawData(Offset + 3))
    GPSDISTANCE_ = GPSDISTANCE_ / 1000 / 1000 'convert from mm to km
End Sub
Page last modified on January 31, 2008, at 05:12 PM