Skip to content

Commit 91db318

Browse files
Restructuring and stripping of code
Remove unused code Add bitrate change support Use vxlapi functions directly instead of wrapping them Timestamps are in absolute time Add flush_tx_buffer()
1 parent 1083940 commit 91db318

File tree

3 files changed

+211
-869
lines changed

3 files changed

+211
-869
lines changed

can/interfaces/vector/canlib.py

Lines changed: 79 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@
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
2222
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
2428
else:
2529
LOG.warning('Vector API does not work on %s platform', sys.platform)
2630
vxlapi = None
@@ -29,86 +33,75 @@
2933
class 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

Comments
 (0)