16
16
17
17
# Define Module Logger
18
18
# ====================
19
- LOG = logging .getLogger ('can.vector' )
19
+ LOG = logging .getLogger (__name__ )
20
20
21
21
# Import safely Vector API module for Travis tests
22
22
if 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
24
28
else :
25
29
LOG .warning ('Vector API does not work on %s platform' , sys .platform )
26
30
vxlapi = None
29
33
class VectorBus (BusABC ):
30
34
"""The CAN Bus implemented for the Vector interface."""
31
35
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 ):
34
38
"""
35
39
:param list channel:
36
40
The channel indexes to create this bus with.
37
41
Can also be a single integer or a comma separated string.
38
42
:param float poll_interval:
39
43
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.
40
48
:param str app_name:
41
49
Name of application in Hardware Config.
42
50
"""
43
51
if vxlapi is None :
44
52
raise ImportError ("The Vector API has not been loaded" )
45
53
self .poll_interval = poll_interval
46
54
if isinstance (channel , (list , tuple )):
47
- self .channel = channel
55
+ self .channels = channel
48
56
elif isinstance (channel , int ):
49
- self .channel = [channel ]
57
+ self .channels = [channel ]
50
58
else :
51
59
# 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 (',' )]
53
61
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 )
55
93
try :
56
- self ._go_on_bus ()
94
+ vxlapi .xlActivateChannel (self .port_handle , self .mask ,
95
+ vxlapi .XL_BUS_TYPE_CAN , 0 )
57
96
except vxlapi .VectorError :
58
97
self .shutdown ()
59
98
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
60
103
super (VectorBus , self ).__init__ ()
61
104
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
-
112
105
def set_filters (self , can_filters = None ):
113
106
if can_filters :
114
107
# Only one filter per ID type allowed
@@ -117,7 +110,7 @@ def set_filters(self, can_filters=None):
117
110
can_filters [0 ].get ("extended" ) != can_filters [1 ].get ("extended" )):
118
111
for can_filter in can_filters :
119
112
try :
120
- vxlapi .can_set_channel_acceptance (
113
+ vxlapi .xlCanSetChannelAcceptance (
121
114
self .port_handle , self .mask ,
122
115
can_filter ["can_id" ], can_filter ["can_mask" ],
123
116
vxlapi .XL_CAN_EXT if can_filter .get ("extended" ) else vxlapi .XL_CAN_STD )
@@ -132,22 +125,26 @@ def recv(self, timeout=None):
132
125
while True :
133
126
event_count = ctypes .c_uint (1 )
134
127
try :
135
- vxlapi .receive (self .port_handle , event_count , event )
128
+ vxlapi .xlReceive (self .port_handle , event_count , event )
136
129
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 :
138
131
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
151
148
if end_time is not None and time .time () > end_time :
152
149
return None
153
150
time .sleep (self .poll_interval )
@@ -161,16 +158,18 @@ def send(self, msg, timeout=None):
161
158
if msg .is_remote_frame :
162
159
flags |= vxlapi .XL_CAN_MSG_FLAG_REMOTE_FRAME
163
160
xl_event = vxlapi .XLevent ()
164
- xl_event .tag = vxlapi .XL_TRANSMIT_MSG . value
161
+ xl_event .tag = vxlapi .XL_TRANSMIT_MSG
165
162
xl_event .tagData .msg .id = msg_id
166
163
xl_event .tagData .msg .dlc = msg .dlc
167
164
xl_event .tagData .msg .flags = flags
168
165
for idx , value in enumerate (msg .data ):
169
166
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 )
172
171
173
172
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