dbc_rs/extended_multiplexing/
mod.rs

1//! Extended Multiplexing definition (SG_MUL_VAL_)
2//!
3//! Represents extended multiplexing entries that define which multiplexer switch values
4//! activate specific multiplexed signals.
5//!
6//! Extended multiplexing allows signals to be active for ranges of multiplexer switch
7//! values, rather than just a single value (as with basic `m0`, `m1` multiplexing).
8//!
9//! # DBC Format
10//!
11//! ```text
12//! SG_MUL_VAL_ <message_id> <signal_name> <switch_name> <range1>,<range2>,... ;
13//! ```
14//!
15//! Where each range is `min-max` (inclusive).
16//!
17//! # Example
18//!
19//! ```text
20//! SG_MUL_VAL_ 500 Signal_A Mux1 0-5,10-15 ;
21//! ```
22//!
23//! This means `Signal_A` is decoded when `Mux1` has a value between 0-5 OR 10-15.
24
25use crate::compat::{Name, Vec};
26
27mod impls;
28mod parse;
29
30/// A value range (min, max) for extended multiplexing
31type ValueRange = (u64, u64);
32/// Maximum 64 ranges per extended multiplexing entry
33type ValueRanges = Vec<ValueRange, 64>;
34
35#[cfg(feature = "std")]
36mod builder;
37
38#[cfg(feature = "std")]
39pub use builder::ExtendedMultiplexingBuilder;
40
41/// Extended Multiplexing definition (SG_MUL_VAL_)
42///
43/// Represents extended multiplexing entries that define which multiplexer switch values
44/// activate specific multiplexed signals. This is an extension to basic multiplexing
45/// (`m0`, `m1`, etc.) that allows signals to be active for **ranges** of switch values.
46///
47/// # When to Use Extended Multiplexing
48///
49/// Extended multiplexing is useful when:
50/// - A signal should be active for multiple switch values (e.g., 0-5 and 10-15)
51/// - Multiple multiplexer switches control a single signal (AND logic)
52/// - The activation pattern is more complex than a single value
53///
54/// # Examples
55///
56/// ```rust,no_run
57/// use dbc_rs::Dbc;
58///
59/// let dbc = Dbc::parse(r#"VERSION "1.0"
60///
61/// BU_: ECM
62///
63/// BO_ 500 MuxMessage : 8 ECM
64///  SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
65///  SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
66///
67/// SG_MUL_VAL_ 500 Signal_A Mux1 5-10 ;
68/// "#)?;
69///
70/// // Get extended multiplexing entries for message 500
71/// let entries: Vec<_> = dbc.extended_multiplexing_for_message(500).collect();
72/// assert_eq!(entries.len(), 1);
73///
74/// let entry = entries[0];
75/// assert_eq!(entry.message_id(), 500);
76/// assert_eq!(entry.signal_name(), "Signal_A");
77/// assert_eq!(entry.multiplexer_switch(), "Mux1");
78/// assert_eq!(entry.value_ranges(), &[(5, 10)]);
79///
80/// // Decode - Signal_A will only be decoded when Mux1 is 5-10
81/// let payload = [0x07, 0x00, 0xE8, 0x03, 0x00, 0x00, 0x00, 0x00]; // Mux1=7
82/// let decoded = dbc.decode(500, &payload, false)?;
83/// assert!(decoded.iter().any(|s| s.name == "Signal_A"));
84/// # Ok::<(), dbc_rs::Error>(())
85/// ```
86///
87/// # Multiple Ranges
88///
89/// A signal can be active for multiple non-contiguous ranges:
90///
91/// ```text
92/// SG_MUL_VAL_ 500 Signal_A Mux1 0-5,10-15,20-25 ;
93/// ```
94///
95/// # Multiple Switches (AND Logic)
96///
97/// When multiple `SG_MUL_VAL_` entries exist for the same signal with different
98/// switches, ALL switches must match their respective ranges for the signal to
99/// be decoded (AND logic):
100///
101/// ```text
102/// SG_MUL_VAL_ 500 Signal_A Mux1 5-10 ;
103/// SG_MUL_VAL_ 500 Signal_A Mux2 20-25 ;
104/// ```
105///
106/// Here, `Signal_A` is only decoded when `Mux1` is 5-10 AND `Mux2` is 20-25.
107#[derive(Debug, Clone, PartialEq)]
108pub struct ExtendedMultiplexing {
109    message_id: u32,
110    signal_name: Name,
111    multiplexer_switch: Name,
112    value_ranges: ValueRanges,
113}