├── tests ├── __init___.py ├── test_hwconfig.py ├── test_basic.py └── log.txt ├── vxlapi.h ├── vxlapi64.dll ├── vxlapi64.lib ├── images ├── CANoeDemo.png ├── Debug_View.png ├── configuration_flags.png ├── Vector_Driver_Setup.png └── Vector_XL_Driver_Library.png ├── pyxldrv.py ├── pyxldrv ├── __init__.py └── can.py ├── setup.py ├── README.md └── vxlapi.pxd /tests/__init___.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vxlapi.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdrk1980/pyxldrv/HEAD/vxlapi.h -------------------------------------------------------------------------------- /vxlapi64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdrk1980/pyxldrv/HEAD/vxlapi64.dll -------------------------------------------------------------------------------- /vxlapi64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdrk1980/pyxldrv/HEAD/vxlapi64.lib -------------------------------------------------------------------------------- /images/CANoeDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdrk1980/pyxldrv/HEAD/images/CANoeDemo.png -------------------------------------------------------------------------------- /images/Debug_View.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdrk1980/pyxldrv/HEAD/images/Debug_View.png -------------------------------------------------------------------------------- /images/configuration_flags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdrk1980/pyxldrv/HEAD/images/configuration_flags.png -------------------------------------------------------------------------------- /pyxldrv.py: -------------------------------------------------------------------------------- 1 | # *-* encoding: utf-8 *-* 2 | import vxlapi as xl 3 | import win32event 4 | # To wait Receive(), WaitForSingleObject is to be used - http://timgolden.me.uk/pywin32-docs/win32event__WaitForSingleObject_meth.html 5 | 6 | 7 | -------------------------------------------------------------------------------- /pyxldrv/__init__.py: -------------------------------------------------------------------------------- 1 | # *-* encoding: utf-8 *-* 2 | import vxlapi as xl 3 | import win32event 4 | # To wait Receive(), WaitForSingleObject is to be used - http://timgolden.me.uk/pywin32-docs/win32event__WaitForSingleObject_meth.html 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/test_hwconfig.py: -------------------------------------------------------------------------------- 1 | # *-* encoding: utf-8 *-* 2 | 3 | import unittest 4 | import inspect 5 | import vxlapi as xl 6 | 7 | # python -m unittest tests.test_hwconfig 8 | class Test(unittest.TestCase): 9 | def test_popup(self): 10 | print(inspect.getframeinfo(inspect.currentframe())[2]) 11 | 12 | ret = xl.PopupHwConfig() 13 | self.assertEqual(ret, xl.XL_SUCCESS) 14 | 15 | if __name__ == '__main__': 16 | unittest.main() 17 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | 2 | # *-* encoding: utf-8 *-* 3 | # build command: 4 | # python setup.py build_ext -i --compiler=msvc 5 | 6 | # https://blog.ymyzk.com/2014/11/setuptools-cython/ 7 | 8 | from distutils.core import setup, Extension 9 | from Cython.Build import cythonize 10 | 11 | 12 | ext = Extension( 13 | "vxlapi", 14 | sources=["vxlapi.pyx"], 15 | libraries=["vxlapi64"], 16 | language="c++", 17 | define_macros=[("NOMINMAX",None)] # disable min/max marco see http://d.hatena.ne.jp/yohhoy/20120115/p1 18 | ) 19 | 20 | setup( 21 | ext_modules=cythonize(ext) 22 | ) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyxldrv 2 | 3 | [Vector XL Driver Library][1] Wrapper for Python. 4 | 5 | ## What 6 | 7 | - [Vector XL Driver Library][1] inlclude dlls for C/C++, C# but not for Python. 8 | - pyxldrv makes the dll for C/C++ an importable library(vxlapi). 9 | - To wrap C/C++ dll, pyxldrv uses Cython. 10 | - Cython generates a library for Python("vxlapi.xxxxxx.pyd") from Cython codes(vxlapi.pxd and vxlapi.pyx). 11 | 12 | ``` 13 | import vxlapi as xl 14 | 15 | ret = xl.OpenDriver() 16 | .... 17 | msgs = [] 18 | msgs.append({"flags":0, "id":0x321, "dlc":8, "data":bytearray([0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0])}) 19 | message_count = [len(msgs)] 20 | status = xl.CanTransmit(portHandle[0], accessMask, message_count, msgs) 21 | ... 22 | ret = xl.CloseDriver() 23 | ``` 24 | 25 | - and there is an additional wrapper class for CAN(can.py). 26 | 27 | ## Installation 28 | 29 | ### CANoe 30 | 31 | - Get XL Driver Library and Vector Driver Setup from [Vector Download-Center][2] and install them. 32 | 33 | ![xldriver](./images/Vector_XL_Driver_Library.png) 34 | 35 | ![VectorDriverSetup](./images/Vector_Driver_Setup.png) 36 | 37 | 42 | 43 | 44 | ## Cython and build tool 45 | 46 | - Get Cython via pip at first. 47 | 48 | - For Python 3.6 49 | - Get [Build Tools for Visual Studio 2017](https://www.visualstudio.com/ja/downloads). 50 | 51 | ## Support APIs 52 | 53 | ### Common Commands 54 | 55 | |name|support|remark| 56 | |:---|:---|:---| 57 | |xlOpenDriver|yes|| 58 | |xlCloseDriver|yes|| 59 | |xlGetApplConfig|yes|| 60 | |xlSetApplConfig|yes||| 61 | |xlGetDriverConfig|yes||| 62 | |xlGetRemoteDriverConfig|yes|not tested.| 63 | |xlGetChannelIndex|yes|not tested.| 64 | |xlGetChannelMask|yes|| 65 | |xlOpenPort|yes|| 66 | |xlClosePort|yes|| 67 | |xlSetTimerRate|yes|not tested.| 68 | |xlSetTimerRateAndChannel|yes|not tested.| 69 | |xlResetClock|yes|not tested.| 70 | |xlSetNotification|yes|| 71 | |xlFlushReceiveQueue|yes|not tested.| 72 | |xlGetReceiveQueueLevel|yes|not tested.| 73 | |xlActivateChannel|yes|| 74 | |xlReceive|yes|| 75 | |xlGetEventString|yes|xlReceive and xlGetEventString are intergrated into vxlapi.Receive.| 76 | |xlGetErrorString|yes|| 77 | |xlGetSyncTime|yes|not tested.| 78 | |xlGetChannelTime|yes|not tested.| 79 | |xlGenerateSyncPulse|yes|not tested.| 80 | |xlPopupHwConfig|yes|| 81 | |xlDeactivateChannel|yes|| 82 | |xlGetLicenseInfo|yes|not tested.| 83 | |xlSetGlobalTimeSync|yes|not tested.| 84 | |xlGetKeymanBoxes|yes|not tested.| 85 | |xlGetKeymanInfo|yes|not tested.| 86 | 87 | ### CAN Commands 88 | 89 | |name|support|remark| 90 | |:---|:---|:---| 91 | |xlCanSetChannelMode|yes|not tested.| 92 | |xlCanSetChannelOutput|yes|not tested.| 93 | |xlCanSetReceiveMode|yes|not tested.| 94 | |xlCanSetChannelTransceiver|yes|not tested.| 95 | |xlCanSetChannelParams|yes|not tested.| 96 | |xlCanSetChannelParamsC200|yes|not tested.| 97 | |xlCanSetChannelBitrate|yes|| 98 | |xlCanSetChannelAcceptance|yes|not tested.| 99 | |xlCanAddAcceptanceRange|yes|not tested.| 100 | |xlCanRemoveAcceptanceRange|yes|not tested. 101 | |xlCanResetAcceptance|yes|not tested. 102 | |xlCanRequestChipState|yes|not tested.| 103 | |xlCanTransmit|yes|| 104 | |xlCanFlushTransmitQueue|yes|not tested.| 105 | 106 | ### CAN FD Commands 107 | 108 | |name|support|remark| 109 | |:---|:---|:---| 110 | |xlCanFdSetConfiguration|yes|not tested.| 111 | |xlCanTransmitEx|yes|not tested.| 112 | |xlCanReceive|no|| 113 | |xlCanGetEventString|no|| 114 | 115 | ### LIN Commands 116 | 117 | to be suported. 3rd 118 | 119 | ### Ethernet Commands 120 | 121 | to be suported. 4th 122 | 123 | ### Other Commands(MOST, FlexRay, AR429, ...) 124 | 125 | not to be supported at this moment. 126 | 127 | 128 | ## DebugView for Windows 129 | 130 | For debugging vxlapi.pyx, [DebugView for Windows](https://technet.microsoft.com/en-us/sysinternals/debugview.aspx) can be used. Because DebugView for Windows shows native side(vxlapi.dll) function's status, "debug print" can be reduced. 131 | 132 | See XL Driver Library - Description.pdf 133 | 134 | > ### 2.5 Additional Information 135 | > The XL Driver Library supports debug prints which can be enabled in the Vector 136 | Hardware Configuration tool. In section General information, select Settings and 137 | double-click on Configuration flags. Enter the required flag (see table below). To 138 | activate the flags, restart the PC. 139 | 140 | |Flags|Supported Bus Type| 141 | |:---|:---| 142 | |0x400000|CAN, LIN, DAIO| 143 | |0x002000|MOST| 144 | |0x010000|FlexRay| 145 | 146 | 147 | ![configuration](./images/configuration_flags.png) 148 | 149 | ![Debug_View](./images/Debug_View.png) 150 | 151 | ## build command 152 | 153 | ``` 154 | python setup.py build_ext -i --compiler=msvc 155 | ``` 156 | 157 | setup.py supports only for 64bit version but you can use 158 | 159 | ## basic test 160 | 161 | ``` 162 | python -m unittest tests.test_basic 163 | ``` 164 | 165 | ## License 166 | 167 | ## ref 168 | - https://blog.ymyzk.com/2014/11/setuptools-cython/ 169 | - https://blog.ymyzk.com/2014/11/setuptools-cython/ 170 | - http://qh73xebitbucketorg.readthedocs.io/ja/latest/1.Programmings/python/LIB/cython/wrapperforcpp/ 171 | - https://vector.com/vi_xl_driver_library_en.html 172 | 173 | 174 | [1]:https://vector.com/vi_xl_driver_library_en.html 175 | [2]:https://vector.com/vi_downloadcenter_en.html 176 | [3]:https://vector.com/vi_vn1600_en.html 177 | [4]:https://vector.com/vi_canoe_en.html 178 | -------------------------------------------------------------------------------- /vxlapi.pxd: -------------------------------------------------------------------------------- 1 | # *-* encoding: utf-8 *-* 2 | 3 | # vxlapi.h expects 4 | cdef extern from "": 5 | pass 6 | 7 | cdef extern from "vxlapi.h": 8 | cdef: 9 | DEF XL_MAX_LENGTH = 31 10 | DEF XL_CONFIG_MAX_CHANNELS = 64 11 | DEF XL_INVALID_PORTHANDLE = -1 12 | DEF MAX_MSG_LEN = 8 13 | DEF XL_CAN_MAX_DATA_LEN = 64 14 | DEF XL_CANFD_RX_EVENT_HEADER_SIZE = 32 15 | DEF XL_CANFD_MAX_EVENT_SIZE = 128 16 | 17 | ctypedef short XLstatus 18 | ctypedef unsigned long long XLuint64 19 | ctypedef XLuint64 XLaccess 20 | ctypedef long XLportHandle 21 | ctypedef void* HANDLE 22 | ctypedef HANDLE XLhandle 23 | 24 | struct st_can: 25 | unsigned int bitRate 26 | unsigned char sjw 27 | unsigned char tseg1 28 | unsigned char tseg2 29 | unsigned char sam 30 | unsigned char outputMode 31 | unsigned char reserved[7] 32 | unsigned char canOpMode 33 | 34 | struct st_canFD: 35 | unsigned int arbitrationBitRate 36 | unsigned char sjwAbr 37 | unsigned char tseg1Abr 38 | unsigned char tseg2Abr 39 | unsigned char samAbr 40 | unsigned char outputMode 41 | unsigned char sjwDbr 42 | unsigned char tseg1Dbr 43 | unsigned char tseg2Dbr 44 | unsigned int dataBitRate 45 | unsigned char canOpMode 46 | 47 | struct st_most: 48 | unsigned int activeSpeedGrade 49 | unsigned int compatibleSpeedGrade 50 | unsigned int inicFwVersion 51 | 52 | struct st_flexray: 53 | unsigned int status 54 | unsigned int cfgMode 55 | unsigned int baudrate 56 | 57 | struct st_ethernet: 58 | unsigned char macAddr[6] 59 | unsigned char connector 60 | unsigned char phy 61 | unsigned char link 62 | unsigned char speed 63 | unsigned char clockMode 64 | unsigned char bypass 65 | 66 | struct st_tx: 67 | unsigned int bitrate 68 | unsigned int parity 69 | unsigned int minGap 70 | 71 | struct st_rx: 72 | unsigned int bitrate 73 | unsigned int minBitrate 74 | unsigned int maxBitrate 75 | unsigned int parity 76 | unsigned int minGap 77 | unsigned int autoBaudrate 78 | 79 | union union_dir: 80 | st_tx tx 81 | st_rx rx 82 | unsigned char raw[24] 83 | 84 | struct st_a429: 85 | unsigned short channelDirection 86 | unsigned short res1 87 | union_dir dir 88 | 89 | union union_data: 90 | st_can can 91 | st_canFD canFD 92 | st_most most 93 | st_flexray flexray 94 | st_ethernet ethernet 95 | st_a429 a429 96 | unsigned char raw[28] 97 | 98 | struct XLbusParams: 99 | unsigned int busType 100 | union_data data 101 | 102 | struct XL_CHANNEL_CONFIG: 103 | char name[XL_MAX_LENGTH + 1] 104 | unsigned char hwType 105 | unsigned char hwIndex 106 | unsigned char hwChannel 107 | unsigned short transceiverType 108 | unsigned short transceiverState 109 | unsigned short configError 110 | unsigned char channelIndex 111 | XLuint64 channelMask 112 | unsigned int channelCapabilities 113 | unsigned int channelBusCapabilities 114 | unsigned char isOnBus 115 | unsigned int connectedBusType 116 | XLbusParams busParams 117 | unsigned int _doNotUse 118 | unsigned int driverVersion 119 | unsigned int interfaceVersion 120 | unsigned int raw_data[10] 121 | unsigned int serialNumber 122 | unsigned int articleNumber 123 | char transceiverName [XL_MAX_LENGTH + 1] 124 | unsigned int specialCabFlags 125 | unsigned int dominantTimeout 126 | unsigned char dominantRecessiveDelay 127 | unsigned char recessiveDominantDelay 128 | unsigned char connectionInfo 129 | unsigned char currentlyAvailableTimestamps 130 | unsigned short minimalSupplyVoltage 131 | unsigned short maximalSupplyVoltage 132 | unsigned int maximalBaudrate 133 | unsigned char fpgaCoreCapabilities 134 | unsigned char specialDeviceStatus 135 | unsigned short channelBusActiveCapabilities 136 | unsigned short breakOffset 137 | unsigned short delimiterOffset 138 | unsigned int reserved[3] 139 | 140 | struct XL_DRIVER_CONFIG: 141 | unsigned int dllVersion 142 | unsigned int channelCount 143 | unsigned int reserved[10] 144 | XL_CHANNEL_CONFIG channel[XL_CONFIG_MAX_CHANNELS] 145 | 146 | ctypedef XL_DRIVER_CONFIG XLdriverConfig 147 | 148 | struct s_xl_can_msg: 149 | unsigned long id 150 | unsigned short flags 151 | unsigned short dlc 152 | XLuint64 res1 153 | unsigned char data[MAX_MSG_LEN] 154 | XLuint64 res2 155 | 156 | struct s_xl_chip_state: 157 | unsigned char busStatus 158 | unsigned char txErrorCounter 159 | unsigned char rxErrorCounter 160 | 161 | struct s_xl_transceiver: 162 | unsigned char event_reason 163 | unsigned char is_present 164 | 165 | struct s_xl_lin_msg: 166 | unsigned char id 167 | unsigned char dlc 168 | unsigned short flags 169 | unsigned char data[8] 170 | unsigned char crc 171 | 172 | struct s_xl_lin_sleep: 173 | unsigned char flag 174 | 175 | struct s_xl_lin_no_ans: 176 | unsigned char id 177 | 178 | struct s_xl_lin_wake_up: 179 | unsigned char flag 180 | unsigned char unused[3] 181 | unsigned int startOffs 182 | unsigned int width 183 | 184 | struct s_xl_lin_crc_info: 185 | unsigned char id 186 | unsigned char flags 187 | 188 | union s_xl_lin_msg_api: 189 | s_xl_lin_msg linMsg 190 | s_xl_lin_no_ans linNoAns 191 | s_xl_lin_wake_up linWakeUp 192 | s_xl_lin_sleep linSleep 193 | s_xl_lin_crc_info linCRCinfo 194 | 195 | ctypedef struct XL_IO_DIGITAL_DATA: 196 | unsigned int digitalInputData 197 | 198 | ctypedef struct XL_IO_ANALOG_DATA: 199 | unsigned int measuredAnalogData0 200 | unsigned int measuredAnalogData1 201 | unsigned int measuredAnalogData2 202 | unsigned int measuredAnalogData3 203 | 204 | union st_dio_data: 205 | XL_IO_DIGITAL_DATA digital 206 | XL_IO_ANALOG_DATA analog 207 | 208 | struct s_xl_daio_piggy_data: 209 | unsigned int daioEvtTag 210 | unsigned int triggerType 211 | st_dio_data data 212 | 213 | struct s_xl_daio_data: 214 | unsigned short flags 215 | unsigned int timestamp_correction 216 | unsigned char mask_digital 217 | unsigned char value_digital 218 | unsigned char mask_analog 219 | unsigned char reserved0 220 | unsigned short value_analog[4] 221 | unsigned int pwm_frequency 222 | unsigned short pwm_value 223 | unsigned int reserved1 224 | unsigned int reserved2 225 | 226 | struct s_xl_sync_pulse_ev: 227 | unsigned int triggerSource 228 | unsigned int reserved 229 | XLuint64 time 230 | 231 | struct s_xl_sync_pulse: 232 | unsigned char pulseCode 233 | XLuint64 time 234 | 235 | union s_xl_tag_data: 236 | s_xl_can_msg msg 237 | s_xl_chip_state chipState 238 | s_xl_lin_msg_api linMsgApi 239 | s_xl_sync_pulse syncPulse 240 | s_xl_daio_data daioData 241 | s_xl_transceiver transceiver 242 | s_xl_daio_piggy_data daioPiggyData 243 | 244 | ctypedef unsigned char XLeventTag 245 | ctypedef struct s_xl_event: 246 | XLeventTag tag 247 | unsigned char chanIndex 248 | unsigned short transId 249 | unsigned short portHandle 250 | unsigned char flags 251 | unsigned char reserved 252 | XLuint64 timeStamp 253 | s_xl_tag_data tagData 254 | 255 | ctypedef s_xl_event XLevent 256 | 257 | ctypedef char *XLstringType 258 | 259 | ctypedef struct XLchipParams: 260 | unsigned long bitRate 261 | unsigned char sjw 262 | unsigned char tseg1 263 | unsigned char tseg2 264 | unsigned char sam 265 | 266 | ctypedef struct XL_LICENSE_INFO: 267 | unsigned char bAvailable 268 | char licName[65] 269 | 270 | ctypedef XL_LICENSE_INFO XLlicenseInfo 271 | 272 | ctypedef struct XLcanFdConf: 273 | unsigned int arbitrationBitRate 274 | unsigned int sjwAbr 275 | unsigned int tseg1Abr 276 | unsigned int tseg2Abr 277 | unsigned int dataBitRate 278 | unsigned int sjwDbr 279 | unsigned int tseg1Dbr 280 | unsigned int tseg2Dbr 281 | unsigned int reserved[2] 282 | 283 | 284 | ctypedef struct XL_CAN_TX_MSG: 285 | unsigned int canId 286 | unsigned int msgFlags 287 | unsigned char dlc 288 | unsigned char reserved[7] 289 | unsigned char data[XL_CAN_MAX_DATA_LEN] 290 | 291 | ctypedef union st_tagData: 292 | XL_CAN_TX_MSG canMsg 293 | 294 | ctypedef struct XLcanTxEvent: 295 | unsigned short tag 296 | unsigned short transId 297 | unsigned char channelIndex 298 | unsigned char reserved[3] 299 | st_tagData tagData 300 | 301 | 302 | -------------------------------------------------------------------------------- /tests/test_basic.py: -------------------------------------------------------------------------------- 1 | # *-* encoding: utf-8 *-* 2 | # python -m unittest tests.test_basic 3 | import unittest 4 | import inspect 5 | import vxlapi as xl 6 | from pprint import pprint 7 | import chardet 8 | 9 | 10 | def decode_bin(bin): 11 | return bin.decode(chardet.detect(bin)["encoding"]) 12 | 13 | def get_can_bus_params(hwType, hwIndex, hwChannel, busType): 14 | driverConfig = {} 15 | xl.GetDriverConfig(driverConfig) 16 | can_bus_params = None 17 | for ch in driverConfig["channel"]: 18 | if (ch["hwType"] == hwType and ch["hwIndex"] == hwIndex and ch["hwChannel"] == hwChannel): 19 | if ch["busParams"]["busType"] == busType: 20 | can_bus_params = ch["busParams"]["data"]["can"] 21 | can_bus_params["name"] = ch["name"] 22 | can_bus_params["hwType"] = ch["hwType"] 23 | can_bus_params["hwIndex"] = ch["hwIndex"] 24 | can_bus_params["hwChannel"] = ch["hwChannel"] 25 | return can_bus_params 26 | 27 | # python -m unittest tests.test_basic.TestOpenCloseDriver 28 | class TestOpenCloseDriver(unittest.TestCase): 29 | def test_opendriver_close_driver(self): 30 | print(inspect.getframeinfo(inspect.currentframe())[2]) 31 | 32 | status = xl.OpenDriver() 33 | self.assertEqual(status, xl.XL_SUCCESS) 34 | 35 | status = xl.CloseDriver() 36 | self.assertEqual(status, xl.XL_SUCCESS) 37 | 38 | # python -m unittest tests.test_basic.TestSetGetAppConfig 39 | class TestSetGetAppConfig(unittest.TestCase): 40 | def setUp(self): 41 | xl.OpenDriver() 42 | 43 | def tearDown(self): 44 | xl.CloseDriver() 45 | 46 | def test_setapplconfig_getapplconfig(self): 47 | print(inspect.getframeinfo(inspect.currentframe())[2]) 48 | 49 | # CAN1 -- virtual can bus1.hwch1 50 | status = xl.SetApplConfig(appName=bytes("pyxldrv".encode()), appChannel=0, pHwType=[xl.XL_HWTYPE_VIRTUAL], pHwIndex=[0], pHwChannel=[0], busType=xl.XL_BUS_TYPE_CAN) 51 | self.assertEqual(status, xl.XL_SUCCESS) 52 | 53 | pHwType = [0xff] 54 | pHwIndex = [0xff] 55 | pHwChannel = [0xff] 56 | status = xl.GetApplConfig(appName=bytes("pyxldrv".encode()), appChannel=0, pHwType=pHwType, pHwIndex=pHwIndex, pHwChannel=pHwChannel, busType=xl.XL_BUS_TYPE_CAN) 57 | self.assertEqual(status, xl.XL_SUCCESS) 58 | self.assertEqual(pHwType[0], xl.XL_HWTYPE_VIRTUAL) 59 | self.assertEqual(pHwIndex[0], 0) 60 | self.assertEqual(pHwChannel[0], 0) 61 | 62 | # CAN2 -- virtual can bus1.hwch2 63 | status = xl.SetApplConfig(appName=bytes("pyxldrv".encode()), appChannel=1, pHwType=[xl.XL_HWTYPE_VIRTUAL], pHwIndex=[0], pHwChannel=[1], busType=xl.XL_BUS_TYPE_CAN) 64 | self.assertEqual(status, xl.XL_SUCCESS) 65 | 66 | pHwType = [0xff] 67 | pHwIndex = [0xff] 68 | pHwChannel = [0xff] 69 | status = xl.GetApplConfig(appName=bytes("pyxldrv".encode()), appChannel=1, pHwType=pHwType, pHwIndex=pHwIndex, pHwChannel=pHwChannel, busType=xl.XL_BUS_TYPE_CAN) 70 | self.assertEqual(status, xl.XL_SUCCESS) 71 | self.assertEqual(pHwType[0], xl.XL_HWTYPE_VIRTUAL) 72 | self.assertEqual(pHwIndex[0], 0) 73 | self.assertEqual(pHwChannel[0], 1) 74 | 75 | # python -m unittest tests.test_basic.TestGetDriverConfig 76 | class TestGetDriverConfig(unittest.TestCase): 77 | def setUp(self): 78 | xl.OpenDriver() 79 | 80 | self.appName = bytes("pyxldrv".encode()) 81 | self.appChannel = 0 82 | self.pHwType = [xl.XL_HWTYPE_VIRTUAL] 83 | self.pHwIndex = [0] 84 | self.pHwChannel = [0] 85 | self.busType = xl.XL_BUS_TYPE_CAN 86 | 87 | xl.SetApplConfig(self.appName, self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 88 | xl.GetApplConfig(self.appName, self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 89 | 90 | def tearDown(self): 91 | xl.CloseDriver() 92 | 93 | def test_getdriverconfig(self): 94 | print(inspect.getframeinfo(inspect.currentframe())[2]) 95 | 96 | driverConfig = {} 97 | status = xl.GetDriverConfig(driverConfig) 98 | self.assertEqual(status, xl.XL_SUCCESS) 99 | # pprint(driverConfig) 100 | 101 | # python -m unittest tests.test_basic.TestGetChannelMask 102 | class TestGetChannelMask(unittest.TestCase): 103 | def setUp(self): 104 | xl.OpenDriver() 105 | 106 | self.appName = bytes("pyxldrv".encode()) 107 | self.appChannel = 0 108 | self.pHwType = [xl.XL_HWTYPE_VIRTUAL] 109 | self.pHwIndex = [0] 110 | self.pHwChannel = [0] 111 | self.busType = xl.XL_BUS_TYPE_CAN 112 | 113 | xl.SetApplConfig(self.appName, self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 114 | xl.GetApplConfig(self.appName, self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 115 | 116 | def tearDown(self): 117 | xl.CloseDriver() 118 | 119 | def test_getchannelmask(self): 120 | print(inspect.getframeinfo(inspect.currentframe())[2]) 121 | 122 | accessMask = xl.GetChannelMask(self.pHwType[0], self.pHwIndex[0], self.pHwChannel[0]) 123 | self.assertNotEqual(accessMask,0) 124 | 125 | # python -m unittest tests.test_basic.TestOpenClosePort 126 | class TestOpenClosePort(unittest.TestCase): 127 | def setUp(self): 128 | xl.OpenDriver() 129 | 130 | self.appName = bytes("pyxldrv".encode()) 131 | self.appChannel = 0 132 | self.pHwType = [xl.XL_HWTYPE_VIRTUAL] 133 | self.pHwIndex = [0] 134 | self.pHwChannel = [0] 135 | self.busType = xl.XL_BUS_TYPE_CAN 136 | 137 | xl.SetApplConfig(self.appName, self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 138 | xl.GetApplConfig(self.appName, self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 139 | 140 | self.accessMask = xl.GetChannelMask(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0]) 141 | 142 | def tearDown(self): 143 | xl.CloseDriver() 144 | 145 | def test_openport_closeport(self): 146 | print(inspect.getframeinfo(inspect.currentframe())[2]) 147 | 148 | portHandle = [xl.XL_INVALID_PORTHANDLE] 149 | permissionMask = [self.accessMask] 150 | rxQueueSize = 2^10 151 | appName = self.appName 152 | accessMask = self.accessMask 153 | xlInterfaceVersion = xl.XL_INTERFACE_VERSION 154 | busType = self.busType 155 | 156 | status = xl.OpenPort(portHandle, appName, accessMask, permissionMask, rxQueueSize, xlInterfaceVersion, busType) 157 | 158 | self.assertEqual(status, xl.XL_SUCCESS) 159 | self.assertNotEqual(portHandle, xl.XL_INVALID_PORTHANDLE) 160 | self.assertEqual(permissionMask[0], self.accessMask) 161 | 162 | 163 | status = xl.ClosePort(portHandle[0]) 164 | self.assertEqual(status, xl.XL_SUCCESS) 165 | 166 | status = xl.CloseDriver() 167 | self.assertEqual(status, xl.XL_SUCCESS) 168 | 169 | # python -m unittest tests.test_basic.TestCanSetChannelBitrate 170 | class TestCanSetChannelBitrate(unittest.TestCase): 171 | def setUp(self): 172 | xl.OpenDriver() 173 | 174 | self.pHwType = [xl.XL_HWTYPE_VIRTUAL] 175 | self.pHwIndex = [0] 176 | self.pHwChannel = [0] 177 | self.busType = xl.XL_BUS_TYPE_CAN 178 | self.appName = bytes("pyxldrv".encode()) 179 | xl.SetApplConfig(appName=self.appName, appChannel=0, pHwType=self.pHwType, pHwIndex=self.pHwIndex, pHwChannel=self.pHwChannel, busType=self.busType) 180 | xl.GetApplConfig(appName=self.appName, appChannel=0, pHwType=self.pHwType, pHwIndex=self.pHwIndex, pHwChannel=self.pHwChannel, busType=self.busType) 181 | 182 | self.accessMask = 0 183 | self.accessMask = xl.GetChannelMask(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0]) 184 | 185 | self.portHandle = [0] 186 | self.permissionMask = [self.accessMask] 187 | self.rxQueueSize = 2^10 188 | self.xlInterfaceVersion = xl.XL_INTERFACE_VERSION 189 | xl.OpenPort(self.portHandle, self.appName, self.accessMask, self.permissionMask, self.rxQueueSize, self.xlInterfaceVersion, self.busType) 190 | 191 | def tearDown(self): 192 | xl.ClosePort(self.portHandle[0]) 193 | xl.CloseDriver() 194 | 195 | def test_CanSetChannelBitrate(self): 196 | 197 | # 1st 198 | bitrate = 250_000 199 | status = xl.CanSetChannelBitrate(self.portHandle[0], self.accessMask, 250_000) 200 | self.assertEqual(status, xl.XL_SUCCESS) 201 | 202 | # get driver's bitrate 203 | can_bus_params = get_can_bus_params(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0], self.busType) 204 | print(can_bus_params) 205 | 206 | # check result 207 | self.assertEqual(bitrate, can_bus_params["bitRate"]) 208 | 209 | # 2nd 210 | bitrate = 500_000 211 | status = xl.CanSetChannelBitrate(self.portHandle[0], self.accessMask, bitrate) 212 | self.assertEqual(status, xl.XL_SUCCESS) 213 | 214 | # get driver's bitrate 215 | can_bus_params = get_can_bus_params(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0], self.busType) 216 | print(can_bus_params) 217 | 218 | # check result 219 | self.assertEqual(bitrate, can_bus_params["bitRate"]) 220 | 221 | # 3rd 222 | bitrate = 1_000_000 223 | status = xl.CanSetChannelBitrate(self.portHandle[0], self.accessMask, bitrate) 224 | self.assertEqual(status, xl.XL_SUCCESS) 225 | 226 | # get driver's bitrate 227 | can_bus_params = get_can_bus_params(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0], self.busType) 228 | print(can_bus_params) 229 | 230 | # check result 231 | self.assertEqual(bitrate, can_bus_params["bitRate"]) 232 | 233 | 234 | # python -m unittest tests.test_basic.TestCanSetChannelParams 235 | class TestCanSetChannelParams(unittest.TestCase): 236 | def setUp(self): 237 | xl.OpenDriver() 238 | 239 | self.pHwType = [xl.XL_HWTYPE_VIRTUAL] 240 | self.pHwIndex = [0] 241 | self.pHwChannel = [0] 242 | self.busType = xl.XL_BUS_TYPE_CAN 243 | self.appName = bytes("pyxldrv".encode()) 244 | xl.SetApplConfig(appName=self.appName, appChannel=0, pHwType=self.pHwType, pHwIndex=self.pHwIndex, pHwChannel=self.pHwChannel, busType=self.busType) 245 | xl.GetApplConfig(appName=self.appName, appChannel=0, pHwType=self.pHwType, pHwIndex=self.pHwIndex, pHwChannel=self.pHwChannel, busType=self.busType) 246 | 247 | self.accessMask = 0 248 | self.accessMask = xl.GetChannelMask(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0]) 249 | 250 | self.portHandle = [0] 251 | self.permissionMask = [self.accessMask] 252 | self.rxQueueSize = 2^10 253 | self.xlInterfaceVersion = xl.XL_INTERFACE_VERSION 254 | xl.OpenPort(self.portHandle, self.appName, self.accessMask, self.permissionMask, self.rxQueueSize, self.xlInterfaceVersion, self.busType) 255 | 256 | def tearDown(self): 257 | xl.ClosePort(self.portHandle[0]) 258 | xl.CloseDriver() 259 | 260 | def test_CanSetChannelParams(self): 261 | chipParams = {} 262 | chipParams["bitRate"] =250_000 263 | chipParams["sjw"] = 1 264 | chipParams["tseg1"] = 10 265 | chipParams["tseg2"] = 5 266 | chipParams["sam"] = 1 267 | # status = xl.CanSetChannelParams(self.portHandle[0], self.accessMask, chipParams) 268 | # self.assertEqual(status, xl.XL_SUCCESS) 269 | # .{'bitRate': 250000, 'sjw': 1, 'tseg1': 10, 'tseg2': 5, 'sam': 1, 'outputMode': 1, 'reserved[7]': bytearray(b'\x00\x00\x00\x00\x00\x00\x00'), 'canOpMode': 1, 'name': b'Virtual Channel 1', 'hwType': 1, 'hwIndex': 0, 'hwChannel': 0} 270 | # {'bitRate': 500000, 'sjw': 1, 'tseg1': 10, 'tseg2': 5, 'sam': 1, 'outputMode': 1, 'reserved[7]': bytearray(b'\x00\x00\x00\x00\x00\x00\x00'), 'canOpMode': 1, 'name': b'Virtual Channel 1', 'hwType': 1, 'hwIndex': 0, 'hwChannel': 0} 271 | # {'bitRate': 1000000, 'sjw': 1, 'tseg1': 5, 'tseg2': 2, 'sam': 1, 'outputMode': 1, 'reserved[7]': bytearray(b'\x00\x00\x00\x00\x00\x00\x00'), 'canOpMode': 1, 'name': b'Virtual Channel 1', 'hwType': 1, 'hwIndex': 0, 'hwChannel': 0} 272 | 273 | 274 | pass 275 | 276 | 277 | # python -m unittest tests.test_basic.TestActivateDeactivate 278 | class TestActivateDeactivate(unittest.TestCase): 279 | def setUp(self): 280 | xl.OpenDriver() 281 | 282 | self.appName = bytes("pyxldrv".encode()) 283 | self.appChannel = 0 284 | self.pHwType = [xl.XL_HWTYPE_VIRTUAL] 285 | self.pHwIndex = [0] 286 | self.pHwChannel = [0] 287 | self.busType = xl.XL_BUS_TYPE_CAN 288 | 289 | xl.SetApplConfig(self.appName, self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 290 | xl.GetApplConfig(self.appName, self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 291 | 292 | self.accessMask = xl.GetChannelMask(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0]) 293 | 294 | self.portHandle = [0] 295 | self.permissionMask = [self.accessMask] 296 | self.rxQueueSize = 2^10 297 | self.xlInterfaceVersion = xl.XL_INTERFACE_VERSION 298 | xl.OpenPort(self.portHandle, self.appName, self.accessMask, self.permissionMask, self.rxQueueSize, self.xlInterfaceVersion, self.busType) 299 | 300 | def tearDown(self): 301 | xl.ClosePort(self.portHandle[0]) 302 | xl.CloseDriver() 303 | 304 | def test_activate_deactivate(self): 305 | print(inspect.getframeinfo(inspect.currentframe())[2]) 306 | 307 | portHandle = self.portHandle[0] 308 | accessMask = self.accessMask 309 | busType = self.busType 310 | flags = xl.XL_ACTIVATE_RESET_CLOCK 311 | 312 | status = xl.ActivateChannel(portHandle, accessMask, busType, flags) 313 | self.assertEqual(status, xl.XL_SUCCESS) 314 | 315 | status = xl.DeactivateChannel(portHandle, accessMask) 316 | self.assertEqual(status, xl.XL_SUCCESS) 317 | 318 | # python -m unittest tests.test_basic.TestCanTransmitReceive 319 | class TestCanTransmitReceive(unittest.TestCase): 320 | def setUp(self): 321 | xl.OpenDriver() 322 | 323 | self.pHwType = [xl.XL_HWTYPE_VIRTUAL] 324 | self.pHwIndex = [0] 325 | self.pHwChannel = [0] 326 | self.busType = xl.XL_BUS_TYPE_CAN 327 | self.appName = bytes("pyxldrv".encode()) 328 | xl.SetApplConfig(appName=self.appName, appChannel=0, pHwType=self.pHwType, pHwIndex=self.pHwIndex, pHwChannel=self.pHwChannel, busType=self.busType) 329 | xl.GetApplConfig(appName=self.appName, appChannel=0, pHwType=self.pHwType, pHwIndex=self.pHwIndex, pHwChannel=self.pHwChannel, busType=self.busType) 330 | 331 | self.accessMask = 0 332 | self.accessMask = xl.GetChannelMask(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0]) 333 | 334 | self.portHandle = [0] 335 | self.permissionMask = [self.accessMask] 336 | self.rxQueueSize = 2^10 337 | self.xlInterfaceVersion = xl.XL_INTERFACE_VERSION 338 | xl.OpenPort(self.portHandle, self.appName, self.accessMask, self.permissionMask, self.rxQueueSize, self.xlInterfaceVersion, self.busType) 339 | 340 | self.flags = xl.XL_ACTIVATE_RESET_CLOCK 341 | xl.ActivateChannel(self.portHandle[0], self.accessMask, self.busType, self.flags) 342 | 343 | def tearDown(self): 344 | xl.DeactivateChannel(self.portHandle[0], self.accessMask) 345 | xl.ClosePort(self.portHandle[0]) 346 | xl.CloseDriver() 347 | 348 | def test_cantransmit_receive(self): 349 | print(inspect.getframeinfo(inspect.currentframe())[2]) 350 | 351 | msgs = [] 352 | msgs.append({"flags":0, "id":0x321, "dlc":8, "data":bytearray([0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0])}) 353 | msgs.append({"flags":0, "id":0x123, "dlc":3, "data":bytearray([0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF])}) 354 | message_count = [len(msgs)] 355 | 356 | status = xl.CanTransmit(self.portHandle[0], self.accessMask, message_count, msgs) 357 | self.assertEqual(status, xl.XL_SUCCESS) 358 | 359 | eventcount=[1] 360 | events=[{}] 361 | evstr=[""] 362 | status = xl.Receive(self.portHandle[0],eventcount,events,evstr) 363 | print(decode_bin(evstr[0])) 364 | self.assertEqual(status, xl.XL_SUCCESS) 365 | 366 | status = xl.Receive(self.portHandle[0],eventcount,events,evstr) 367 | print(decode_bin(evstr[0])) 368 | self.assertEqual(status, xl.XL_SUCCESS) 369 | # self.assertEqual(eventcount[0], 0) 370 | 371 | if __name__ == '__main__': 372 | unittest.main() 373 | -------------------------------------------------------------------------------- /pyxldrv/can.py: -------------------------------------------------------------------------------- 1 | # *-* encoding: utf-8 *-* 2 | import vxlapi as xl 3 | import chardet 4 | import win32event 5 | import time 6 | 7 | from logging import getLogger, DEBUG, NullHandler, StreamHandler, FileHandler 8 | logger = getLogger(__name__) 9 | logger.setLevel(DEBUG) 10 | logger.addHandler(NullHandler()) 11 | logger.propagate = False 12 | 13 | def decode_bin(bin): 14 | return bin.decode(chardet.detect(bin)["encoding"]) 15 | 16 | def get_can_bus_params(hwType, hwIndex, hwChannel, busType): 17 | driverConfig = {} 18 | xl.GetDriverConfig(driverConfig) 19 | can_bus_params = None 20 | for ch in driverConfig["channel"]: 21 | if (ch["hwType"] == hwType and ch["hwIndex"] == hwIndex and ch["hwChannel"] == hwChannel): 22 | if ch["busParams"]["busType"] == busType: 23 | can_bus_params = ch["busParams"]["data"]["can"] 24 | can_bus_params["name"] = decode_bin(ch["name"]) 25 | can_bus_params["hwType"] = ch["hwType"] 26 | can_bus_params["hwIndex"] = ch["hwIndex"] 27 | can_bus_params["hwChannel"] = ch["hwChannel"] 28 | return can_bus_params 29 | 30 | def print_can_networks(): 31 | driverConfig = {} 32 | xl.GetDriverConfig(driverConfig) 33 | for ch in driverConfig["channel"]: 34 | if ch["busParams"]["busType"] == xl.XL_BUS_TYPE_CAN: 35 | name = decode_bin(ch["name"]) 36 | print(f"name : {name}") 37 | hwType=ch["hwType"] 38 | print(f"hwType : {hwType}") 39 | hwIndex=ch["hwIndex"] 40 | print(f"hwIndex : {hwIndex}") 41 | hwChannel = ch["hwChannel"] 42 | print(f"hwChannel : {hwChannel}") 43 | bitRate = ch["busParams"]["data"]["can"]["bitRate"] 44 | print(f"bitRate : {bitRate//1000} kbps") 45 | print() 46 | class Can: 47 | def __init__(self, *, appName="pyxldrv", appChannel=0, HwType=xl.XL_HWTYPE_VIRTUAL, HwIndex=0, HwChannel=0, rxQueueSize=2**10, busType=xl.XL_BUS_TYPE_CAN, flags=xl.XL_ACTIVATE_RESET_CLOCK, queueLevel=1, logger=logger): 48 | self.log = logger 49 | self.log.debug(f"[{self.__class__.__name__:8}][{self.__init__.__name__:8}] new instance. appName:{appName}, appChannel:{appChannel}, HwType:{HwType}, HwIndex:{HwIndex}, HwChannel:{HwChannel}, rxQueueSize:{rxQueueSize}, busType:{busType}, flags:{flags}") 50 | 51 | # set by param 52 | self.appName = appName 53 | self.pHwType = [HwType] 54 | self.pHwIndex = [HwIndex] 55 | self.pHwChannel = [HwChannel] 56 | self.busType = busType 57 | self.rxQueueSize = rxQueueSize 58 | self.flags = flags 59 | self.appChannel = appChannel 60 | self.queueLevel = queueLevel 61 | 62 | # internal use 63 | self.accessMask = 0 64 | self.portHandle = [0] 65 | self.permissionMask = [self.accessMask] 66 | self.xlInterfaceVersion = xl.XL_INTERFACE_VERSION 67 | self.xlHandle = [0] 68 | 69 | # internal use for error 70 | self.last_error = xl.XL_SUCCESS 71 | 72 | # 73 | # Setup Driver. see 4.2 Flowchart in "XL Driver Library - Description.pdf" 74 | # 75 | status = xl.OpenDriver() 76 | if status != xl.XL_SUCCESS: 77 | self.log.error(f"[{self.appName:8}][{self.__init__.__name__:8}] !! OpenDriver() returned {status} !!") 78 | 79 | status = xl.SetApplConfig(bytes(self.appName.encode()), self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 80 | if status != xl.XL_SUCCESS: 81 | self.log.debug(f"[{self.appName:8}][{self.__init__.__name__:8}] SetApplConfig returned {status}. appName:{self.appName}, appChannel:{self.appChannel}, pHwType:{self.pHwType}, pHwIndex:{self.pHwIndex}, pHwChannel:{self.pHwChannel}, busType:{self.busType}") 82 | 83 | status = xl.GetApplConfig(bytes(self.appName.encode()), self.appChannel, self.pHwType, self.pHwIndex, self.pHwChannel, self.busType) 84 | if status != xl.XL_SUCCESS: 85 | self.log.debug(f"[{self.appName:8}][{self.__init__.__name__:8}] GetApplConfig returned {status}. appName:{self.appName}, appChannel:{self.appChannel}, pHwType:{self.pHwType}, pHwIndex:{self.pHwIndex}, pHwChannel:{self.pHwChannel}, busType:{self.busType}") 86 | 87 | # accessMask should be OR(|=), if multi-HwChannels are used. (In this case, OR(|=) has little meaning.) 88 | self.accessMask |= xl.GetChannelMask(self.pHwType[0],self.pHwIndex[0],self.pHwChannel[0]) 89 | if self.accessMask == 0: 90 | self.log.error(f"[{self.appName:8}][{self.__init__.__name__:8}]!! GetChannelMask returned accessMask={self.accessMask}!! pHwType:{self.pHwType}, pHwIndex:{self.pHwIndex}, pHwChannel:{self.pHwChannel}") 91 | 92 | # permissionMask should be same as accessMask at when OpenPort timing. 93 | self.permissionMask = [self.accessMask] 94 | status = xl.OpenPort(self.portHandle, bytes(self.appName.encode()), self.accessMask, self.permissionMask, self.rxQueueSize, self.xlInterfaceVersion, self.busType) 95 | if status != xl.XL_SUCCESS: 96 | self.log.error(f"[{self.appName:8}][{self.__init__.__name__:8}]!! OpenPort returned {status} !! portHandle:{self.portHandle}, appName:{self.appName}, accessMask:{self.accessMask}, permissionMask:{self.permissionMask}, rxQueueSize:{self.rxQueueSize}, xlInterfaceVersion:{self.xlInterfaceVersion}, busType:{self.busType}") 97 | 98 | # check permissionMask for logging. see 3.2.9 xlOpenPort in "XL Driver Library - Description.pdf" 99 | if self.permissionMask[0] == 0: 100 | self.log.debug(f"[{self.appName:8}][{self.__init__.__name__:8}] permissionMask({self.permissionMask[0]}) is 0. If this is not init access for CANs, this is no issue.") 101 | 102 | # check portHandle for logging. 103 | if self.portHandle[0] == xl.XL_INVALID_PORTHANDLE: 104 | self.log.error(f"[{self.appName:8}][{self.__init__.__name__:8}]!! portHandle({self.portHandle[0]}) is XL_INVALID_PORTHANDLE !!") 105 | 106 | status = xl.ActivateChannel(self.portHandle[0], self.accessMask, self.busType, self.flags) 107 | if status != xl.XL_SUCCESS: 108 | self.log.debug(f"[{self.appName:8}][{self.__init__.__name__:8}] ActivateChannel returned {status}. portHandle:{self.portHandle}, accessMask:{self.accessMask}, busType:{self.busType}, flags:{self.flags}") 109 | 110 | status = xl.SetNotification(self.portHandle[0], self.xlHandle, self.queueLevel ) 111 | if status != xl.XL_SUCCESS: 112 | self.log.debug(f"[{self.appName:8}][{self.__init__.__name__:8}] SetNotification returned {status}. portHandle:{self.portHandle}, xlHandle:{self.xlHandle}, queueLevel:{self.queueLevel}") 113 | 114 | def __del__(self): 115 | # 116 | # tearDown Driver. see 4.2 Flowchart in XL Driver Library - Description.pdf 117 | # 118 | status = xl.DeactivateChannel(self.portHandle[0], self.accessMask) 119 | if status != xl.XL_SUCCESS: 120 | self.log.debug(f"[{self.appName:8}][{self.__del__.__name__:8}] DeactivateChannel returned {status}. portHandle:{self.portHandle}, accessMask:{self.accessMask}") 121 | 122 | status = xl.ClosePort(self.portHandle[0]) 123 | if status != xl.XL_SUCCESS: 124 | self.log.debug(f"[{self.appName:8}][{self.__del__.__name__:8}] ClosePort returned {status}. portHandle:{self.portHandle}") 125 | 126 | status = xl.CloseDriver() 127 | if status != xl.XL_SUCCESS: 128 | self.log.debug(f"[{self.appName:8}][{self.__del__.__name__:8}] CloseDriver returned {status}") 129 | 130 | 131 | def send(self, *, can_id, data, user_flags=0, user_dlc=None): 132 | ret = True 133 | 134 | # dlc must be 0-8, even if user_dlc is not 0-8. 135 | dlc = None 136 | if user_dlc: 137 | if user_dlc <= 8: 138 | dlc = user_dlc 139 | else: 140 | self.log.warn(f"[{self.appName:8}][{self.send.__name__:8}] user_dlc({user_dlc}) is ignored.") 141 | 142 | # if dlc is not determined by user_dlc, it is estimated by len(data). 143 | if dlc is None: 144 | if len(data) <= 8: 145 | dlc = len(data) 146 | else: 147 | self.log.warn(f"[{self.appName:8}][{self.send.__name__:8}] len(data)({len(data)}) is over 8. dlc is changed into 8.") 148 | dlc = 8 149 | 150 | # the size of data is 0-8byte. 151 | data_buf = [0]*8 152 | for i in range(dlc): 153 | data_buf[i] = data[i] 154 | 155 | # flags 156 | flags = user_flags 157 | 158 | msgs = [{"flags":flags, "id":can_id, "dlc":dlc, "data":bytearray(data_buf)}] 159 | messageCount = [len(msgs)] 160 | 161 | status = xl.CanTransmit(self.portHandle[0], self.accessMask, messageCount, msgs) 162 | if status != xl.XL_SUCCESS: 163 | self.log.error(f"[{self.appName:8}][{self.send.__name__:8}]!! CanTransmit retruns {status} !!") 164 | ret = False 165 | return ret 166 | 167 | def _recv_nonblock(self): 168 | pEventCount = [1] 169 | pEventList = [{}] 170 | pEventString = [b""] 171 | status = xl.Receive(self.portHandle[0], pEventCount, pEventList, pEventString) 172 | return (status, pEventList[0], pEventString[0]) 173 | 174 | def recv(self, *, timeout_sec=3, t_WaitForSingleObject_msec=300): 175 | start_sec = time.time() 176 | elapsed_sec = 0 177 | 178 | while True: 179 | ret = False 180 | msg_flags = 0 181 | timestamp = 0 182 | ch = None 183 | can_id = None 184 | dlc = None 185 | data = [] 186 | 187 | # wait for the signal from vector xl driver 188 | self.debug(self.recv, f"call WaitForSingleObject. xlHandle:{self.xlHandle[0]}, t_WaitForSingleObject_msec:{t_WaitForSingleObject_msec} msec") 189 | ret_win32 = win32event.WaitForSingleObject(self.xlHandle[0], t_WaitForSingleObject_msec) 190 | 191 | if ret_win32 == win32event.WAIT_OBJECT_0: 192 | self.debug(self.recv, f"WaitForSingleObject returned WAIT_OBJECT_0(xlHandle was signaled correctly).") 193 | 194 | # get the event which signals the xHandle via _recv_nonblock->xlReceive. 195 | status, xlevent, xlevstr = self._recv_nonblock() 196 | 197 | # analysis of the event 198 | if status == xl.XL_SUCCESS: 199 | xlevent_tag = xlevent["tag"] 200 | if xlevent_tag == xl.XL_RECEIVE_MSG: # Normal case : the event was rx msg(exected event). 201 | msg_flags = xlevent["tagData"]["msg"]["flags"] 202 | if (msg_flags == 0) or (msg_flags & xl.XL_CAN_MSG_FLAG_ERROR_FRAME): # Normal case : valid receive message or error frame was received. 203 | ret = True 204 | msg_flags = msg_flags 205 | timestamp = xlevent["timeStamp"] / 1_000_000_000 # unit conversion from nanoseconds to seconds. 206 | ch = xlevent["chanIndex"] 207 | can_id = xlevent["tagData"]["msg"]["id"] 208 | dlc = xlevent["tagData"]["msg"]["dlc"] 209 | data = xlevent["tagData"]["msg"]["data"][:dlc] 210 | break # loop end normally (ret = True) 211 | 212 | # logging unhandled event. 213 | self.debug(self.recv, f"{self._decode_bin(xlevstr)}") 214 | else: 215 | # status != xl.XL_SUCCESS 216 | self.warn(self.recv, f"! _recv_nonblock retruns {self._decode_bin(xl.GetErrorString(status))} !") 217 | elif ret_win32 == win32event.WAIT_TIMEOUT: 218 | # continue recv() loop 219 | self.debug(self.recv, f"WaitForSingleObject returned WAIT_TIMEOUT. xlHandle:{self.xlHandle[0]}, t_WaitForSingleObject_msec:{t_WaitForSingleObject_msec} msec") 220 | else: 221 | # critical errors. this loop must be finished. 222 | if ret_win32 == win32event.WAIT_ABANDONED: 223 | # xlHandle might be no longer valid. 224 | self.critical(self.recv, f"!! break recv() loop (ret = False). WaitForSingleObject returned WAIT_ABANDONED. xlHandle:{self.xlHandle[0]}, t_WaitForSingleObject_msec:{t_WaitForSingleObject_msec} msec") 225 | break 226 | elif ret_win32 == win32event.WAIT_FAILED: 227 | # win32api error occured. to get extra info, GetLastError should be used. 228 | self.critical(self.recv, f"!! break recv() loop (ret = False). WaitForSingleObject returned WAIT_FAILED. xlHandle:{self.xlHandle[0]}, t_WaitForSingleObject_msec:{t_WaitForSingleObject_msec} msec") 229 | break 230 | else: 231 | # unkown error occured. 232 | self.critical(self.recv, f"!! break recv() loop (ret = False). WaitForSingleObject returned unkown value({win32event}) break recv() loop !! xlHandle:{self.xlHandle[0]}, t_WaitForSingleObject_msec:{t_WaitForSingleObject_msec} msec") 233 | break 234 | 235 | # timeout detection 236 | elapsed_sec = time.time() - start_sec 237 | if elapsed_sec > timeout_sec: 238 | self.info(self.recv, f"break recv() loop due to no event (ret = False). elapsed_sec:{elapsed_sec:<.3}, timeout_sec:{timeout_sec}") 239 | break 240 | return (ret, msg_flags, timestamp, ch, can_id, dlc, data) 241 | 242 | def info(self,method,s): 243 | self.log.info(f"[{self.appName:8}][{method.__name__:8}] {s}") 244 | 245 | def debug(self,method,s): 246 | self.log.debug(f"[{self.appName:8}][{method.__name__:8}] {s}") 247 | 248 | def warn(self,method,s): 249 | self.log.warn(f"[{self.appName:8}][{method.__name__:8}] {s}") 250 | 251 | def critical(self,method,s): 252 | self.log.critical(f"[{self.appName:8}][{method.__name__:8}] {s}") 253 | 254 | def _decode_bin(self,bin): 255 | return bin.decode(chardet.detect(bin)["encoding"]) 256 | 257 | def _parse_msg_flags(self, msg_flags): 258 | msg_flags_str = "" 259 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_ERROR_FRAME else "|XL_CAN_MSG_FLAG_ERROR_FRAME" 260 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_OVERRUN else "|XL_CAN_MSG_FLAG_OVERRUN" 261 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_NERR else "|XL_CAN_MSG_FLAG_NERR" 262 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_WAKEUP else "|XL_CAN_MSG_FLAG_WAKEUP" 263 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_REMOTE_FRAME else "|XL_CAN_MSG_FLAG_REMOTE_FRAME" 264 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_RESERVED_1 else "|XL_CAN_MSG_FLAG_RESERVED_1" 265 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_TX_COMPLETED else "|XL_CAN_MSG_FLAG_TX_COMPLETED" 266 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_TX_REQUEST else "|XL_CAN_MSG_FLAG_TX_REQUEST" 267 | msg_flags_str += "" if msg_flags & xl.XL_CAN_MSG_FLAG_SRR_BIT_DOM else "|XL_CAN_MSG_FLAG_SRR_BIT_DOM" 268 | return msg_flags_str 269 | 270 | 271 | def recv_thread(can, timeout_sec): 272 | logger.debug("recv_task - start") 273 | while True: 274 | ret, msg_flags, timestamp, ch, can_id, dlc, data = can.recv(timeout_sec=timeout_sec) 275 | if ret == True: 276 | if msg_flags == 0: 277 | data = " ".join(map(lambda d:f"{d:02X}",data)) 278 | #___0.081289 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 279 | print(f"{timestamp:>11.6f} {ch+1:<2} {can_id:3x} Rx d {dlc:1} {data}") 280 | elif msg_flags & xl.XL_CAN_MSG_FLAG_ERROR_FRAME: 281 | print(f"{timestamp:>11.6f} {ch+1:<2} ERROR FRAME") 282 | else: 283 | # ignore other flags 284 | pass 285 | else: 286 | break 287 | logger.debug("recv_task - end") 288 | return True 289 | 290 | if __name__ == "__main__": 291 | from logging import basicConfig, Formatter 292 | basicConfig(level=DEBUG) 293 | logger = getLogger(__name__) 294 | handler = StreamHandler() 295 | handler.setLevel(DEBUG) 296 | handler.setFormatter(Formatter("%(asctime)s [%(levelname)-7s][%(name)-10s]%(message)s")) 297 | logger.addHandler(handler) 298 | 299 | print_can_networks() 300 | # xl.PopupHwConfig() 301 | from concurrent.futures import ThreadPoolExecutor 302 | 303 | executor = ThreadPoolExecutor(max_workers=1) 304 | 305 | receiver=Can(appName="receiver") 306 | executor.submit(recv_thread, can=receiver, timeout_sec=3) 307 | 308 | sender=Can(appName="sender") 309 | for i in range(10): 310 | sender.send(can_id=0x123, data=[0,1,2,3,4,5]) 311 | time.sleep(0.1) 312 | 313 | executor.shutdown() 314 | -------------------------------------------------------------------------------- /tests/log.txt: -------------------------------------------------------------------------------- 1 | 0.002977 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 2 | 0.003953 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 3 | 0.004961 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 4 | 0.005953 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 5 | 0.006929 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 6 | 0.007937 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 7 | 0.008929 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 8 | 0.009937 1 5BE Rx d 8 00 00 00 00 00 00 00 00 Length = 976000 BitCount = 126 ID = 1470 9 | 0.010561 1 7D0 Rx d 3 00 00 00 Length = 592000 BitCount = 78 ID = 2000 10 | 0.011537 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 11 | 0.012545 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 12 | 0.013537 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 13 | 0.014521 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 14 | 0.015505 1 46C Rx d 8 00 20 55 7F C0 14 00 00 Length = 952000 BitCount = 123 ID = 1132 15 | 0.016505 1 5B6 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1462 16 | 0.017033 1 470 Rx d 2 A0 00 Length = 496000 BitCount = 66 ID = 1136 17 | 0.017985 1 5C6 Rx d 8 00 14 50 50 52 80 00 00 Length = 920000 BitCount = 119 ID = 1478 18 | 0.018961 1 5BC Rx d 8 00 05 60 40 04 19 90 00 Length = 944000 BitCount = 122 ID = 1468 19 | 0.019929 1 5CE Rx d 8 65 40 00 00 00 00 00 00 Length = 936000 BitCount = 121 ID = 1486 20 | 0.020929 1 5C0 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1472 21 | 0.021777 1 760 Rx d 6 00 00 00 00 00 00 Length = 816000 BitCount = 106 ID = 1888 22 | 0.022777 1 5C4 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1476 23 | 0.023617 1 764 Rx d 6 00 00 00 00 00 00 Length = 808000 BitCount = 105 ID = 1892 24 | 0.024593 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 25 | 0.025601 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 26 | 0.026593 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 27 | 0.027569 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 28 | 0.028577 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 29 | 0.029569 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 30 | 0.030553 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 31 | 0.031529 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 32 | 0.032537 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 33 | 0.033529 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 34 | 0.034505 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 35 | 0.035513 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 36 | 0.036505 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 37 | 0.037481 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 38 | 0.038489 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 39 | 0.039481 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 40 | 0.040465 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 41 | 0.041449 1 46C Rx d 8 00 20 55 7F C0 14 00 00 Length = 952000 BitCount = 123 ID = 1132 42 | 0.042425 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 43 | 0.043433 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 44 | 0.044425 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 45 | 0.045401 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 46 | 0.046409 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 47 | 0.047401 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 48 | 0.048385 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 49 | 0.049361 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 50 | 0.050369 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 51 | 0.051361 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 52 | 0.052337 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 53 | 0.053345 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 54 | 0.054337 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 55 | 0.055345 1 5BE Rx d 8 00 00 00 00 00 00 00 00 Length = 976000 BitCount = 126 ID = 1470 56 | 0.056321 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 57 | 0.057329 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 58 | 0.058321 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 59 | 0.059305 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 60 | 0.060289 1 46C Rx d 8 00 20 55 7F C0 14 00 00 Length = 952000 BitCount = 123 ID = 1132 61 | 0.061289 1 5B6 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1462 62 | 0.061817 1 470 Rx d 2 A0 00 Length = 496000 BitCount = 66 ID = 1136 63 | 0.062769 1 5C6 Rx d 8 00 14 50 50 52 80 00 00 Length = 920000 BitCount = 119 ID = 1478 64 | 0.063745 1 5BC Rx d 8 00 05 60 40 04 19 90 00 Length = 944000 BitCount = 122 ID = 1468 65 | 0.064713 1 5CE Rx d 8 65 40 00 00 00 00 00 00 Length = 936000 BitCount = 121 ID = 1486 66 | 0.065713 1 5C0 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1472 67 | 0.066561 1 760 Rx d 6 00 00 00 00 00 00 Length = 816000 BitCount = 106 ID = 1888 68 | 0.067561 1 5C4 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1476 69 | 0.068401 1 764 Rx d 6 00 00 00 00 00 00 Length = 808000 BitCount = 105 ID = 1892 70 | 0.069377 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 71 | 0.070385 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 72 | 0.071377 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 73 | 0.072353 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 74 | 0.073361 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 75 | 0.074353 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 76 | 0.075337 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 77 | 0.076313 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 78 | 0.077321 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 79 | 0.078313 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 80 | 0.079289 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 81 | 0.080297 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 82 | 0.081289 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 83 | 0.081913 1 7D0 Rx d 3 00 00 00 Length = 592000 BitCount = 78 ID = 2000 84 | 0.082889 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 85 | 0.083897 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 86 | 0.084889 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 87 | 0.085873 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 88 | 0.086857 1 46C Rx d 8 00 20 55 7F C0 14 00 00 Length = 952000 BitCount = 123 ID = 1132 89 | 0.087833 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 90 | 0.088841 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 91 | 0.089833 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 92 | 0.090809 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 93 | 0.091817 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 94 | 0.092809 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 95 | 0.093793 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 96 | 0.094769 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 97 | 0.095777 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 98 | 0.096769 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 99 | 0.097745 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 100 | 0.098753 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 101 | 0.099745 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 102 | 0.100753 1 5BE Rx d 8 00 00 00 00 00 00 00 00 Length = 976000 BitCount = 126 ID = 1470 103 | 0.101729 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 104 | 0.102737 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 105 | 0.103729 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 106 | 0.104713 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 107 | 0.105697 1 46C Rx d 8 00 20 55 7F C0 14 00 00 Length = 952000 BitCount = 123 ID = 1132 108 | 0.106697 1 5B6 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1462 109 | 0.107225 1 470 Rx d 2 A0 00 Length = 496000 BitCount = 66 ID = 1136 110 | 0.108177 1 5C6 Rx d 8 00 14 50 50 52 80 00 00 Length = 920000 BitCount = 119 ID = 1478 111 | 0.109153 1 5BC Rx d 8 00 05 60 40 04 19 90 00 Length = 944000 BitCount = 122 ID = 1468 112 | 0.110121 1 5CE Rx d 8 65 40 00 00 00 00 00 00 Length = 936000 BitCount = 121 ID = 1486 113 | 0.111121 1 5C0 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1472 114 | 0.111969 1 760 Rx d 6 00 00 00 00 00 00 Length = 816000 BitCount = 106 ID = 1888 115 | 0.112969 1 5C4 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1476 116 | 0.113809 1 764 Rx d 6 00 00 00 00 00 00 Length = 808000 BitCount = 105 ID = 1892 117 | 0.114785 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 118 | 0.115793 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 119 | 0.116785 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 120 | 0.117761 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 121 | 0.118769 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 122 | 0.119761 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 123 | 0.120745 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 124 | 0.121721 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 125 | 0.122729 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 126 | 0.123721 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 127 | 0.124697 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 128 | 0.125705 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 129 | 0.126697 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 130 | 0.127673 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 131 | 0.128681 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 132 | 0.129673 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 133 | 0.130657 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 134 | 0.131641 1 46C Rx d 8 00 20 55 7F C0 14 00 00 Length = 952000 BitCount = 123 ID = 1132 135 | 0.132617 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 136 | 0.133625 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 137 | 0.134617 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 138 | 0.135593 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 139 | 0.136601 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 140 | 0.137593 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 141 | 0.138577 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 142 | 0.139553 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 143 | 0.140561 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 144 | 0.141553 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 145 | 0.142529 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 146 | 0.143537 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 147 | 0.144529 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 148 | 0.145537 1 5BE Rx d 8 00 00 00 00 00 00 00 00 Length = 976000 BitCount = 126 ID = 1470 149 | 0.146161 1 7D0 Rx d 3 00 00 00 Length = 592000 BitCount = 78 ID = 2000 150 | 0.147137 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 151 | 0.148145 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 152 | 0.149137 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 153 | 0.150121 1 356 Rx d 8 00 00 00 C0 08 00 00 00 Length = 952000 BitCount = 123 ID = 854 154 | 0.151105 1 46C Rx d 8 00 20 55 7F C0 14 00 00 Length = 952000 BitCount = 123 ID = 1132 155 | 0.152105 1 5B6 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1462 156 | 0.152633 1 470 Rx d 2 A0 00 Length = 496000 BitCount = 66 ID = 1136 157 | 0.153585 1 5C6 Rx d 8 00 14 50 50 52 80 00 00 Length = 920000 BitCount = 119 ID = 1478 158 | 0.154561 1 5BC Rx d 8 00 05 60 40 04 19 90 00 Length = 944000 BitCount = 122 ID = 1468 159 | 0.155529 1 5CE Rx d 8 65 40 00 00 00 00 00 00 Length = 936000 BitCount = 121 ID = 1486 160 | 0.156529 1 5C0 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1472 161 | 0.157377 1 760 Rx d 6 00 00 00 00 00 00 Length = 816000 BitCount = 106 ID = 1888 162 | 0.158377 1 5C4 Rx d 8 00 00 00 00 00 00 00 00 Length = 968000 BitCount = 125 ID = 1476 163 | 0.159217 1 764 Rx d 6 00 00 00 00 00 00 Length = 808000 BitCount = 105 ID = 1892 164 | 0.160193 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 165 | 0.161201 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 166 | 0.162193 1 3E6 Rx d 8 50 00 00 00 00 00 00 00 Length = 960000 BitCount = 124 ID = 998 167 | 0.163169 1 3E2 Rx d 8 00 3F E4 00 00 00 03 02 Length = 944000 BitCount = 122 ID = 994 168 | 0.164177 1 3E4 Rx d 8 00 00 00 00 00 00 80 20 Length = 976000 BitCount = 126 ID = 996 -------------------------------------------------------------------------------- /images/Vector_Driver_Setup.png: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | xldrv/vector_Driver_Setup.PNG at master · tdrk1980/xldrv 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 |
109 | Skip to content 110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 326 | 327 | 328 | 329 |
330 | 331 |
332 | 333 |
334 | 335 | 336 |
337 | 338 | 339 | 340 |
341 |
342 |
343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 |
352 |
353 | 354 |
    355 |
  • 356 |
    357 | 358 |
    359 | 371 | 376 | 377 |
    378 |
    379 |
    380 | 381 | Notifications 382 |
    383 | 384 | 426 | 427 |
    428 |
    429 |
    430 |
    431 |
  • 432 | 433 |
  • 434 | 435 |
    436 |
    437 | 438 | 446 | 450 |
    451 |
    452 | 453 | 461 | 465 |
    466 | 467 |
  • 468 | 469 |
  • 470 | 471 | 472 | Fork 473 | 474 | 478 |
  • 479 |
480 | 481 |

482 | 483 | /xldrv 486 | 487 |

488 | 489 |
490 | 491 | 539 | 540 | 541 |
542 | 543 |
544 |
545 | 546 | 547 | Permalink 548 | 549 | 550 | 551 | 552 | 553 |
554 | 555 |
556 | 562 | 563 |
564 | 565 |
566 |
567 | 568 | Switch branches/tags 569 |
570 | 571 |
572 |
573 | 574 |
575 |
576 | 584 |
585 |
586 | 587 | 615 | 616 |
617 |
618 | 619 | 620 |
621 | 622 |
Nothing to show
623 |
624 | 625 |
626 |
627 |
628 | 629 |
630 | 634 | Find file 635 | 636 | 637 | Copy path 638 | 639 |
640 | 643 |
644 | 645 | 646 | 647 |
648 | Fetching contributors… 649 |
650 | 651 |
652 | 653 | Cannot retrieve contributors at this time 654 |
655 |
656 | 657 | 658 |
659 |
660 |
661 | 662 |
663 | Download 664 | History 665 |
666 | 667 | 671 | 672 | 673 | 674 |
675 | 679 |
680 | 681 |
682 | 46.8 KB 683 |
684 |
685 | 686 | 687 | 688 |
689 |
690 | vector_Driver_Setup.PNG 691 |
692 |
693 | 694 |
695 | 696 |
697 | 698 | 699 |
700 | 701 | 702 |
703 |
704 | 705 | 706 |
707 | 708 |
709 | 710 |
711 |
712 | 713 |
714 | 715 | 716 | 744 | 745 | 746 | 747 |
748 | 749 | 752 | You can’t perform that action at this time. 753 |
754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 |
764 | 765 | You signed in with another tab or window. Reload to refresh your session. 766 | You signed out in another tab or window. Reload to refresh your session. 767 |
768 | 777 | 778 | 782 | 783 |
784 | Press h to open a hovercard with more details. 785 |
786 | 787 | 788 | 789 | 790 | 791 | -------------------------------------------------------------------------------- /images/Vector_XL_Driver_Library.png: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | xldrv/Vector_XL_Driver_Library.PNG at master · tdrk1980/xldrv 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 |
109 | Skip to content 110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 326 | 327 | 328 | 329 |
330 | 331 |
332 | 333 |
334 | 335 | 336 |
337 | 338 | 339 | 340 |
341 |
342 |
343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 |
352 |
353 | 354 |
    355 |
  • 356 |
    357 | 358 |
    359 | 371 | 376 | 377 |
    378 |
    379 |
    380 | 381 | Notifications 382 |
    383 | 384 | 426 | 427 |
    428 |
    429 |
    430 |
    431 |
  • 432 | 433 |
  • 434 | 435 |
    436 |
    437 | 438 | 446 | 450 |
    451 |
    452 | 453 | 461 | 465 |
    466 | 467 |
  • 468 | 469 |
  • 470 | 471 | 472 | Fork 473 | 474 | 478 |
  • 479 |
480 | 481 |

482 | 483 | /xldrv 486 | 487 |

488 | 489 |
490 | 491 | 539 | 540 | 541 |
542 | 543 |
544 |
545 | 546 | 547 | Permalink 548 | 549 | 550 | 551 | 552 | 553 |
554 | 555 |
556 | 562 | 563 |
564 | 565 |
566 |
567 | 568 | Switch branches/tags 569 |
570 | 571 |
572 |
573 | 574 |
575 |
576 | 584 |
585 |
586 | 587 | 615 | 616 |
617 |
618 | 619 | 620 |
621 | 622 |
Nothing to show
623 |
624 | 625 |
626 |
627 |
628 | 629 |
630 | 634 | Find file 635 | 636 | 637 | Copy path 638 | 639 |
640 | 643 |
644 | 645 | 646 | 647 |
648 | Fetching contributors… 649 |
650 | 651 |
652 | 653 | Cannot retrieve contributors at this time 654 |
655 |
656 | 657 | 658 |
659 |
660 |
661 | 662 |
663 | Download 664 | History 665 |
666 | 667 | 671 | 672 | 673 | 674 |
675 | 679 |
680 | 681 |
682 | 50.5 KB 683 |
684 |
685 | 686 | 687 | 688 |
689 |
690 | Vector_XL_Driver_Library.PNG 691 |
692 |
693 | 694 |
695 | 696 |
697 | 698 | 699 |
700 | 701 | 702 |
703 |
704 | 705 | 706 |
707 | 708 |
709 | 710 |
711 |
712 | 713 |
714 | 715 | 716 | 744 | 745 | 746 | 747 |
748 | 749 | 752 | You can’t perform that action at this time. 753 |
754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 |
764 | 765 | You signed in with another tab or window. Reload to refresh your session. 766 | You signed out in another tab or window. Reload to refresh your session. 767 |
768 | 777 | 778 | 782 | 783 |
784 | Press h to open a hovercard with more details. 785 |
786 | 787 | 788 | 789 | 790 | 791 | --------------------------------------------------------------------------------