1use atsamd_hal_macros::hal_cfg;
4
5use super::{AnyConfig, Capability, CharSize, Config, Duplex, Rx, Tx};
6use crate::{
7 sercom::*,
8 typelevel::{NoneT, Sealed},
9};
10use core::marker::PhantomData;
11
12#[hal_cfg("sercom0-d21")]
13use crate::gpio::AnyPin;
14
15pub trait RxpoTxpo {
34 const RXPO: u8;
36
37 const TXPO: u8;
39}
40
41impl<S, RX, TX, RTS, CTS> RxpoTxpo for Pads<S, RX, TX, RTS, CTS>
44where
45 S: Sercom,
46 RX: OptionalPad,
47 TX: OptionalPad,
48 RTS: OptionalPad,
49 CTS: OptionalPad,
50 (RX::PadNum, TX::PadNum, RTS::PadNum, CTS::PadNum): RxpoTxpo,
51{
52 const RXPO: u8 = <(RX::PadNum, TX::PadNum, RTS::PadNum, CTS::PadNum)>::RXPO;
53 const TXPO: u8 = <(RX::PadNum, TX::PadNum, RTS::PadNum, CTS::PadNum)>::TXPO;
54}
55
56macro_rules! impl_rxpotxpo {
62 ($RX:ident, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@check_rts_cts, $RX, $TX, $RTS, $CTS); };
64
65 (@check_rts_cts, $RX:ident, $TX:ident, NoneT, NoneT) => { impl_rxpotxpo!(@rxpo, $RX, $TX, NoneT, NoneT); };
68 (@check_rts_cts, $RX:ident, $TX:ident, Pad2, NoneT) => { impl_rxpotxpo!(@rxpo, $RX, $TX, Pad2, NoneT); };
69 (@check_rts_cts, $RX:ident, $TX:ident, NoneT, Pad3) => { impl_rxpotxpo!(@rxpo, $RX, $TX, NoneT, Pad3); };
70 (@check_rts_cts, $RX:ident, $TX:ident, Pad2, Pad3) => { impl_rxpotxpo!(@rxpo, $RX, $TX, Pad2, Pad3); };
71
72 (@check_rts_cts, $RX:ident, $TX:ident, $RTS:ident, $CTS:ident) => { };
74
75 (@rxpo, NoneT, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, NoneT, $TX, $RTS, $CTS, 0); };
78 (@rxpo, Pad0, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, Pad0, $TX, $RTS, $CTS, 0); };
79 (@rxpo, Pad1, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, Pad1, $TX, $RTS, $CTS, 1); };
80 (@rxpo, Pad2, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, Pad2, $TX, $RTS, $CTS, 2); };
81 (@rxpo, Pad3, $TX:ident, $RTS:ident, $CTS:ident) => { impl_rxpotxpo!(@txpo, Pad3, $TX, $RTS, $CTS, 3); };
82
83 (@txpo, $RX:ident, NoneT, NoneT, $CTS:ident, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, NoneT, NoneT, $CTS, $RXPO, 0); };
85 (@txpo, $RX:ident, NoneT, Pad2, $CTS:ident, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, NoneT, Pad2, $CTS, $RXPO, 2); };
86 (@txpo, $RX:ident, Pad0, NoneT, $CTS:ident, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, Pad0, NoneT, $CTS, $RXPO, 0); };
87 (@txpo, $RX:ident, Pad2, NoneT, $CTS:ident, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, Pad2, NoneT, $CTS, $RXPO, 1); };
88 (@txpo, $RX:ident, Pad0, Pad2, $CTS:ident, $RXPO:literal) => { impl_rxpotxpo!(@filter, $RX, Pad0, Pad2, $CTS, $RXPO, 2); };
89
90 (@txpo, $RX:ident, $TX:ident, $RTS:ident, $CTS:ident, $RXPO:literal) => { };
92
93 (@filter, NoneT, NoneT, $RTS:ident, $CTS:ident, $RXPO:literal, $TXPO:literal) => { }; (@filter, Pad0, Pad0, $RTS:ident, $CTS:ident, $RXPO:literal, $TXPO:literal) => { }; (@filter, Pad2, Pad2, $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, 0, $TXPO:literal) => { }; (@filter, Pad3, $TX:ident, $RTS:ident, $CTS:ident, 1, $TXPO:literal) => { }; (@filter, $RX:ident, $TX:ident, $RTS:ident, $CTS:ident, $RXPO:literal, $TXPO:literal) => {
104 impl_rxpotxpo!(@implement, $RX, $TX, $RTS, $CTS, $RXPO, $TXPO);
105 };
106
107 (@implement, $RX:ident, $TX:ident, $RTS:ident, $CTS:ident, $RXPO:literal, $TXPO:literal) => {
109 impl RxpoTxpo for ($RX, $TX, $RTS, $CTS) {
110 const RXPO: u8 = $RXPO;
111 const TXPO: u8 = $TXPO;
112 }
113 };
114}
115
116macro_rules! padnum_permutations {
129 (
132 ( $RX:ident $TX:ident $RTS:ident $CTS:ident ) [ $( $Pads:ident )* ]
133 ) => {
134 impl_rxpotxpo!($RX, $TX, $RTS, $CTS);
135 };
136 (
139 ( $($Perm:ident)* ) [ $($Pads:ident)+ ]
140 ) => {
141 padnum_permutations!( ( $($Perm)* ) [ $($Pads)+ ] [ $($Pads)+ ] );
142 };
143 (
144 ( $($Perm:ident)* ) [ $Head:ident $($Tail:ident)* ] [ $($Pads:ident)+ ]
145 ) => {
146 padnum_permutations!( ( $($Perm)* $Head ) [ $($Pads)+ ] );
149
150 padnum_permutations!( ( $($Perm)* ) [ $($Tail)* ] [ $($Pads)+ ] );
152 };
153 ( ( $($Perm:ident)* ) [ ] [ $($Pads:ident)+ ] ) => { };
155 }
156
157padnum_permutations!( () [NoneT Pad0 Pad1 Pad2 Pad3] );
158
159pub struct Pads<S, RX = NoneT, TX = NoneT, RTS = NoneT, CTS = NoneT>
168where
169 S: Sercom,
170 RX: OptionalPad,
171 TX: OptionalPad,
172 RTS: OptionalPad,
173 CTS: OptionalPad,
174{
175 sercom: PhantomData<S>,
176 receive: RX,
177 transmit: TX,
178 ready_to_send: RTS,
179 clear_to_send: CTS,
180}
181
182impl<S: Sercom> Default for Pads<S> {
183 fn default() -> Self {
184 Self {
185 sercom: PhantomData,
186 receive: NoneT,
187 transmit: NoneT,
188 ready_to_send: NoneT,
189 clear_to_send: NoneT,
190 }
191 }
192}
193
194impl<S, RX, TX, RTS, CTS> Pads<S, RX, TX, RTS, CTS>
195where
196 S: Sercom,
197 RX: OptionalPad,
198 TX: OptionalPad,
199 RTS: OptionalPad,
200 CTS: OptionalPad,
201{
202 #[inline]
204 pub fn free(self) -> (RX, TX, RTS, CTS) {
205 (
206 self.receive,
207 self.transmit,
208 self.ready_to_send,
209 self.clear_to_send,
210 )
211 }
212}
213
214#[hal_cfg("sercom0-d11")]
215impl<S, RX, TX, RTS, CTS> Pads<S, RX, TX, RTS, CTS>
216where
217 S: Sercom,
218 RX: OptionalPad,
219 TX: OptionalPad,
220 RTS: OptionalPad,
221 CTS: OptionalPad,
222{
223 #[inline]
225 pub fn rx<P: IsPad>(self, pin: P) -> Pads<S, P, TX, RTS, CTS> {
226 Pads {
227 sercom: self.sercom,
228 receive: pin,
229 transmit: self.transmit,
230 ready_to_send: self.ready_to_send,
231 clear_to_send: self.clear_to_send,
232 }
233 }
234
235 #[inline]
237 pub fn tx<P: IsPad>(self, pin: P) -> Pads<S, RX, P, RTS, CTS> {
238 Pads {
239 sercom: self.sercom,
240 receive: self.receive,
241 transmit: pin,
242 ready_to_send: self.ready_to_send,
243 clear_to_send: self.clear_to_send,
244 }
245 }
246
247 #[inline]
249 pub fn rts<P: IsPad>(self, pin: P) -> Pads<S, RX, TX, P, CTS> {
250 Pads {
251 sercom: self.sercom,
252 receive: self.receive,
253 transmit: self.transmit,
254 ready_to_send: pin,
255 clear_to_send: self.clear_to_send,
256 }
257 }
258
259 #[inline]
261 pub fn cts<P: IsPad>(self, pin: P) -> Pads<S, RX, TX, RTS, P> {
262 Pads {
263 sercom: self.sercom,
264 receive: self.receive,
265 transmit: self.transmit,
266 ready_to_send: self.ready_to_send,
267 clear_to_send: pin,
268 }
269 }
270}
271
272#[hal_cfg("sercom0-d21")]
273impl<S, RX, TX, RTS, CTS> Pads<S, RX, TX, RTS, CTS>
274where
275 S: Sercom,
276 RX: OptionalPad,
277 TX: OptionalPad,
278 RTS: OptionalPad,
279 CTS: OptionalPad,
280{
281 #[inline]
283 pub fn rx<I>(self, pin: impl AnyPin<Id = I>) -> Pads<S, Pad<S, I>, TX, RTS, CTS>
284 where
285 I: GetPad<S>,
286 Pad<S, I>: IsPad,
287 {
288 Pads {
289 sercom: self.sercom,
290 receive: pin.into().into_mode(),
291 transmit: self.transmit,
292 ready_to_send: self.ready_to_send,
293 clear_to_send: self.clear_to_send,
294 }
295 }
296
297 #[inline]
299 pub fn tx<I>(self, pin: impl AnyPin<Id = I>) -> Pads<S, RX, Pad<S, I>, RTS, CTS>
300 where
301 I: GetPad<S>,
302 Pad<S, I>: IsPad,
303 {
304 Pads {
305 sercom: self.sercom,
306 receive: self.receive,
307 transmit: pin.into().into_mode(),
308 ready_to_send: self.ready_to_send,
309 clear_to_send: self.clear_to_send,
310 }
311 }
312
313 #[inline]
315 pub fn rts<I>(self, pin: impl AnyPin<Id = I>) -> Pads<S, RX, TX, Pad<S, I>, CTS>
316 where
317 I: GetPad<S>,
318 Pad<S, I>: IsPad,
319 {
320 Pads {
321 sercom: self.sercom,
322 receive: self.receive,
323 transmit: self.transmit,
324 ready_to_send: pin.into().into_mode(),
325 clear_to_send: self.clear_to_send,
326 }
327 }
328
329 #[inline]
331 pub fn cts<I>(self, pin: impl AnyPin<Id = I>) -> Pads<S, RX, TX, RTS, Pad<S, I>>
332 where
333 I: GetPad<S>,
334 Pad<S, I>: IsPad,
335 {
336 Pads {
337 sercom: self.sercom,
338 receive: self.receive,
339 transmit: self.transmit,
340 ready_to_send: self.ready_to_send,
341 clear_to_send: pin.into().into_mode(),
342 }
343 }
344}
345
346#[hal_cfg("sercom0-d21")]
376pub type PadsFromIds<S, RX = NoneT, TX = NoneT, RTS = NoneT, CTS = NoneT> = Pads<
377 S,
378 <RX as GetOptionalPad<S>>::Pad,
379 <TX as GetOptionalPad<S>>::Pad,
380 <RTS as GetOptionalPad<S>>::Pad,
381 <CTS as GetOptionalPad<S>>::Pad,
382>;
383
384pub trait PadSet: Sealed {
405 type Sercom: Sercom;
406 type Rx: OptionalPad;
407 type Tx: OptionalPad;
408 type Rts: OptionalPad;
409 type Cts: OptionalPad;
410}
411
412impl<S, RX, TX, RTS, CTS> Sealed for Pads<S, RX, TX, RTS, CTS>
413where
414 S: Sercom,
415 RX: OptionalPad,
416 TX: OptionalPad,
417 RTS: OptionalPad,
418 CTS: OptionalPad,
419{
420}
421
422impl<S, RX, TX, RTS, CTS> PadSet for Pads<S, RX, TX, RTS, CTS>
423where
424 S: Sercom,
425 RX: OptionalPad,
426 TX: OptionalPad,
427 RTS: OptionalPad,
428 CTS: OptionalPad,
429{
430 type Sercom = S;
431 type Rx = RX;
432 type Tx = TX;
433 type Rts = RTS;
434 type Cts = CTS;
435}
436
437pub trait ValidPads: PadSet + RxpoTxpo {
449 type Capability: Capability;
450}
451
452impl<S, RX, RTS> ValidPads for Pads<S, RX, NoneT, RTS, NoneT>
453where
454 S: Sercom,
455 RX: SomePad,
456 RTS: OptionalPad,
457 Self: PadSet + RxpoTxpo,
458{
459 type Capability = Rx;
460}
461
462impl<S, TX, CTS> ValidPads for Pads<S, NoneT, TX, NoneT, CTS>
463where
464 S: Sercom,
465 TX: SomePad,
466 CTS: OptionalPad,
467 Self: PadSet + RxpoTxpo,
468{
469 type Capability = Tx;
470}
471
472impl<S, RX, TX, RTS, CTS> ValidPads for Pads<S, RX, TX, RTS, CTS>
473where
474 S: Sercom,
475 RX: SomePad,
476 TX: SomePad,
477 RTS: OptionalPad,
478 CTS: OptionalPad,
479 Self: PadSet + RxpoTxpo,
480{
481 type Capability = Duplex;
482}
483
484pub trait ValidConfig: AnyConfig {}
493
494impl<P: ValidPads, C: CharSize> ValidConfig for Config<P, C> {}