Skip to content

Commit 8754b15

Browse files
committed
simplify instantiation from sample point
1 parent e790c01 commit 8754b15

File tree

1 file changed

+88
-71
lines changed

1 file changed

+88
-71
lines changed

can/bit_timing.py

Lines changed: 88 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -145,24 +145,29 @@ def from_sample_point(
145145
for brp in range(1, 65):
146146
nbt = round(int(f_clock / (bitrate * brp)))
147147
if nbt < 8:
148+
break
149+
150+
actual_bitrate = f_clock / (nbt * brp)
151+
if abs(actual_bitrate - bitrate) > bitrate / 256:
148152
continue
149153

150154
tseg1 = int(round(sample_point / 100 * nbt)) - 1
151155
tseg2 = nbt - tseg1 - 1
152156

153-
for sjw in range(1, 5):
154-
try:
155-
bt = BitTiming(
156-
f_clock=f_clock,
157-
bitrate=bitrate,
158-
tseg1=tseg1,
159-
tseg2=tseg2,
160-
sjw=sjw,
161-
)
162-
if abs(bt.sample_point - sample_point) < 1:
163-
possible_solutions.append(bt)
164-
except ValueError:
165-
continue
157+
sjw = min(tseg2, 4)
158+
159+
try:
160+
bt = BitTiming(
161+
f_clock=f_clock,
162+
bitrate=bitrate,
163+
tseg1=tseg1,
164+
tseg2=tseg2,
165+
sjw=sjw,
166+
)
167+
if abs(bt.sample_point - sample_point) < 1:
168+
possible_solutions.append(bt)
169+
except ValueError:
170+
continue
166171

167172
if not possible_solutions:
168173
raise ValueError("No suitable bit timings found.")
@@ -229,8 +234,8 @@ def sample_point(self) -> float:
229234
def oscillator_tolerance(self) -> float:
230235
"""Oscillator tolerance in percent."""
231236
df_clock_list = [
232-
_oscillator_tolerance_criterion_1(nom_sjw=self.sjw, nbt=self.nbt),
233-
_oscillator_tolerance_criterion_2(nbt=self.nbt, nom_tseg2=self.tseg2),
237+
_oscillator_tolerance_condition_1(nom_sjw=self.sjw, nbt=self.nbt),
238+
_oscillator_tolerance_condition_2(nbt=self.nbt, nom_tseg2=self.tseg2),
234239
]
235240
return min(df_clock_list) * 100
236241

@@ -423,48 +428,55 @@ def from_sample_point(
423428

424429
possible_solutions: List[BitTimingFd] = []
425430

426-
def _generate_bit_timings() -> Iterator[BitTimingFdDict]:
427-
for nom_brp in range(1, 257):
428-
nbt = round(int(f_clock / (nom_bitrate * nom_brp)))
429-
if nbt < 8:
430-
continue
431+
for nom_brp in range(1, 257):
432+
nbt = round(int(f_clock / (nom_bitrate * nom_brp)))
433+
if nbt < 8:
434+
break
431435

432-
nom_tseg1 = int(round(nom_sample_point / 100 * nbt)) - 1
433-
nom_tseg2 = nbt - nom_tseg1 - 1
434-
435-
for nom_sjw in range(1, 129):
436-
for data_brp in range(1, 257):
437-
dbt = round(int(f_clock / (data_bitrate * data_brp)))
438-
if dbt < 8:
439-
continue
440-
441-
data_tseg1 = int(round(data_sample_point / 100 * dbt)) - 1
442-
data_tseg2 = dbt - data_tseg1 - 1
443-
444-
for data_sjw in range(1, 17):
445-
yield {
446-
"f_clock": f_clock,
447-
"nom_bitrate": nom_bitrate,
448-
"nom_tseg1": nom_tseg1,
449-
"nom_tseg2": nom_tseg2,
450-
"nom_sjw": nom_sjw,
451-
"data_bitrate": data_bitrate,
452-
"data_tseg1": data_tseg1,
453-
"data_tseg2": data_tseg2,
454-
"data_sjw": data_sjw,
455-
}
456-
457-
for bit_timings in _generate_bit_timings():
458-
try:
459-
bt = BitTimingFd(**bit_timings)
460-
if (
461-
abs(bt.nom_sample_point - nom_sample_point) < 1
462-
and abs(bt.data_sample_point - bt.data_sample_point) < 1
463-
):
464-
possible_solutions.append(bt)
465-
except ValueError:
436+
actual_nom_bitrate = f_clock / (nbt * nom_brp)
437+
if abs(actual_nom_bitrate - nom_bitrate) > nom_bitrate / 256:
466438
continue
467439

440+
nom_tseg1 = int(round(nom_sample_point / 100 * nbt)) - 1
441+
nom_tseg2 = nbt - nom_tseg1 - 1
442+
443+
nom_sjw = min(nom_tseg2, 128)
444+
445+
for data_brp in range(1, 257):
446+
dbt = round(int(f_clock / (data_bitrate * data_brp)))
447+
if dbt < 8:
448+
break
449+
450+
actual_data_bitrate = f_clock / (dbt * data_brp)
451+
if abs(actual_data_bitrate - data_bitrate) > data_bitrate / 256:
452+
continue
453+
454+
data_tseg1 = int(round(data_sample_point / 100 * dbt)) - 1
455+
data_tseg2 = dbt - data_tseg1 - 1
456+
457+
data_sjw = min(data_tseg2, 16)
458+
459+
bit_timings = {
460+
"f_clock": f_clock,
461+
"nom_bitrate": nom_bitrate,
462+
"nom_tseg1": nom_tseg1,
463+
"nom_tseg2": nom_tseg2,
464+
"nom_sjw": nom_sjw,
465+
"data_bitrate": data_bitrate,
466+
"data_tseg1": data_tseg1,
467+
"data_tseg2": data_tseg2,
468+
"data_sjw": data_sjw,
469+
}
470+
try:
471+
bt = BitTimingFd(**bit_timings)
472+
if (
473+
abs(bt.nom_sample_point - nom_sample_point) < 1
474+
and abs(bt.data_sample_point - bt.data_sample_point) < 1
475+
):
476+
possible_solutions.append(bt)
477+
except ValueError:
478+
continue
479+
468480
if not possible_solutions:
469481
raise ValueError("No suitable bit timings found.")
470482

@@ -479,8 +491,6 @@ def _generate_bit_timings() -> Iterator[BitTimingFdDict]:
479491
for key, reverse in (
480492
(lambda x: x.data_brp, False),
481493
(lambda x: x.nom_brp, False),
482-
(lambda x: x.data_sjw, True),
483-
(lambda x: x.nom_sjw, True),
484494
(lambda x: x.oscillator_tolerance, True),
485495
):
486496
possible_solutions.sort(key=key, reverse=reverse)
@@ -555,16 +565,16 @@ def f_clock(self) -> int:
555565
def oscillator_tolerance(self) -> float:
556566
"""Oscillator tolerance in percent."""
557567
df_clock_list = [
558-
_oscillator_tolerance_criterion_1(nom_sjw=self.nom_sjw, nbt=self.nbt),
559-
_oscillator_tolerance_criterion_2(nbt=self.nbt, nom_tseg2=self.nom_tseg2),
560-
_oscillator_tolerance_criterion_3(data_sjw=self.data_sjw, dbt=self.dbt),
561-
_oscillator_tolerance_criterion_4(
568+
_oscillator_tolerance_condition_1(nom_sjw=self.nom_sjw, nbt=self.nbt),
569+
_oscillator_tolerance_condition_2(nbt=self.nbt, nom_tseg2=self.nom_tseg2),
570+
_oscillator_tolerance_condition_3(data_sjw=self.data_sjw, dbt=self.dbt),
571+
_oscillator_tolerance_condition_4(
562572
data_tseg2=self.data_tseg2,
563573
nbt=self.nbt,
564574
data_brp=self.data_brp,
565575
nom_brp=self.nom_brp,
566576
),
567-
_oscillator_tolerance_criterion_5(
577+
_oscillator_tolerance_condition_5(
568578
data_sjw=self.data_sjw,
569579
data_brp=self.data_brp,
570580
nom_brp=self.nom_brp,
@@ -650,25 +660,29 @@ def __iter__(self) -> Iterator[str]:
650660
return self._data.__iter__()
651661

652662

653-
def _oscillator_tolerance_criterion_1(nom_sjw: int, nbt: int) -> float:
654-
return nom_sjw / (20 * nbt)
663+
def _oscillator_tolerance_condition_1(nom_sjw: int, nbt: int) -> float:
664+
"""Arbitration phase - resynchronization"""
665+
return nom_sjw / (2 * 10 * nbt)
655666

656667

657-
def _oscillator_tolerance_criterion_2(nbt: int, nom_tseg2: int) -> float:
668+
def _oscillator_tolerance_condition_2(nbt: int, nom_tseg2: int) -> float:
669+
"""Arbitration phase - sampling of bit after error flag"""
658670
return nom_tseg2 / (2 * (13 * nbt - nom_tseg2))
659671

660672

661-
def _oscillator_tolerance_criterion_3(data_sjw: int, dbt: int) -> float:
662-
return data_sjw / (20 * dbt)
673+
def _oscillator_tolerance_condition_3(data_sjw: int, dbt: int) -> float:
674+
"""Data phase - resynchronization"""
675+
return data_sjw / (2 * 10 * dbt)
663676

664677

665-
def _oscillator_tolerance_criterion_4(
678+
def _oscillator_tolerance_condition_4(
666679
data_tseg2: int, nbt: int, data_brp: int, nom_brp: int
667680
) -> float:
668-
return data_tseg2 / (2 * ((2 * nbt - data_tseg2) * data_brp / nom_brp + 7 * nbt))
681+
"""Data phase - sampling of bit after error flag"""
682+
return data_tseg2 / (2 * ((6 * nbt - data_tseg2) * data_brp / nom_brp + 7 * nbt))
669683

670684

671-
def _oscillator_tolerance_criterion_5(
685+
def _oscillator_tolerance_condition_5(
672686
data_sjw: int,
673687
data_brp: int,
674688
nom_brp: int,
@@ -677,6 +691,9 @@ def _oscillator_tolerance_criterion_5(
677691
nbt: int,
678692
dbt: int,
679693
) -> float:
680-
return (data_sjw - (nom_brp / data_brp - 1)) / (
681-
2 * ((2 * nbt - nom_tseg2) * nom_brp / data_brp + data_tseg2 + 4 * dbt)
694+
"""Data phase - bit rate switch"""
695+
max_correctable_phase_shift = data_sjw - max(0.0, nom_brp / data_brp - 1)
696+
time_between_resync = 2 * (
697+
(2 * nbt - nom_tseg2) * nom_brp / data_brp + data_tseg2 + 4 * dbt
682698
)
699+
return max_correctable_phase_shift / time_between_resync

0 commit comments

Comments
 (0)