' ****************************************************************************************************
' **    Copyright (C) 2018 - 2020 HMS Technology Center Ravensburg GmbH, all rights reserved
' ****************************************************************************************************
' **
' **        File: simply.vb
' **     Summary: SimplyCAN API for VB.NET
' **              The simplyCAN API provides a simple programming interface for the development
' **              of CAN applications on Windows PCs.
' **
' ****************************************************************************************************
' **    This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
' ****************************************************************************************************
Imports System
Imports System.Text
Imports System.Runtime.InteropServices

''' <summary>
''' Class SimplyCAN declares constants And function prototypes of IXXAT simplyCAN programming
''' interface
''' </summary>
Public Class simply

    ''' <summary>
    ''' Name of the DLL that provides the simplyCAN API
    ''' </summary>
    'Public Const SimplyCANlib As String = "simplyCAN.dll"
    Public Const SimplyCANlib As String = "simplyCAN-64.dll"


#Region "simply Constants"

    ''' <summary>
    ''' CAN status definitions
    ''' </summary>
    Public Const CAN_STATUS_RUNNING As UInt16 = &H1
    Public Const CAN_STATUS_RESET As UInt16 = &H2
    Public Const CAN_STATUS_BUSOFF As UInt16 = &H4
    Public Const CAN_STATUS_ERRORSTATUS As UInt16 = &H8
    Public Const CAN_STATUS_RXOVERRUN As UInt16 = &H10
    Public Const CAN_STATUS_TXOVERRUN As UInt16 = &H20
    Public Const CAN_STATUS_PENDING As UInt16 = &H40

    ''' <summary>
    ''' Error codes of the API functions <para>
    ''' Return value code 0 indicates that no error occured. </para><para>
    ''' Actual errors have a negative value code. </para><para>
    ''' Non-critical errors have a positive value code. </para>
    ''' </summary>
    Public Const SIMPLY_S_NO_ERROR As Int16 = 0 ' No Error occurred
    Public Const SIMPLY_E_SERIAL_OPEN As Int16 = -1 ' Unable To open the serial port
    Public Const SIMPLY_E_SERIAL_ACCESS As Int16 = -2 ' Access On serial port denied
    Public Const SIMPLY_E_SERIAL_CLOSED As Int16 = -3 ' Serial communication port Is closed
    Public Const SIMPLY_E_SERIAL_COMM As Int16 = -4 ' Serial communication Error
    Public Const SIMPLY_E_CMND_REQ_UNKNOWN As Int16 = -5 ' Command() unknown On device
    Public Const SIMPLY_E_CMND_RESP_TIMEOUT As Int16 = -6 ' Command() response timeout reached
    Public Const SIMPLY_E_CMND_RESP_UNEXPECTED As Int16 = -7 ' Unexpected command response received
    Public Const SIMPLY_E_CMND_RESP_ERROR As Int16 = -8 ' Command() response Error
    Public Const SIMPLY_E_INVALID_PROTOCOL_VERSION As Int16 = -9 ' Invalid simplyCAN protocol version
    Public Const SIMPLY_E_INVALID_FW_VERSION As Int16 = -10 ' Invalid device firmware version
    Public Const SIMPLY_E_INVALID_PRODUCT_STRING As Int16 = -11 ' Invalid simplyCAN product String
    Public Const SIMPLY_E_CAN_INVALID_STATE As Int16 = -12 ' Invalid CAN state
    Public Const SIMPLY_E_CAN_INVALID_BAUDRATE As Int16 = -13 ' Invalid CAN baud-rate
    Public Const SIMPLY_E_TX_BUSY As Int16 = -14 ' Message could Not be sent. TX Is busy
    Public Const SIMPLY_E_API_BUSY As Int16 = -15 ' API Is busy

#End Region


#Region "simply Structures"


    ''' <summary>
    ''' Device identification
    ''' </summary>
    <StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Ansi)>
    Public Structure identification_t
        ''' <summary>
        ''' Firmware version string e.g. "1.00.00"
        ''' </summary>
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=8)>
        Public fw_version As String
        ''' <summary>
        ''' Hardware version string e.g. "1.00.00"
        ''' </summary>
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=8)>
        Public hw_version As String
        ''' <summary>
        ''' Product version string e.g. "1.00.00"
        ''' </summary>
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=8)>
        Public product_version As String
        ''' <summary>
        ''' Product name string e.g. "simplyCAN 1.0"
        ''' </summary>
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=30)>
        Public product_string As String
        ''' <summary> 
        ''' Serial number e.g. "HW123456"
        ''' </summary>
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=9)>
        Public serial_number As String
    End Structure

    ''' <summary>
    ''' CAN Message (classic CAN)
    ''' </summary>
    <StructLayout(LayoutKind.Sequential, Pack:=1)>
    Public Structure can_msg_t
        ''' <summary>
        ''' Timestamp in milliseconds
        ''' </summary>
        Public timestamp As UInt32
        ''' <summary>
        ''' CAN identifier (MSB=1: extended frame)
        ''' </summary>
        Public ident As UInt32
        ''' <summary>
        ''' Data Length Code (MSB=1: remote frame)
        ''' </summary>
        Public dlc As Byte
        ''' <summary>
        ''' Data field of classic CAN, must be 8 bytes size
        ''' </summary>
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)>
        Public payload As Byte()
    End Structure

    ''' <summary>
    ''' CAN Status
    ''' </summary>
    <StructLayout(LayoutKind.Sequential, Pack:=1)>
    Public Structure can_sts_t
        ''' <summary>
        ''' Bit coded status flags (see CAN status definitions)
        ''' </summary>
        Public sts As UInt16
        ''' <summary>
        '''  Number of free elements in CAN message tx FIFO
        '''  </summary>
        Public tx_free As UInt16
    End Structure

#End Region

#Region "simply Export Function Delegates"

    ''' <summary>
    ''' Opens the serial communication interface. The message filter of the CAN controller Is opened
    ''' for all message identifiers.
    ''' </summary>
    ''' <param name="serial_port">
    ''' Name of the serial communication port (e.g. COM1 Or /dev/ttyACM0).
    ''' Use the simplyCAN bus monitor to detect on which serial COM port the 
    ''' simplyCAN Is connected. With Windows it Is also possible to use the 
    ''' device manager And with Linux the command "ls -l /dev/serial/by-id".)
    ''' </param>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_open(<MarshalAs(UnmanagedType.LPStr)> serial_port As String) As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Closes the serial communication interface And resets the CAN controller.
    ''' </summary>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_close() As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function



    ''' <summary>
    ''' Initializes the CAN controller.
    ''' </summary>
    ''' <param name="bitrate">
    ''' CAN bitrate as integer value, possible values: 10, 20, 50, 125, 250, 500, 800, 1000
    ''' </param>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_initialize_can(bitrate As UShort) As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Gets firmware And hardware information about the simplyCAN device.
    ''' </summary>
    ''' <param name="p_identification">
    ''' Identification record
    ''' </param>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_identify(ByRef p_identification As identification_t) As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Starts the CAN controller. Sets the CAN controller into running mode And clears the CAN
    ''' message FIFOs. In running mode CAN messages can be transmitted And received.
    ''' </summary>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_start_can() As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Stops the CAN controller. Sets the CAN controller into init mode. Does Not reset the message
    ''' filter of the CAN controller. Only stop the CAN controller when the CAN_STATUS_PENDING flag
    ''' Is Not set.
    ''' </summary>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_stop_can() As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Resets the CAN controller (hardware reset) And clears the message filter (open for all message
    ''' identifiers). Sets the CAN controller into init mode.
    ''' </summary>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_reset_can() As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Gets the status of the CAN controller.
    ''' </summary>
    ''' <param name="can_sts">
    ''' Status as bit coded 16 bit value
    ''' </param>
    ''' <seealso cref="can_sts_t"/>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_can_status(ByRef can_sts As can_sts_t) As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Sets the 11 Or 29 bit message filter of the CAN controller. To set the 29 bit message filter,
    ''' the MSB in parameter value must be set.
    ''' </summary>
    ''' <param name="mask">
    ''' 11 Or 29 bit CAN message identifier mask
    ''' </param>
    ''' <param name="value">
    ''' 11 Or 29 bit CAN message identifier value, set MSB to set the 29 bit 
    ''' message filter
    ''' </param>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_set_filter(ByRef mask As UInt32, ByRef value As UInt32) As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Receives a single CAN message.
    ''' </summary>
    ''' <param name="can_msg">
    ''' Received CAN message
    ''' </param>
    ''' <returns><para>
    ''' 1 - Message received </para><para>
    ''' 0 - No message available in the receive queue </para><para>
    ''' -1 - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_receive(ByRef can_msg As can_msg_t) As SByte
    End Function


    ''' <summary>
    ''' Writes a CAN message to the transmit FIFO. To check if the message Is transmitted, request
    ''' the CAN status with simply_can_status.
    ''' </summary>
    ''' <param name="can_msg">
    ''' CAN message to be transmitted
    ''' </param>
    ''' <returns><para>
    ''' true - Function succeeded </para><para>
    ''' false - Error occurred, call simply_get_last_error for more information. </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_send(ByRef can_msg As can_msg_t) As <MarshalAsAttribute(UnmanagedType.I1)> Boolean
    End Function

    ''' <summary>
    ''' Gets the last error code. After reading the error code with simply_get_last_error the error
    ''' code Is set to 0. Each error can only be read once.
    ''' </summary>
    ''' <returns><para>
    ''' 0 - No error occurred </para><para>
    ''' else - Error occurred (see SIMPLY_E_XXX) </para>
    ''' </returns>
    <DllImport(SimplyCANlib, CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function simply_get_last_error() As Short
    End Function



#End Region


End Class
