1use std::fmt;
11use std::str::FromStr;
12
13mod data;
14pub mod pack;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
18pub enum Port {
19 A,
20 B,
21 C,
22 D,
23 E,
24 F,
25 G,
26 H,
27}
28
29impl Port {
30 pub const fn letter(self) -> char {
32 match self {
33 Port::A => 'A',
34 Port::B => 'B',
35 Port::C => 'C',
36 Port::D => 'D',
37 Port::E => 'E',
38 Port::F => 'F',
39 Port::G => 'G',
40 Port::H => 'H',
41 }
42 }
43
44 const fn from_letter(c: char) -> Option<Port> {
45 match c {
46 'A' | 'a' => Some(Port::A),
47 'B' | 'b' => Some(Port::B),
48 'C' | 'c' => Some(Port::C),
49 'D' | 'd' => Some(Port::D),
50 'E' | 'e' => Some(Port::E),
51 'F' | 'f' => Some(Port::F),
52 'G' | 'g' => Some(Port::G),
53 'H' | 'h' => Some(Port::H),
54 _ => None,
55 }
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
61pub struct Pin {
62 pub port: Port,
63 pub number: u8,
64}
65
66impl Pin {
67 pub const fn new(port: Port, number: u8) -> Pin {
68 Pin { port, number }
69 }
70}
71
72impl fmt::Display for Pin {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 write!(f, "P{}{}", self.port.letter(), self.number)
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct ParsePinError(String);
81
82impl fmt::Display for ParsePinError {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 write!(f, "invalid pin name: {:?} (expected e.g. \"PA7\")", self.0)
85 }
86}
87
88impl std::error::Error for ParsePinError {}
89
90impl FromStr for Pin {
91 type Err = ParsePinError;
92
93 fn from_str(s: &str) -> Result<Pin, ParsePinError> {
94 let err = || ParsePinError(s.to_string());
95 let rest = s
96 .strip_prefix('P')
97 .or_else(|| s.strip_prefix('p'))
98 .ok_or_else(err)?;
99 let mut chars = rest.chars();
100 let port = chars.next().and_then(Port::from_letter).ok_or_else(err)?;
101 let number: u8 = chars.as_str().parse().map_err(|_| err())?;
102 if number > 15 {
103 return Err(err());
104 }
105 Ok(Pin { port, number })
106 }
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112pub struct AfMapping {
113 pub pin: Pin,
114 pub af: u8,
115 pub peripheral: &'static str,
117 pub signal: &'static str,
119}
120
121#[derive(Debug, Clone, Copy)]
123pub struct Database {
124 entries: &'static [AfMapping],
125}
126
127impl Database {
128 pub const fn f446re() -> Database {
130 Database {
131 entries: data::F446RE,
132 }
133 }
134
135 pub const fn f411re() -> Database {
138 Database {
139 entries: data::F411RE,
140 }
141 }
142
143 pub fn has_peripheral(&self, peripheral: &str) -> bool {
146 self.entries.iter().any(|m| m.peripheral == peripheral)
147 }
148
149 pub fn lookup(&self, pin: Pin, af: u8) -> impl Iterator<Item = &AfMapping> {
155 self.entries
156 .iter()
157 .filter(move |m| m.pin == pin && m.af == af)
158 }
159
160 pub fn alt_functions(&self, pin: Pin) -> impl Iterator<Item = &AfMapping> {
162 self.entries.iter().filter(move |m| m.pin == pin)
163 }
164
165 pub fn pins(&self) -> Vec<Pin> {
168 let mut pins: Vec<Pin> = self.entries.iter().map(|m| m.pin).collect();
169 pins.sort_unstable();
170 pins.dedup();
171 pins
172 }
173
174 pub fn find_af(&self, pin: Pin, peripheral: &str, signal: &str) -> Option<u8> {
177 self.entries
178 .iter()
179 .find(|m| m.pin == pin && m.peripheral == peripheral && m.signal == signal)
180 .map(|m| m.af)
181 }
182}
183
184#[cfg(test)]
185mod tests;