5
5
import time
6
6
from datetime import datetime
7
7
import platform
8
- from typing import Optional , List , Tuple
8
+ from typing import Optional , List , Tuple , Union , Any
9
9
10
10
from packaging import version
11
11
12
12
from can import (
13
13
BusABC ,
14
14
BusState ,
15
+ BitTiming ,
16
+ BitTimingFd ,
17
+ Message ,
15
18
CanError ,
16
19
CanOperationError ,
17
20
CanInitializationError ,
18
- Message ,
19
21
)
20
- from can .util import len2dlc , dlc2len
21
-
22
+ from can .util import check_or_adjust_timing_clock , dlc2len , len2dlc
22
23
from .basic import (
23
24
PCAN_BITRATES ,
24
25
PCAN_FD_PARAMETER_LIST ,
61
62
FEATURE_FD_CAPABLE ,
62
63
PCAN_DICT_STATUS ,
63
64
PCAN_BUSOFF_AUTORESET ,
65
+ TPCANBaudrate ,
64
66
PCAN_ATTACHED_CHANNELS ,
65
67
TPCANChannelInformation ,
66
68
)
112
114
class PcanBus (BusABC ):
113
115
def __init__ (
114
116
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 ,
121
123
):
122
124
"""A PCAN USB interface to CAN.
123
125
@@ -142,6 +144,18 @@ def __init__(
142
144
BusState of the channel.
143
145
Default is ACTIVE
144
146
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
+
145
159
:param int bitrate:
146
160
Bitrate of channel in bit/s.
147
161
Default is 500 kbit/s.
@@ -231,8 +245,7 @@ def __init__(
231
245
raise ValueError (err_msg )
232
246
233
247
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 )
236
249
237
250
hwtype = PCAN_TYPE_ISA
238
251
ioport = 0x02A0
@@ -250,7 +263,41 @@ def __init__(
250
263
else :
251
264
raise ValueError ("BusState must be Active or Passive" )
252
265
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 :
254
301
f_clock_val = kwargs .get ("f_clock" , None )
255
302
if f_clock_val is None :
256
303
f_clock = "{}={}" .format ("f_clock_mhz" , kwargs .get ("f_clock_mhz" , None ))
@@ -269,6 +316,7 @@ def __init__(
269
316
self .m_PcanHandle , self .fd_bitrate
270
317
)
271
318
else :
319
+ pcan_bitrate = PCAN_BITRATES .get (bitrate , PCAN_BAUD_500K )
272
320
result = self .m_objPCANBasic .Initialize (
273
321
self .m_PcanHandle , pcan_bitrate , hwtype , ioport , interrupt
274
322
)
@@ -312,7 +360,7 @@ def __init__(
312
360
if result != PCAN_ERROR_OK :
313
361
raise PcanCanInitializationError (self ._get_formatted_error (result ))
314
362
315
- super ().__init__ (channel = channel , state = state , bitrate = bitrate , * args , * *kwargs )
363
+ super ().__init__ (channel = channel , state = state , bitrate = bitrate , ** kwargs )
316
364
317
365
def _find_channel_by_dev_id (self , device_id ):
318
366
"""
0 commit comments