stm32builder/
gpio_bank.rs

1//! Gpio bank input and output types
2
3use crate::{
4    api::{Convertible, PeripheralOnBus, Validatable},
5    device::DeviceIn,
6    gpio_pin::{GpioPinIn, GpioPinOut},
7    peripheral_bus::{PeripheralBusIn, PeripheralBusOut},
8    types::{DeviceId, Valid},
9};
10use serde::de::{Deserialize, Deserializer};
11use serde_derive::{Deserialize, Serialize};
12
13/// A gpio bank (from device file).
14#[derive(Debug, Deserialize)]
15pub struct GpioBankIn {
16    /// The gpio bank name.
17    pub name: String,
18    /// The gpio bank pins.
19    #[serde(deserialize_with = "seq_of_pins_as_string_or_struct")]
20    pub pins: Vec<GpioPinIn>,
21    /// This gpio bank is valid
22    #[serde(flatten)]
23    pub valid: Valid,
24    /// The rcc controlled bus this bank is connected to.
25    pub bus: PeripheralBusIn,
26}
27
28/// A gpio bank (to template).
29#[allow(non_snake_case)]
30#[derive(Debug, PartialEq, Serialize)]
31pub struct GpioBankOut {
32    /// The gpio bank type (aka GPIOA).
33    pub GPIO: String,
34    /// The gpio bank name (aka gpioa).
35    pub gpio: String,
36    /// The gpio bank pins.
37    pub pins: Vec<GpioPinOut>,
38}
39
40impl Convertible for GpioBankIn {
41    type Output = GpioBankOut;
42
43    /// Convert to outputable gpio bank.
44    fn to_output(&self, id: &DeviceId, device: &DeviceIn) -> GpioBankOut {
45        GpioBankOut {
46            GPIO: self.name.clone().to_uppercase(),
47            gpio: self.name.clone().to_lowercase(),
48            pins: self
49                .pins
50                .iter()
51                .filter(|pin| pin.is_valid_for(&id, &device))
52                .map(|pin| pin.to_output(&id, &device))
53                .collect(),
54        }
55    }
56}
57
58impl Validatable for GpioBankIn {
59    fn is_valid_for(&self, id: &DeviceId, device: &DeviceIn) -> bool {
60        self.valid.is_valid_for(&id, &device)
61    }
62}
63
64impl PeripheralOnBus for GpioBankIn {
65    fn peripheral_bus(&self) -> PeripheralBusOut {
66        PeripheralBusOut {
67            peripheral: self.name.clone().to_lowercase(),
68            bus: self.bus.name.clone(),
69            field: self.bus.field.clone(),
70            resetable: self.bus.resetable,
71        }
72    }
73}
74
75fn seq_of_pins_as_string_or_struct<'de, D>(deserializer: D) -> Result<Vec<GpioPinIn>, D::Error>
76where
77    D: Deserializer<'de>,
78{
79    #[derive(Deserialize)]
80    struct Wrapper(
81        #[serde(deserialize_with = "crate::helpers::serde::string_or_struct")] GpioPinIn,
82    );
83
84    let v = Vec::deserialize(deserializer)?;
85    Ok(v.into_iter().map(|Wrapper(a)| a).collect())
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91    use crate::tests::*;
92    use crate::types::*;
93
94    fn bank_under_test() -> GpioBankOut {
95        GpioBankIn {
96            name: "gpioa".to_owned(),
97            pins: vec![
98                GpioPinIn {
99                    name: "pa0".to_owned(),
100                    initial_mode: None,
101                    valid: Valid::default(),
102                },
103                GpioPinIn {
104                    name: "pa1".to_owned(),
105                    initial_mode: None,
106                    valid: Valid::default(),
107                },
108            ],
109            valid: Valid::default(),
110            bus: PeripheralBusIn {
111                name: Bus::AHB,
112                field: "IOPA".to_string(),
113                resetable: true,
114            },
115        }
116        .to_output(&valid_device_id(), &valid_device_in())
117    }
118
119    #[test]
120    fn has_a_type() {
121        assert_eq!(bank_under_test().GPIO, "GPIOA");
122    }
123    #[test]
124    fn has_a_name() {
125        assert_eq!(bank_under_test().gpio, "gpioa");
126    }
127    #[test]
128    fn has_some_pins() {
129        let pins = bank_under_test().pins;
130        let mut pins = pins.iter();
131        assert_eq!(pins.next().unwrap().PIN, "PA0");
132        assert_eq!(pins.next().unwrap().PIN, "PA1");
133        assert!(pins.next().is_none());
134    }
135}