can_utils/
timing_calculator.rs1use core::cmp;
4
5type BaudRatePrescalaInnerType = u32;
6
7type BitSamplePointInnerType = u16;
8
9type SegmentLengthInnerType = u8;
10
11pub struct BitsPerSecond(u32);
13
14pub struct MegaHertz(u32);
16
17pub struct SegmentLength(SegmentLengthInnerType);
19
20pub struct CanTimingLimits {
22 pub max_baud_rate_prescaler: u32,
24 pub max_segment_1_length: SegmentLength,
26 pub max_segment_2_length: SegmentLength,
28 pub max_jump_width: SegmentLength,
30}
31
32pub struct CanBitTimingParameters {
34 pub baud_rate_prescaler: BaudRatePrescalaInnerType,
36 pub seg1: SegmentLength,
38 pub seg2: SegmentLength,
40 pub jump_width: SegmentLength,
42}
43
44pub struct BitSamplePoint {
46 tenths_of_a_percent: BitSamplePointInnerType,
48}
49
50impl BitSamplePoint {
51 pub const MINIMUM_SAMPLE_POINT: BitSamplePoint = BitSamplePoint { tenths_of_a_percent: 500 };
53 pub const MAXIMUM_SAMPLE_POINT: BitSamplePoint = BitSamplePoint { tenths_of_a_percent: 990 };
55
56 pub fn new(tenths_of_a_percent: BitSamplePointInnerType) -> BitSamplePoint {
58 BitSamplePoint { tenths_of_a_percent }
60 }
61}
62
63pub struct CanBitTimingParameterIter<'a> {
65 bit_width: u32,
66 jump_width: SegmentLengthInnerType,
67 target_sample_point: BitSamplePointInnerType,
68 last_attempted_prescaler: BaudRatePrescalaInnerType,
69
70 interface_limits: &'a CanTimingLimits,
71}
72
73impl<'a> Iterator for CanBitTimingParameterIter<'a> {
74 type Item = CanBitTimingParameters;
75
76 fn next(&mut self) -> Option<CanBitTimingParameters> {
77 let mut result: Option<CanBitTimingParameters> = None;
78
79 while result.is_none() &&
80 self.last_attempted_prescaler < self.interface_limits.max_baud_rate_prescaler {
81 self.last_attempted_prescaler += 1;
82 if self.bit_width % self.last_attempted_prescaler != 0 {
83 continue;
84 }
85 let tq = self.bit_width / self.last_attempted_prescaler;
86 if tq < 8 { continue;
88 }
89 let sample = tq * 1000 / (self.target_sample_point as u32);
91 let seg2 = cmp::max(1, tq - sample) as SegmentLengthInnerType; let seg1 = tq as SegmentLengthInnerType - seg2 - 1; if seg1 > self.interface_limits.max_segment_1_length.0 ||
96 seg2 > self.interface_limits.max_segment_2_length.0 {
97 continue;
98 }
99 result = Some(CanBitTimingParameters {
100 baud_rate_prescaler: self.last_attempted_prescaler,
101 seg1: SegmentLength(seg1),
102 seg2: SegmentLength(seg2),
103 jump_width: SegmentLength(self.jump_width),
104 });
105 }
106 result
107 }
108}
109
110pub fn compute_timing_parameters<'a>(clock_speed: MegaHertz,
113 nominal_bitrate: BitsPerSecond,
114 target_sample_point: BitSamplePoint,
115 jump_width: SegmentLength,
116 limits: &'a CanTimingLimits) -> CanBitTimingParameterIter {
117 CanBitTimingParameterIter {
118 bit_width: 1_000_000 * clock_speed.0 / nominal_bitrate.0,
119 jump_width: jump_width.0,
120 target_sample_point: target_sample_point.tenths_of_a_percent,
121 last_attempted_prescaler: 1,
122 interface_limits: limits,
123 }
124}
125
126pub mod recommended_sample_points {
128 use super::BitSamplePoint;
129 pub const ARINC825: BitSamplePoint = BitSamplePoint { tenths_of_a_percent: 750 };
131 pub const CANOPEN: BitSamplePoint = BitSamplePoint { tenths_of_a_percent: 875 };
133 pub const DEVICENET: BitSamplePoint = BitSamplePoint { tenths_of_a_percent: 875 };
135 pub const J1939: BitSamplePoint = BitSamplePoint { tenths_of_a_percent: 900 };
137 pub const J2284: BitSamplePoint = BitSamplePoint { tenths_of_a_percent: 900 };
139 }