|
4 | 4 |
|
5 | 5 |
|
6 | 6 | class BitTiming(Mapping):
|
7 |
| - """Representation of a bit timing configuration. |
| 7 | + """Representation of a bit timing configuration for a CAN 2.0 bus. |
8 | 8 |
|
9 |
| - The class can be constructed in various ways, depending on the information |
10 |
| - available or the capabilities of the interfaces that need to be supported. |
11 |
| -
|
12 |
| - The preferred way is using bitrate, CAN clock frequency, TSEG1, TSEG2, SJW:: |
| 9 | + The class can be constructed in multiple ways, depending on the information |
| 10 | + available. The preferred way is using bitrate, CAN clock frequency, tseg1, tseg2 and sjw:: |
13 | 11 |
|
14 | 12 | can.BitTiming(bitrate=1_000_000, f_clock=8_000_000, tseg1=5, tseg2=1, sjw=1)
|
15 | 13 |
|
16 |
| - It is also possible specify BTR registers directly:: |
| 14 | + It is also possible to specify BTR registers:: |
17 | 15 |
|
18 | 16 | can.BitTiming.from_registers(f_clock=8_000_000, btr0=0x00, btr1=0x14)
|
| 17 | +
|
| 18 | + or to calculate the timings for a given sample point:: |
| 19 | +
|
| 20 | + can.BitTiming.from_sample_point(f_clock=16_000_000, bitrate=500_000, sample_point=81.25) |
19 | 21 | """
|
20 | 22 |
|
21 | 23 | def __init__(
|
@@ -305,6 +307,36 @@ def __iter__(self) -> Iterator[str]:
|
305 | 307 |
|
306 | 308 |
|
307 | 309 | class BitTimingFd(Mapping):
|
| 310 | + """Representation of a bit timing configuration for a CAN FD bus. |
| 311 | +
|
| 312 | + The class can be constructed in multiple ways, depending on the information |
| 313 | + available. The preferred way is using bitrate, CAN clock frequency, tseg1, tseg2 and sjw |
| 314 | + for both the arbitration (nominal) and data phase:: |
| 315 | +
|
| 316 | + can.BitTimingFd( |
| 317 | + f_clock=80_000_000, |
| 318 | + nom_bitrate=1_000_000, |
| 319 | + nom_tseg1=59, |
| 320 | + nom_tseg2=20, |
| 321 | + nom_sjw=10, |
| 322 | + data_bitrate=8_000_000, |
| 323 | + data_tseg1=6, |
| 324 | + data_tseg2=3, |
| 325 | + data_sjw=2, |
| 326 | + ) |
| 327 | +
|
| 328 | + It is also possible to calculate the timings for a given |
| 329 | + pair of arbitration and data sample points:: |
| 330 | +
|
| 331 | + can.BitTimingFd.from_sample_point( |
| 332 | + f_clock=80_000_000, |
| 333 | + nom_bitrate=1_000_000, |
| 334 | + nom_sample_point=75.0, |
| 335 | + data_bitrate=8_000_000, |
| 336 | + data_sample_point=70.0, |
| 337 | + ) |
| 338 | + """ |
| 339 | + |
308 | 340 | def __init__(
|
309 | 341 | self,
|
310 | 342 | f_clock: int,
|
@@ -416,6 +448,20 @@ def from_sample_point(
|
416 | 448 | data_bitrate: int,
|
417 | 449 | data_sample_point: float,
|
418 | 450 | ) -> "BitTimingFd":
|
| 451 | + """Create a BitTimingFd instance for a given nominal/data sample point pair. |
| 452 | +
|
| 453 | + :param int f_clock: |
| 454 | + The CAN system clock frequency in Hz. |
| 455 | + Usually the oscillator frequency divided by 2. |
| 456 | + :param int nom_bitrate: |
| 457 | + Nominal bitrate in bit/s. |
| 458 | + :param int nom_sample_point: |
| 459 | + The sample point value of the arbitration phase in percent. |
| 460 | + :param int data_bitrate: |
| 461 | + Data bitrate in bit/s. |
| 462 | + :param int data_sample_point: |
| 463 | + The sample point value of the data phase in percent. |
| 464 | + """ |
419 | 465 | if nom_sample_point < 50.0:
|
420 | 466 | raise ValueError(
|
421 | 467 | f"nom_sample_point (={nom_sample_point}) must not be below 50%."
|
@@ -499,58 +545,84 @@ def from_sample_point(
|
499 | 545 |
|
500 | 546 | @property
|
501 | 547 | def nom_bitrate(self) -> int:
|
| 548 | + """Nominal (arbitration phase) bitrate.""" |
502 | 549 | return self["nom_bitrate"]
|
503 | 550 |
|
504 | 551 | @property
|
505 | 552 | def nom_brp(self) -> int:
|
| 553 | + """Prescaler value for the arbitration phase.""" |
506 | 554 | return int(round(self.f_clock / (self.nom_bitrate * self.nbt)))
|
507 | 555 |
|
508 | 556 | @property
|
509 | 557 | def nbt(self) -> int:
|
| 558 | + """Number of time quanta in a bit of the arbitration phase.""" |
510 | 559 | return 1 + self.nom_tseg1 + self.nom_tseg2
|
511 | 560 |
|
512 | 561 | @property
|
513 | 562 | def nom_tseg1(self) -> int:
|
| 563 | + """Time segment 1 value of the arbitration phase. |
| 564 | +
|
| 565 | + This is the sum of the propagation time segment and the phase buffer segment 1. |
| 566 | + """ |
514 | 567 | return self["nom_tseg1"]
|
515 | 568 |
|
516 | 569 | @property
|
517 | 570 | def nom_tseg2(self) -> int:
|
| 571 | + """Time segment 2 value of the arbitration phase. Also known as phase buffer segment 2.""" |
518 | 572 | return self["nom_tseg2"]
|
519 | 573 |
|
520 | 574 | @property
|
521 | 575 | def nom_sjw(self) -> int:
|
| 576 | + """Synchronization jump width of the arbitration phase. |
| 577 | +
|
| 578 | + The phase buffer segments may be shortened or lengthened by this value. |
| 579 | + """ |
522 | 580 | return self["nom_sjw"]
|
523 | 581 |
|
524 | 582 | @property
|
525 | 583 | def nom_sample_point(self) -> float:
|
| 584 | + """Sample point of the arbitration phase in percent.""" |
526 | 585 | return 100.0 * (1 + self.nom_tseg1) / (1 + self.nom_tseg1 + self.nom_tseg2)
|
527 | 586 |
|
528 | 587 | @property
|
529 | 588 | def data_bitrate(self) -> int:
|
| 589 | + """Bitrate of the data phase in bit/s.""" |
530 | 590 | return self["data_bitrate"]
|
531 | 591 |
|
532 | 592 | @property
|
533 | 593 | def data_brp(self) -> int:
|
| 594 | + """Prescaler value for the data phase.""" |
534 | 595 | return int(round(self.f_clock / (self.data_bitrate * self.dbt)))
|
535 | 596 |
|
536 | 597 | @property
|
537 | 598 | def dbt(self) -> int:
|
| 599 | + """Number of time quanta in a bit of the data phase.""" |
538 | 600 | return 1 + self.data_tseg1 + self.data_tseg2
|
539 | 601 |
|
540 | 602 | @property
|
541 | 603 | def data_tseg1(self) -> int:
|
| 604 | + """TSEG1 value of the data phase. |
| 605 | +
|
| 606 | + This is the sum of the propagation time segment and the phase buffer segment 1. |
| 607 | + """ |
542 | 608 | return self["data_tseg1"]
|
543 | 609 |
|
544 | 610 | @property
|
545 | 611 | def data_tseg2(self) -> int:
|
| 612 | + """TSEG2 value of the data phase. Also known as phase buffer segment 2.""" |
546 | 613 | return self["data_tseg2"]
|
547 | 614 |
|
548 | 615 | @property
|
549 | 616 | def data_sjw(self) -> int:
|
| 617 | + """Synchronization jump width of the data phase. |
| 618 | +
|
| 619 | + The phase buffer segments may be shortened or lengthened by this value. |
| 620 | + """ |
550 | 621 | return self["data_sjw"]
|
551 | 622 |
|
552 | 623 | @property
|
553 | 624 | def data_sample_point(self) -> float:
|
| 625 | + """Sample point of the data phase in percent.""" |
554 | 626 | return 100.0 * (1 + self.data_tseg1) / (1 + self.data_tseg1 + self.data_tseg2)
|
555 | 627 |
|
556 | 628 | @property
|
|
0 commit comments