@@ -169,6 +169,12 @@ def __check_bus_handle_validity(handle, function, arguments):
169169 restype = canstat .c_canStatus ,
170170 errcheck = __check_status )
171171
172+ canSetBusParamsFd = __get_canlib_function ("canSetBusParamsFd" ,
173+ argtypes = [c_canHandle , ctypes .c_long ,
174+ ctypes .c_uint , ctypes .c_uint ,
175+ ctypes .c_uint ],
176+ restype = canstat .c_canStatus ,
177+ errcheck = __check_status )
172178
173179 canSetBusOutputControl = __get_canlib_function ("canSetBusOutputControl" ,
174180 argtypes = [c_canHandle ,
@@ -254,15 +260,25 @@ def init_kvaser_library():
254260DRIVER_MODE_NORMAL = True
255261
256262
257- BITRATE_OBJS = {1000000 : canstat .canBITRATE_1M ,
258- 500000 : canstat .canBITRATE_500K ,
259- 250000 : canstat .canBITRATE_250K ,
260- 125000 : canstat .canBITRATE_125K ,
261- 100000 : canstat .canBITRATE_100K ,
262- 83000 : canstat .canBITRATE_83K ,
263- 62000 : canstat .canBITRATE_62K ,
264- 50000 : canstat .canBITRATE_50K ,
265- 10000 : canstat .canBITRATE_10K }
263+ BITRATE_OBJS = {
264+ 1000000 : canstat .canBITRATE_1M ,
265+ 500000 : canstat .canBITRATE_500K ,
266+ 250000 : canstat .canBITRATE_250K ,
267+ 125000 : canstat .canBITRATE_125K ,
268+ 100000 : canstat .canBITRATE_100K ,
269+ 83000 : canstat .canBITRATE_83K ,
270+ 62000 : canstat .canBITRATE_62K ,
271+ 50000 : canstat .canBITRATE_50K ,
272+ 10000 : canstat .canBITRATE_10K
273+ }
274+
275+ BITRATE_FD = {
276+ 500000 : canstat .canFD_BITRATE_500K_80P ,
277+ 1000000 : canstat .canFD_BITRATE_1M_80P ,
278+ 2000000 : canstat .canFD_BITRATE_2M_80P ,
279+ 4000000 : canstat .canFD_BITRATE_4M_80P ,
280+ 8000000 : canstat .canFD_BITRATE_8M_60P
281+ }
266282
267283
268284class KvaserBus (BusABC ):
@@ -285,6 +301,8 @@ def __init__(self, channel, can_filters=None, **config):
285301
286302 :param int bitrate:
287303 Bitrate of channel in bit/s
304+ :param bool accept_virtual:
305+ If virtual channels should be accepted.
288306 :param int tseg1:
289307 Time segment 1, that is, the number of quanta from (but not including)
290308 the Sync Segment to the sampling point.
@@ -313,6 +331,11 @@ def __init__(self, channel, can_filters=None, **config):
313331 Only works if single_handle is also False.
314332 If you want to receive messages from other applications on the same
315333 computer, set this to True or set single_handle to True.
334+ :param bool fd:
335+ If CAN-FD frames should be supported.
336+ :param int data_bitrate:
337+ Which bitrate to use for data phase in CAN FD.
338+ Defaults to arbitration bitrate.
316339 """
317340 log .info ("CAN Filters: {}" .format (can_filters ))
318341 log .info ("Got configuration of: {}" .format (config ))
@@ -324,16 +347,16 @@ def __init__(self, channel, can_filters=None, **config):
324347 driver_mode = config .get ('driver_mode' , DRIVER_MODE_NORMAL )
325348 single_handle = config .get ('single_handle' , False )
326349 receive_own_messages = config .get ('receive_own_messages' , False )
350+ accept_virtual = config .get ('accept_virtual' , True )
351+ fd = config .get ('fd' , False )
352+ data_bitrate = config .get ('data_bitrate' , None )
327353
328354 try :
329355 channel = int (channel )
330356 except ValueError :
331357 raise ValueError ('channel must be an integer' )
332358 self .channel = channel
333359
334- if 'tseg1' not in config and bitrate in BITRATE_OBJS :
335- bitrate = BITRATE_OBJS [bitrate ]
336-
337360 log .debug ('Initialising bus instance' )
338361 self .single_handle = single_handle
339362
@@ -348,12 +371,33 @@ def __init__(self, channel, can_filters=None, **config):
348371 if idx == channel :
349372 self .channel_info = channel_info
350373
374+ flags = 0
375+ if accept_virtual :
376+ flags |= canstat .canOPEN_ACCEPT_VIRTUAL
377+ if fd :
378+ flags |= canstat .canOPEN_CAN_FD
379+
351380 log .debug ('Creating read handle to bus channel: %s' % channel )
352- self ._read_handle = canOpenChannel (channel , canstat . canOPEN_ACCEPT_VIRTUAL )
381+ self ._read_handle = canOpenChannel (channel , flags )
353382 canIoCtl (self ._read_handle ,
354383 canstat .canIOCTL_SET_TIMER_SCALE ,
355384 ctypes .byref (ctypes .c_long (TIMESTAMP_RESOLUTION )),
356385 4 )
386+
387+ if fd :
388+ if 'tseg1' not in config and bitrate in BITRATE_FD :
389+ # Use predefined bitrate for arbitration
390+ bitrate = BITRATE_FD [bitrate ]
391+ if data_bitrate in BITRATE_FD :
392+ # Use predefined bitrate for data
393+ data_bitrate = BITRATE_FD [data_bitrate ]
394+ elif not data_bitrate :
395+ # Use same bitrate for arbitration and data phase
396+ data_bitrate = bitrate
397+ canSetBusParamsFd (self ._read_handle , bitrate , tseg1 , tseg2 , sjw )
398+ else :
399+ if 'tseg1' not in config and bitrate in BITRATE_OBJS :
400+ bitrate = BITRATE_OBJS [bitrate ]
357401 canSetBusParams (self ._read_handle , bitrate , tseg1 , tseg2 , sjw , no_samp , 0 )
358402
359403 # By default, use local echo if single handle is used (see #160)
@@ -370,7 +414,7 @@ def __init__(self, channel, can_filters=None, **config):
370414 self ._write_handle = self ._read_handle
371415 else :
372416 log .debug ('Creating separate handle for TX on channel: %s' % channel )
373- self ._write_handle = canOpenChannel (channel , canstat . canOPEN_ACCEPT_VIRTUAL )
417+ self ._write_handle = canOpenChannel (channel , flags )
374418 canBusOn (self ._read_handle )
375419
376420 self .set_filters (can_filters )
@@ -437,7 +481,7 @@ def recv(self, timeout=None):
437481 Read a message from kvaser device.
438482 """
439483 arb_id = ctypes .c_long (0 )
440- data = ctypes .create_string_buffer (8 )
484+ data = ctypes .create_string_buffer (64 )
441485 dlc = ctypes .c_uint (0 )
442486 flags = ctypes .c_uint (0 )
443487 timestamp = ctypes .c_ulong (0 )
@@ -467,13 +511,19 @@ def recv(self, timeout=None):
467511 is_extended = bool (flags & canstat .canMSG_EXT )
468512 is_remote_frame = bool (flags & canstat .canMSG_RTR )
469513 is_error_frame = bool (flags & canstat .canMSG_ERROR_FRAME )
514+ is_fd = bool (flags & canstat .canFDMSG_FDF )
515+ bitrate_switch = bool (flags & canstat .canFDMSG_BRS )
516+ error_state_indicator = bool (flags & canstat .canFDMSG_ESI )
470517 msg_timestamp = timestamp .value * TIMESTAMP_FACTOR
471518 rx_msg = Message (arbitration_id = arb_id .value ,
472519 data = data_array [:dlc .value ],
473520 dlc = dlc .value ,
474521 extended_id = is_extended ,
475522 is_error_frame = is_error_frame ,
476523 is_remote_frame = is_remote_frame ,
524+ is_fd = is_fd ,
525+ bitrate_switch = bitrate_switch ,
526+ error_state_indicator = error_state_indicator ,
477527 channel = self .channel ,
478528 timestamp = msg_timestamp + self ._timestamp_offset )
479529 rx_msg .flags = flags
@@ -491,6 +541,10 @@ def send(self, msg, timeout=None):
491541 flags |= canstat .canMSG_RTR
492542 if msg .is_error_frame :
493543 flags |= canstat .canMSG_ERROR_FRAME
544+ if msg .is_fd :
545+ flags |= canstat .canFDMSG_FDF
546+ if msg .bitrate_switch :
547+ flags |= canstat .canFDMSG_BRS
494548 ArrayConstructor = ctypes .c_byte * msg .dlc
495549 buf = ArrayConstructor (* msg .data )
496550 canWrite (self ._write_handle ,
@@ -520,9 +574,10 @@ def shutdown(self):
520574 # Wait for transmit queue to be cleared
521575 try :
522576 canWriteSync (self ._write_handle , 100 )
523- except CANLIBError as e :
524- log .warning ("There may be messages in the transmit queue that could "
525- "not be transmitted before going bus off (%s)" , e )
577+ except CANLIBError :
578+ # Not a huge deal and it seems that we get timeout if no messages
579+ # exists in the buffer at all
580+ pass
526581 if not self .single_handle :
527582 canBusOff (self ._read_handle )
528583 canClose (self ._read_handle )
0 commit comments