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
1919use 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 ) ) ]
7070pub 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 ) ) ]
8495pub 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
99102impl 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 ) ]
129124pub 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 ) ]
355350pub 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}
0 commit comments