From e8e328f6af0a362ecb2ec6fe96aeb21b68d0096d Mon Sep 17 00:00:00 2001 From: Christian Sandberg Date: Sun, 16 Jun 2019 21:43:44 +0200 Subject: [PATCH 1/3] Bit timing config for PCAN Fixes #538 Part of #614 --- can/interfaces/pcan/pcan.py | 143 ++++++++++++------------------------ 1 file changed, 49 insertions(+), 94 deletions(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 80b6054d0..6a668730d 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -6,6 +6,7 @@ import logging import time +import warnings from can import CanError, Message, BusABC from can.bus import BusState @@ -62,26 +63,17 @@ } -pcan_fd_parameter_list = [ - "nom_brp", - "nom_tseg1", - "nom_tseg2", - "nom_sjw", - "data_brp", - "data_tseg1", - "data_tseg2", - "data_sjw", -] - - class PcanBus(BusABC): def __init__( self, channel="PCAN_USBBUS1", state=BusState.ACTIVE, bitrate=500000, + timing=None, + data_timing=None, + fd=False, *args, - **kwargs + **kwargs, ): """A PCAN USB interface to CAN. @@ -104,77 +96,14 @@ def __init__( :param bool fd: Should the Bus be initialized in CAN-FD mode. - - :param int f_clock: - Clock rate in Hz. - Any of the following: - 20000000, 24000000, 30000000, 40000000, 60000000, 80000000. - Ignored if not using CAN-FD. - Pass either f_clock or f_clock_mhz. - - :param int f_clock_mhz: - Clock rate in MHz. - Any of the following: - 20, 24, 30, 40, 60, 80. - Ignored if not using CAN-FD. - Pass either f_clock or f_clock_mhz. - - :param int nom_brp: - Clock prescaler for nominal time quantum. - In the range (1..1024) - Ignored if not using CAN-FD. - - :param int nom_tseg1: - Time segment 1 for nominal bit rate, - that is, the number of quanta from (but not including) - the Sync Segment to the sampling point. - In the range (1..256). - Ignored if not using CAN-FD. - - :param int nom_tseg2: - Time segment 2 for nominal bit rate, - that is, the number of quanta from the sampling - point to the end of the bit. - In the range (1..128). - Ignored if not using CAN-FD. - - :param int nom_sjw: - Synchronization Jump Width for nominal bit rate. - Decides the maximum number of time quanta - that the controller can resynchronize every bit. - In the range (1..128). - Ignored if not using CAN-FD. - - :param int data_brp: - Clock prescaler for fast data time quantum. - In the range (1..1024) - Ignored if not using CAN-FD. - - :param int data_tseg1: - Time segment 1 for fast data bit rate, - that is, the number of quanta from (but not including) - the Sync Segment to the sampling point. - In the range (1..32). - Ignored if not using CAN-FD. - - :param int data_tseg2: - Time segment 2 for fast data bit rate, - that is, the number of quanta from the sampling - point to the end of the bit. - In the range (1..16). - Ignored if not using CAN-FD. - - :param int data_sjw: - Synchronization Jump Width for fast data bit rate. - Decides the maximum number of time quanta - that the controller can resynchronize every bit. - In the range (1..16). - Ignored if not using CAN-FD. - + :param can.BitTiming timing: + Bit timing configuration. + For CAN-FD this also applies to arbitration/nominal phase. + :param can.BitTiming data_timing: + Bit timing configuration for data phase. """ self.channel_info = channel - self.fd = kwargs.get("fd", False) - pcan_bitrate = pcan_bitrate_objs.get(bitrate, PCAN_BAUD_500K) + self.fd = fd hwtype = PCAN_TYPE_ISA ioport = 0x02A0 @@ -189,24 +118,50 @@ def __init__( raise ArgumentError("BusState must be Active or Passive") if self.fd: - f_clock_val = kwargs.get("f_clock", None) - if f_clock_val is None: - f_clock = "{}={}".format("f_clock_mhz", kwargs.get("f_clock_mhz", None)) + params = {} + if timing and data_timing: + params["f_clock"] = timing.f_clock + params["nom_brp"] = timing.brp + params["nom_tseg1"] = timing.tseg1 + params["nom_tseg2"] = timing.tseg2 + params["nom_sjw"] = timing.sjw + params["data_brp"] = data_timing.brp + params["data_tseg1"] = data_timing.tseg1 + params["data_tseg2"] = data_timing.tseg2 + params["data_sjw"] = data_timing.sjw + elif "nom_tseg1" in kwargs: + warnings.warn( + "Specifying bit timing as direct keyword arguments is depreceated. Use the can.BitTiming class instead.", + DeprecationWarning, + ) + if "f_clock" in kwargs: + params["f_clock"] = kwargs["f_clock"] + if "f_clock_mhz" in kwargs: + params["f_clock_mhz"] = kwargs["f_clock_mhz"] + params["nom_brp"] = kwargs["nom_brp"] + params["nom_tseg1"] = kwargs["nom_tseg1"] + params["nom_tseg2"] = kwargs["nom_tseg2"] + params["nom_sjw"] = kwargs["nom_sjw"] + params["data_brp"] = kwargs["data_brp"] + params["data_tseg1"] = kwargs["data_tseg1"] + params["data_tseg2"] = kwargs["data_tseg2"] + params["data_sjw"] = kwargs["data_sjw"] else: - f_clock = "{}={}".format("f_clock", kwargs.get("f_clock", None)) - - fd_parameters_values = [f_clock] + [ - "{}={}".format(key, kwargs.get(key, None)) - for key in pcan_fd_parameter_list - if kwargs.get(key, None) is not None - ] + raise ArgumentError("timing and data_timing arguments missing") - self.fd_bitrate = " ,".join(fd_parameters_values).encode("ascii") + fd_bitrate = ",".join(f"{key}={val}" for key, val in params.items()) result = self.m_objPCANBasic.InitializeFD( - self.m_PcanHandle, self.fd_bitrate + self.m_PcanHandle, fd_bitrate.encode("ascii") ) else: + if timing: + pcan_bitrate = TPCANBaudrate(timing.btr0 << 8 | timing.btr1) + elif bitrate in pcan_bitrate_objs: + pcan_bitrate = pcan_bitrate_objs[bitrate] + else: + log.warning("Unknown bitrate. Falling back to 500 kbit/s.") + pcan_bitrate = PCAN_BAUD_500K result = self.m_objPCANBasic.Initialize( self.m_PcanHandle, pcan_bitrate, hwtype, ioport, interrupt ) From 3dda5f178206dc1d1faea57b3f66ac97c8d990fc Mon Sep 17 00:00:00 2001 From: Christian Sandberg Date: Sun, 16 Jun 2019 21:47:49 +0200 Subject: [PATCH 2/3] Add debug for FD bit rate string --- can/interfaces/pcan/pcan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 6a668730d..e1930a7b7 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -150,6 +150,7 @@ def __init__( raise ArgumentError("timing and data_timing arguments missing") fd_bitrate = ",".join(f"{key}={val}" for key, val in params.items()) + log.debug("FD bit rate string: " + fd_bitrate) result = self.m_objPCANBasic.InitializeFD( self.m_PcanHandle, fd_bitrate.encode("ascii") From 3f1c99c28d21295a7247a7bab026558f9c354eb0 Mon Sep 17 00:00:00 2001 From: Christian Sandberg Date: Sun, 16 Jun 2019 21:57:44 +0200 Subject: [PATCH 3/3] Fix Lint --- can/interfaces/pcan/pcan.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index e1930a7b7..db28b4d2e 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -150,7 +150,7 @@ def __init__( raise ArgumentError("timing and data_timing arguments missing") fd_bitrate = ",".join(f"{key}={val}" for key, val in params.items()) - log.debug("FD bit rate string: " + fd_bitrate) + log.debug("FD bit rate string: %s", fd_bitrate) result = self.m_objPCANBasic.InitializeFD( self.m_PcanHandle, fd_bitrate.encode("ascii")