Skip to content

Commit ab1fa8b

Browse files
committed
add BitTiming parameter to PcanBus
1 parent dcf15c9 commit ab1fa8b

File tree

1 file changed

+62
-14
lines changed

1 file changed

+62
-14
lines changed

can/interfaces/pcan/pcan.py

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@
55
import time
66
from datetime import datetime
77
import platform
8-
from typing import Optional, List, Tuple
8+
from typing import Optional, List, Tuple, Union, Any
99

1010
from packaging import version
1111

1212
from can import (
1313
BusABC,
1414
BusState,
15+
BitTiming,
16+
BitTimingFd,
17+
Message,
1518
CanError,
1619
CanOperationError,
1720
CanInitializationError,
18-
Message,
1921
)
20-
from can.util import len2dlc, dlc2len
21-
22+
from can.util import check_or_adjust_timing_clock, dlc2len, len2dlc
2223
from .basic import (
2324
PCAN_BITRATES,
2425
PCAN_FD_PARAMETER_LIST,
@@ -61,6 +62,7 @@
6162
FEATURE_FD_CAPABLE,
6263
PCAN_DICT_STATUS,
6364
PCAN_BUSOFF_AUTORESET,
65+
TPCANBaudrate,
6466
PCAN_ATTACHED_CHANNELS,
6567
TPCANChannelInformation,
6668
)
@@ -112,12 +114,12 @@
112114
class PcanBus(BusABC):
113115
def __init__(
114116
self,
115-
channel="PCAN_USBBUS1",
116-
device_id=None,
117-
state=BusState.ACTIVE,
118-
bitrate=500000,
119-
*args,
120-
**kwargs,
117+
channel: str = "PCAN_USBBUS1",
118+
device_id: Optional[int] = None,
119+
state: BusState = BusState.ACTIVE,
120+
timing: Optional[Union[BitTiming, BitTimingFd]] = None,
121+
bitrate: int = 500000,
122+
**kwargs: Any,
121123
):
122124
"""A PCAN USB interface to CAN.
123125
@@ -142,6 +144,18 @@ def __init__(
142144
BusState of the channel.
143145
Default is ACTIVE
144146
147+
:param timing:
148+
An instance of :class:`~can.BitTiming` or :class:`~can.BitTimingFd`
149+
to specify the bit timing parameters for the PCAN interface. If this parameter
150+
is provided, it takes precedence over all other timing-related parameters.
151+
If this parameter is not provided, the bit timing parameters can be specified
152+
using the `bitrate` parameter for standard CAN or the `fd`, `f_clock`,
153+
`f_clock_mhz`, `nom_brp`, `nom_tseg1`, `nom_tseg2`, `nom_sjw`, `data_brp`,
154+
`data_tseg1`, `data_tseg2`, and `data_sjw` parameters for CAN FD.
155+
Note that the `f_clock` value of the `timing` instance must be 8_000_000
156+
for standard CAN or any of the following values for CAN FD: 20_000_000,
157+
24_000_000, 30_000_000, 40_000_000, 60_000_000, 80_000_000.
158+
145159
:param int bitrate:
146160
Bitrate of channel in bit/s.
147161
Default is 500 kbit/s.
@@ -231,8 +245,7 @@ def __init__(
231245
raise ValueError(err_msg)
232246

233247
self.channel_info = str(channel)
234-
self.fd = kwargs.get("fd", False)
235-
pcan_bitrate = PCAN_BITRATES.get(bitrate, PCAN_BAUD_500K)
248+
self.fd = isinstance(timing, BitTimingFd) if timing else kwargs.get("fd", False)
236249

237250
hwtype = PCAN_TYPE_ISA
238251
ioport = 0x02A0
@@ -250,7 +263,41 @@ def __init__(
250263
else:
251264
raise ValueError("BusState must be Active or Passive")
252265

253-
if self.fd:
266+
if isinstance(timing, BitTimingFd):
267+
valid_fd_f_clocks = [
268+
20_000_000,
269+
24_000_000,
270+
30_000_000,
271+
40_000_000,
272+
60_000_000,
273+
80_000_000,
274+
]
275+
timing = check_or_adjust_timing_clock(
276+
timing, sorted(valid_fd_f_clocks, reverse=True)
277+
)
278+
self.fd_bitrate = (
279+
f"f_clock={timing.f_clock},"
280+
f"nom_brp={timing.nom_brp},"
281+
f"nom_tseg1={timing.nom_tseg1},"
282+
f"nom_tseg2={timing.nom_tseg2},"
283+
f"nom_sjw={timing.nom_sjw},"
284+
f"data_brp={timing.data_brp},"
285+
f"data_tseg1={timing.data_tseg1},"
286+
f"data_tseg2={timing.data_tseg2},"
287+
f"data_sjw={timing.data_sjw}"
288+
).encode("ascii")
289+
result = self.m_objPCANBasic.InitializeFD(
290+
self.m_PcanHandle, self.fd_bitrate
291+
)
292+
293+
elif isinstance(timing, BitTiming):
294+
timing = check_or_adjust_timing_clock(timing, [8_000_000])
295+
pcan_bitrate = TPCANBaudrate(timing.btr0 << 8 | timing.btr1)
296+
result = self.m_objPCANBasic.Initialize(
297+
self.m_PcanHandle, pcan_bitrate, hwtype, ioport, interrupt
298+
)
299+
300+
elif self.fd:
254301
f_clock_val = kwargs.get("f_clock", None)
255302
if f_clock_val is None:
256303
f_clock = "{}={}".format("f_clock_mhz", kwargs.get("f_clock_mhz", None))
@@ -269,6 +316,7 @@ def __init__(
269316
self.m_PcanHandle, self.fd_bitrate
270317
)
271318
else:
319+
pcan_bitrate = PCAN_BITRATES.get(bitrate, PCAN_BAUD_500K)
272320
result = self.m_objPCANBasic.Initialize(
273321
self.m_PcanHandle, pcan_bitrate, hwtype, ioport, interrupt
274322
)
@@ -312,7 +360,7 @@ def __init__(
312360
if result != PCAN_ERROR_OK:
313361
raise PcanCanInitializationError(self._get_formatted_error(result))
314362

315-
super().__init__(channel=channel, state=state, bitrate=bitrate, *args, **kwargs)
363+
super().__init__(channel=channel, state=state, bitrate=bitrate, **kwargs)
316364

317365
def _find_channel_by_dev_id(self, device_id):
318366
"""

0 commit comments

Comments
 (0)