1use core::marker::PhantomData;
2
3use crate::gpio::{bank0::*, pin::pin_sealed::TypeLevelPinId, AnyPin, FunctionUart};
4use crate::pac::{UART0, UART1};
5use crate::typelevel::{OptionT, OptionTNone, OptionTSome, Sealed};
6
7use super::UartDevice;
8
9macro_rules! pin_validation {
11 ($p:ident) => {
12 paste::paste!{
13 #[doc = "Indicates a valid " $p " pin for UART0 or UART1"]
14 pub trait [<ValidPinId $p>]<UART: UartDevice>: Sealed {}
15
16 #[doc = "Indicates a valid " $p " pin for UART0 or UART1"]
17 pub trait [<ValidPin $p>]<UART: UartDevice>: Sealed {}
18
19 impl<T, U: UartDevice> [<ValidPin $p>]<U> for T
20 where
21 T: AnyPin<Function = FunctionUart>,
22 T::Id: [<ValidPinId $p>]<U>,
23 {
24 }
25
26 #[doc = "A runtime validated " $p " pin for uart."]
27 pub struct [<ValidatedPin $p>]<P, Uart>(P, PhantomData<Uart>);
28 impl<P, UART: UartDevice> Sealed for [<ValidatedPin $p>]<P, UART> {}
29 impl<P, UART: UartDevice> [<ValidPin $p>]<UART> for [<ValidatedPin $p>]<P, UART> {}
30 impl<P, U> [<ValidatedPin $p>]<P, U>
31 where
32 P: AnyPin<Function = FunctionUart>,
33 U: UartDevice,
34 {
35 #[doc = "Will err if the pin cannot be used as a " $p " pin for that Uart."]
38 pub fn validate(p: P, _u: &U) -> Result<Self, P> {
39 if [<$p:upper>].contains(&(p.borrow().id().num, U::ID)) &&
40 p.borrow().id().bank == crate::gpio::DynBankId::Bank0 {
41 Ok(Self(p, PhantomData))
42 } else {
43 Err(p)
44 }
45 }
46 }
47
48 #[doc = "Indicates a valid optional " $p " pin for UART0 or UART1"]
49 pub trait [<ValidOption $p>]<U>: OptionT {}
50
51 impl<U: UartDevice> [<ValidOption $p>]<U> for OptionTNone {}
52 impl<U, T> [<ValidOption $p>]<U> for OptionTSome<T>
53 where
54 U: UartDevice,
55 T: [<ValidPin $p>]<U>,
56 {
57 }
58 }
59 };
60 ($($p:ident),*) => {
61 $(
62 pin_validation!($p);
63 )*
64 };
65}
66pin_validation!(Tx, Rx, Cts, Rts);
67
68macro_rules! impl_valid_uart {
69 ($($uart:ident: {
70 tx: [$($tx:ident),*],
71 rx: [$($rx:ident),*],
72 cts: [$($cts:ident),*],
73 rts: [$($rts:ident),*],
74 }),*) => {
75 $(
76 $(impl ValidPinIdTx<$uart> for $tx {})*
77 $(impl ValidPinIdRx<$uart> for $rx {})*
78 $(impl ValidPinIdCts<$uart> for $cts {})*
79 $(impl ValidPinIdRts<$uart> for $rts {})*
80 )*
81 const RX: &[(u8, usize)] = &[$($(($rx::ID.num, $uart::ID)),*),*];
82 const TX: &[(u8, usize)] = &[$($(($tx::ID.num, $uart::ID)),*),*];
83 const CTS: &[(u8, usize)] = &[$($(($cts::ID.num, $uart::ID)),*),*];
84 const RTS: &[(u8, usize)] = &[$($(($rts::ID.num, $uart::ID)),*),*];
85 };
86}
87
88impl_valid_uart!(
89 UART0: {
90 tx: [Gpio0, Gpio12, Gpio16, Gpio28],
91 rx: [Gpio1, Gpio13, Gpio17, Gpio29],
92 cts: [Gpio2, Gpio14, Gpio18],
93 rts: [Gpio3, Gpio15, Gpio19],
94 },
95 UART1: {
96 tx: [Gpio4, Gpio8, Gpio20, Gpio24],
97 rx: [Gpio5, Gpio9, Gpio21, Gpio25],
98 cts: [Gpio6, Gpio10, Gpio22, Gpio26],
99 rts: [Gpio7, Gpio11, Gpio23, Gpio27],
100 }
101);
102
103pub trait ValidUartPinout<U: UartDevice>: Sealed {
105 #[allow(missing_docs)]
106 type Rx: ValidOptionRx<U>;
107 #[allow(missing_docs)]
108 type Tx: ValidOptionTx<U>;
109 #[allow(missing_docs)]
110 type Cts: ValidOptionCts<U>;
111 #[allow(missing_docs)]
112 type Rts: ValidOptionRts<U>;
113}
114
115impl<Uart, Tx, Rx> ValidUartPinout<Uart> for (Tx, Rx)
116where
117 Uart: UartDevice,
118 Tx: ValidPinTx<Uart>,
119 Rx: ValidPinRx<Uart>,
120{
121 type Tx = OptionTSome<Tx>;
122 type Rx = OptionTSome<Rx>;
123 type Cts = OptionTNone;
124 type Rts = OptionTNone;
125}
126
127impl<Uart, Tx, Rx, Cts, Rts> ValidUartPinout<Uart> for (Tx, Rx, Cts, Rts)
128where
129 Uart: UartDevice,
130 Tx: ValidPinTx<Uart>,
131 Rx: ValidPinRx<Uart>,
132 Cts: ValidPinCts<Uart>,
133 Rts: ValidPinRts<Uart>,
134{
135 type Rx = OptionTSome<Rx>;
136 type Tx = OptionTSome<Tx>;
137 type Cts = OptionTSome<Cts>;
138 type Rts = OptionTSome<Rts>;
139}
140
141pub struct Pins<Tx, Rx, Cts, Rts> {
169 #[allow(missing_docs)]
170 pub tx: Tx,
171 #[allow(missing_docs)]
172 pub rx: Rx,
173 #[allow(missing_docs)]
174 pub cts: Cts,
175 #[allow(missing_docs)]
176 pub rts: Rts,
177}
178
179impl Default for Pins<OptionTNone, OptionTNone, OptionTNone, OptionTNone> {
180 fn default() -> Self {
181 Self {
182 tx: OptionTNone,
183 rx: OptionTNone,
184 rts: OptionTNone,
185 cts: OptionTNone,
186 }
187 }
188}
189
190impl<Tx, Rx, Cts, Rts> Pins<Tx, Rx, Cts, Rts> {
191 pub fn tx<NewTx>(self, tx: NewTx) -> Pins<OptionTSome<NewTx>, Rx, Cts, Rts> {
193 Pins {
194 tx: OptionTSome(tx),
195 rx: self.rx,
196 rts: self.rts,
197 cts: self.cts,
198 }
199 }
200 pub fn rx<NewRx>(self, rx: NewRx) -> Pins<Tx, OptionTSome<NewRx>, Cts, Rts> {
202 Pins {
203 tx: self.tx,
204 rx: OptionTSome(rx),
205 rts: self.rts,
206 cts: self.cts,
207 }
208 }
209 pub fn cts<NewCts>(self, cts: NewCts) -> Pins<Tx, Rx, OptionTSome<NewCts>, Rts> {
211 Pins {
212 tx: self.tx,
213 rx: self.rx,
214 rts: self.rts,
215 cts: OptionTSome(cts),
216 }
217 }
218 pub fn rts<NewRts>(self, rts: NewRts) -> Pins<Tx, Rx, Cts, OptionTSome<NewRts>> {
220 Pins {
221 tx: self.tx,
222 rx: self.rx,
223 rts: OptionTSome(rts),
224 cts: self.cts,
225 }
226 }
227}
228
229impl<Tx, Rx, Cts, Rts> Sealed for Pins<Tx, Rx, Cts, Rts> {}
230impl<Uart, Tx, Rx, Cts, Rts> ValidUartPinout<Uart> for Pins<Tx, Rx, Cts, Rts>
231where
232 Uart: UartDevice,
233 Tx: ValidOptionTx<Uart>,
234 Rx: ValidOptionRx<Uart>,
235 Cts: ValidOptionCts<Uart>,
236 Rts: ValidOptionRts<Uart>,
237{
238 type Rx = Rx;
239 type Tx = Tx;
240 type Cts = Cts;
241 type Rts = Rts;
242}