1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use super::{ExtendedMultiplexing, ValueRanges};
use crate::compat::Name;
impl ExtendedMultiplexing {
pub(crate) fn new(
message_id: u32,
signal_name: Name,
multiplexer_switch: Name,
value_ranges: ValueRanges,
) -> Self {
Self {
message_id,
signal_name,
multiplexer_switch,
value_ranges,
}
}
/// Returns the CAN message ID this extended multiplexing entry applies to.
///
/// # Examples
///
/// ```rust,no_run
/// use dbc_rs::Dbc;
///
/// let dbc = Dbc::parse(r#"VERSION "1.0"
///
/// BU_: ECM
///
/// BO_ 500 MuxMessage : 8 ECM
/// SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
/// SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
///
/// SG_MUL_VAL_ 500 Signal_A Mux1 5-10 ;
/// "#)?;
///
/// let entry = dbc.extended_multiplexing_for_message(500).next().unwrap();
/// assert_eq!(entry.message_id(), 500);
/// # Ok::<(), dbc_rs::Error>(())
/// ```
#[inline]
#[must_use = "return value should be used"]
pub fn message_id(&self) -> u32 {
self.message_id
}
/// Returns the name of the signal this extended multiplexing entry controls.
///
/// The signal will only be decoded when the multiplexer switch value falls
/// within one of the defined value ranges.
///
/// # Examples
///
/// ```rust,no_run
/// use dbc_rs::Dbc;
///
/// let dbc = Dbc::parse(r#"VERSION "1.0"
///
/// BU_: ECM
///
/// BO_ 500 MuxMessage : 8 ECM
/// SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
/// SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
///
/// SG_MUL_VAL_ 500 Signal_A Mux1 5-10 ;
/// "#)?;
///
/// let entry = dbc.extended_multiplexing_for_message(500).next().unwrap();
/// assert_eq!(entry.signal_name(), "Signal_A");
/// # Ok::<(), dbc_rs::Error>(())
/// ```
#[inline]
#[must_use = "return value should be used"]
pub fn signal_name(&self) -> &str {
self.signal_name.as_str()
}
/// Returns the name of the multiplexer switch signal that controls activation.
///
/// The multiplexer switch is a signal marked with `M` in the DBC file. When
/// decoding, the switch's current value is compared against the value ranges
/// to determine if the controlled signal should be decoded.
///
/// # Examples
///
/// ```rust,no_run
/// use dbc_rs::Dbc;
///
/// let dbc = Dbc::parse(r#"VERSION "1.0"
///
/// BU_: ECM
///
/// BO_ 500 MuxMessage : 8 ECM
/// SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
/// SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
///
/// SG_MUL_VAL_ 500 Signal_A Mux1 5-10 ;
/// "#)?;
///
/// let entry = dbc.extended_multiplexing_for_message(500).next().unwrap();
/// assert_eq!(entry.multiplexer_switch(), "Mux1");
/// # Ok::<(), dbc_rs::Error>(())
/// ```
#[inline]
#[must_use = "return value should be used"]
pub fn multiplexer_switch(&self) -> &str {
self.multiplexer_switch.as_str()
}
/// Returns the value ranges that activate the controlled signal.
///
/// Each tuple `(min, max)` defines an inclusive range. The signal is decoded
/// when the multiplexer switch value falls within **any** of these ranges.
///
/// For example, `[(0, 5), (10, 15)]` means the signal is active when the
/// switch value is 0-5 OR 10-15.
///
/// # Examples
///
/// ```rust,no_run
/// use dbc_rs::Dbc;
///
/// let dbc = Dbc::parse(r#"VERSION "1.0"
///
/// BU_: ECM
///
/// BO_ 500 MuxMessage : 8 ECM
/// SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
/// SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
///
/// SG_MUL_VAL_ 500 Signal_A Mux1 0-5,10-15 ;
/// "#)?;
///
/// let entry = dbc.extended_multiplexing_for_message(500).next().unwrap();
/// let ranges = entry.value_ranges();
///
/// // Check if switch value 3 activates the signal
/// let switch_value = 3u64;
/// let is_active = ranges.iter().any(|(min, max)| switch_value >= *min && switch_value <= *max);
/// assert!(is_active);
/// # Ok::<(), dbc_rs::Error>(())
/// ```
#[inline]
#[must_use = "return value should be used"]
pub fn value_ranges(&self) -> &[(u64, u64)] {
self.value_ranges.as_slice()
}
}