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