Attribute VB_Name = "modDP5_Protocol"
Option Explicit

Public strCommStatus As String
Public Declare Function timeGetTime Lib "winmm.dll" () As Long
Public Packet_Received As Boolean
Public PacketIn(24648) As Byte ' largest possible IN packet
Public PIN As Packet_In
Public UDP_offset As Integer
Public USB_Default_Timeout As Boolean

Public RS232ComPortTest As Boolean
Public USBDeviceTest As Boolean
Public INETRemoteDevice As Boolean

Public Enum TRANSMIT_PACKET_TYPE
     'REQUEST_PACKETS_TO_DP5
    XMTPT_SEND_STATUS
    XMTPT_SEND_SPECTRUM
    XMTPT_SEND_CLEAR_SPECTRUM
    XMTPT_SEND_SPECTRUM_STATUS
    XMTPT_SEND_CLEAR_SPECTRUM_STATUS
    XMTPT_BUFFER_SPECTRUM
    XMTPT_BUFFER_CLEAR_SPECTRUM
    XMTPT_SEND_BUFFER
    XMTPT_SEND_DP4_STYLE_STATUS
    XMTPT_SEND_PX4_CONFIG
    XMTPT_SEND_SCOPE_DATA
    XMTPT_SEND_512_BYTE_MISC_DATA
    XMTPT_SEND_SCOPE_DATA_REARM
    XMTPT_SEND_ETHERNET_SETTINGS
    XMTPT_SEND_DIAGNOSTIC_DATA
    XMTPT_SEND_NETFINDER_PACKET
    XMTPT_SEND_HARDWARE_DESCRIPTION
    XMTPT_SEND_SCA
    XMTPT_LATCH_SEND_SCA
    XMTPT_LATCH_CLEAR_SEND_SCA
    XMTPT_SEND_ROI_OR_FIXED_BLOCK
    XMTPT_PX4_STYLE_CONFIG_PACKET
    XMTPT_SEND_CONFIG_PACKET_EX
    XMTPT_SEND_CONFIG_PACKET_TO_HW
    XMTPT_READ_CONFIG_PACKET
    XMTPT_FULL_READ_CONFIG_PACKET
    XMTPT_ERASE_FPGA_IMAGE
    XMTPT_UPLOAD_PACKET_FPGA
    XMTPT_REINITIALIZE_FPGA
    XMTPT_ERASE_UC_IMAGE_0
    XMTPT_ERASE_UC_IMAGE_1
    XMTPT_ERASE_UC_IMAGE_2
    XMTPT_UPLOAD_PACKET_UC
    XMTPT_SWITCH_TO_UC_IMAGE_0
    XMTPT_SWITCH_TO_UC_IMAGE_1
    XMTPT_SWITCH_TO_UC_IMAGE_2
    XMTPT_UC_FPGA_CHECKSUMS

    'VENDOR_REQUESTS_TO_DP5
    XMTPT_CLEAR_SPECTRUM_BUFFER_A
    XMTPT_ENABLE_MCA_MCS
    XMTPT_DISABLE_MCA_MCS
    XMTPT_ARM_DIGITAL_OSCILLOSCOPE
    XMTPT_AUTOSET_INPUT_OFFSET
    XMTPT_AUTOSET_FAST_THRESHOLD
    XMTPT_READ_IO3_0
    XMTPT_WRITE_IO3_0
    XMTPT_WRITE_512_BYTE_MISC_DATA
    XMTPT_SET_DCAL
    XMTPT_SET_PZ_CORRECTION_UC_TEMP_CAL_PZ
    XMTPT_SET_PZ_CORRECTION_UC_TEMP_CAL_UC
    XMTPT_SET_BOOT_FLAGS
    XMTPT_SET_HV_DP4_EMULATION
    XMTPT_SET_TEC_DP4_EMULATION
    XMTPT_SET_INPUT_OFFSET_DP4_EMULATION
    XMTPT_SET_ADC_CAL_GAIN_OFFSET
    XMTPT_SET_SPECTRUM_OFFSET
    XMTPT_REQ_SCOPE_DATA_MISC_DATA_SCA_PACKETS
    XMTPT_SET_SERIAL_NUMBER
    XMTPT_CLEAR_GP_COUNTER
    XMTPT_SWITCH_SUPPLIES
    
    XMTPT_SEND_TEST_PACKET
    XMTPT_SET_ETHERNET_SETTINGS
    
    XMTPT_KEEP_ALIVE_ALLOW_SHAREING
    XMTPT_KEEP_ALIVE_NO_SHARING
    XMTPT_KEEP_ALIVE_LOCK_IP
'    PID2_ETHERNET_ALLOW_SHAREING = &H20
'    PID2_ETHERNET_NO_SHARING = &H21
'    PID2_ETHERNET_LOCK_IP = &H22
End Enum  'TRANSMIT_PACKET_TYPE

'Public Enum RECEIVE_PACKET_TYPE
'     'RESPONSE_PACKETS_FROM_DP5
'    RCVPT_DP4_STYLE_STATUS
'    RCVPT_256_CHANNEL_SPECTRUM
'    RCVPT_256_CHANNEL_SPECTRUM_STATUS
'    RCVPT_512_CHANNEL_SPECTRUM
'    RCVPT_512_CHANNEL_SPECTRUM_STATUS
'    RCVPT_1024_CHANNEL_SPECTRUM
'    RCVPT_1024_CHANNEL_SPECTRUM_STATUS
'    RCVPT_2048_CHANNEL_SPECTRUM
'    RCVPT_2048_CHANNEL_SPECTRUM_STATUS
'    RCVPT_4096_CHANNEL_SPECTRUM
'    RCVPT_4096_CHANNEL_SPECTRUM_STATUS
'    RCVPT_8192_CHANNEL_SPECTRUM
'    RCVPT_8192_CHANNEL_SPECTRUM_STATUS
'    RCVPT_SCOPE_DATA
'    RCVPT_512_BYTE_MISC_DATA
'    RCVPT_IO3_0_STATE
'End Enum  'RECEIVE_PACKET_TYPE

Public Enum PID1_TYPE
    PID1_REQ_STATUS = &H1
    PID1_REQ_SPECTRUM = &H2
    PID1_REQ_SCOPE_MISC = &H3
    PID1_REQ_SCA = &H4
    PID1_REQ_CONFIG = &H20
    PID1_REQ_FPGA_UC = &H30
    PID1_RCV_STATUS = &H80
    PID1_RCV_SPECTRUM = &H81
    PID1_RCV_SCOPE_MISC = &H82
    PID1_RCV_SCA = &H83
    PID1_VENDOR_REQ = &HF0
    PID1_ACK = &HFF
End Enum  'PID1_TYPE

Public Enum PID2_REQ_STATUS_TYPE
    PID2_SEND_DP4_STYLE_STATUS = &H1
End Enum  'PID2_REQ_STATUS_TYPE

Public Enum PID2_REQ_SPECTRUM_TYPE
    ' REQUEST_PACKETS_TO_DP5
    PID2_SEND_SPECTRUM = &H1
    PID2_SEND_CLEAR_SPECTRUM = &H2
    PID2_SEND_SPECTRUM_STATUS = &H3
    PID2_SEND_CLEAR_SPECTRUM_STATUS = &H4
    'PID2_BUFFER_SPECTRUM
    'PID2_BUFFER_CLEAR_SPECTRUM
    'PID2_SEND_BUFFER
    'PID2_SEND_CONFIG
End Enum  'PID2_REQ_SPECTRUM_TYPE

Public Enum PID2_REQ_SCOPE_MISC_TYPE
    PID2_SEND_SCOPE_DATA = &H1
    PID2_SEND_512_BYTE_MISC_DATA = &H2
    PID2_SEND_SCOPE_DATA_REARM = &H3
    PID2_SEND_ETHERNET_SETTINGS = &H4
    PID2_SEND_DIAGNOSTIC_DATA = &H5
    PID2_SEND_HARDWARE_DESCRIPTION = &H6
    PID2_SEND_NETFINDER_READBACK = &H7
End Enum  'PID2_REQ_SCOPE_MISC_TYPE

Public Enum PID2_REQ_SCA_TYPE
    PID2_SEND_SCA = &H1
    PID2_LATCH_SEND_SCA = &H2
    PID2_LATCH_CLEAR_SEND_SCA = &H3
End Enum  'PID2_REQ_SCA_TYPE

Public Enum PID2_REQ_CONFIG_TYPE
    PID2_PX4_STYLE_CONFIG_PACKET = &H1
    PID2_TEXT_CONFIG_PACKET = &H2
    PID2_CONFIG_READBACK_PACKET = &H3
End Enum  'PID2_SEND_CONFIG_TYPE

Public Enum PID2_REQ_FPGA_UC_TYPE
    PID2_ERASE_FPGA_IMAGE = &H1
    PID2_UPLOAD_PACKET_FPGA = &H2
    PID2_REINITIALIZE_FPGA = &H3
    PID2_ERASE_UC_IMAGE_0 = &H4
    PID2_ERASE_UC_IMAGE_1 = &H5
    PID2_ERASE_UC_IMAGE_2 = &H6
    PID2_UPLOAD_PACKET_UC = &H7
    PID2_SWITCH_TO_UC_IMAGE_0 = &H8
    PID2_SWITCH_TO_UC_IMAGE_1 = &H9
    PID2_SWITCH_TO_UC_IMAGE_2 = &HA
    'PID2_UC_FPGA_CHECKSUMS
End Enum  'PID2_REQ_FPGA_UC_TYPE

Public Enum PID2_VENDOR_REQ_TYPE
    PID2_CLEAR_SPECTRUM_BUFFER_A = &H1
    PID2_ENABLE_MCA_MCS = &H2
    PID2_DISABLE_MCA_MCS = &H3
    PID2_ARM_DIGITAL_OSCILLOSCOPE = &H4
    PID2_AUTOSET_INPUT_OFFSET = &H5
    PID2_AUTOSET_FAST_THRESHOLD = &H6
    PID2_READ_IO3_0 = &H7
    PID2_WRITE_IO3_0 = &H8
    PID2_WRITE_512_BYTE_MISC_DATA = &H9
    PID2_SET_DCAL = &HA
    PID2_SET_PZ_CORRECTION_UC_TEMP_CAL_PZ = &HB
    PID2_SET_PZ_CORRECTION_UC_TEMP_CAL_UC = &HC
    PID2_SET_BOOT_FLAGS = &HD
    'PID2_SET_HV_DP4_EMULATION
    'PID2_SET_TEC_DP4_EMULATION
    'PID2_SET_INPUT_OFFSET_DP4_EMULATION
    PID2_SET_ADC_CAL_GAIN_OFFSET = &HE
    'PID2_SET_SPECTRUM_OFFSET
    'PID2_REQ_SCOPE_DATA_MISC_DATA_SCA_PACKETS
    PID2_SET_SERIAL_NUMBER = &HF
    PID2_CLEAR_GP_COUNTER = &H10
    PID2_SET_ETHERNET_SETTINGS = &H11
    'PID2_SWITCH_SUPPLIES
    PID2_ETHERNET_ALLOW_SHAREING = &H20
    PID2_ETHERNET_NO_SHARING = &H21
    PID2_ETHERNET_LOCK_IP = &H22
End Enum  'PID2_VENDOR_REQ_TYPE

Public Enum PID2_RCV_STATUS_TYPE
    RCVPT_DP4_STYLE_STATUS = &H1
End Enum  'PID2_RCV_STATUS_TYPE
    
Public Enum PID2_RCV_SPECTRUM_TYPE
    RCVPT_256_CHANNEL_SPECTRUM = &H1
    RCVPT_256_CHANNEL_SPECTRUM_STATUS = &H2
    RCVPT_512_CHANNEL_SPECTRUM = &H3
    RCVPT_512_CHANNEL_SPECTRUM_STATUS = &H4
    RCVPT_1024_CHANNEL_SPECTRUM = &H5
    RCVPT_1024_CHANNEL_SPECTRUM_STATUS = &H6
    RCVPT_2048_CHANNEL_SPECTRUM = &H7
    RCVPT_2048_CHANNEL_SPECTRUM_STATUS = &H8
    RCVPT_4096_CHANNEL_SPECTRUM = &H9
    RCVPT_4096_CHANNEL_SPECTRUM_STATUS = &HA
    RCVPT_8192_CHANNEL_SPECTRUM = &HB
    RCVPT_8192_CHANNEL_SPECTRUM_STATUS = &HC
End Enum  'PID2_RCV_SPECTRUM_TYPE

Public Enum PID2_RCV_SCOPE_MISC_TYPE
    RCVPT_SCOPE_DATA = &H1
    RCVPT_512_BYTE_MISC_DATA = &H2
    RCVPT_SCOPE_DATA_WITH_OVERFLOW = &H3
    RCVPT_ETHERNET_SETTINGS = &H4
    RCVPT_DIAGNOSTIC_DATA = &H5
    RCVPT_HARDWARE_DESCRIPTION = &H6
    RCVPT_CONFIG_READBACK = &H7
    RCVPT_NETFINDER_READBACK = &H8
End Enum  'PID2_REQ_SCOPE_MISC_TYPE

Public Enum PID2_RCV_SCA_TYPE
    RCVPT_SCA = &H1
End Enum  'PID2_REQ_SCA_TYPE

Public Enum PID2_ACK_TYPE  'PID1_ACK, PID2_ACK_TYPE)
    PID2_ACK_OK = &H0
    PID2_ACK_SYNC_ERROR = &H1
    PID2_ACK_PID_ERROR = &H2
    PID2_ACK_LEN_ERROR = &H3
    PID2_ACK_CHECKSUM_ERROR = &H4
    PID2_ACK_BAD_PARAM = &H5
    PID2_ACK_BAD_HEX_REC = &H6
    PID2_ACK_UNRECOG = &H7
    PID2_ACK_FPGA_ERROR = &H8
    PID2_ACK_CP2201_NOT_FOUND = &H9
    PID2_ACK_SCOPE_DATA_NOT_AVAIL = &HA
    PID2_ACK_PC5_NOT_PRESENT = &HB
    PID2_ACK_OK_ETHERNET_SHARE_REQ = &HC
    PID2_ACK_ETHERNET_BUSY = &HD
End Enum  'PID2_ACK_TYPE

'Public Const PID1_ACK = &HFF


Public Const ACK = 0
'Public Const STATUS = 1
'Public Const SPECTRUM = 2
Public Const SYNC1_ = &HF5
Public Const SYNC2_ = &HFA

Public Const RS232 = 0
Public Const USB = 1
Public Const ETHERNET = 2

Public Const ETHERNET_TIMEOUT = 1000   ' default timeout of 1000mS
Public Const INTERNET_TIMEOUT = 3000   ' 3 seconds if DP5 is on different subnet than this PC
Public Const RS232_TIMEOUT = 2500      ' default timeout of 2500mS (8K spectrum ~2.2s)
Public Const USB_TIMEOUT = 500         ' default timeout of 500mS

Public Const ETHERNET_KEEPALIVE = 1500 ' send a keep-alive after 1.5s of interface inactivity
Public Const Retries = 2   ' total of 3 attempts

Public OutStr As String
Public InPacketType As Integer
'Public PacketIn(24648) As Byte ' largest possible IN packet
Public RS232HeaderReceived As Boolean
Public RS232PacketPtr As Integer
'Public CurrentInterface As Byte
Public PlotColor As Long
Public Scope(0 To 2047) As Byte  ' make this a structure, with scope info?
Public ScopeOverFlow As Boolean
Public MiscData(512) As Byte
Public CommError As Boolean

Public Type Packet_In
    PID1 As Byte
    PID2 As Byte
    LEN As Integer  ' signed, but data payload always less than 32768
    STATUS As Byte
    DATA(32768) As Byte
    CheckSum As Long
End Type

Public BufferOUT(520) As Byte

Public Type Packet_Out
    PID1 As Byte
    PID2 As Byte
    LEN As Integer  ' signed, but data payload always less than 32768
    EXPECTEDRESPONSE As Byte
    DATA(514) As Byte
End Type

Public Type Spec
    DATA() As Long  ' this keeps total of static data under 64K VB limit
    Channels As Integer
End Type

Public Type Stat
    RAW(64) As Byte
    SN As Long
    FAST_COUNT As Single    ' LONG is signed :(
    SLOW_COUNT As Single
    FP As Byte
    FW As Byte
    BUILD As Byte
    ACC_TIME As Single
    HV As Single
    DET_TEMP As Single
    DP5_TEMP As Single
    PX4 As Boolean
    AFAST_LOCKED As Boolean
    MCA_EN As Boolean
    PRESET_COUNT_REACHED As Boolean
    PRESET_REALTIME_REACHED As Boolean
    SUPPLIES_ON As Boolean
    SCOPE_DR As Boolean
    DP5_CONFIGURED As Boolean
    GP_COUNTER As Single
    AOFFSET_LOCKED As Boolean
    MCS_DONE As Boolean
    DCAL As Single
    PZCORR As Byte  ' or single?
    UC_TEMP_OFFSET As Byte
    AN_IN As Single
    VREF_IN As Single
    PC5_SN As Long
    PC5_PRESENT As Boolean
    PC5_HV_POL As Boolean
    PC5_8_5V As Boolean
    LIVETIME As Single
    REALTIME As Single
    BOOT_FLAG_LSB As Byte
    BOOT_FLAG_MSB As Byte
    BOOT_HV As Single
    BOOT_TEC As Single
    BOOT_INPOFFSET As Single    ' or long?
    ADC_GAIN_CAL As Single
    ADC_OFFSET_CAL As Byte
    SPECTRUM_OFFSET As Long     ' or single?
    DEVICE_ID As Byte           ' 0=DP5, 1=PX5, 2=DP5G
    REBOOT_FLAG As Boolean      ' FW6.05 and later
    strDeviceID As String
    
    DPP_options As Byte         ' 1=HPGe HVPS
    HPGe_HV_INH As Boolean
    HPGe_HV_INH_POL As Boolean
  
End Type



Public STATUS As Stat
Public SPECTRUM As Spec

'Public POUT As Packet_Out

Public Function msTimeExpired(curStartTimeMS As Currency, curDelayTimeMS As Currency) As Boolean
    Dim curNewTime As Currency
    curNewTime = timeGetTime()
    If curStartTimeMS < 0 Then curStartTimeMS = curStartTimeMS + CCur(2 ^ 32)
    If ((curNewTime < 0) Or (curNewTime < curStartTimeMS)) Then
        curNewTime = curNewTime + CCur(2 ^ 32)
    End If
    msTimeExpired = CBool(curNewTime >= (curStartTimeMS + curDelayTimeMS))
End Function

Public Function msTimeStart() As Currency
    Dim curNewTime As Currency
    msTimeStart = timeGetTime()
End Function

Public Function msTimeDiff(curStartTime As Currency) As Currency
    Dim curNewTime As Currency
    curNewTime = timeGetTime()
    If (curNewTime < curStartTime) Then
        curStartTime = curStartTime
        curNewTime = curNewTime + (2 ^ 32)
        msTimeDiff = curNewTime - curStartTime
    Else
        msTimeDiff = curNewTime - curStartTime
    End If
End Function

Public Function msDelay(MSec As Long) As Boolean
    Dim curStart As Currency
    Dim TimeExpired As Boolean
    Dim i As Long
    TimeExpired = False
    curStart = msTimeStart()
    Do
        DoEvents
        TimeExpired = msTimeExpired(curStart, CCur(MSec))
    Loop While (Not TimeExpired)
    msDelay = TimeExpired
End Function

Public Function SendPacketRS232(IntCtrl As Object, ByRef Buffer() As Byte, ByRef PacketIn() As Byte) As Boolean
    Dim bytesWritten As Long, bytesRead As Long
    Dim success As Boolean
    Dim curStartTime As Currency
    Dim isExpired As Boolean
    Dim strLog As String
    Dim i As Long
    Dim PLen As Long
    
    PLen = (Buffer(4) * 256) + Buffer(5) + 7

    ACK_Received = False
    Packet_Received = False ' a response packet is always expected
    PIN.STATUS = &HFF   ' packet invalid - will be overwritten soon by response/ACK packet

    ' send the packet
    'For i = 0 To POUT.LEN + 7
    For i = 0 To PLen
        IntCtrl.OutPut = Chr(Buffer(i))
    Next i
    Timeout_flag = False
    curStartTime = msTimeStart()
    Do
        DoEvents    ' receive bytes and parse packet
        isExpired = msTimeExpired(curStartTime, 1000)
        If (isExpired) Then Timeout_flag = True
    Loop While (PIN.STATUS = &HFF) And (Timeout_flag = False)  ' wait for ACK or timeout
    If Timeout_flag Then
        strLog = strLog + "Timeout: no response packet!" + vbCrLf
        SendPacketRS232 = False
    Else
        SendPacketRS232 = True
    End If
End Function

Public Function SendPacketInet(IntCtrl As Object, ByRef Buffer() As Byte, ByRef PacketIn() As Byte) As Boolean
    Dim bytesWritten As Long, bytesRead As Long
    Dim success As Boolean
    Dim curStartTime As Currency
    Dim isExpired As Boolean
    Dim strLog As String
    Dim idxData As Long
    Dim PLen As Long
    Dim Buffer_Eth() As Byte
    On Error GoTo SendPacketInetErr
    
    UDP_offset = 0  ' start at the beginning of InPacket()
    PLen = (Buffer(4) * 256) + Buffer(5) + 7
    ReDim Buffer_Eth(PLen)  'make a buffer the size of the data
    ACK_Received = False
    Packet_Received = False ' a response packet is always expected
    PIN.STATUS = &HFF   ' packet invalid - will be overwritten soon by response/ACK packet
    
    For idxData = 0 To PLen
        Buffer_Eth(idxData) = Buffer(idxData)
    Next
    IntCtrl.SendData Buffer_Eth()
    SendPacketInet = True
    
    Exit Function
SendPacketInetErr:
    SendPacketInet = False
End Function



