From 5c8ab29bba02a19ebe12124febd0770a1b6919d8 Mon Sep 17 00:00:00 2001 From: Simon Ausserlechner Date: Fri, 11 Jun 2021 11:03:43 +0200 Subject: [PATCH] feat: extend IXXAT backend to support CAN-FD --- can/interfaces/ixxat/canlib.py | 201 +++++++++++++++++++---------- can/interfaces/ixxat/constants.py | 122 ++++++++++++++++- can/interfaces/ixxat/structures.py | 87 ++++++++++++- 3 files changed, 338 insertions(+), 72 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 13709c71c..13f0247fe 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -47,7 +47,7 @@ # TODO: Use ECI driver for linux if sys.platform == "win32" or sys.platform == "cygwin": try: - _canlib = CLibrary("vcinpl.dll") + _canlib = CLibrary("vcinpl2.dll") except Exception as e: log.warning("Cannot load IXXAT vcinpl library: %s", e) else: @@ -88,7 +88,7 @@ def __vciFormatError(library_instance, function, HRESULT): """ buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) - library_instance.vciFormatError(HRESULT, buf, constants.VCI_MAX_ERRSTRLEN) + library_instance.vciFormatErrorA(HRESULT, buf, constants.VCI_MAX_ERRSTRLEN) return "function {} failed ({})".format( function._name, buf.value.decode("utf-8", "replace") ) @@ -134,9 +134,9 @@ def __check_status(result, function, arguments): # HRESULT VCIAPI vciInitialize ( void ); _canlib.map_symbol("vciInitialize", ctypes.c_long, (), __check_status) - # void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize); + # void VCIAPI vciFormatErrorA (HRESULT hrError, PCHAR pszText, UINT32 dwLength); _canlib.map_symbol( - "vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) + "vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) ) # Hack to have vciFormatError as a free function vciFormatError = functools.partial(__vciFormatError, _canlib) @@ -167,11 +167,19 @@ def __check_status(result, function, arguments): (HANDLE, ctypes.c_uint32, ctypes.c_long, PHANDLE), __check_status, ) - # EXTERN_C HRESULT VCIAPI canChannelInitialize( IN HANDLE hCanChn, IN UINT16 wRxFifoSize, IN UINT16 wRxThreshold, IN UINT16 wTxFifoSize, IN UINT16 wTxThreshold ); + # EXTERN_C HRESULT VCIAPI canChannelInitialize( IN HANDLE hCanChn, IN UINT16 wRxFifoSize, IN UINT16 wRxThreshold, IN UINT16 wTxFifoSize, IN UINT16 wTxThreshold, IN UINT32 dwFilterSize, IN UINT8 bFilterMode ); _canlib.map_symbol( "canChannelInitialize", ctypes.c_long, - (HANDLE, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16), + ( + HANDLE, + ctypes.c_uint16, + ctypes.c_uint16, + ctypes.c_uint16, + ctypes.c_uint16, + ctypes.c_uint32, + ctypes.c_uint8, + ), __check_status, ) # EXTERN_C HRESULT VCIAPI canChannelActivate( IN HANDLE hCanChn, IN BOOL fEnable ); @@ -180,18 +188,18 @@ def __check_status(result, function, arguments): ) # HRESULT canChannelClose( HANDLE hChannel ) _canlib.map_symbol("canChannelClose", ctypes.c_long, (HANDLE,), __check_status) - # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG pCanMsg ); + # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG2 pCanMsg ); _canlib.map_symbol( "canChannelReadMessage", ctypes.c_long, - (HANDLE, ctypes.c_uint32, structures.PCANMSG), + (HANDLE, ctypes.c_uint32, structures.PCANMSG2), __check_status, ) - # HRESULT canChannelPeekMessage(HANDLE hChannel,PCANMSG pCanMsg ); + # HRESULT canChannelPeekMessage(HANDLE hChannel,PCANMSG2 pCanMsg ); _canlib.map_symbol( "canChannelPeekMessage", ctypes.c_long, - (HANDLE, structures.PCANMSG), + (HANDLE, structures.PCANMSG2), __check_status, ) # HRESULT canChannelWaitTxEvent (HANDLE hChannel UINT32 dwMsTimeout ); @@ -208,18 +216,18 @@ def __check_status(result, function, arguments): (HANDLE, ctypes.c_uint32), __check_status, ) - # HRESULT canChannelPostMessage (HANDLE hChannel, PCANMSG pCanMsg ); + # HRESULT canChannelPostMessage (HANDLE hChannel, PCANMSG2 pCanMsg ); _canlib.map_symbol( "canChannelPostMessage", ctypes.c_long, - (HANDLE, structures.PCANMSG), + (HANDLE, structures.PCANMSG2), __check_status, ) - # HRESULT canChannelSendMessage (HANDLE hChannel, UINT32 dwMsTimeout, PCANMSG pCanMsg ); + # HRESULT canChannelSendMessage (HANDLE hChannel, UINT32 dwMsTimeout, PCANMSG2 pCanMsg ); _canlib.map_symbol( "canChannelSendMessage", ctypes.c_long, - (HANDLE, ctypes.c_uint32, structures.PCANMSG), + (HANDLE, ctypes.c_uint32, structures.PCANMSG2), __check_status, ) @@ -230,11 +238,23 @@ def __check_status(result, function, arguments): (HANDLE, ctypes.c_uint32, PHANDLE), __check_status, ) - # EXTERN_C HRESULT VCIAPI canControlInitialize( IN HANDLE hCanCtl, IN UINT8 bMode, IN UINT8 bBtr0, IN UINT8 bBtr1 ); + # EXTERN_C HRESULT VCIAPI canControlInitialize( IN HANDLE hCanCtl, IN UINT8 bOpMode, IN UINT8 bExMode, IN UINT8 bSFMode ); + # IN UINT8 bEFMode, IN UINT32 dwSFIds, IN UINT32 dwEFIds, IN PCANBTP pBtpSDR, + # IN PCANBTP pBTPFDR ); _canlib.map_symbol( "canControlInitialize", ctypes.c_long, - (HANDLE, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8), + ( + HANDLE, + ctypes.c_uint8, + ctypes.c_uint8, + ctypes.c_uint8, + ctypes.c_uint8, + ctypes.c_uint32, + ctypes.c_uint32, + structures.PCANBTP, + structures.PCANBTP, + ), __check_status, ) # EXTERN_C HRESULT VCIAPI canControlClose( IN HANDLE hCanCtl ); @@ -245,18 +265,18 @@ def __check_status(result, function, arguments): _canlib.map_symbol( "canControlStart", ctypes.c_long, (HANDLE, ctypes.c_long), __check_status ) - # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS pStatus ); + # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS2 pStatus ); _canlib.map_symbol( "canControlGetStatus", ctypes.c_long, - (HANDLE, structures.PCANLINESTATUS), + (HANDLE, structures.PCANLINESTATUS2), __check_status, ) - # EXTERN_C HRESULT VCIAPI canControlGetCaps( IN HANDLE hCanCtl, OUT PCANCAPABILITIES pCanCaps ); + # EXTERN_C HRESULT VCIAPI canControlGetCaps( IN HANDLE hCanCtl, OUT PCANCAPABILITIES2 pCanCaps ); _canlib.map_symbol( "canControlGetCaps", ctypes.c_long, - (HANDLE, structures.PCANCAPABILITIES), + (HANDLE, structures.PCANCAPABILITIES2), __check_status, ) # EXTERN_C HRESULT VCIAPI canControlSetAccFilter( IN HANDLE hCanCtl, IN BOOL fExtend, IN UINT32 dwCode, IN UINT32 dwMask ); @@ -289,11 +309,11 @@ def __check_status(result, function, arguments): ) # EXTERN_C HRESULT canSchedulerClose (HANDLE hScheduler ); _canlib.map_symbol("canSchedulerClose", ctypes.c_long, (HANDLE,), __check_status) - # EXTERN_C HRESULT canSchedulerGetCaps (HANDLE hScheduler, PCANCAPABILITIES pCaps ); + # EXTERN_C HRESULT canSchedulerGetCaps (HANDLE hScheduler, PCANCAPABILITIES2 pCaps ); _canlib.map_symbol( "canSchedulerGetCaps", ctypes.c_long, - (HANDLE, structures.PCANCAPABILITIES), + (HANDLE, structures.PCANCAPABILITIES2), __check_status, ) # EXTERN_C HRESULT canSchedulerActivate ( HANDLE hScheduler, BOOL fEnable ); @@ -304,7 +324,7 @@ def __check_status(result, function, arguments): _canlib.map_symbol( "canSchedulerAddMessage", ctypes.c_long, - (HANDLE, structures.PCANCYCLICTXMSG, ctypes.POINTER(ctypes.c_uint32)), + (HANDLE, structures.PCANCYCLICTXMSG2, ctypes.POINTER(ctypes.c_uint32)), __check_status, ) # EXTERN_C HRESULT canSchedulerRemMessage (HANDLE hScheduler, UINT32 dwIndex ); @@ -375,40 +395,30 @@ class IXXATBus(BusABC): """ - CHANNEL_BITRATES = { - 0: { - 10000: constants.CAN_BT0_10KB, - 20000: constants.CAN_BT0_20KB, - 50000: constants.CAN_BT0_50KB, - 100000: constants.CAN_BT0_100KB, - 125000: constants.CAN_BT0_125KB, - 250000: constants.CAN_BT0_250KB, - 500000: constants.CAN_BT0_500KB, - 666000: constants.CAN_BT0_667KB, - 666666: constants.CAN_BT0_667KB, - 666667: constants.CAN_BT0_667KB, - 667000: constants.CAN_BT0_667KB, - 800000: constants.CAN_BT0_800KB, - 1000000: constants.CAN_BT0_1000KB, - }, - 1: { - 10000: constants.CAN_BT1_10KB, - 20000: constants.CAN_BT1_20KB, - 50000: constants.CAN_BT1_50KB, - 100000: constants.CAN_BT1_100KB, - 125000: constants.CAN_BT1_125KB, - 250000: constants.CAN_BT1_250KB, - 500000: constants.CAN_BT1_500KB, - 666000: constants.CAN_BT1_667KB, - 666666: constants.CAN_BT1_667KB, - 666667: constants.CAN_BT1_667KB, - 667000: constants.CAN_BT1_667KB, - 800000: constants.CAN_BT1_800KB, - 1000000: constants.CAN_BT1_1000KB, - }, + CAN_BTP = { + 5000: constants.CAN_BTP_5KB, + 10000: constants.CAN_BTP_10KB, + 20000: constants.CAN_BTP_20KB, + 50000: constants.CAN_BTP_50KB, + 100000: constants.CAN_BTP_100KB, + 125000: constants.CAN_BTP_125KB, + 250000: constants.CAN_BTP_250KB, + 500000: constants.CAN_BTP_500KB, + 800000: constants.CAN_BTP_800KB, + 1000000: constants.CAN_BTP_1000KB, } - def __init__(self, channel, can_filters=None, **kwargs): + CAN_BTP_DBR = { + 1000000: constants.CAN_BTP_DBR_SL_1000KB, + 2000000: constants.CAN_BTP_DBR_SL_2000KB, + 4000000: constants.CAN_BTP_DBR_SL_4000KB, + 5000000: constants.CAN_BTP_DBR_SL_5000KB, + 6667000: constants.CAN_BTP_DBR_SL_6667KB, + 8000000: constants.CAN_BTP_DBR_SL_8000KB, + 10000000: constants.CAN_BTP_DBR_SL_10000KB, + } + + def __init__(self, channel, can_filters=None, fd=False, **kwargs): """ :param int channel: The Channel id to create this bus with. @@ -416,6 +426,9 @@ def __init__(self, channel, can_filters=None, **kwargs): :param list can_filters: See :meth:`can.BusABC.set_filters`. + :param bool fd: + If CAN-FD frames should be supported. + :param bool receive_own_messages: Enable self-reception of sent messages. @@ -424,6 +437,9 @@ def __init__(self, channel, can_filters=None, **kwargs): :param int bitrate: Channel bitrate in bit/s + + :param int data_bitrate: + Channel data bitrate in bit/s (CAN-FD) """ if _canlib is None: raise CanInterfaceNotImplementedError( @@ -433,6 +449,7 @@ def __init__(self, channel, can_filters=None, **kwargs): log.info("Got configuration of: %s", kwargs) # Configuration options bitrate = kwargs.get("bitrate", 500000) + data_bitrate = kwargs.get("data_bitrate", bitrate) UniqueHardwareId = kwargs.get("UniqueHardwareId", None) rxFifoSize = kwargs.get("rxFifoSize", 16) txFifoSize = kwargs.get("txFifoSize", 16) @@ -440,9 +457,12 @@ def __init__(self, channel, can_filters=None, **kwargs): # Usually comes as a string from the config file channel = int(channel) - if bitrate not in self.CHANNEL_BITRATES[0]: + if bitrate not in self.CAN_BTP: raise ValueError("Invalid bitrate {}".format(bitrate)) + if fd and data_bitrate not in self.CAN_BTP_DBR: + raise ValueError("Invalid data bitrate {}".format(data_bitrate)) + if rxFifoSize <= 0: raise ValueError("rxFifoSize must be > 0") @@ -456,9 +476,9 @@ def __init__(self, channel, can_filters=None, **kwargs): self._device_info = structures.VCIDEVICEINFO() self._control_handle = HANDLE() self._channel_handle = HANDLE() - self._channel_capabilities = structures.CANCAPABILITIES() - self._message = structures.CANMSG() - self._payload = (ctypes.c_byte * 8)() + self._channel_capabilities = structures.CANCAPABILITIES2() + self._message = structures.CANMSG2() + self._payload = (ctypes.c_byte * 64)() # Search for supplied device if UniqueHardwareId is None: @@ -525,20 +545,44 @@ def __init__(self, channel, can_filters=None, **kwargs): ) # Signal TX/RX events when at least one frame has been handled - _canlib.canChannelInitialize(self._channel_handle, rxFifoSize, 1, txFifoSize, 1) + # note: we do not apply message filtering on channel level + _canlib.canChannelInitialize( + self._channel_handle, + rxFifoSize, + 1, + txFifoSize, + 1, + 2048, + constants.CAN_FILTER_INCL, + ) _canlib.canChannelActivate(self._channel_handle, constants.TRUE) log.info("Initializing control %d bitrate %d", channel, bitrate) _canlib.canControlOpen( self._device_handle, channel, ctypes.byref(self._control_handle) ) + + exmode = 0 + if fd: + exmode |= constants.CAN_EXMODE_EXTDATA + exmode |= constants.CAN_EXMODE_FASTDATA + _canlib.canControlInitialize( self._control_handle, constants.CAN_OPMODE_STANDARD | constants.CAN_OPMODE_EXTENDED | constants.CAN_OPMODE_ERRFRAME, - self.CHANNEL_BITRATES[0][bitrate], - self.CHANNEL_BITRATES[1][bitrate], + exmode, + constants.CAN_FILTER_PASS + if can_filters is None + else constants.CAN_FILTER_INCL, + constants.CAN_FILTER_PASS + if can_filters is None + else constants.CAN_FILTER_INCL, + 0 if can_filters is None else 2048, + 0 if can_filters is None else 2048, + ctypes.byref(self.CAN_BTP[bitrate]), + ctypes.byref(self.CAN_BTP_DBR[data_bitrate] if fd else structures.CANBTP()), ) _canlib.canControlGetCaps( self._control_handle, ctypes.byref(self._channel_capabilities) @@ -550,7 +594,7 @@ def __init__(self, channel, can_filters=None, **kwargs): # frequency [1/s] = dwClockFreq / dwTscDivisor # We explicitly cast to float for Python 2.x users self._tick_resolution = float( - self._channel_capabilities.dwClockFreq + self._channel_capabilities.dwTscClkFreq / self._channel_capabilities.dwTscDivisor ) @@ -694,6 +738,11 @@ def _recv_internal(self, timeout): # Timed out / can message type is not DATA return None, True + if self._message.uMsgInfo.Bits.edl: + length = constants.CAN_EDLC_XLT[self._message.uMsgInfo.Bits.dlc] + else: + length = self._message.uMsgInfo.Bits.dlc + # The _message.dwTime is a 32bit tick value and will overrun, # so expect to see the value restarting from 0 rx_msg = Message( @@ -702,8 +751,11 @@ def _recv_internal(self, timeout): is_remote_frame=bool(self._message.uMsgInfo.Bits.rtr), is_extended_id=bool(self._message.uMsgInfo.Bits.ext), arbitration_id=self._message.dwMsgId, + is_fd=bool(self._message.uMsgInfo.Bits.edl), + bitrate_switch=bool(self._message.uMsgInfo.Bits.fdr), + error_state_indicator=bool(self._message.uMsgInfo.Bits.esi), dlc=self._message.uMsgInfo.Bits.dlc, - data=self._message.abData[: self._message.uMsgInfo.Bits.dlc], + data=self._message.abData[:length], channel=self.channel, ) @@ -722,16 +774,27 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: :class:CanOperationError """ # This system is not designed to be very efficient - message = structures.CANMSG() + message = structures.CANMSG2() message.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_DATA + # message.uMsgInfo.Bits.ssm = 0 + # message.uMsgInfo.Bits.hpm = 0 + message.uMsgInfo.Bits.edl = 1 if msg.is_fd else 0 + message.uMsgInfo.Bits.fdr = 1 if msg.bitrate_switch else 0 + message.uMsgInfo.Bits.esi = 1 if msg.error_state_indicator else 0 + + # message.uMsgInfo.Bits.ovr = 0 + message.uMsgInfo.Bits.srr = 1 if self._receive_own_messages else 0 message.uMsgInfo.Bits.rtr = 1 if msg.is_remote_frame else 0 message.uMsgInfo.Bits.ext = 1 if msg.is_extended_id else 0 - message.uMsgInfo.Bits.srr = 1 if self._receive_own_messages else 0 + message.dwMsgId = msg.arbitration_id - if msg.dlc: + if msg.is_fd: + message.uMsgInfo.Bits.dlc = constants.CAN_ELEN_XLT[msg.dlc] + ctypes.memset(message.abData, 0, message.uMsgInfo.Bits.dlc) + else: message.uMsgInfo.Bits.dlc = msg.dlc - adapter = (ctypes.c_uint8 * len(msg.data)).from_buffer(msg.data) - ctypes.memmove(message.abData, adapter, len(msg.data)) + adapter = (ctypes.c_uint8 * len(msg.data)).from_buffer(msg.data) + ctypes.memmove(message.abData, adapter, len(msg.data)) if timeout: _canlib.canChannelSendMessage( diff --git a/can/interfaces/ixxat/constants.py b/can/interfaces/ixxat/constants.py index e911a580a..44d881252 100644 --- a/can/interfaces/ixxat/constants.py +++ b/can/interfaces/ixxat/constants.py @@ -3,6 +3,7 @@ Copyright (C) 2016 Giuseppe Corbelli """ +from .structures import CANBTP FALSE = 0 TRUE = 1 @@ -33,6 +34,37 @@ CAN_BT0_1000KB = 0x00 CAN_BT1_1000KB = 0x14 +CAN_BT01_5KB = (0x3F, 0x7F) +CAN_BT01_10KB = (0x31, 0x1C) +CAN_BT01_20KB = (0x18, 0x1C) +CAN_BT01_50KB = (0x09, 0x1C) +CAN_BT01_100KB = (0x04, 0x1C) +CAN_BT01_125KB = (0x03, 0x1C) +CAN_BT01_250KB = (0x01, 0x1C) +CAN_BT01_500KB = (0x00, 0x1C) +CAN_BT01_800KB = (0x00, 0x16) +CAN_BT01_1000KB = (0x00, 0x14) + +CAN_BTP_EMPTY = CANBTP(0, 0, 0, 0, 0, 0) +CAN_BTP_5KB = CANBTP(0, 5000, 17, 8, 1, 0) +CAN_BTP_10KB = CANBTP(0, 10000, 14, 2, 1, 0) +CAN_BTP_20KB = CANBTP(0, 20000, 14, 2, 1, 0) +CAN_BTP_50KB = CANBTP(0, 50000, 14, 2, 1, 0) +CAN_BTP_100KB = CANBTP(0, 100000, 14, 2, 1, 0) +CAN_BTP_125KB = CANBTP(0, 125000, 14, 2, 1, 0) +CAN_BTP_250KB = CANBTP(0, 250000, 14, 2, 1, 0) +CAN_BTP_500KB = CANBTP(0, 500000, 14, 2, 1, 0) +CAN_BTP_800KB = CANBTP(0, 800000, 8, 2, 1, 0) +CAN_BTP_1000KB = CANBTP(0, 1000000, 6, 2, 1, 0) + +CAN_BTP_DBR_SL_1000KB = CANBTP(0, 1000000, 1600, 400, 400, 1600) +CAN_BTP_DBR_SL_2000KB = CANBTP(0, 2000000, 1600, 400, 400, 1600) +CAN_BTP_DBR_SL_4000KB = CANBTP(0, 4000000, 800, 200, 200, 800) +CAN_BTP_DBR_SL_5000KB = CANBTP(0, 5000000, 600, 200, 200, 600) +CAN_BTP_DBR_SL_6667KB = CANBTP(0, 6666666, 400, 200, 200, 402) +CAN_BTP_DBR_SL_8000KB = CANBTP(0, 8000000, 400, 100, 100, 250) +CAN_BTP_DBR_SL_10000KB = CANBTP(0, 10000000, 300, 100, 100, 200) + # Facilities/severities SEV_INFO = 0x40000000 SEV_WARN = 0x80000000 @@ -119,6 +151,12 @@ CAN_OPMODE_LISTONLY = 0x08 CAN_OPMODE_LOWSPEED = 0x10 +# Extended operating modes +CAN_EXMODE_DISABLED = 0x00 # no extended operation +CAN_EXMODE_EXTDATA = 0x01 # extended data length +CAN_EXMODE_FASTDATA = 0x02 # fast data bit rate +CAN_EXMODE_NONISO = 0x04 # non ISO conform frames + # Message types CAN_MSGTYPE_DATA = 0 CAN_MSGTYPE_INFO = 1 @@ -143,6 +181,88 @@ CAN_ERROR_CRC = 6 # CRC error CAN_ERROR_OTHER = 7 # other (unspecified) error -# acceptance code and mask to reject all CAN IDs +# Filter selection +CAN_FILTER_STD = 1 # select standard filter (11-bit) +CAN_FILTER_EXT = 2 # select extended filter (29-bit) + +# Filter mode +CAN_FILTER_VOID = 0x00 # invalid or unknown filter mode (do not use for initialization) +CAN_FILTER_LOCK = 0x01 # lock filter (inhibit all IDs) +CAN_FILTER_PASS = 0x02 # bypass filter (pass all IDs) +CAN_FILTER_INCL = 0x03 # inclusive filtering (pass registered IDs) +CAN_FILTER_EXCL = 0x04 # exclusive filtering (inhibit registered IDs) + +# additional filter mode flag for ICanChannel2 initialization +CAN_FILTER_SRRA = 0x80 # pass self-rec messages from all channels + CAN_ACC_MASK_NONE = 0xFFFFFFFF CAN_ACC_CODE_NONE = 0x80000000 + +CAN_EDLC_XLT = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64] +CAN_ELEN_XLT = [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 9, + 9, + 9, + 10, + 10, + 10, + 10, + 11, + 11, + 11, + 11, + 12, + 12, + 12, + 12, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, +] diff --git a/can/interfaces/ixxat/structures.py b/can/interfaces/ixxat/structures.py index 73c01823d..433fc0e51 100644 --- a/can/interfaces/ixxat/structures.py +++ b/can/interfaces/ixxat/structures.py @@ -68,6 +68,20 @@ def __str__(self): PVCIDEVICEINFO = ctypes.POINTER(VCIDEVICEINFO) +class CANBTP(ctypes.Structure): + _fields_ = [ + ("dwMode", ctypes.c_uint32), + ("dwBPS", ctypes.c_uint32), + ("wTS1", ctypes.c_uint16), + ("wTS2", ctypes.c_uint16), + ("wSJW", ctypes.c_uint16), + ("wTDO", ctypes.c_uint16), + ] + + +PCANBTP = ctypes.POINTER(CANBTP) + + class CANLINESTATUS(ctypes.Structure): _fields_ = [ ("bOpMode", ctypes.c_uint8), @@ -81,6 +95,21 @@ class CANLINESTATUS(ctypes.Structure): PCANLINESTATUS = ctypes.POINTER(CANLINESTATUS) +class CANLINESTATUS2(ctypes.Structure): + _fields_ = [ + ("bOpMode", ctypes.c_uint8), + ("bExMode", ctypes.c_uint8), + ("bBusLoad", ctypes.c_uint8), + ("bReserved", ctypes.c_uint8), + ("sBtpSdr", ctypes.c_uint32), + ("sBtpFdr", ctypes.c_uint32), + ("dwStatus", ctypes.c_uint32), + ] + + +PCANLINESTATUS2 = ctypes.POINTER(CANLINESTATUS2) + + class CANCHANSTATUS(ctypes.Structure): _fields_ = [ ("sLineStatus", CANLINESTATUS), @@ -111,6 +140,30 @@ class CANCAPABILITIES(ctypes.Structure): PCANCAPABILITIES = ctypes.POINTER(CANCAPABILITIES) +class CANCAPABILITIES2(ctypes.Structure): + _fields_ = [ + ("wCtrlType", ctypes.c_uint16), + ("wBusCoupling", ctypes.c_uint16), + ("dwFeatures", ctypes.c_uint32), + ("dwCanClkFreq", ctypes.c_uint32), + ("sSdrRangeMin", CANBTP), + ("sSdrRangeMax", CANBTP), + ("sFdrRangeMin", CANBTP), + ("sFdrRangeMax", CANBTP), + ("dwTscClkFreq", ctypes.c_uint32), + ("dwTscDivisor", ctypes.c_uint32), + ("dwCmsClkFreq", ctypes.c_uint32), + ("dwCmsDivisor", ctypes.c_uint32), + ("dwCmsMaxTicks", ctypes.c_uint32), + ("dwDtxClkFreq", ctypes.c_uint32), + ("dwDtxDivisor", ctypes.c_uint32), + ("dwDtxMaxTicks", ctypes.c_uint32), + ] + + +PCANCAPABILITIES2 = ctypes.POINTER(CANCAPABILITIES2) + + class CANMSGINFO(ctypes.Union): class Bytes(ctypes.Structure): _fields_ = [ @@ -124,8 +177,11 @@ class Bits(ctypes.Structure): _fields_ = [ ("type", ctypes.c_uint32, 8), ("ssm", ctypes.c_uint32, 1), - ("hi", ctypes.c_uint32, 2), - ("res", ctypes.c_uint32, 5), + ("hpm", ctypes.c_uint32, 1), + ("edl", ctypes.c_uint32, 1), + ("fdr", ctypes.c_uint32, 1), + ("esi", ctypes.c_uint32, 1), + ("res", ctypes.c_uint32, 3), ("dlc", ctypes.c_uint32, 4), ("ovr", ctypes.c_uint32, 1), ("srr", ctypes.c_uint32, 1), @@ -152,6 +208,19 @@ class CANMSG(ctypes.Structure): PCANMSG = ctypes.POINTER(CANMSG) +class CANMSG2(ctypes.Structure): + _fields_ = [ + ("dwTime", ctypes.c_uint32), + ("_rsvd_", ctypes.c_uint32), + ("dwMsgId", ctypes.c_uint32), + ("uMsgInfo", CANMSGINFO), + ("abData", ctypes.c_uint8 * 64), + ] + + +PCANMSG2 = ctypes.POINTER(CANMSG2) + + class CANCYCLICTXMSG(ctypes.Structure): _fields_ = [ ("wCycleTime", ctypes.c_uint16), @@ -164,3 +233,17 @@ class CANCYCLICTXMSG(ctypes.Structure): PCANCYCLICTXMSG = ctypes.POINTER(CANCYCLICTXMSG) + + +class CANCYCLICTXMSG2(ctypes.Structure): + _fields_ = [ + ("wCycleTime", ctypes.c_uint16), + ("bIncrMode", ctypes.c_uint8), + ("bByteIndex", ctypes.c_uint8), + ("dwMsgId", ctypes.c_uint32), + ("uMsgInfo", CANMSGINFO), + ("abData", ctypes.c_uint8 * 64), + ] + + +PCANCYCLICTXMSG2 = ctypes.POINTER(CANCYCLICTXMSG2)