1616
1717# Define Module Logger
1818# ====================
19- LOG = logging .getLogger ('can.vector' )
19+ LOG = logging .getLogger (__name__ )
2020
2121# Import safely Vector API module for Travis tests
2222if sys .platform == 'win32' :
23- from . import vxlapi
23+ try :
24+ from . import vxlapi
25+ except Exception as exc :
26+ LOG .error ('Could not import vxlapi: %s' , exc )
27+ vxlapi = None
2428else :
2529 LOG .warning ('Vector API does not work on %s platform' , sys .platform )
2630 vxlapi = None
2933class VectorBus (BusABC ):
3034 """The CAN Bus implemented for the Vector interface."""
3135
32- def __init__ (self , channel , can_filters = None , poll_interval = 0.005 ,
33- app_name = "CANalyzer" , ** config ):
36+ def __init__ (self , channel , can_filters = None , poll_interval = 0.01 ,
37+ bitrate = None , rx_queue_size = 256 , app_name = "CANalyzer" , ** config ):
3438 """
3539 :param list channel:
3640 The channel indexes to create this bus with.
3741 Can also be a single integer or a comma separated string.
3842 :param float poll_interval:
3943 Poll interval in seconds.
44+ :param int bitrate:
45+ Bitrate in bits/s.
46+ :param int rx_queue_size:
47+ Number of messages in receive queue.
4048 :param str app_name:
4149 Name of application in Hardware Config.
4250 """
4351 if vxlapi is None :
4452 raise ImportError ("The Vector API has not been loaded" )
4553 self .poll_interval = poll_interval
4654 if isinstance (channel , (list , tuple )):
47- self .channel = channel
55+ self .channels = channel
4856 elif isinstance (channel , int ):
49- self .channel = [channel ]
57+ self .channels = [channel ]
5058 else :
5159 # Assume comma separated string of channels
52- self .channel = [int (channel ) for channel in channel .split (',' )]
60+ self .channels = [int (ch . strip ()) for ch in channel .split (',' )]
5361 self ._app_name = app_name .encode ()
54- self ._driver_init (can_filters )
62+ self .channel_info = 'Application %s: %s' % (
63+ app_name , ', ' .join ('CAN %d' % (ch + 1 ) for ch in self .channels ))
64+
65+ vxlapi .xlOpenDriver ()
66+ self .port_handle = vxlapi .XLportHandle (vxlapi .XL_INVALID_PORTHANDLE )
67+ self .mask = 0
68+ # Get channels masks
69+ for channel in self .channels :
70+ hw_type = ctypes .c_uint (0 )
71+ hw_index = ctypes .c_uint (0 )
72+ hw_channel = ctypes .c_uint (0 )
73+ vxlapi .xlGetApplConfig (self ._app_name , channel , hw_type , hw_index ,
74+ hw_channel , vxlapi .XL_BUS_TYPE_CAN )
75+ LOG .debug ('Channel index %d found' , channel )
76+ mask = vxlapi .xlGetChannelMask (hw_type .value , hw_index .value ,
77+ hw_channel .value )
78+ LOG .debug ('Channel %d, Type: %d, Mask: %d' ,
79+ hw_channel .value , hw_type .value , mask )
80+ self .mask |= mask
81+ permission_mask = vxlapi .XLaccess ()
82+ vxlapi .xlOpenPort (self .port_handle , self ._app_name , self .mask ,
83+ permission_mask , rx_queue_size ,
84+ vxlapi .XL_INTERFACE_VERSION , vxlapi .XL_BUS_TYPE_CAN )
85+ LOG .debug (
86+ 'Open Port: PortHandle: %d, PermissionMask: 0x%X' ,
87+ self .port_handle .value , permission_mask .value )
88+ if bitrate :
89+ if permission_mask .value != self .mask :
90+ LOG .warning ('Can not set bitrate since no init access' )
91+ vxlapi .xlCanSetChannelBitrate (self .port_handle , permission_mask , bitrate )
92+ self .set_filters (can_filters )
5593 try :
56- self ._go_on_bus ()
94+ vxlapi .xlActivateChannel (self .port_handle , self .mask ,
95+ vxlapi .XL_BUS_TYPE_CAN , 0 )
5796 except vxlapi .VectorError :
5897 self .shutdown ()
5998 raise
99+ # Calculate time offset for absolute timestamps
100+ offset = vxlapi .XLuint64 ()
101+ vxlapi .xlGetSyncTime (self .port_handle , offset )
102+ self ._time_offset = time .time () - offset .value / 1000000000.0
60103 super (VectorBus , self ).__init__ ()
61104
62- def _driver_init (self , can_filters ):
63- xl_status = vxlapi .open_driver ()
64- LOG .debug ('Open Driver: Status: %d' , xl_status .value )
65- if xl_status .value == vxlapi .XL_SUCCESS :
66- channel_mask = []
67- # Get channels masks
68- for channel in self .channel :
69- app_channel = ctypes .c_uint (channel )
70- hw_type = ctypes .c_uint (0 )
71- hw_index = ctypes .c_uint (0 )
72- hw_channel = ctypes .c_uint (0 )
73- xl_status = vxlapi .get_appl_config (
74- app_name = self ._app_name ,
75- app_channel = app_channel ,
76- hw_type = hw_type ,
77- hw_index = hw_index ,
78- hw_channel = hw_channel )
79- if xl_status .value == vxlapi .XL_SUCCESS :
80- LOG .debug ('Channel index %d found' , app_channel .value )
81- hw_type = ctypes .c_int (hw_type .value )
82- hw_index = ctypes .c_int (hw_index .value )
83- hw_channel = ctypes .c_int (hw_channel .value )
84- channel_mask .append (
85- vxlapi .get_channel_mask (hw_type , hw_index , hw_channel ))
86- LOG .debug ('Channel %d, Type: %d, Mask: %d' ,
87- hw_channel .value , hw_type .value ,
88- channel_mask [app_channel .value ].value )
89- # Open one port for all channels
90- self .mask = vxlapi .XLaccess (0 )
91- for CM in channel_mask :
92- self .mask .value += CM .value
93- self .port_handle = vxlapi .XLportHandle (
94- vxlapi .XL_INVALID_PORTHANDLE )
95- access_mask = self .mask
96- permission_mask = self .mask
97- xl_status = vxlapi .open_port (
98- user_name = self ._app_name ,
99- port_handle = self .port_handle ,
100- access_mask = access_mask ,
101- permission_mask = permission_mask )
102- LOG .debug (
103- 'Open Port: PortHandle: %d, PermissionMask: %s, Status: %d' ,
104- self .port_handle .value , permission_mask .value , xl_status .value )
105- self .set_filters (can_filters )
106- return xl_status
107-
108- def _go_on_bus (self ):
109- vxlapi .activate_channel (
110- port_handle = self .port_handle , access_mask = self .mask )
111-
112105 def set_filters (self , can_filters = None ):
113106 if can_filters :
114107 # Only one filter per ID type allowed
@@ -117,7 +110,7 @@ def set_filters(self, can_filters=None):
117110 can_filters [0 ].get ("extended" ) != can_filters [1 ].get ("extended" )):
118111 for can_filter in can_filters :
119112 try :
120- vxlapi .can_set_channel_acceptance (
113+ vxlapi .xlCanSetChannelAcceptance (
121114 self .port_handle , self .mask ,
122115 can_filter ["can_id" ], can_filter ["can_mask" ],
123116 vxlapi .XL_CAN_EXT if can_filter .get ("extended" ) else vxlapi .XL_CAN_STD )
@@ -132,22 +125,26 @@ def recv(self, timeout=None):
132125 while True :
133126 event_count = ctypes .c_uint (1 )
134127 try :
135- vxlapi .receive (self .port_handle , event_count , event )
128+ vxlapi .xlReceive (self .port_handle , event_count , event )
136129 except vxlapi .VectorError as exc :
137- if exc .status != vxlapi .XL_ERR_QUEUE_IS_EMPTY :
130+ if exc .error_code != vxlapi .XL_ERR_QUEUE_IS_EMPTY :
138131 raise
139- if event .tag == vxlapi .XL_RECEIVE_MSG .value :
140- msg_id = event .tagData .msg .id
141- dlc = event .tagData .msg .dlc
142- flags = event .tagData .msg .flags
143- return Message (
144- timestamp = event .timeStamp / 1000000000.0 ,
145- arbitration_id = msg_id & 0x1FFFFFFF ,
146- extended_id = bool (msg_id & vxlapi .XL_CAN_EXT_MSG_ID ),
147- is_remote_frame = bool (flags & vxlapi .XL_CAN_MSG_FLAG_REMOTE_FRAME ),
148- is_error_frame = bool (flags & vxlapi .XL_CAN_MSG_FLAG_ERROR_FRAME ),
149- dlc = dlc ,
150- data = event .tagData .msg .data [:dlc ])
132+ else :
133+ if event .tag == vxlapi .XL_RECEIVE_MSG :
134+ msg_id = event .tagData .msg .id
135+ dlc = event .tagData .msg .dlc
136+ flags = event .tagData .msg .flags
137+ timestamp = event .timeStamp / 1000000000.0
138+ msg = Message (
139+ timestamp = timestamp + self ._time_offset ,
140+ arbitration_id = msg_id & 0x1FFFFFFF ,
141+ extended_id = bool (msg_id & vxlapi .XL_CAN_EXT_MSG_ID ),
142+ is_remote_frame = bool (flags & vxlapi .XL_CAN_MSG_FLAG_REMOTE_FRAME ),
143+ is_error_frame = bool (flags & vxlapi .XL_CAN_MSG_FLAG_ERROR_FRAME ),
144+ dlc = dlc ,
145+ data = event .tagData .msg .data [:dlc ])
146+ msg .channel = event .chanIndex
147+ return msg
151148 if end_time is not None and time .time () > end_time :
152149 return None
153150 time .sleep (self .poll_interval )
@@ -161,16 +158,18 @@ def send(self, msg, timeout=None):
161158 if msg .is_remote_frame :
162159 flags |= vxlapi .XL_CAN_MSG_FLAG_REMOTE_FRAME
163160 xl_event = vxlapi .XLevent ()
164- xl_event .tag = vxlapi .XL_TRANSMIT_MSG . value
161+ xl_event .tag = vxlapi .XL_TRANSMIT_MSG
165162 xl_event .tagData .msg .id = msg_id
166163 xl_event .tagData .msg .dlc = msg .dlc
167164 xl_event .tagData .msg .flags = flags
168165 for idx , value in enumerate (msg .data ):
169166 xl_event .tagData .msg .data [idx ] = value
170- xl_status = vxlapi .can_transmit (
171- self .port_handle , self .mask , message_count , xl_event )
167+ vxlapi .xlCanTransmit (self .port_handle , self .mask , message_count , xl_event )
168+
169+ def flush_tx_buffer (self ):
170+ vxlapi .xlCanFlushTransmitQueue (self .port_handle , self .mask )
172171
173172 def shutdown (self ):
174- vxlapi .deactivate_channel (self .port_handle , self .mask )
175- vxlapi .close_port (self .port_handle )
176- vxlapi .close_driver ()
173+ vxlapi .xlDeactivateChannel (self .port_handle , self .mask )
174+ vxlapi .xlClosePort (self .port_handle )
175+ vxlapi .xlCloseDriver ()
0 commit comments