1010import logging
1111import sys
1212import time
13+ from typing import Optional , Union
1314
14- from can import BusABC , CanProtocol , Message
15- from can .util import time_perfcounter_correlation
15+ from can import BitTiming , BitTimingFd , BusABC , CanProtocol , Message
16+ from can .exceptions import CanError , CanInitializationError , CanOperationError
17+ from can .typechecking import CanFilters
18+ from can .util import check_or_adjust_timing_clock , time_perfcounter_correlation
1619
17- from ...exceptions import CanError , CanInitializationError , CanOperationError
1820from . import constants as canstat
1921from . import structures
2022
@@ -199,6 +201,17 @@ def __check_bus_handle_validity(handle, function, arguments):
199201 errcheck = __check_status_initialization ,
200202 )
201203
204+ canSetBusParamsC200 = __get_canlib_function (
205+ "canSetBusParamsC200" ,
206+ argtypes = [
207+ c_canHandle ,
208+ ctypes .c_byte ,
209+ ctypes .c_byte ,
210+ ],
211+ restype = canstat .c_canStatus ,
212+ errcheck = __check_status_initialization ,
213+ )
214+
202215 canSetBusParamsFd = __get_canlib_function (
203216 "canSetBusParamsFd" ,
204217 argtypes = [
@@ -360,7 +373,13 @@ class KvaserBus(BusABC):
360373 The CAN Bus implemented for the Kvaser interface.
361374 """
362375
363- def __init__ (self , channel , can_filters = None , ** kwargs ):
376+ def __init__ (
377+ self ,
378+ channel : int ,
379+ can_filters : Optional [CanFilters ] = None ,
380+ timing : Optional [Union [BitTiming , BitTimingFd ]] = None ,
381+ ** kwargs ,
382+ ):
364383 """
365384 :param int channel:
366385 The Channel id to create this bus with.
@@ -370,6 +389,12 @@ def __init__(self, channel, can_filters=None, **kwargs):
370389
371390 Backend Configuration
372391
392+ :param timing:
393+ An instance of :class:`~can.BitTiming` or :class:`~can.BitTimingFd`
394+ to specify the bit timing parameters for the Kvaser interface. If provided, it
395+ takes precedence over the all other timing-related parameters.
396+ Note that the `f_clock` property of the `timing` instance must be 16_000_000 (16MHz)
397+ for standard CAN or 80_000_000 (80MHz) for CAN FD.
373398 :param int bitrate:
374399 Bitrate of channel in bit/s
375400 :param bool accept_virtual:
@@ -427,7 +452,7 @@ def __init__(self, channel, can_filters=None, **kwargs):
427452 exclusive = kwargs .get ("exclusive" , False )
428453 override_exclusive = kwargs .get ("override_exclusive" , False )
429454 accept_virtual = kwargs .get ("accept_virtual" , True )
430- fd = kwargs .get ("fd" , False )
455+ fd = isinstance ( timing , BitTimingFd ) if timing else kwargs .get ("fd" , False )
431456 data_bitrate = kwargs .get ("data_bitrate" , None )
432457
433458 try :
@@ -468,22 +493,43 @@ def __init__(self, channel, can_filters=None, **kwargs):
468493 ctypes .byref (ctypes .c_long (TIMESTAMP_RESOLUTION )),
469494 4 ,
470495 )
471-
472- if fd :
473- if "tseg1" not in kwargs and bitrate in BITRATE_FD :
474- # Use predefined bitrate for arbitration
475- bitrate = BITRATE_FD [bitrate ]
476- if data_bitrate in BITRATE_FD :
477- # Use predefined bitrate for data
478- data_bitrate = BITRATE_FD [data_bitrate ]
479- elif not data_bitrate :
480- # Use same bitrate for arbitration and data phase
481- data_bitrate = bitrate
482- canSetBusParamsFd (self ._read_handle , data_bitrate , tseg1 , tseg2 , sjw )
496+ if isinstance (timing , BitTimingFd ):
497+ timing = check_or_adjust_timing_clock (timing , [80_000_000 ])
498+ canSetBusParams (
499+ self ._read_handle ,
500+ timing .nom_bitrate ,
501+ timing .nom_tseg1 ,
502+ timing .nom_tseg2 ,
503+ timing .nom_sjw ,
504+ 1 ,
505+ 0 ,
506+ )
507+ canSetBusParamsFd (
508+ self ._read_handle ,
509+ timing .data_bitrate ,
510+ timing .data_tseg1 ,
511+ timing .data_tseg2 ,
512+ timing .data_sjw ,
513+ )
514+ elif isinstance (timing , BitTiming ):
515+ timing = check_or_adjust_timing_clock (timing , [16_000_000 ])
516+ canSetBusParamsC200 (self ._read_handle , timing .btr0 , timing .btr1 )
483517 else :
484- if "tseg1" not in kwargs and bitrate in BITRATE_OBJS :
485- bitrate = BITRATE_OBJS [bitrate ]
486- canSetBusParams (self ._read_handle , bitrate , tseg1 , tseg2 , sjw , no_samp , 0 )
518+ if fd :
519+ if "tseg1" not in kwargs and bitrate in BITRATE_FD :
520+ # Use predefined bitrate for arbitration
521+ bitrate = BITRATE_FD [bitrate ]
522+ if data_bitrate in BITRATE_FD :
523+ # Use predefined bitrate for data
524+ data_bitrate = BITRATE_FD [data_bitrate ]
525+ elif not data_bitrate :
526+ # Use same bitrate for arbitration and data phase
527+ data_bitrate = bitrate
528+ canSetBusParamsFd (self ._read_handle , data_bitrate , tseg1 , tseg2 , sjw )
529+ else :
530+ if "tseg1" not in kwargs and bitrate in BITRATE_OBJS :
531+ bitrate = BITRATE_OBJS [bitrate ]
532+ canSetBusParams (self ._read_handle , bitrate , tseg1 , tseg2 , sjw , no_samp , 0 )
487533
488534 # By default, use local echo if single handle is used (see #160)
489535 local_echo = single_handle or receive_own_messages
0 commit comments