Skip to content

Commit 79d9768

Browse files
committed
clean up structs
1 parent b326bbd commit 79d9768

2 files changed

Lines changed: 107 additions & 122 deletions

File tree

src/can/bitrate.rs

Lines changed: 97 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
//! - otherwise: sample point 0.875
1414
//!
1515
//! The resulting [`BitrateConfig`] contains:
16-
//! - the adapter-facing values (`brp`, `tseg1`, `tseg2`, `sjw`)
17-
//! - the resulting `bitrate` and `sample_point`
16+
//! - nominal/arbitration phase settings as one [`AdapterBitTiming`]
17+
//! - optional CAN-FD data phase settings as one [`AdapterBitTiming`]
1818
1919
use thiserror::Error;
2020

@@ -64,8 +64,8 @@ pub struct AdapterTimingConst {
6464
pub data: Option<BitTimingConst>,
6565
}
6666

67-
/// Generic timing values typically needed by CAN adapter drivers.
68-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67+
/// Resolved timing and bitrate values for one CAN phase.
68+
#[derive(Debug, Clone, Copy, PartialEq)]
6969
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7070
pub struct AdapterBitTiming {
7171
/// Bitrate prescaler.
@@ -76,36 +76,38 @@ pub struct AdapterBitTiming {
7676
pub tseg2: u32,
7777
/// Synchronization jump width.
7878
pub sjw: u32,
79+
/// Actual bitrate in bits per second.
80+
pub bitrate: u32,
81+
/// Actual sample point in normalized form (`0.0 < sample_point < 1.0`).
82+
pub sample_point: f64,
83+
}
84+
85+
impl AdapterBitTiming {
86+
/// Duration of one phase bit in time quanta.
87+
pub fn bit_time_tq(&self) -> u32 {
88+
CAN_SYNC_SEG + self.tseg1 + self.tseg2
89+
}
7990
}
8091

8192
/// Resolved bitrate configuration.
8293
#[derive(Debug, Clone, Copy, PartialEq)]
8394
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8495
pub struct BitrateConfig {
85-
/// Adapter-facing timing values.
86-
pub timing: AdapterBitTiming,
87-
/// Actual bitrate in bits per second.
88-
pub bitrate: u32,
89-
/// Actual sample point in normalized form (`0.0 < sample_point < 1.0`).
90-
pub sample_point: f64,
91-
/// Optional CAN-FD data phase adapter-facing timing values.
92-
pub data_timing: Option<AdapterBitTiming>,
93-
/// Optional CAN-FD data phase bitrate in bits per second.
94-
pub data_bitrate: Option<u32>,
95-
/// Optional CAN-FD data phase sample point in normalized form (`0.0 < sample_point < 1.0`).
96-
pub data_sample_point: Option<f64>,
96+
/// Nominal/arbitration phase settings (also used for classic CAN).
97+
pub nominal: AdapterBitTiming,
98+
/// Optional CAN-FD data phase settings.
99+
pub data: Option<AdapterBitTiming>,
97100
}
98101

99102
impl BitrateConfig {
100-
/// Duration of one bit in time quanta.
103+
/// Duration of one nominal/arbitration bit in time quanta.
101104
pub fn bit_time_tq(&self) -> u32 {
102-
CAN_SYNC_SEG + self.timing.tseg1 + self.timing.tseg2
105+
self.nominal.bit_time_tq()
103106
}
104107

105108
/// Duration of one CAN-FD data phase bit in time quanta.
106109
pub fn data_bit_time_tq(&self) -> Option<u32> {
107-
self.data_timing
108-
.map(|timing| CAN_SYNC_SEG + timing.tseg1 + timing.tseg2)
110+
self.data.map(|data| data.bit_time_tq())
109111
}
110112
}
111113

@@ -117,13 +119,6 @@ struct SamplePointCandidate {
117119
tseg2: u32,
118120
}
119121

120-
#[derive(Debug, Clone, Copy, PartialEq)]
121-
struct PhaseBitrateConfig {
122-
timing: AdapterBitTiming,
123-
bitrate: u32,
124-
sample_point: f64,
125-
}
126-
127122
/// Error type returned by [`BitrateBuilder::build`].
128123
#[derive(Error, Debug, Clone, PartialEq, Eq)]
129124
pub enum BitrateError {
@@ -237,8 +232,8 @@ pub enum BitrateError {
237232
/// .build()
238233
/// .unwrap();
239234
///
240-
/// assert_eq!(cfg.bitrate, 500_000);
241-
/// assert!((cfg.sample_point - 0.8).abs() < 1e-9);
235+
/// assert_eq!(cfg.nominal.bitrate, 500_000);
236+
/// assert!((cfg.nominal.sample_point - 0.8).abs() < 1e-9);
242237
/// ```
243238
///
244239
/// ## Direct timing mode
@@ -289,8 +284,8 @@ pub enum BitrateError {
289284
/// .build()
290285
/// .unwrap();
291286
///
292-
/// assert_eq!(cfg.bitrate, 500_000);
293-
/// assert!((cfg.sample_point - 0.8).abs() < 1e-9);
287+
/// assert_eq!(cfg.nominal.bitrate, 500_000);
288+
/// assert!((cfg.nominal.sample_point - 0.8).abs() < 1e-9);
294289
/// ```
295290
///
296291
/// ## CAN-FD data phase
@@ -349,7 +344,7 @@ pub enum BitrateError {
349344
/// .build()
350345
/// .unwrap();
351346
///
352-
/// assert_eq!(cfg.data_bitrate, Some(2_000_000));
347+
/// assert_eq!(cfg.data.map(|data| data.bitrate), Some(2_000_000));
353348
/// ```
354349
#[derive(Debug, Clone, Copy)]
355350
pub struct BitrateBuilder {
@@ -496,49 +491,37 @@ impl BitrateBuilder {
496491
self.build_from_direct_mode()?
497492
};
498493

499-
let (data_timing, data_bitrate, data_sample_point) =
500-
if let Some(data_bitrate_target) = self.data_bitrate {
501-
let data_timing_const = self
502-
.timing_const
503-
.data
504-
.ok_or(BitrateError::DataBitrateNotSupported)?;
505-
validate_timing_const(&data_timing_const)?;
506-
507-
let data = solve_bitrate_mode(
508-
&data_timing_const,
509-
data_bitrate_target,
510-
self.data_sample_point,
511-
self.data_sjw,
512-
self.max_bitrate_error,
513-
)?;
514-
515-
if data.bitrate < nominal.bitrate {
516-
return Err(BitrateError::DataBitrateLowerThanNominal {
517-
data_bitrate: data.bitrate,
518-
arbitration_bitrate: nominal.bitrate,
519-
});
520-
}
521-
522-
(
523-
Some(data.timing),
524-
Some(data.bitrate),
525-
Some(data.sample_point),
526-
)
527-
} else {
528-
(None, None, None)
529-
};
530-
531-
Ok(BitrateConfig {
532-
timing: nominal.timing,
533-
bitrate: nominal.bitrate,
534-
sample_point: nominal.sample_point,
535-
data_timing,
536-
data_bitrate,
537-
data_sample_point,
538-
})
539-
}
540-
541-
fn build_from_bitrate_mode(self) -> Result<PhaseBitrateConfig, BitrateError> {
494+
let data = if let Some(data_bitrate_target) = self.data_bitrate {
495+
let data_timing_const = self
496+
.timing_const
497+
.data
498+
.ok_or(BitrateError::DataBitrateNotSupported)?;
499+
validate_timing_const(&data_timing_const)?;
500+
501+
let data = solve_bitrate_mode(
502+
&data_timing_const,
503+
data_bitrate_target,
504+
self.data_sample_point,
505+
self.data_sjw,
506+
self.max_bitrate_error,
507+
)?;
508+
509+
if data.bitrate < nominal.bitrate {
510+
return Err(BitrateError::DataBitrateLowerThanNominal {
511+
data_bitrate: data.bitrate,
512+
arbitration_bitrate: nominal.bitrate,
513+
});
514+
}
515+
516+
Some(data)
517+
} else {
518+
None
519+
};
520+
521+
Ok(BitrateConfig { nominal, data })
522+
}
523+
524+
fn build_from_bitrate_mode(self) -> Result<AdapterBitTiming, BitrateError> {
542525
let bitrate = self.bitrate.ok_or(BitrateError::MissingConfiguration)?;
543526

544527
solve_bitrate_mode(
@@ -550,7 +533,7 @@ impl BitrateBuilder {
550533
)
551534
}
552535

553-
fn build_from_direct_mode(self) -> Result<PhaseBitrateConfig, BitrateError> {
536+
fn build_from_direct_mode(self) -> Result<AdapterBitTiming, BitrateError> {
554537
if self.sample_point.is_some() {
555538
return Err(BitrateError::SamplePointRequiresBitrate);
556539
}
@@ -612,7 +595,7 @@ fn solve_bitrate_mode(
612595
sample_point: Option<f64>,
613596
sjw: Option<u32>,
614597
max_bitrate_error: u32,
615-
) -> Result<PhaseBitrateConfig, BitrateError> {
598+
) -> Result<AdapterBitTiming, BitrateError> {
616599
if bitrate == 0 {
617600
return Err(BitrateError::InvalidBitrate);
618601
}
@@ -694,13 +677,11 @@ fn solve_bitrate_mode(
694677

695678
let bit_time_tq = CAN_SYNC_SEG + candidate.tseg1 + candidate.tseg2;
696679
let actual_bitrate = btc.clock_hz / (best_brp * bit_time_tq);
697-
Ok(PhaseBitrateConfig {
698-
timing: AdapterBitTiming {
699-
brp: best_brp,
700-
tseg1: candidate.tseg1,
701-
tseg2: candidate.tseg2,
702-
sjw,
703-
},
680+
Ok(AdapterBitTiming {
681+
brp: best_brp,
682+
tseg1: candidate.tseg1,
683+
tseg2: candidate.tseg2,
684+
sjw,
704685
bitrate: actual_bitrate,
705686
sample_point: sample_point_to_float(candidate.sample_point),
706687
})
@@ -712,7 +693,7 @@ fn solve_direct_mode(
712693
tseg1: u32,
713694
tseg2: u32,
714695
sjw: Option<u32>,
715-
) -> Result<PhaseBitrateConfig, BitrateError> {
696+
) -> Result<AdapterBitTiming, BitrateError> {
716697
check_ranges(btc, brp, tseg1, tseg2)?;
717698

718699
let sjw = sjw.unwrap_or_else(|| calc_default_sjw(tseg1, tseg2));
@@ -721,13 +702,11 @@ fn solve_direct_mode(
721702
let bit_time_tq = CAN_SYNC_SEG + tseg1 + tseg2;
722703
let bitrate = btc.clock_hz / (brp * bit_time_tq);
723704
let sample_point = sample_point_to_float(1000 * (CAN_SYNC_SEG + tseg1) / bit_time_tq);
724-
Ok(PhaseBitrateConfig {
725-
timing: AdapterBitTiming {
726-
brp,
727-
tseg1,
728-
tseg2,
729-
sjw,
730-
},
705+
Ok(AdapterBitTiming {
706+
brp,
707+
tseg1,
708+
tseg2,
709+
sjw,
731710
bitrate,
732711
sample_point,
733712
})
@@ -954,10 +933,10 @@ mod tests {
954933
.build()
955934
.unwrap();
956935

957-
assert_eq!(cfg.bitrate, 500_000);
958-
assert!((cfg.sample_point - 0.8).abs() < 1e-9);
959-
assert!(cfg.timing.brp >= PEAK_NOMINAL_BTC.brp_min);
960-
assert!(cfg.timing.brp <= PEAK_NOMINAL_BTC.brp_max);
936+
assert_eq!(cfg.nominal.bitrate, 500_000);
937+
assert!((cfg.nominal.sample_point - 0.8).abs() < 1e-9);
938+
assert!(cfg.nominal.brp >= PEAK_NOMINAL_BTC.brp_min);
939+
assert!(cfg.nominal.brp <= PEAK_NOMINAL_BTC.brp_max);
961940
}
962941

963942
#[test]
@@ -968,7 +947,7 @@ mod tests {
968947
.build()
969948
.unwrap();
970949

971-
assert_eq!(cfg.bitrate, 500_000);
950+
assert_eq!(cfg.nominal.bitrate, 500_000);
972951
}
973952

974953
#[test]
@@ -1017,7 +996,7 @@ mod tests {
1017996
.build()
1018997
.unwrap();
1019998

1020-
assert_eq!(cfg.timing.sjw, 1);
999+
assert_eq!(cfg.nominal.sjw, 1);
10211000
}
10221001

10231002
#[test]
@@ -1029,9 +1008,9 @@ mod tests {
10291008
.build()
10301009
.unwrap();
10311010

1032-
assert_eq!(cfg.bitrate, 500_000);
1033-
assert!((cfg.sample_point - 0.8).abs() < 1e-9);
1034-
assert_eq!(cfg.timing.sjw, 2);
1011+
assert_eq!(cfg.nominal.bitrate, 500_000);
1012+
assert!((cfg.nominal.sample_point - 0.8).abs() < 1e-9);
1013+
assert_eq!(cfg.nominal.sjw, 2);
10351014
}
10361015

10371016
#[test]
@@ -1159,12 +1138,12 @@ mod tests {
11591138
.build()
11601139
.unwrap();
11611140

1162-
assert_eq!(cfg.bitrate, 500_000);
1163-
assert!((cfg.sample_point - 0.8).abs() < 1e-9);
1141+
assert_eq!(cfg.nominal.bitrate, 500_000);
1142+
assert!((cfg.nominal.sample_point - 0.8).abs() < 1e-9);
11641143

1165-
assert_eq!(cfg.data_bitrate, Some(2_000_000));
1166-
assert!(cfg.data_timing.is_some());
1167-
assert!((cfg.data_sample_point.unwrap() - 0.75).abs() < 1e-9);
1144+
assert_eq!(cfg.data.map(|data| data.bitrate), Some(2_000_000));
1145+
assert!(cfg.data.is_some());
1146+
assert!((cfg.data.unwrap().sample_point - 0.75).abs() < 1e-9);
11681147
}
11691148

11701149
#[test]
@@ -1229,14 +1208,20 @@ mod tests {
12291208
.unwrap();
12301209

12311210
let cfg_from_direct = BitrateBuilder::new::<DummyTimingAdapter>()
1232-
.brp(cfg_from_bitrate.timing.brp)
1233-
.tseg1(cfg_from_bitrate.timing.tseg1)
1234-
.tseg2(cfg_from_bitrate.timing.tseg2)
1235-
.sjw(cfg_from_bitrate.timing.sjw)
1211+
.brp(cfg_from_bitrate.nominal.brp)
1212+
.tseg1(cfg_from_bitrate.nominal.tseg1)
1213+
.tseg2(cfg_from_bitrate.nominal.tseg2)
1214+
.sjw(cfg_from_bitrate.nominal.sjw)
12361215
.build()
12371216
.unwrap();
12381217

1239-
assert_eq!(cfg_from_direct.bitrate, cfg_from_bitrate.bitrate);
1240-
assert!((cfg_from_direct.sample_point - cfg_from_bitrate.sample_point).abs() < 1e-9);
1218+
assert_eq!(
1219+
cfg_from_direct.nominal.bitrate,
1220+
cfg_from_bitrate.nominal.bitrate
1221+
);
1222+
assert!(
1223+
(cfg_from_direct.nominal.sample_point - cfg_from_bitrate.nominal.sample_point).abs()
1224+
< 1e-9
1225+
);
12411226
}
12421227
}

src/vector/types.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,18 +124,18 @@ impl Eq for XLcanFdConf {}
124124

125125
impl From<BitrateConfig> for XLcanFdConf {
126126
fn from(config: BitrateConfig) -> Self {
127-
let data_timing = config.data_timing.unwrap_or(config.timing);
128-
let data_bitrate = config.data_bitrate.unwrap_or(config.bitrate);
127+
let nominal = config.nominal;
128+
let data = config.data.unwrap_or(nominal);
129129

130130
Self {
131-
arbitrationBitRate: config.bitrate,
132-
sjwAbr: config.timing.sjw,
133-
tseg1Abr: config.timing.tseg1,
134-
tseg2Abr: config.timing.tseg2,
135-
dataBitRate: data_bitrate,
136-
sjwDbr: data_timing.sjw,
137-
tseg1Dbr: data_timing.tseg1,
138-
tseg2Dbr: data_timing.tseg2,
131+
arbitrationBitRate: nominal.bitrate,
132+
sjwAbr: nominal.sjw,
133+
tseg1Abr: nominal.tseg1,
134+
tseg2Abr: nominal.tseg2,
135+
dataBitRate: data.bitrate,
136+
sjwDbr: data.sjw,
137+
tseg1Dbr: data.tseg1,
138+
tseg2Dbr: data.tseg2,
139139
reserved: 0,
140140
options: 0,
141141
reserved1: [0, 0],

0 commit comments

Comments
 (0)