29
29
)
30
30
serial = None
31
31
32
-
33
32
HAS_EVENTS = False
34
33
35
34
try :
@@ -59,6 +58,8 @@ class slcanBus(BusABC):
59
58
750000 : "S7" ,
60
59
1000000 : "S8" ,
61
60
83300 : "S9" ,
61
+ 2000000 : "Y2" ,
62
+ 5000000 : "Y5" ,
62
63
}
63
64
64
65
_SLEEP_AFTER_SERIAL_OPEN = 2 # in seconds
@@ -69,11 +70,33 @@ class slcanBus(BusABC):
69
70
70
71
LINE_TERMINATOR = b"\r "
71
72
73
+ DLC2BYTE_LEN = {
74
+ 0 : 0 ,
75
+ 1 : 1 ,
76
+ 2 : 2 ,
77
+ 3 : 3 ,
78
+ 4 : 4 ,
79
+ 5 : 5 ,
80
+ 6 : 6 ,
81
+ 7 : 7 ,
82
+ 8 : 8 ,
83
+ 9 : 12 ,
84
+ 10 : 16 ,
85
+ 11 : 20 ,
86
+ 12 : 24 ,
87
+ 13 : 32 ,
88
+ 14 : 48 ,
89
+ 15 : 64 ,
90
+ }
91
+ BYTE_LEN2DLC = {j : i for i , j in DLC2BYTE_LEN .items ()}
92
+
72
93
def __init__ (
73
94
self ,
74
95
channel : typechecking .ChannelStr ,
75
96
ttyBaudrate : int = 115200 ,
76
97
bitrate : Optional [int ] = None ,
98
+ fd : bool = False ,
99
+ data_bitrate : Optional [int ] = None ,
77
100
btr : Optional [str ] = None ,
78
101
poll_interval : float = _POLL_INTERVAL ,
79
102
receive_own_messages : bool = False ,
@@ -91,6 +114,10 @@ def __init__(
91
114
baudrate of underlying serial or usb device (Ignored if set via the ``channel`` parameter)
92
115
:param bitrate:
93
116
Bitrate in bit/s
117
+ :param bool fd:
118
+ If CAN-FD frames should be supported.
119
+ :param int data_bitrate:
120
+ Which bitrate to use for data phase in CAN FD.
94
121
:param btr:
95
122
BTR register value to set custom can speed
96
123
:param receive_own_messages:
@@ -144,6 +171,8 @@ def __init__(
144
171
self .set_bitrate (bitrate )
145
172
if btr is not None :
146
173
self .set_bitrate_reg (btr )
174
+ if fd and data_bitrate is not None :
175
+ self .set_data_bitrate (data_bitrate )
147
176
self .open ()
148
177
149
178
self ._timestamp_offset = time .time () - time .perf_counter ()
@@ -176,6 +205,23 @@ def set_bitrate(self, bitrate: int) -> None:
176
205
self ._write (bitrate_code )
177
206
self .open ()
178
207
208
+ def set_data_bitrate (self , data_bitrate : int ) -> None :
209
+ """
210
+ :param data_bitrate:
211
+ Bitrate in bit/s
212
+
213
+ :raise ValueError: if ``data_bitrate`` is not among the possible values
214
+ """
215
+ if data_bitrate in self ._BITRATES :
216
+ data_bitrate_code = self ._BITRATES [data_bitrate ]
217
+ else :
218
+ data_bitrates = ", " .join (str (k ) for k in self ._BITRATES .keys ())
219
+ raise ValueError (f"Invalid bitrate, choose one of { data_bitrates } ." )
220
+
221
+ self .close ()
222
+ self ._write (data_bitrate_code )
223
+ self .open ()
224
+
179
225
def set_bitrate_reg (self , btr : str ) -> None :
180
226
"""
181
227
:param btr:
@@ -222,12 +268,7 @@ def _read_can_thread(self, event_read):
222
268
time .sleep (self .poll_interval )
223
269
224
270
def _read_can (self ) -> List [Message ]:
225
- canId = None
226
- remote = False
227
- extended = False
228
- data = None
229
271
msgs = []
230
-
231
272
with error_check ("Could not read from serial device" ):
232
273
# Due to accessing `serialPortOrig.in_waiting` too often will reduce the performance.
233
274
# We read the `serialPortOrig.in_waiting` only once here.
@@ -242,37 +283,72 @@ def _read_can(self) -> List[Message]:
242
283
if new_byte in (self ._ERROR , self ._OK ):
243
284
string = self ._buffer .decode ()
244
285
self ._buffer .clear ()
245
-
246
286
if not string :
247
- pass
248
- elif string [0 ] in (
249
- "T" ,
250
- "x" , # x is an alternative extended message identifier for CANDapter
251
- ):
287
+ continue
288
+ canId = None
289
+ remote = False
290
+ extended = False
291
+ brs = False
292
+ fd = False
293
+ data = None
294
+ s0 = string [0 ]
295
+ if s0 in ("T" , "x" ):
252
296
# extended frame
253
297
canId = int (string [1 :9 ], 16 )
254
298
dlc = int (string [9 ])
255
299
extended = True
256
300
data = bytearray .fromhex (string [10 : 10 + dlc * 2 ])
257
- elif string [ 0 ] == "t" :
301
+ elif s0 == "t" :
258
302
# normal frame
259
303
canId = int (string [1 :4 ], 16 )
260
304
dlc = int (string [4 ])
261
305
data = bytearray .fromhex (string [5 : 5 + dlc * 2 ])
262
- elif string [ 0 ] == "r" :
306
+ elif s0 == "r" :
263
307
# remote frame
264
308
canId = int (string [1 :4 ], 16 )
265
309
dlc = int (string [4 ])
266
310
remote = True
267
- elif string [0 ] == "R" :
311
+ data = bytearray .fromhex (string [5 : 5 + dlc * 2 ])
312
+ elif s0 == "R" :
268
313
# remote extended frame
269
314
canId = int (string [1 :9 ], 16 )
270
315
dlc = int (string [9 ])
271
316
extended = True
272
317
remote = True
318
+ data = bytearray .fromhex (string [10 : 10 + dlc * 2 ])
319
+ elif s0 == "d" :
320
+ # fd_frame
321
+ fd = True
322
+ canId = int (string [1 :4 ], 16 )
323
+ dlc = self .DLC2BYTE_LEN [int (string [4 ])]
324
+ data = bytearray .fromhex (string [5 : 5 + dlc * 2 ])
325
+ elif s0 == "D" :
326
+ # extended fd_frame
327
+ fd = True
328
+ extended = True
329
+ canId = int (string [1 :9 ], 16 )
330
+ dlc = self .DLC2BYTE_LEN [int (string [9 ])]
331
+ data = bytearray .fromhex (string [10 : 10 + dlc * 2 ])
332
+ elif s0 == "b" :
333
+ # fd_frame
334
+ fd = True
335
+ brs = True
336
+ canId = int (string [1 :4 ], 16 )
337
+ dlc = self .DLC2BYTE_LEN [int (string [4 ])]
338
+ data = bytearray .fromhex (string [5 : 5 + dlc * 2 ])
339
+ elif s0 == "B" :
340
+ # extended fd_frame
341
+ fd = True
342
+ brs = True
343
+ extended = True
344
+ canId = int (string [1 :9 ], 16 )
345
+ dlc = self .DLC2BYTE_LEN [int (string [9 ])]
346
+ data = bytearray .fromhex (string [10 : 10 + dlc * 2 ])
273
347
274
348
if canId is not None :
275
349
msg = Message (
350
+ is_fd = fd ,
351
+ bitrate_switch = brs ,
276
352
arbitration_id = canId ,
277
353
is_extended_id = extended ,
278
354
timestamp = self ._timestamp_offset
@@ -287,20 +363,33 @@ def _read_can(self) -> List[Message]:
287
363
def send (self , msg : Message , timeout : Optional [float ] = None ) -> None :
288
364
if timeout != self .serialPortOrig .write_timeout :
289
365
self .serialPortOrig .write_timeout = timeout
290
- if msg .is_remote_frame :
291
- if msg .is_extended_id :
292
- sendStr = f"R{ msg .arbitration_id :08X} { msg .dlc :d} "
366
+ if msg .is_fd :
367
+ dlc = self .BYTE_LEN2DLC [msg .dlc ]
368
+ if not msg .bitrate_switch :
369
+ if not msg .is_extended_id :
370
+ sendStr = f"d{ msg .arbitration_id :03X} { dlc :x} "
371
+ else :
372
+ sendStr = f"D{ msg .arbitration_id :08X} { dlc :x} "
293
373
else :
294
- sendStr = f"r{ msg .arbitration_id :03X} { msg .dlc :d} "
374
+ if not msg .is_extended_id :
375
+ sendStr = f"b{ msg .arbitration_id :03X} { dlc :x} "
376
+ else :
377
+ sendStr = f"B{ msg .arbitration_id :08X} { dlc :x} "
295
378
else :
296
- if msg .is_extended_id :
297
- sendStr = f"T{ msg .arbitration_id :08X} { msg .dlc :d} "
379
+ if msg .is_remote_frame :
380
+ if msg .is_extended_id :
381
+ sendStr = f"R{ msg .arbitration_id :08X} { msg .dlc :d} "
382
+ else :
383
+ sendStr = f"r{ msg .arbitration_id :03X} { msg .dlc :d} "
298
384
else :
299
- sendStr = f"t{ msg .arbitration_id :03X} { msg .dlc :d} "
300
- sendStr += msg .data .hex ().upper ()
385
+ if msg .is_extended_id :
386
+ sendStr = f"T{ msg .arbitration_id :08X} { msg .dlc :d} "
387
+ else :
388
+ sendStr = f"t{ msg .arbitration_id :03X} { msg .dlc :d} "
389
+ sendStr += msg .data .hex ().upper ()
301
390
if self .receive_own_messages :
302
391
msg .is_rx = False
303
- msg .timestamp = self ._timestamp_offset + time .perf_counter () # Better than nothing...
392
+ msg .timestamp = self ._timestamp_offset + time .perf_counter () # Better than nothing...
304
393
self .queue_read .put (msg )
305
394
self ._write (sendStr )
306
395
0 commit comments