Skip to content

Commit 4a8eee5

Browse files
committed
add strict parameter to can.BitTiming
1 parent dc0ae68 commit 4a8eee5

File tree

2 files changed

+29
-11
lines changed

2 files changed

+29
-11
lines changed

can/bit_timing.py

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def __init__(
3636
tseg2: int,
3737
sjw: int,
3838
nof_samples: int = 1,
39+
strict: bool = False,
3940
) -> None:
4041
"""
4142
:param int f_clock:
@@ -56,6 +57,10 @@ def __init__(
5657
In this case, the bit will be sampled three quanta in a row,
5758
with the last sample being taken in the edge between TSEG1 and TSEG2.
5859
Three samples should only be used for relatively slow baudrates.
60+
:param strict:
61+
If True, restrict bit timings to the minimum required range as defined in
62+
ISO 11898. This can be used to ensure compatibility across a wide variety
63+
of CAN hardware.
5964
:raises ValueError:
6065
if the arguments are invalid.
6166
"""
@@ -68,19 +73,13 @@ def __init__(
6873
"nof_samples": nof_samples,
6974
}
7075
self._validate()
76+
if strict:
77+
self._restrict_to_minimum_range()
7178

7279
def _validate(self) -> None:
73-
if not 8 <= self.nbt <= 25:
74-
raise ValueError(f"nominal bit time (={self.nbt}) must be in [8...25].")
75-
7680
if not 1 <= self.brp <= 64:
7781
raise ValueError(f"bitrate prescaler (={self.brp}) must be in [1...64].")
7882

79-
if not 5_000 <= self.bitrate <= 2_000_000:
80-
raise ValueError(
81-
f"bitrate (={self.bitrate}) must be in [5,000...2,000,000]."
82-
)
83-
8483
if not 1 <= self.tseg1 <= 16:
8584
raise ValueError(f"tseg1 (={self.tseg1}) must be in [1...16].")
8685

@@ -104,6 +103,18 @@ def _validate(self) -> None:
104103
if self.nof_samples not in (1, 3):
105104
raise ValueError("nof_samples must be 1 or 3")
106105

106+
def _restrict_to_minimum_range(self) -> None:
107+
if not 8 <= self.nbt <= 25:
108+
raise ValueError(f"nominal bit time (={self.nbt}) must be in [8...25].")
109+
110+
if not 1 <= self.brp <= 32:
111+
raise ValueError(f"bitrate prescaler (={self.brp}) must be in [1...32].")
112+
113+
if not 5_000 <= self.bitrate <= 1_000_000:
114+
raise ValueError(
115+
f"bitrate (={self.bitrate}) must be in [5,000...1,000,000]."
116+
)
117+
107118
@classmethod
108119
def from_bitrate_and_segments(
109120
cls,
@@ -175,6 +186,11 @@ def from_registers(
175186
:raises ValueError:
176187
if the arguments are invalid.
177188
"""
189+
if not 0 <= btr0 < 2**16:
190+
raise ValueError(f"Invalid btr0 value. ({btr0})")
191+
if not 0 <= btr1 < 2**16:
192+
raise ValueError(f"Invalid btr1 value. ({btr1})")
193+
178194
brp = (btr0 & 0x3F) + 1
179195
sjw = (btr0 >> 6) + 1
180196
tseg1 = (btr1 & 0xF) + 1
@@ -239,6 +255,7 @@ def from_sample_point(
239255
tseg1=tseg1,
240256
tseg2=tseg2,
241257
sjw=sjw,
258+
strict=True,
242259
)
243260
possible_solutions.append(bt)
244261
except ValueError:
@@ -316,12 +333,12 @@ def sample_point(self) -> float:
316333

317334
@property
318335
def btr0(self) -> int:
319-
"""Bit timing register 0."""
336+
"""Bit timing register 0 for SJA1000."""
320337
return (self.sjw - 1) << 6 | self.brp - 1
321338

322339
@property
323340
def btr1(self) -> int:
324-
"""Bit timing register 1."""
341+
"""Bit timing register 1 for SJA1000."""
325342
sam = 1 if self.nof_samples == 3 else 0
326343
return sam << 7 | (self.tseg2 - 1) << 4 | self.tseg1 - 1
327344

can/util.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ def _create_bus_config(config: Dict[str, Any]) -> typechecking.BusConfig:
257257
**{
258258
key: int(config[key])
259259
for key in typechecking.BitTimingDict.__annotations__
260-
}
260+
},
261+
strict=False,
261262
)
262263
except (ValueError, TypeError):
263264
pass

0 commit comments

Comments
 (0)