pedalkernel/compiler/components/
transformer.rs1use crate::compiler::component::{
4 Component, ComponentEdge, EdgeKind, GraphRole, PinConfig, PinDirection, StampResult,
5};
6use crate::compiler::dyn_node::DynNode;
7use crate::dsl::{TransformerConfig, WindingType};
8use crate::tree::MnaSystem;
9
10use super::impl_component_dyn;
11
12#[derive(Debug, Clone, PartialEq)]
17pub struct TransformerComp {
18 pub config: TransformerConfig,
19}
20
21impl Component for TransformerComp {
22 impl_component_dyn!();
23
24 fn type_tag(&self) -> &'static str {
25 "transformer"
26 }
27
28 fn is_passive(&self) -> bool {
29 true
30 }
31
32 fn pin_config(&self) -> PinConfig {
33 PinConfig {
34 valid_pins: &[
35 "a",
36 "b",
37 "c",
38 "d",
39 "e",
40 "f",
41 "primary.a",
42 "primary.b",
43 "secondary.a",
44 "secondary.b",
45 "tertiary.a",
46 "tertiary.b",
47 "pri.a",
48 "pri.b",
49 "sec.a",
50 "sec.b",
51 "ter.a",
52 "ter.b",
53 "pri_a",
54 "pri_b",
55 "sec_a",
56 "sec_b",
57 "ter_a",
58 "ter_b",
59 "pri_ct",
60 "pri.ct",
61 "sec_ct",
62 "sec.ct",
63 "ct",
64 "primary.ct",
65 "secondary.ct",
66 ],
67 aliases: &[],
68 }
69 }
70
71 fn graph_role(&self) -> GraphRole {
72 GraphRole::Transformer
73 }
74
75 fn stamp_mna(
76 &self,
77 _comp_id: &str,
78 _n1: Option<usize>,
79 _n2: Option<usize>,
80 _mna: &mut MnaSystem,
81 _sample_rate: f64,
82 ) -> StampResult {
83 StampResult::Skip
84 }
85
86 fn make_leaf(&self, _comp_id: &str, sample_rate: f64) -> Option<DynNode> {
87 let config = crate::model_lookup::transformer_config_from_dsl(&self.config);
88 let l_primary = config.primary_inductance;
89 let n = config.turns_ratio;
90 let l_secondary = l_primary / (n * n);
91 let secondary = Box::new(DynNode::Inductor(
92 None,
93 l_secondary as crate::Wave,
94 (2.0 * sample_rate * l_secondary) as crate::Wave,
95 ));
96 if let Some(n_tertiary) = config.tertiary_turns_ratio {
97 let l_tertiary = l_primary / (n_tertiary * n_tertiary);
98 let tertiary = Box::new(DynNode::Inductor(
99 None,
100 l_tertiary as crate::Wave,
101 (2.0 * sample_rate * l_tertiary) as crate::Wave,
102 ));
103 let r_sec = secondary.port_resistance();
104 let r_ter = tertiary.port_resistance();
105 let adaptor =
106 crate::tree::RTypeAdaptor::three_winding_transformer(
107 n as crate::Wave,
108 n_tertiary as crate::Wave,
109 r_sec,
110 r_ter,
111 );
112 Some(DynNode::RType {
113 adaptor,
114 children: vec![secondary, tertiary],
115 })
116 } else {
117 Some(DynNode::TransformerNode(secondary, n as crate::Wave))
118 }
119 }
120
121 fn edges(&self) -> Vec<ComponentEdge> {
122 vec![ComponentEdge {
123 pin_a: "a",
124 pin_b: "b",
125 kind: EdgeKind::Reactive,
126 port_group: None,
127 }]
128 }
129
130 fn footprint_ref(&self) -> (&'static str, &'static str) {
131 match (self.config.primary_type, self.config.secondary_type) {
132 (WindingType::PushPull, WindingType::Standard) => {
133 ("Transformer:Transformer_1P_1S", "T")
134 }
135 (WindingType::Standard, WindingType::CenterTap) => {
136 ("Transformer:Transformer_1P_1S_CT", "T")
137 }
138 (WindingType::PushPull, WindingType::CenterTap) => {
139 ("Transformer:Transformer_1P_CT_1S_CT", "T")
140 }
141 _ => ("Transformer:Transformer_1P_1S", "T"),
142 }
143 }
144
145 fn symbol_name(&self) -> &'static str {
146 "transformer"
147 }
148 fn layout_class(&self) -> &'static str {
149 "transformer"
150 }
151
152 fn signal_adjacencies(&self) -> Vec<(&'static str, &'static str)> {
153 let mut adj = vec![("a", "b"), ("c", "d")];
154 if self.config.has_tertiary() {
155 adj.push(("e", "f"));
156 }
157 adj
158 }
159
160 fn pin_direction(&self, pin: &str) -> PinDirection {
161 if pin.starts_with("pri") || pin == "a" || pin == "b" {
162 PinDirection::Input
163 } else if pin.starts_with("sec")
164 || pin == "c"
165 || pin == "d"
166 || pin.starts_with("ter")
167 || pin == "e"
168 || pin == "f"
169 {
170 PinDirection::Output
171 } else {
172 PinDirection::Bidirectional
173 }
174 }
175
176 fn is_transformer(&self) -> bool {
177 true
178 }
179 fn transformer_config(&self) -> Option<&crate::dsl::TransformerConfig> {
180 Some(&self.config)
181 }
182}