1#[derive(Debug)]
2pub struct PinBuilder<'a> {
3 pin_type: &'a str,
4 position: Position,
5 name: &'a str,
6 signals: Option<Vec<String>>,
7 current: Option<usize>,
8}
9
10impl<'a> PinBuilder<'a> {
11 pub fn new(pin_type: &'a str, position: Position, name: &'a str) -> PinBuilder<'a> {
12 PinBuilder {
13 pin_type: pin_type,
14 name: name,
15 position: position,
16 signals: None,
17 current: None,
18 }
19 }
20
21 pub fn signals(&mut self, signals: Vec<String>, current: usize) -> PinBuilder<'a> {
22 PinBuilder {
23 pin_type: self.pin_type,
24 name: self.name,
25 position: self.position,
26 signals: Some(signals),
27 current: Some(current),
28 }
29 }
30
31 pub fn finish(self) -> Pin {
32 let current = match self.current {
33 Some(idx) => match &self.signals {
34 &Some(ref signals) => {
35 if idx < signals.len() {
36 Some(idx)
37 } else {
38 None
39 }
40 }
41 &None => None,
42 },
43 None => None,
44 };
45
46 match self.pin_type {
48 "NC" => Pin::NC {
49 name: String::from(self.name),
50 position: self.position,
51 },
52 "BOOT" => Pin::BOOT {
53 name: String::from(self.name),
54 position: self.position,
55 },
56 "Reset" => Pin::NRST {
57 name: String::from(self.name),
58 position: self.position,
59 },
60 "Power" => Pin::POWER {
61 name: String::from(self.name),
62 position: self.position,
63 },
64 "I/O" => {
65 return Pin::IO {
66 name: String::from(self.name),
67 position: self.position,
68 params: Box::new(IOPin {
69 reset: true,
70 label: String::new(),
71 signals: match self.signals {
72 Some(s) => s,
73 None => Vec::new(),
74 },
75 current: current,
76 }),
77 }
78 }
79 &_ => Pin::NC {
80 name: String::from(self.name),
81 position: self.position,
82 },
83 }
84 }
85}
86
87#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)]
88pub enum Position {
89 Linear(u16),
90 Grid(u8, u8),
91}
92
93#[derive(Serialize, Deserialize, Debug)]
94pub struct IOPin {
95 reset: bool,
96 label: String,
97 signals: Vec<String>,
98 current: Option<usize>,
99}
100
101impl IOPin {
102 pub fn reset(&mut self) {
103 self.reset = true;
104 }
105
106 pub fn is_reset(&self) -> bool {
107 self.reset
108 }
109
110 pub fn set_label(&mut self, label: &str) {
111 self.label = label.to_string();
112 }
113
114 pub fn label(&self) -> &str {
115 &self.label
116 }
117
118 pub fn signals(&self) -> &Vec<String> {
119 &self.signals
120 }
121
122 pub fn select_signal(&mut self, signal: &str) -> bool {
123 let item = self.signals.iter().position(|r| r.as_str() == signal);
124
125 match item {
126 Some(idx) => {
127 self.current = Some(idx);
128 true
129 }
130 None => {
131 self.current = None;
132 false
133 }
134 }
135 }
136
137 pub fn current_signal(&self) -> Option<&str> {
138 match self.current {
139 Some(idx) => Some(&self.signals[idx]),
140 None => None,
141 }
142 }
143}
144
145#[derive(Serialize, Deserialize, Debug)]
146pub enum Pin {
147 NC {
148 name: String,
149 position: Position,
150 },
151 IO {
152 name: String,
153 position: Position,
154 params: Box<IOPin>,
155 },
156 BOOT {
157 name: String,
158 position: Position,
159 },
160 NRST {
161 name: String,
162 position: Position,
163 },
164 POWER {
165 name: String,
166 position: Position,
167 },
168}
169
170impl Pin {
171 pub fn name(&self) -> &str {
172 match *self {
173 Pin::NC { ref name, .. } => &name,
174 Pin::IO { ref name, .. } => &name,
175 Pin::BOOT { ref name, .. } => &name,
176 Pin::NRST { ref name, .. } => &name,
177 Pin::POWER { ref name, .. } => &name,
178 }
179 }
180
181 pub fn position(&self) -> &Position {
182 match *self {
183 Pin::NC { ref position, .. } => &position,
184 Pin::IO { ref position, .. } => &position,
185 Pin::BOOT { ref position, .. } => &position,
186 Pin::NRST { ref position, .. } => &position,
187 Pin::POWER { ref position, .. } => &position,
188 }
189 }
190
191 pub fn params(&self) -> Option<&IOPin> {
192 match *self {
193 Pin::IO { ref params, .. } => Some(params),
194 _ => None,
195 }
196 }
197
198 pub fn params_mut(&mut self) -> Option<&mut IOPin> {
199 match *self {
200 Pin::IO { ref mut params, .. } => Some(params),
201 _ => None,
202 }
203 }
204}
205
206#[cfg(test)]
207mod tests {
208
209 use super::*;
210
211 #[test]
212 fn pin_ok() {
213 let pin = Pin::POWER {
214 name: "VDD".to_string(),
215 position: Position::Grid(4, 3),
216 };
217
218 assert_eq!(pin.name(), "VDD");
219 assert_eq!(*pin.position(), Position::Grid(4, 3));
220 }
221
222 #[test]
223 fn pin_reset() {
224 let pin = Pin::IO {
225 name: "PA3".to_string(),
226 position: Position::Grid(4, 3),
227 params: Box::new(IOPin {
228 reset: true,
229 label: "".to_string(),
230 signals: vec![],
231 current: None,
232 }),
233 };
234
235 let params = pin.params().unwrap();
236 assert_eq!(params.is_reset(), true);
237 }
238
239 #[test]
240 fn pin_label() {
241 let mut pin = Pin::IO {
242 name: "PA3".to_string(),
243 position: Position::Grid(4, 3),
244 params: Box::new(IOPin {
245 reset: true,
246 label: "".to_string(),
247 signals: vec![],
248 current: None,
249 }),
250 };
251
252 let params = pin.params_mut().unwrap();
253 params.set_label("PWM");
254
255 assert_eq!(params.label(), "PWM");
256 }
257
258 #[test]
259 fn pin_signals() {
260 let mut pin = Pin::IO {
261 name: "PA3".to_string(),
262 position: Position::Grid(4, 3),
263 params: Box::new(IOPin {
264 reset: true,
265 label: "".to_string(),
266 signals: vec![
267 "Input".to_string(),
268 "Output".to_string(),
269 "EXTI".to_string(),
270 ],
271 current: Some(0),
272 }),
273 };
274
275 let params = pin.params_mut().unwrap();
276 let signals = params.signals();
277
278 assert_eq!(
279 *signals,
280 vec![
281 "Input".to_string(),
282 "Output".to_string(),
283 "EXTI".to_string(),
284 ]
285 );
286 }
287
288 #[test]
289 fn pin_select_signal_present() {
290 let mut pin = Pin::IO {
291 name: "PA3".to_string(),
292 position: Position::Grid(4, 3),
293 params: Box::new(IOPin {
294 reset: true,
295 label: "".to_string(),
296 signals: vec![
297 "Input".to_string(),
298 "Output".to_string(),
299 "EXTI".to_string(),
300 ],
301 current: Some(1),
302 }),
303 };
304
305 let params = pin.params_mut().unwrap();
306 let ret = params.select_signal("Output");
307
308 assert_eq!(ret, true);
309 assert_eq!(params.current_signal().unwrap(), "Output");
310 }
311
312 #[test]
313 fn pin_select_signal_missing() {
314 let mut pin = Pin::IO {
315 name: "PA3".to_string(),
316 position: Position::Grid(4, 3),
317 params: Box::new(IOPin {
318 reset: true,
319 label: "".to_string(),
320 signals: vec![
321 "Input".to_string(),
322 "Output".to_string(),
323 "EXTI".to_string(),
324 ],
325 current: Some(0),
326 }),
327 };
328
329 let params = pin.params_mut().unwrap();
330 let ret = params.select_signal("Missing");
331
332 assert_eq!(ret, false);
333 assert_eq!(params.current_signal().is_none(), true);
334 }
335
336 #[test]
338 fn build_nc_pin() {
339 let pinbuilder = PinBuilder::new("NC", Position::Linear(10), "NotConnected");
340 let pin = pinbuilder.finish();
341
342 match pin {
343 Pin::NC { .. } => assert!(true),
344 _ => assert!(false),
345 }
346 }
347
348 #[test]
349 fn build_boot_pin() {
350 let pinbuilder = PinBuilder::new("BOOT", Position::Linear(10), "WakeUp");
351 let pin = pinbuilder.finish();
352
353 match pin {
354 Pin::BOOT { .. } => assert!(true),
355 _ => assert!(false),
356 }
357 }
358
359 #[test]
360 fn build_power_pin() {
361 let pinbuilder = PinBuilder::new("Power", Position::Linear(10), "VCC");
362 let pin = pinbuilder.finish();
363
364 match pin {
365 Pin::POWER { .. } => assert!(true),
366 _ => assert!(false),
367 }
368 }
369
370 #[test]
371 fn build_nrst_pin() {
372 let pinbuilder = PinBuilder::new("Reset", Position::Linear(10), "NRST");
373 let pin = pinbuilder.finish();
374
375 match pin {
376 Pin::NRST { .. } => assert!(true),
377 _ => assert!(false),
378 }
379 }
380
381 #[test]
383 fn build_io_pin() {
384 let pinbuilder = PinBuilder::new("I/O", Position::Linear(10), "PA1")
385 .signals(vec![String::from("Input"), String::from("Output")], 0);
386 let pin = pinbuilder.finish();
387
388 match pin {
389 Pin::IO { .. } => assert!(true),
390 _ => assert!(false),
391 }
392 }
393}