1use super::{AnyConfig, Capability, CharSize, Config, Duplex, Rx, Tx};
4use crate::{
5 gpio::AnyPin,
6 gpio::Pin,
7 sercom::*,
8 typelevel::{NoneT, Sealed},
9};
10use core::marker::PhantomData;
11
12pub trait RxpoTxpo {
31 const RXPO: u8;
33
34 const TXPO: u8;
36}
37
38impl<S, RX, TX, RTS, CTS> RxpoTxpo for Pads<S, RX, TX, RTS, CTS>
41where
42 S: Sercom,
43 RX: OptionalPad,
44 TX: OptionalPad,
45 RTS: OptionalPad,
46 CTS: OptionalPad,
47 (RX, TX, RTS, CTS): ShareIoSet,
48 (RX::PadNum, TX::PadNum, RTS::PadNum, CTS::PadNum): RxpoTxpo,
49{
50 const RXPO: u8 = <(RX::PadNum, TX::PadNum, RTS::PadNum, CTS::PadNum)>::RXPO;
51 const TXPO: u8 = <(RX::PadNum, TX::PadNum, RTS::PadNum, CTS::PadNum)>::TXPO;
52}
53
54macro_rules! impl_rxpotxpo {
60 ($RX:ident, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@check_rts_cts, $RX, $TX, $RTS, $CTS); };
62
63 (@check_rts_cts, $RX:ident, $TX:ident, NoneT, NoneT) => { impl_rxpotxpo!(@rxpo, $RX, $TX, NoneT, NoneT); };
66 (@check_rts_cts, $RX:ident, $TX:ident, Pad2, NoneT) => { impl_rxpotxpo!(@rxpo, $RX, $TX, Pad2, NoneT); };
67 (@check_rts_cts, $RX:ident, $TX:ident, NoneT, Pad3) => { impl_rxpotxpo!(@rxpo, $RX, $TX, NoneT, Pad3); };
68 (@check_rts_cts, $RX:ident, $TX:ident, Pad2, Pad3) => { impl_rxpotxpo!(@rxpo, $RX, $TX, Pad2, Pad3); };
69
70 (@check_rts_cts, $RX:ident, $TX:ident, $RTS:ident, $CTS:ident) => { };
72
73 (@rxpo, NoneT, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, NoneT, $TX, $RTS, $CTS, 0); };
76 (@rxpo, Pad0, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, Pad0, $TX, $RTS, $CTS, 0); };
77 (@rxpo, Pad1, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, Pad1, $TX, $RTS, $CTS, 1); };
78 (@rxpo, Pad2, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, Pad2, $TX, $RTS, $CTS, 2); };
79 (@rxpo, Pad3, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, Pad3, $TX, $RTS, $CTS, 3); };
80
81 (@txpo, $RX:ident, NoneT, NoneT, NoneT, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, NoneT, NoneT, NoneT, $RXPO, 0); };
83 (@txpo, $RX:ident, NoneT, Pad2, NoneT, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, NoneT, Pad2, NoneT, $RXPO, 3); };
84 (@txpo, $RX:ident, NoneT, Pad2, Pad3, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, NoneT, Pad2, Pad3, $RXPO, 2); };
85 (@txpo, $RX:ident, Pad0, NoneT, NoneT, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, Pad0, NoneT, NoneT, $RXPO, 0); };
86 (@txpo, $RX:ident, Pad0, Pad2, NoneT, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, Pad0, Pad2, NoneT, $RXPO, 3); };
87 (@txpo, $RX:ident, Pad0, Pad2, Pad3, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, Pad0, Pad2, Pad3, $RXPO, 2); };
88
89 (@txpo, $RX:ident, $TX:ident, $RTS:ident, $CTS:ident, $RXPO:literal) => { };
91
92 (@filter, NoneT, NoneT, $RTS:ident, $CTS:ident, $RXPO:literal, $TXPO:literal) => { }; (@filter, Pad0, Pad0, $RTS:ident, $CTS:ident, $RXPO:literal, $TXPO:literal) => { }; (@filter, Pad2, $TX:ident, Pad2, $CTS:ident, $RXPO:literal, $TXPO:literal) => { }; (@filter, Pad3, $TX:ident, $RTS:ident, Pad3, $RXPO:literal, $TXPO:literal) => { }; (@filter, Pad1, $TX:ident, $RTS:ident, $CTS:ident, 1, 0) => { }; (@filter, Pad1, $TX:ident, $RTS:ident, $CTS:ident, 1, 3) => { }; (@filter, $RX:ident, $TX:ident, $RTS:ident, $CTS:ident, $RXPO:literal, $TXPO:literal) => {
102 impl_rxpotxpo!(@implement, $RX, $TX, $RTS, $CTS, $RXPO, $TXPO);
103 };
104
105 (@implement, $RX:ident, $TX:ident, $RTS:ident, $CTS:ident, $RXPO:literal, $TXPO:literal) => {
107 impl RxpoTxpo for ($RX, $TX, $RTS, $CTS) {
108 const RXPO: u8 = $RXPO;
109 const TXPO: u8 = $TXPO;
110 }
111 };
112}
113
114macro_rules! padnum_permutations {
127 (
130 ( $RX:ident $TX:ident $RTS:ident $CTS:ident ) [ $( $Pads:ident )* ]
131 ) => {
132 impl_rxpotxpo!($RX, $TX, $RTS, $CTS);
133 };
134 (
137 ( $($Perm:ident)* ) [ $($Pads:ident)+ ]
138 ) => {
139 padnum_permutations!( ( $($Perm)* ) [ $($Pads)+ ] [ $($Pads)+ ] );
140 };
141 (
142 ( $($Perm:ident)* ) [ $Head:ident $($Tail:ident)* ] [ $($Pads:ident)+ ]
143 ) => {
144 padnum_permutations!( ( $($Perm)* $Head ) [ $($Pads)+ ] );
147
148 padnum_permutations!( ( $($Perm)* ) [ $($Tail)* ] [ $($Pads)+ ] );
150 };
151 ( ( $($Perm:ident)* ) [ ] [ $($Pads:ident)+ ] ) => { };
153 }
154
155padnum_permutations!( () [NoneT Pad0 Pad1 Pad2 Pad3] );
156
157pub struct Pads<S, RX = NoneT, TX = NoneT, RTS = NoneT, CTS = NoneT>
166where
167 S: Sercom,
168 RX: OptionalPad,
169 TX: OptionalPad,
170 RTS: OptionalPad,
171 CTS: OptionalPad,
172 (RX, TX, RTS, CTS): ShareIoSet,
173{
174 sercom: PhantomData<S>,
175 receive: RX,
176 transmit: TX,
177 ready_to_send: RTS,
178 clear_to_send: CTS,
179}
180
181impl<S: Sercom> Default for Pads<S> {
182 fn default() -> Self {
183 Self {
184 sercom: PhantomData,
185 receive: NoneT,
186 transmit: NoneT,
187 ready_to_send: NoneT,
188 clear_to_send: NoneT,
189 }
190 }
191}
192
193impl<S, RX, TX, RTS, CTS> Pads<S, RX, TX, RTS, CTS>
194where
195 S: Sercom,
196 RX: OptionalPad,
197 TX: OptionalPad,
198 RTS: OptionalPad,
199 CTS: OptionalPad,
200 (RX, TX, RTS, CTS): ShareIoSet,
201{
202 #[inline]
204 pub fn rx<Id>(self, pin: impl AnyPin<Id = Id>) -> Pads<S, Pad<S, Id>, TX, RTS, CTS>
205 where
206 Id: GetPad<S>,
207 (Pad<S, Id>, TX, RTS, CTS): ShareIoSet,
208 Pin<Id, <Id as GetPad<S>>::PinMode>: IsPad,
209 {
210 Pads {
211 sercom: self.sercom,
212 receive: pin.into().into_mode(),
213 transmit: self.transmit,
214 ready_to_send: self.ready_to_send,
215 clear_to_send: self.clear_to_send,
216 }
217 }
218
219 #[inline]
221 pub fn tx<Id>(self, pin: impl AnyPin<Id = Id>) -> Pads<S, RX, Pad<S, Id>, RTS, CTS>
222 where
223 Id: GetPad<S>,
224 (RX, Pad<S, Id>, RTS, CTS): ShareIoSet,
225 Pin<Id, <Id as GetPad<S>>::PinMode>: IsPad,
226 {
227 Pads {
228 sercom: self.sercom,
229 receive: self.receive,
230 transmit: pin.into().into_mode(),
231 ready_to_send: self.ready_to_send,
232 clear_to_send: self.clear_to_send,
233 }
234 }
235
236 #[inline]
238 pub fn rts<Id>(self, pin: impl AnyPin<Id = Id>) -> Pads<S, RX, TX, Pad<S, Id>, CTS>
239 where
240 Id: GetPad<S>,
241 (RX, TX, Pad<S, Id>, CTS): ShareIoSet,
242 Pin<Id, <Id as GetPad<S>>::PinMode>: IsPad,
243 {
244 Pads {
245 sercom: self.sercom,
246 receive: self.receive,
247 transmit: self.transmit,
248 ready_to_send: pin.into().into_mode(),
249 clear_to_send: self.clear_to_send,
250 }
251 }
252
253 #[inline]
255 pub fn cts<Id>(self, pin: impl AnyPin<Id = Id>) -> Pads<S, RX, TX, RTS, Pad<S, Id>>
256 where
257 Id: GetPad<S>,
258 (RX, TX, RTS, Pad<S, Id>): ShareIoSet,
259 Pin<Id, <Id as GetPad<S>>::PinMode>: IsPad,
260 {
261 Pads {
262 sercom: self.sercom,
263 receive: self.receive,
264 transmit: self.transmit,
265 ready_to_send: self.ready_to_send,
266 clear_to_send: pin.into().into_mode(),
267 }
268 }
269
270 #[inline]
272 pub fn free(self) -> (RX, TX, RTS, CTS) {
273 (
274 self.receive,
275 self.transmit,
276 self.ready_to_send,
277 self.clear_to_send,
278 )
279 }
280}
281
282pub type PadsFromIds<S, RX = NoneT, TX = NoneT, RTS = NoneT, CTS = NoneT> = Pads<
311 S,
312 <RX as GetOptionalPad<S>>::Pad,
313 <TX as GetOptionalPad<S>>::Pad,
314 <RTS as GetOptionalPad<S>>::Pad,
315 <CTS as GetOptionalPad<S>>::Pad,
316>;
317
318pub trait PadSet: Sealed {
339 type Sercom: Sercom;
340 type Rx: OptionalPad;
341 type Tx: OptionalPad;
342 type Rts: OptionalPad;
343 type Cts: OptionalPad;
344}
345
346impl<S, RX, TX, RTS, CTS> Sealed for Pads<S, RX, TX, RTS, CTS>
347where
348 S: Sercom,
349 RX: OptionalPad,
350 TX: OptionalPad,
351 RTS: OptionalPad,
352 CTS: OptionalPad,
353 (RX, TX, RTS, CTS): ShareIoSet,
354{
355}
356
357impl<S, RX, TX, RTS, CTS> PadSet for Pads<S, RX, TX, RTS, CTS>
358where
359 S: Sercom,
360 RX: OptionalPad,
361 TX: OptionalPad,
362 RTS: OptionalPad,
363 CTS: OptionalPad,
364 (RX, TX, RTS, CTS): ShareIoSet,
365{
366 type Sercom = S;
367 type Rx = RX;
368 type Tx = TX;
369 type Rts = RTS;
370 type Cts = CTS;
371}
372
373pub trait ValidPads: PadSet + RxpoTxpo {
385 type Capability: Capability;
386}
387
388impl<S, RX, RTS> ValidPads for Pads<S, RX, NoneT, RTS, NoneT>
389where
390 S: Sercom,
391 RX: SomePad,
392 RTS: OptionalPad,
393 (RX, NoneT, RTS, NoneT): ShareIoSet,
394 Self: PadSet + RxpoTxpo,
395{
396 type Capability = Rx;
397}
398
399impl<S, TX, CTS> ValidPads for Pads<S, NoneT, TX, NoneT, CTS>
400where
401 S: Sercom,
402 TX: SomePad,
403 CTS: OptionalPad,
404 (NoneT, TX, NoneT, CTS): ShareIoSet,
405 Self: PadSet + RxpoTxpo,
406{
407 type Capability = Tx;
408}
409
410impl<S, RX, TX, RTS, CTS> ValidPads for Pads<S, RX, TX, RTS, CTS>
411where
412 S: Sercom,
413 RX: SomePad,
414 TX: SomePad,
415 RTS: OptionalPad,
416 CTS: OptionalPad,
417 (RX, TX, RTS, CTS): ShareIoSet,
418 Self: PadSet + RxpoTxpo,
419{
420 type Capability = Duplex;
421}
422
423pub trait ValidConfig: AnyConfig {}
432
433impl<P: ValidPads, C: CharSize> ValidConfig for Config<P, C> {}