@@ -148,7 +148,8 @@ def __init__(
148
148
If the bus could not be set up.
149
149
This may or may not be a :class:`~can.interfaces.vector.VectorInitializationError`.
150
150
"""
151
- if os .name != "nt" and not kwargs .get ("_testing" , False ):
151
+ self .__testing = kwargs .get ("_testing" , False )
152
+ if os .name != "nt" and not self .__testing :
152
153
raise CanInterfaceNotImplementedError (
153
154
f"The Vector interface is only supported on Windows, "
154
155
f'but you are running "{ os .name } "'
@@ -232,66 +233,20 @@ def __init__(
232
233
233
234
# set CAN settings
234
235
for channel in self .channels :
235
- if self ._has_init_access (channel ):
236
- if fd :
237
- self ._set_bitrate_canfd (
238
- channel = channel ,
239
- bitrate = bitrate ,
240
- data_bitrate = data_bitrate ,
241
- sjw_abr = sjw_abr ,
242
- tseg1_abr = tseg1_abr ,
243
- tseg2_abr = tseg2_abr ,
244
- sjw_dbr = sjw_dbr ,
245
- tseg1_dbr = tseg1_dbr ,
246
- tseg2_dbr = tseg2_dbr ,
247
- )
248
- elif bitrate :
249
- self ._set_bitrate_can (channel = channel , bitrate = bitrate )
250
-
251
- # Check CAN settings
252
- for channel in self .channels :
253
- if kwargs .get ("_testing" , False ):
254
- # avoid check if xldriver is mocked for testing
255
- break
256
-
257
- bus_params = self ._read_bus_params (channel )
258
236
if fd :
259
- _canfd = bus_params .canfd
260
- if not all (
261
- [
262
- bus_params .bus_type is xldefine .XL_BusTypes .XL_BUS_TYPE_CAN ,
263
- _canfd .can_op_mode
264
- & xldefine .XL_CANFD_BusParams_CanOpMode .XL_BUS_PARAMS_CANOPMODE_CANFD ,
265
- _canfd .bitrate == bitrate if bitrate else True ,
266
- _canfd .sjw_abr == sjw_abr if bitrate else True ,
267
- _canfd .tseg1_abr == tseg1_abr if bitrate else True ,
268
- _canfd .tseg2_abr == tseg2_abr if bitrate else True ,
269
- _canfd .data_bitrate == data_bitrate if data_bitrate else True ,
270
- _canfd .sjw_dbr == sjw_dbr if data_bitrate else True ,
271
- _canfd .tseg1_dbr == tseg1_dbr if data_bitrate else True ,
272
- _canfd .tseg2_dbr == tseg2_dbr if data_bitrate else True ,
273
- ]
274
- ):
275
- raise CanInitializationError (
276
- f"The requested CAN FD settings could not be set for channel { channel } . "
277
- f"Another application might have set incompatible settings. "
278
- f"These are the currently active settings: { _canfd ._asdict ()} "
279
- )
280
- else :
281
- _can = bus_params .can
282
- if not all (
283
- [
284
- bus_params .bus_type is xldefine .XL_BusTypes .XL_BUS_TYPE_CAN ,
285
- _can .can_op_mode
286
- & xldefine .XL_CANFD_BusParams_CanOpMode .XL_BUS_PARAMS_CANOPMODE_CAN20 ,
287
- _can .bitrate == bitrate if bitrate else True ,
288
- ]
289
- ):
290
- raise CanInitializationError (
291
- f"The requested CAN settings could not be set for channel { channel } . "
292
- f"Another application might have set incompatible settings. "
293
- f"These are the currently active settings: { _can ._asdict ()} "
294
- )
237
+ self ._set_bitrate_canfd (
238
+ channel = channel ,
239
+ bitrate = bitrate ,
240
+ data_bitrate = data_bitrate ,
241
+ sjw_abr = sjw_abr ,
242
+ tseg1_abr = tseg1_abr ,
243
+ tseg2_abr = tseg2_abr ,
244
+ sjw_dbr = sjw_dbr ,
245
+ tseg1_dbr = tseg1_dbr ,
246
+ tseg2_dbr = tseg2_dbr ,
247
+ )
248
+ elif bitrate :
249
+ self ._set_bitrate_can (channel = channel , bitrate = bitrate )
295
250
296
251
# Enable/disable TX receipts
297
252
tx_receipts = 1 if receive_own_messages else 0
@@ -422,32 +377,85 @@ def _set_bitrate_can(
422
377
)
423
378
424
379
# set parameters if channel has init access
425
- if any (kwargs ):
426
- chip_params = xlclass .XLchipParams ()
427
- chip_params .bitRate = bitrate
428
- chip_params .sjw = sjw
429
- chip_params .tseg1 = tseg1
430
- chip_params .tseg2 = tseg2
431
- chip_params .sam = sam
432
- self .xldriver .xlCanSetChannelParams (
433
- self .port_handle ,
434
- self .channel_masks [channel ],
435
- chip_params ,
380
+ if self ._has_init_access (channel ):
381
+ if any (kwargs ):
382
+ chip_params = xlclass .XLchipParams ()
383
+ chip_params .bitRate = bitrate
384
+ chip_params .sjw = sjw
385
+ chip_params .tseg1 = tseg1
386
+ chip_params .tseg2 = tseg2
387
+ chip_params .sam = sam
388
+ self .xldriver .xlCanSetChannelParams (
389
+ self .port_handle ,
390
+ self .channel_masks [channel ],
391
+ chip_params ,
392
+ )
393
+ LOG .info (
394
+ "xlCanSetChannelParams: baudr.=%u, sjwAbr=%u, tseg1Abr=%u, tseg2Abr=%u" ,
395
+ chip_params .bitRate ,
396
+ chip_params .sjw ,
397
+ chip_params .tseg1 ,
398
+ chip_params .tseg2 ,
399
+ )
400
+ else :
401
+ self .xldriver .xlCanSetChannelBitrate (
402
+ self .port_handle ,
403
+ self .channel_masks [channel ],
404
+ bitrate ,
405
+ )
406
+ LOG .info ("xlCanSetChannelBitrate: baudr.=%u" , bitrate )
407
+
408
+ if self .__testing :
409
+ return
410
+
411
+ # Compare requested CAN settings to active settings
412
+ bus_params = self ._read_bus_params (channel )
413
+ settings_acceptable = True
414
+
415
+ # check bus type
416
+ settings_acceptable &= (
417
+ bus_params .bus_type is xldefine .XL_BusTypes .XL_BUS_TYPE_CAN
418
+ )
419
+
420
+ # check CAN operation mode. For CANcaseXL can_op_mode remains 0
421
+ if bus_params .can .can_op_mode != 0 :
422
+ settings_acceptable &= bool (
423
+ bus_params .can .can_op_mode
424
+ & xldefine .XL_CANFD_BusParams_CanOpMode .XL_BUS_PARAMS_CANOPMODE_CAN20
436
425
)
437
- LOG .info (
438
- "xlCanSetChannelParams: baudr.=%u, sjwAbr=%u, tseg1Abr=%u, tseg2Abr=%u" ,
439
- chip_params .bitRate ,
440
- chip_params .sjw ,
441
- chip_params .tseg1 ,
442
- chip_params .tseg2 ,
426
+
427
+ # check bitrate
428
+ settings_acceptable &= abs (bus_params .can .bitrate - bitrate ) < bitrate / 256
429
+
430
+ # check sample point
431
+ if all (kwargs ):
432
+ requested_sample_point = (
433
+ 100
434
+ * (1 + tseg1 ) # type: ignore[operator]
435
+ / (1 + tseg1 + tseg2 ) # type: ignore[operator]
443
436
)
444
- else :
445
- self .xldriver .xlCanSetChannelBitrate (
446
- self .port_handle ,
447
- self .channel_masks [channel ],
448
- bitrate ,
437
+ actual_sample_point = (
438
+ 100
439
+ * (1 + bus_params .can .tseg1 )
440
+ / (1 + bus_params .can .tseg1 + bus_params .can .tseg2 )
441
+ )
442
+ settings_acceptable &= (
443
+ abs (actual_sample_point - requested_sample_point )
444
+ < 1.0 # 1 percent threshold
445
+ )
446
+
447
+ if not settings_acceptable :
448
+ active_settings = ", " .join (
449
+ [
450
+ f"{ key } : { getattr (val , 'name' , val )} " # print int or Enum/Flag name
451
+ for key , val in bus_params .can ._asdict ().items ()
452
+ ]
453
+ )
454
+ raise CanInitializationError (
455
+ f"The requested CAN settings could not be set for channel { channel } . "
456
+ f"Another application might have set incompatible settings. "
457
+ f"These are the currently active settings: { active_settings } "
449
458
)
450
- LOG .info ("xlCanSetChannelBitrate: baudr.=%u" , bitrate )
451
459
452
460
def _set_bitrate_canfd (
453
461
self ,
@@ -462,42 +470,112 @@ def _set_bitrate_canfd(
462
470
tseg2_dbr : int = 3 ,
463
471
) -> None :
464
472
# set parameters if channel has init access
465
- canfd_conf = xlclass .XLcanFdConf ()
466
- if bitrate :
467
- canfd_conf .arbitrationBitRate = int (bitrate )
468
- else :
469
- canfd_conf .arbitrationBitRate = 500_000
470
- canfd_conf .sjwAbr = int (sjw_abr )
471
- canfd_conf .tseg1Abr = int (tseg1_abr )
472
- canfd_conf .tseg2Abr = int (tseg2_abr )
473
- if data_bitrate :
474
- canfd_conf .dataBitRate = int (data_bitrate )
475
- else :
476
- canfd_conf .dataBitRate = int (canfd_conf .arbitrationBitRate )
477
- canfd_conf .sjwDbr = int (sjw_dbr )
478
- canfd_conf .tseg1Dbr = int (tseg1_dbr )
479
- canfd_conf .tseg2Dbr = int (tseg2_dbr )
480
- self .xldriver .xlCanFdSetConfiguration (
481
- self .port_handle , self .channel_masks [channel ], canfd_conf
482
- )
483
- LOG .info (
484
- "xlCanFdSetConfiguration.: ABaudr.=%u, DBaudr.=%u" ,
485
- canfd_conf .arbitrationBitRate ,
486
- canfd_conf .dataBitRate ,
487
- )
488
- LOG .info (
489
- "xlCanFdSetConfiguration.: sjwAbr=%u, tseg1Abr=%u, tseg2Abr=%u" ,
490
- canfd_conf .sjwAbr ,
491
- canfd_conf .tseg1Abr ,
492
- canfd_conf .tseg2Abr ,
473
+ if self ._has_init_access (channel ):
474
+ canfd_conf = xlclass .XLcanFdConf ()
475
+ if bitrate :
476
+ canfd_conf .arbitrationBitRate = int (bitrate )
477
+ else :
478
+ canfd_conf .arbitrationBitRate = 500_000
479
+ canfd_conf .sjwAbr = int (sjw_abr )
480
+ canfd_conf .tseg1Abr = int (tseg1_abr )
481
+ canfd_conf .tseg2Abr = int (tseg2_abr )
482
+ if data_bitrate :
483
+ canfd_conf .dataBitRate = int (data_bitrate )
484
+ else :
485
+ canfd_conf .dataBitRate = int (canfd_conf .arbitrationBitRate )
486
+ canfd_conf .sjwDbr = int (sjw_dbr )
487
+ canfd_conf .tseg1Dbr = int (tseg1_dbr )
488
+ canfd_conf .tseg2Dbr = int (tseg2_dbr )
489
+ self .xldriver .xlCanFdSetConfiguration (
490
+ self .port_handle , self .channel_masks [channel ], canfd_conf
491
+ )
492
+ LOG .info (
493
+ "xlCanFdSetConfiguration.: ABaudr.=%u, DBaudr.=%u" ,
494
+ canfd_conf .arbitrationBitRate ,
495
+ canfd_conf .dataBitRate ,
496
+ )
497
+ LOG .info (
498
+ "xlCanFdSetConfiguration.: sjwAbr=%u, tseg1Abr=%u, tseg2Abr=%u" ,
499
+ canfd_conf .sjwAbr ,
500
+ canfd_conf .tseg1Abr ,
501
+ canfd_conf .tseg2Abr ,
502
+ )
503
+ LOG .info (
504
+ "xlCanFdSetConfiguration.: sjwDbr=%u, tseg1Dbr=%u, tseg2Dbr=%u" ,
505
+ canfd_conf .sjwDbr ,
506
+ canfd_conf .tseg1Dbr ,
507
+ canfd_conf .tseg2Dbr ,
508
+ )
509
+
510
+ if self .__testing :
511
+ return
512
+
513
+ # Compare requested CAN settings to active settings
514
+ bus_params = self ._read_bus_params (channel )
515
+ settings_acceptable = True
516
+
517
+ # check bus type
518
+ settings_acceptable &= (
519
+ bus_params .bus_type is xldefine .XL_BusTypes .XL_BUS_TYPE_CAN
493
520
)
494
- LOG . info (
495
- "xlCanFdSetConfiguration.: sjwDbr=%u, tseg1Dbr=%u, tseg2Dbr=%u" ,
496
- canfd_conf . sjwDbr ,
497
- canfd_conf . tseg1Dbr ,
498
- canfd_conf . tseg2Dbr ,
521
+
522
+ # check CAN operation mode
523
+ settings_acceptable &= bool (
524
+ bus_params . canfd . can_op_mode
525
+ & xldefine . XL_CANFD_BusParams_CanOpMode . XL_BUS_PARAMS_CANOPMODE_CANFD
499
526
)
500
527
528
+ # check bitrates
529
+ if bitrate :
530
+ settings_acceptable &= (
531
+ abs (bus_params .canfd .bitrate - bitrate ) < bitrate / 256
532
+ )
533
+ if data_bitrate :
534
+ settings_acceptable &= (
535
+ abs (bus_params .canfd .data_bitrate - data_bitrate ) < data_bitrate / 256
536
+ )
537
+
538
+ # check sample points
539
+ if bitrate :
540
+ requested_nom_sample_point = (
541
+ 100 * (1 + tseg1_abr ) / (1 + tseg1_abr + tseg2_abr )
542
+ )
543
+ actual_nom_sample_point = (
544
+ 100
545
+ * (1 + bus_params .canfd .tseg1_abr )
546
+ / (1 + bus_params .canfd .tseg1_abr + bus_params .canfd .tseg2_abr )
547
+ )
548
+ settings_acceptable &= (
549
+ abs (actual_nom_sample_point - requested_nom_sample_point )
550
+ < 1.0 # 1 percent threshold
551
+ )
552
+ if data_bitrate :
553
+ requested_data_sample_point = (
554
+ 100 * (1 + tseg1_dbr ) / (1 + tseg1_dbr + tseg2_dbr )
555
+ )
556
+ actual_data_sample_point = (
557
+ 100
558
+ * (1 + bus_params .canfd .tseg1_dbr )
559
+ / (1 + bus_params .canfd .tseg1_dbr + bus_params .canfd .tseg2_dbr )
560
+ )
561
+ settings_acceptable &= (
562
+ abs (actual_data_sample_point - requested_data_sample_point )
563
+ < 1.0 # 1 percent threshold
564
+ )
565
+
566
+ if not settings_acceptable :
567
+ active_settings = ", " .join (
568
+ [
569
+ f"{ key } : { getattr (val , 'name' , val )} " # print int or Enum/Flag name
570
+ for key , val in bus_params .canfd ._asdict ().items ()
571
+ ]
572
+ )
573
+ raise CanInitializationError (
574
+ f"The requested CAN FD settings could not be set for channel { channel } . "
575
+ f"Another application might have set incompatible settings. "
576
+ f"These are the currently active settings: { active_settings } ."
577
+ )
578
+
501
579
def _apply_filters (self , filters : Optional [CanFilters ]) -> None :
502
580
if filters :
503
581
# Only up to one filter per ID type allowed
0 commit comments