Skip to main content

pedalkernel/compiler/components/
switches.rs

1//! Switch component structs: Switch, RotarySwitch, TriggerInputComp.
2
3use crate::compiler::component::{
4    Component, ControlParam, ControlParamKind, GraphRole, PinConfig, StampResult,
5};
6use crate::compiler::validate::Severity;
7use crate::tree::MnaSystem;
8
9use super::impl_component_dyn;
10
11// ═══════════════════════════════════════════════════════════════════════════
12// Switch
13// ═══════════════════════════════════════════════════════════════════════════
14
15#[derive(Debug, Clone, PartialEq)]
16pub struct Switch {
17    pub positions: usize,
18}
19
20impl Component for Switch {
21    impl_component_dyn!();
22
23    fn type_tag(&self) -> &'static str {
24        "switch"
25    }
26
27    fn is_passive(&self) -> bool {
28        false
29    }
30
31    fn is_control_only(&self) -> bool {
32        true
33    }
34
35    fn pin_config(&self) -> PinConfig {
36        PinConfig {
37            valid_pins: &[],
38            aliases: &[],
39        }
40    }
41
42    fn graph_role(&self) -> GraphRole {
43        GraphRole::Virtual
44    }
45
46    fn stamp_mna(
47        &self,
48        _comp_id: &str,
49        _n1: Option<usize>,
50        _n2: Option<usize>,
51        _mna: &mut MnaSystem,
52        _sample_rate: f64,
53    ) -> StampResult {
54        StampResult::Skip
55    }
56
57    fn validate_values(&self, comp_id: &str) -> Vec<(Severity, String)> {
58        let mut w = Vec::new();
59        if self.positions < 2 {
60            w.push((
61                Severity::Warning,
62                format!(
63                    "Switch '{}' has {} position(s) \u{2014} a switch needs at least 2",
64                    comp_id, self.positions
65                ),
66            ));
67        }
68        w
69    }
70
71    fn controls(&self) -> Vec<ControlParam> {
72        vec![ControlParam {
73            name: "position",
74            kind: ControlParamKind::SwitchPosition {
75                num_positions: self.positions,
76            },
77        }]
78    }
79
80    fn footprint_ref(&self) -> (&'static str, &'static str) {
81        match self.positions {
82            2 => ("Switch:SW_SPDT", "SW"),
83            3 => ("Switch:SW_Rotary4", "SW"),
84            _ => ("Switch:SW_Rotary4", "SW"),
85        }
86    }
87
88    fn symbol_name(&self) -> &'static str {
89        "switch"
90    }
91    fn layout_class(&self) -> &'static str {
92        "switch"
93    }
94}
95
96// ═══════════════════════════════════════════════════════════════════════════
97// RotarySwitch
98// ═══════════════════════════════════════════════════════════════════════════
99
100#[derive(Debug, Clone, PartialEq)]
101pub struct RotarySwitch {
102    pub linked_ids: Vec<String>,
103}
104
105impl Component for RotarySwitch {
106    impl_component_dyn!();
107
108    fn type_tag(&self) -> &'static str {
109        "rotary switch"
110    }
111
112    fn is_passive(&self) -> bool {
113        false
114    }
115
116    fn is_control_only(&self) -> bool {
117        true
118    }
119
120    fn pin_config(&self) -> PinConfig {
121        PinConfig {
122            valid_pins: &[],
123            aliases: &[],
124        }
125    }
126
127    fn graph_role(&self) -> GraphRole {
128        GraphRole::Virtual
129    }
130
131    fn stamp_mna(
132        &self,
133        _comp_id: &str,
134        _n1: Option<usize>,
135        _n2: Option<usize>,
136        _mna: &mut MnaSystem,
137        _sample_rate: f64,
138    ) -> StampResult {
139        StampResult::Skip
140    }
141
142    fn controls(&self) -> Vec<ControlParam> {
143        vec![ControlParam {
144            name: "position",
145            kind: ControlParamKind::SwitchPosition {
146                num_positions: self.linked_ids.len(),
147            },
148        }]
149    }
150
151    fn footprint_ref(&self) -> (&'static str, &'static str) {
152        let positions = self.linked_ids.len().max(2);
153        match positions {
154            2..=4 => ("Switch:SW_Rotary4", "SW"),
155            5..=6 => ("Switch:SW_Rotary6", "SW"),
156            7..=8 => ("Switch:SW_Rotary8", "SW"),
157            _ => ("Switch:SW_Rotary12", "SW"),
158        }
159    }
160
161    fn symbol_name(&self) -> &'static str {
162        "switch"
163    }
164    fn layout_class(&self) -> &'static str {
165        "rotary_switch"
166    }
167}
168
169// ═══════════════════════════════════════════════════════════════════════════
170// TriggerInput
171// ═══════════════════════════════════════════════════════════════════════════
172
173#[derive(Debug, Clone, PartialEq)]
174pub struct TriggerInputComp;
175
176impl Component for TriggerInputComp {
177    impl_component_dyn!();
178
179    fn type_tag(&self) -> &'static str {
180        "trigger_input"
181    }
182
183    fn is_passive(&self) -> bool {
184        false
185    }
186
187    fn is_control_only(&self) -> bool {
188        true
189    }
190
191    fn pin_config(&self) -> PinConfig {
192        PinConfig {
193            valid_pins: &["out"],
194            aliases: &[],
195        }
196    }
197
198    fn graph_role(&self) -> GraphRole {
199        GraphRole::Virtual
200    }
201
202    fn stamp_mna(
203        &self,
204        _comp_id: &str,
205        _n1: Option<usize>,
206        _n2: Option<usize>,
207        _mna: &mut MnaSystem,
208        _sample_rate: f64,
209    ) -> StampResult {
210        StampResult::Skip
211    }
212
213    fn controls(&self) -> Vec<ControlParam> {
214        vec![ControlParam {
215            name: "trigger",
216            kind: ControlParamKind::Trigger,
217        }]
218    }
219
220    fn footprint_ref(&self) -> (&'static str, &'static str) {
221        ("Connector:TestPoint", "TP")
222    }
223
224    fn symbol_name(&self) -> &'static str {
225        "switch"
226    }
227    fn layout_class(&self) -> &'static str {
228        "trigger_input"
229    }
230
231    fn is_trigger(&self) -> bool {
232        true
233    }
234}