bl702_hal/
gpio.rs

1//! General Purpose Input/Output
2use core::marker::PhantomData;
3
4use crate::pac;
5
6/// Extension trait to split GLB peripheral into independent pins, registers and other modules
7pub trait GlbExt {
8    /// Splits the register block into independent pins and modules
9    fn split(self) -> Parts;
10}
11
12#[derive(Copy, Clone)]
13pub enum Event {
14    /// Trigger on the falling edge
15    NegativePulse = 0,
16    /// Trigger on the rising edge
17    PositivePulse = 1,
18    /// Trigger while low level
19    NegativeLevel = 2,
20    /// Trigger while high level
21    HighLevel = 3,
22}
23
24/// Extension trait to setup/enable/disable/clear/check input pins
25pub trait InterruptPin {
26    // Is make_interrupt_source redundant?
27    //fn make_interrupt_source(&mut self, afio: &mut afio::Parts);
28    fn trigger_on_event(&mut self, event: Event);
29    fn control_asynchronous(&mut self);
30    fn control_synchronous(&mut self);
31    fn enable_interrupt(&mut self);
32    fn disable_interrupt(&mut self);
33    fn clear_interrupt_pending_bit(&mut self);
34    fn check_interrupt(&self) -> bool;
35}
36
37pub use uart_sig::*;
38
39/// UART signals
40pub mod uart_sig {
41    use core::marker::PhantomData;
42
43    use crate::pac;
44
45    /// UART0 RTS (type state)
46    pub struct Uart0Rts;
47
48    /// UART0 CTS (type state)
49    pub struct Uart0Cts;
50
51    /// UART0 TXD (type state)
52    pub struct Uart0Tx;
53
54    /// UART0 RXD (type state)
55    pub struct Uart0Rx;
56
57    /// UART1 RXD (type state)
58    pub struct Uart1Rx;
59
60    /// UART1 RTS (type state)
61    pub struct Uart1Rts;
62
63    /// UART1 CTS (type state)
64    pub struct Uart1Cts;
65
66    /// UART1 TXD (type state)
67    pub struct Uart1Tx;
68
69    macro_rules! impl_uart_sig {
70        ($UartSigi: ident, $doc1: expr, $sigi:ident, $UartMuxi: ident, $doc2: expr) => {
71            #[doc = $doc1]
72            pub struct $UartSigi;
73
74            #[doc = $doc2]
75            pub struct $UartMuxi<MODE> {
76                pub(crate) _mode: PhantomData<MODE>,
77            }
78
79            impl<MODE> $UartMuxi<MODE> {
80                /// Configure the internal UART signal to UART0-RTS
81                pub fn into_uart0_rts(self) -> $UartMuxi<Uart0Rts> {
82                    self.into_uart_mode(0)
83                }
84
85                /// Configure the internal UART signal to UART0-CTS
86                pub fn into_uart0_cts(self) -> $UartMuxi<Uart0Cts> {
87                    self.into_uart_mode(1)
88                }
89
90                /// Configure the internal UART signal to UART0-TX
91                pub fn into_uart0_tx(self) -> $UartMuxi<Uart0Tx> {
92                    self.into_uart_mode(2)
93                }
94
95                /// Configure the internal UART signal to UART0-RX
96                pub fn into_uart0_rx(self) -> $UartMuxi<Uart0Rx> {
97                    self.into_uart_mode(3)
98                }
99
100                /// Configure the internal UART signal to UART1-RTS
101                pub fn into_uart1_rts(self) -> $UartMuxi<Uart1Rts> {
102                    self.into_uart_mode(4)
103                }
104
105                /// Configure the internal UART signal to UART1-CTS
106                pub fn into_uart1_cts(self) -> $UartMuxi<Uart1Cts> {
107                    self.into_uart_mode(5)
108                }
109
110                /// Configure the internal UART signal to UART1-TX
111                pub fn into_uart1_tx(self) -> $UartMuxi<Uart1Tx> {
112                    self.into_uart_mode(6)
113                }
114
115                /// Configure the internal UART signal to UART1-RX
116                pub fn into_uart1_rx(self) -> $UartMuxi<Uart1Rx> {
117                    self.into_uart_mode(7)
118                }
119
120                paste::paste! {
121                    #[inline]
122                    fn into_uart_mode<T>(self, mode: u8) -> $UartMuxi<T> {
123                        let glb = unsafe { &*pac::GLB::ptr() };
124
125                        glb.uart_sig_sel_0.modify(|_r, w| unsafe { w
126                            .[<uart_ $sigi _sel>]().bits(mode)
127                        });
128
129                        $UartMuxi { _mode: PhantomData }
130                    }
131                }
132            }
133        };
134    }
135
136    impl_uart_sig!(
137        UartSig0,
138        "UART signal 0 (type state)",
139        sig_0,
140        UartMux0,
141        "UART multiplexer peripherals for signal 0"
142    );
143
144    impl_uart_sig!(
145        UartSig1,
146        "UART signal 1 (type state)",
147        sig_1,
148        UartMux1,
149        "UART multiplexer peripherals for signal 1"
150    );
151
152    impl_uart_sig!(
153        UartSig2,
154        "UART signal 2 (type state)",
155        sig_2,
156        UartMux2,
157        "UART multiplexer peripherals for signal 2"
158    );
159
160    impl_uart_sig!(
161        UartSig3,
162        "UART signal 3 (type state)",
163        sig_3,
164        UartMux3,
165        "UART multiplexer peripherals for signal 3"
166    );
167
168    impl_uart_sig!(
169        UartSig4,
170        "UART signal 4 (type state)",
171        sig_4,
172        UartMux4,
173        "UART multiplexer peripherals for signal 4"
174    );
175
176    impl_uart_sig!(
177        UartSig5,
178        "UART signal 5 (type state)",
179        sig_5,
180        UartMux5,
181        "UART multiplexer peripherals for signal 5"
182    );
183
184    impl_uart_sig!(
185        UartSig6,
186        "UART signal 6 (type state)",
187        sig_6,
188        UartMux6,
189        "UART multiplexer peripherals for signal 6"
190    );
191
192    impl_uart_sig!(
193        UartSig7,
194        "UART signal 7 (type state)",
195        sig_7,
196        UartMux7,
197        "UART multiplexer peripherals for signal 7"
198    );
199}
200
201/// Clock configurator registers
202pub struct ClkCfg {
203    pub(crate) _ownership: (),
204}
205
206/*
207// todo: english
208    在GPIO模式下,可以设置内部上下拉,以类型状态机模式设计
209    SPI、UART、I2C等数字功能下,可以设置内部上下拉,但不会影响返回类型的状态
210    ADC、DAC下,软件禁止设置内部上下拉。HAL库不会生成此类函数,以免出错。
211*/
212
213/// Hi-Z Floating pin (type state)
214pub struct Floating;
215/// Pulled down pin (type state)
216pub struct PullDown;
217/// Pulled up pin (type state)
218pub struct PullUp;
219
220/// Input mode (type state)
221pub struct Input<MODE> {
222    _mode: PhantomData<MODE>,
223}
224
225/// Output mode (type state)
226pub struct Output<MODE> {
227    _mode: PhantomData<MODE>,
228}
229
230/// UART pin mode (type state)
231pub struct Uart;
232
233/// SPI pin mode (type state)
234pub struct Spi;
235
236/// I2C pin mode (type state)
237pub struct I2c;
238
239#[doc(hidden)]
240pub trait UartPin<SIG> {}
241
242// There are Pin0 to Pin22, totally 23 pins
243
244pub use self::pin::*;
245
246macro_rules! impl_glb {
247    ($($Pini: ident: ($pini: ident, $gpio_cfgctli: ident, $UartSigi: ident, $sigi: ident, $spi_kind: ident, $i2c_kind: ident, $gpio_i: ident, $gpio_int_mode_seti: ident, $pin_id: literal) ,)+) => {
248        impl GlbExt for pac::GLB {
249            fn split(self) -> Parts {
250                Parts {
251                    $( $pini: $Pini { _mode: PhantomData }, )+
252                    uart_mux0: UartMux0 { _mode: PhantomData },
253                    uart_mux1: UartMux1 { _mode: PhantomData },
254                    uart_mux2: UartMux2 { _mode: PhantomData },
255                    uart_mux3: UartMux3 { _mode: PhantomData },
256                    uart_mux4: UartMux4 { _mode: PhantomData },
257                    uart_mux5: UartMux5 { _mode: PhantomData },
258                    uart_mux6: UartMux6 { _mode: PhantomData },
259                    uart_mux7: UartMux7 { _mode: PhantomData },
260                    clk_cfg: ClkCfg { _ownership: () },
261                }
262            }
263        }
264
265        /// GPIO parts
266        pub struct Parts {
267            $( pub $pini: $Pini<Input<Floating>>, )+
268            pub uart_mux0: UartMux0<Uart0Cts>,
269            pub uart_mux1: UartMux1<Uart0Cts>,
270            pub uart_mux2: UartMux2<Uart0Cts>,
271            pub uart_mux3: UartMux3<Uart0Cts>,
272            pub uart_mux4: UartMux4<Uart0Cts>,
273            pub uart_mux5: UartMux5<Uart0Cts>,
274            pub uart_mux6: UartMux6<Uart0Cts>,
275            pub uart_mux7: UartMux7<Uart0Cts>,
276            pub clk_cfg: ClkCfg,
277        }
278
279        /// GPIO pins
280        pub mod pin {
281            use core::marker::PhantomData;
282            use core::convert::Infallible;
283            use embedded_hal::digital::blocking::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin};
284            use embedded_hal_zero::digital::v2::{
285                InputPin as InputPinZero,
286                OutputPin as OutputPinZero,
287                StatefulOutputPin as StatefulOutputPinZero,
288                ToggleableOutputPin as ToggleableOutputPinZero
289            };
290            use crate::pac;
291            use super::*;
292
293            /// Simple implementation of InputPin trait to use within EH0 and EH1 impls without name conflicts
294            trait InternalInputPinImpl {
295                fn is_high_inner(&self) -> bool;
296                fn is_low_inner(&self) -> bool;
297            }
298
299            /// Simple implementation of OutputPin trait to use within EH0 and EH1 impls without name conflicts
300            trait InternalOutputPinImp {
301                fn set_high_inner(&self);
302                fn set_low_inner(&self);
303            }
304
305            /// Simple implementation of StatefulOutputPin trait to use within EH0 and EH1 impls without name conflicts
306            trait InternalStatefulOutputImp {
307                fn is_output_high_inner(&self) -> bool;
308                fn is_output_low_inner(&self) -> bool;
309            }
310
311            $(
312            /// Pin
313            pub struct $Pini<MODE> {
314                pub(crate) _mode: PhantomData<MODE>,
315            }
316
317            impl<MODE> $Pini<MODE> {
318                // 11 -> GPIO_FUN_SWGPIO
319                /// Configures the pin to operate as a Hi-Z floating output pin.
320                pub fn into_floating_output(self) -> $Pini<Output<Floating>> {
321                    self.into_pin_with_mode(11, false, false, false)
322                }
323
324                /// Configures the pin to operate as a pull-up output pin.
325                pub fn into_pull_up_output(self) -> $Pini<Output<PullUp>> {
326                    self.into_pin_with_mode(11, true, false, false)
327                }
328
329                /// Configures the pin to operate as a pull-down output pin.
330                pub fn into_pull_down_output(self) -> $Pini<Output<PullDown>> {
331                    self.into_pin_with_mode(11, false, true, false)
332                }
333
334                /// Configures the pin to operate as a Hi-Z floating input pin.
335                pub fn into_floating_input(self) -> $Pini<Input<Floating>> {
336                    self.into_pin_with_mode(11, false, false, true)
337                }
338
339                /// Configures the pin to operate as a pull-up input pin.
340                pub fn into_pull_up_input(self) -> $Pini<Input<PullUp>> {
341                    self.into_pin_with_mode(11, true, false, true)
342                }
343
344                /// Configures the pin to operate as a pull-down input pin.
345                pub fn into_pull_down_input(self) -> $Pini<Input<PullDown>> {
346                    self.into_pin_with_mode(11, false, true, true)
347                }
348
349                paste::paste! {
350                    #[inline]
351                    fn into_pin_with_mode<T>(self, mode: u8, pu: bool, pd: bool, ie: bool) -> $Pini<T> {
352                        let glb = unsafe { &*pac::GLB::ptr() };
353
354                        glb.$gpio_cfgctli.modify(|_r, w| unsafe { w
355                            .[<reg_ $gpio_i _func_sel>]().bits(mode)
356                            .[<reg_ $gpio_i _ie>]().bit(ie) // output
357                            .[<reg_ $gpio_i _pu>]().bit(pu)
358                            .[<reg_ $gpio_i _pd>]().bit(pd)
359                            .[<reg_ $gpio_i _drv>]().bits(0) // disabled
360                            .[<reg_ $gpio_i _smt>]().clear_bit()
361                        });
362
363                        // If we're an input clear the Output Enable bit as well, else set it.
364                        glb.gpio_cfgctl34.modify(|_, w| w.[<reg_ $gpio_i _oe>]().bit(!ie));
365
366                        $Pini { _mode: PhantomData }
367                    }
368                }
369            }
370
371            impl<MODE> $Pini<Input<MODE>> {
372                paste::paste! {
373                    /// Enable smitter GPIO input filter
374                    pub fn enable_smitter(&mut self) {
375                        let glb = unsafe { &*pac::GLB::ptr() };
376
377                        glb.$gpio_cfgctli.modify(|_, w| w.[<reg_ $gpio_i _smt>]().set_bit());
378                    }
379
380                    /// Enable smitter GPIO output filter
381                    pub fn disable_smitter(&mut self) {
382                        let glb = unsafe { &*pac::GLB::ptr() };
383
384                        glb.$gpio_cfgctli.modify(|_, w| w.[<reg_ $gpio_i _smt>]().clear_bit());
385                    }
386                }
387            }
388
389            impl<MODE> $Pini<MODE> {
390                paste::paste! {
391                    /// Configures the pin to UART alternate mode
392                    pub fn [<into_uart_ $sigi>](self) -> $Pini<Uart> {
393                        // 7 -> GPIO_FUN_UART
394                        self.into_pin_with_mode(7, true, false, true)
395                    }
396
397                    /// Configures the pin to SPI alternate mode
398                    pub fn [<into_spi_ $spi_kind>](self) -> $Pini<Spi> {
399                        // 4 -> GPIO0_FUN_SPI_x
400                        self.into_pin_with_mode(4, true, false, true)
401                    }
402
403                    /// Configures the pin to I2C alternate mode
404                    pub fn [<into_i2c_ $i2c_kind>](self) -> $Pini<I2c> {
405                        // 6 -> GPIO_FUN_I2C_x
406                        self.into_pin_with_mode(6, true, false, true)
407                    }
408                }
409            }
410
411            impl UartPin<$UartSigi> for $Pini<Uart> {}
412
413            impl<MODE> InternalInputPinImpl for $Pini<Input<MODE>> {
414                paste::paste! {
415                    fn is_high_inner(&self) -> bool {
416                        let glb = unsafe { &*pac::GLB::ptr() };
417                        glb.gpio_cfgctl30.read().[<reg_ $gpio_i _i>]().bit_is_set()
418                    }
419                }
420                paste::paste! {
421                    fn is_low_inner(&self) -> bool {
422                        let glb = unsafe { &*pac::GLB::ptr() };
423                        glb.gpio_cfgctl30.read().[<reg_ $gpio_i _i>]().bit_is_clear()
424                    }
425                }
426            }
427
428            impl<MODE> InternalOutputPinImp for $Pini<Output<MODE>> {
429                paste::paste! {
430                    fn set_high_inner(&self) {
431                        let glb = unsafe { &*pac::GLB::ptr() };
432                        glb.gpio_cfgctl32.modify(|_, w| w.[<reg_ $gpio_i _o>]().set_bit())
433                    }
434                }
435                paste::paste! {
436                    fn set_low_inner(&self)  {
437                        let glb = unsafe { &*pac::GLB::ptr() };
438                        glb.gpio_cfgctl32.modify(|_, w| w.[<reg_ $gpio_i _o>]().clear_bit())
439                    }
440                }
441            }
442
443            impl<MODE> InternalStatefulOutputImp for $Pini<Output<MODE>> {
444                paste::paste! {
445                    fn is_output_high_inner(&self) -> bool {
446                        let glb = unsafe { &*pac::GLB::ptr() };
447                        glb.gpio_cfgctl32.read().[<reg_ $gpio_i _o>]().bit_is_set()
448                    }
449
450                    fn is_output_low_inner(& self) -> bool {
451                        let glb = unsafe { &*pac::GLB::ptr() };
452                        glb.gpio_cfgctl32.read().[<reg_ $gpio_i _o>]().bit_is_clear()
453                    }
454                }
455            }
456
457
458            impl<MODE> InputPin for $Pini<Input<MODE>> {
459                type Error = Infallible;
460
461                fn is_high(&self) -> Result<bool, Self::Error> {
462                    Ok(self.is_high_inner())
463                }
464
465                fn is_low(&self) -> Result<bool, Self::Error> {
466                    Ok(self.is_low_inner())
467                }
468            }
469
470            impl<MODE> InputPinZero for $Pini<Input<MODE>> {
471                type Error = Infallible;
472
473                fn is_high(&self) -> Result<bool, Self::Error> {
474                    Ok(self.is_high_inner())
475                }
476
477                fn is_low(&self) -> Result<bool, Self::Error> {
478                    Ok(self.is_low_inner())
479                }
480            }
481
482            impl<MODE> InterruptPin for $Pini<Input<MODE>> {
483
484                paste::paste! {
485                    fn trigger_on_event(&mut self, event: Event) {
486                        let glb = unsafe { &*pac::GLB::ptr() };
487                        // 10 pins per register
488                        let pin_id = $pin_id % 10;
489                        // each pin uses 3 bits
490                        let offset = pin_id * 3;
491                        // ensure our event fits in the mask
492                        let event = (0b11 & event as u32) << offset;
493                        // Write new event
494                        glb.$gpio_int_mode_seti.modify(|r,w| {
495                            // Mask off previous bits
496                            let mask = 0b11 << offset;
497                            let prev = r.bits() & ! mask;
498                            unsafe {w.bits(prev | event)}
499                        });
500                    }
501
502                    fn control_asynchronous(&mut self) {
503                        let glb = unsafe { &*pac::GLB::ptr() };
504                        let pin_id = $pin_id % 10;
505                        let offset = pin_id * 3;
506                        glb.$gpio_int_mode_seti.modify(|r,w| {
507                            let mask = 0b100 << offset;
508                            unsafe {w.bits(r.bits() | mask)}
509                        });
510                    }
511
512                    fn control_synchronous(&mut self) {
513                        let glb = unsafe { &*pac::GLB::ptr() };
514                        let pin_id = $pin_id % 10;
515                        // each pin uses 3 bits
516                        let offset = pin_id * 3;
517                        glb.gpio_int_mode_set1.modify(|r,w| {
518                            let mask = 0b100 << offset;
519                            unsafe {w.bits(r.bits() & !mask)}
520                        });
521                    }
522
523                    fn enable_interrupt(&mut self) {
524                        let glb = unsafe { &*pac::GLB::ptr() };
525
526                        glb.gpio_int_mask1.modify(|r,w| {
527                            unsafe {
528                            w.bits(r.bits() | (1 << $pin_id))
529                            }
530                        });
531                    }
532
533                    fn disable_interrupt(&mut self) {
534                        let glb = unsafe { &*pac::GLB::ptr() };
535
536                        glb.gpio_int_mask1.modify(|r, w| {
537                            unsafe {
538                                w.bits(r.bits() & (0xFFFF_FFFF - (1 << $pin_id)))
539                            }
540                        });
541                    }
542
543                    fn clear_interrupt_pending_bit(&mut self) {
544                        let glb = unsafe { &*pac::GLB::ptr() };
545
546                        glb.gpio_int_clr1.write(|w| {
547                            unsafe {
548                            w.bits(1 << $pin_id)
549                            }
550                        });
551                    }
552
553                    fn check_interrupt(&self) -> bool {
554                        let glb = unsafe { &*pac::GLB::ptr() };
555                        let intstat:u32 = glb.gpio_int_stat1.read().gpio_int_stat1().bits();
556                        let int_masked:u32 = intstat | (1 << $pin_id);
557                        0 != int_masked
558                    }
559                }
560            }
561
562
563            impl<MODE> OutputPin for $Pini<Output<MODE>> {
564                type Error = Infallible;
565
566                fn set_high(&mut self) -> Result<(), Self::Error> {
567                    self.set_high_inner();
568                    Ok(())
569                }
570
571                fn set_low(&mut self) -> Result<(), Self::Error> {
572                    self.set_low_inner();
573                    Ok(())
574                }
575            }
576
577            impl<MODE> OutputPinZero for $Pini<Output<MODE>> {
578                type Error = Infallible;
579
580                fn set_high(&mut self) -> Result<(), Self::Error> {
581                    self.set_high_inner();
582                    Ok(())
583                }
584
585                fn set_low(&mut self) -> Result<(), Self::Error> {
586                    self.set_low_inner();
587                    Ok(())
588                }
589            }
590
591            impl<MODE> StatefulOutputPin for $Pini<Output<MODE>> {
592                fn is_set_high(&self) -> Result<bool, Self::Error> {
593                    Ok(self.is_output_high_inner())
594                }
595
596                fn is_set_low(&self) -> Result<bool, Self::Error> {
597                    Ok(self.is_output_low_inner())
598                }
599            }
600
601            impl<MODE> StatefulOutputPinZero for $Pini<Output<MODE>> {
602                fn is_set_high(&self) -> Result<bool, Self::Error> {
603                    Ok(self.is_output_high_inner())
604                }
605
606                fn is_set_low(&self) -> Result<bool, Self::Error> {
607                    Ok(self.is_output_low_inner())
608                }
609            }
610
611
612            impl<MODE> ToggleableOutputPin for $Pini<Output<MODE>> {
613                type Error = Infallible;
614
615                fn toggle(&mut self) -> Result<(), Self::Error> {
616                    if self.is_output_high_inner() {
617                        self.set_low_inner()
618                    } else {
619                        self.set_high_inner()
620                    }
621                    Ok(())
622                }
623            }
624
625            impl<MODE> ToggleableOutputPinZero for $Pini<Output<MODE>> {
626                type Error = Infallible;
627
628                fn toggle(&mut self) -> Result<(), Self::Error> {
629                    if self.is_output_high_inner() {
630                        self.set_low_inner()
631                    } else {
632                        self.set_high_inner()
633                    }
634                    Ok(())
635                }
636            }
637
638            )+
639        }
640    };
641}
642
643// bl702-6 has pins numbered Pin0 to Pin37, 38 pins in total.
644// there are at most 32 GPIO, the other 6 pins are analogue only
645// TODO: implement the rest of the pins
646impl_glb! {
647    Pin0: (pin0, gpio_cfgctl0, UartSig0, sig0, miso, scl, gpio_0, gpio_int_mode_set1,0),
648    Pin1: (pin1, gpio_cfgctl0, UartSig1, sig1, mosi, sda, gpio_1, gpio_int_mode_set1,1),
649    Pin2: (pin2, gpio_cfgctl1, UartSig2, sig2, ss, scl, gpio_2, gpio_int_mode_set1,2),
650    Pin3: (pin3, gpio_cfgctl1, UartSig3, sig3, sclk, sda, gpio_3, gpio_int_mode_set1,3),
651    Pin4: (pin4, gpio_cfgctl2, UartSig4, sig4, miso, scl, gpio_4, gpio_int_mode_set1,4),
652    Pin5: (pin5, gpio_cfgctl2, UartSig5, sig5, mosi, sda, gpio_5, gpio_int_mode_set1,5),
653    Pin6: (pin6, gpio_cfgctl3, UartSig6, sig6, ss, scl, gpio_6, gpio_int_mode_set1,6),
654    Pin7: (pin7, gpio_cfgctl3, UartSig7, sig7, sclk, sda, gpio_7, gpio_int_mode_set1,7),
655    Pin8: (pin8, gpio_cfgctl4, UartSig0, sig0, miso, scl, gpio_8, gpio_int_mode_set1,8),
656    Pin9: (pin9, gpio_cfgctl4, UartSig1, sig1, mosi, sda, gpio_9, gpio_int_mode_set1,9),
657    Pin10: (pin10, gpio_cfgctl5, UartSig2, sig2, ss, scl, gpio_10, gpio_int_mode_set2,11),
658    Pin11: (pin11, gpio_cfgctl5, UartSig3, sig3, sclk, sda, gpio_11, gpio_int_mode_set2,12),
659    Pin12: (pin12, gpio_cfgctl6, UartSig4, sig4, miso, scl, gpio_12, gpio_int_mode_set2,13),
660    Pin13: (pin13, gpio_cfgctl6, UartSig5, sig5, mosi, sda, gpio_13, gpio_int_mode_set2,14),
661    Pin14: (pin14, gpio_cfgctl7, UartSig6, sig6, ss, scl, gpio_14, gpio_int_mode_set2,15),
662    Pin15: (pin15, gpio_cfgctl7, UartSig7, sig7, sclk, sda, gpio_15, gpio_int_mode_set2,16),
663    Pin16: (pin16, gpio_cfgctl8, UartSig0, sig0, miso, scl, gpio_16, gpio_int_mode_set2,17),
664    Pin17: (pin17, gpio_cfgctl8, UartSig1, sig1, mosi, sda, gpio_17, gpio_int_mode_set2,18),
665    Pin18: (pin18, gpio_cfgctl9, UartSig2, sig2, ss, scl, gpio_18, gpio_int_mode_set2,19),
666    Pin19: (pin19, gpio_cfgctl9, UartSig3, sig3, sclk, sda, gpio_19, gpio_int_mode_set2,20),
667    Pin20: (pin20, gpio_cfgctl10, UartSig4, sig4, miso, scl, gpio_20, gpio_int_mode_set3,21),
668    Pin21: (pin21, gpio_cfgctl10, UartSig5, sig5, mosi, sda, gpio_21, gpio_int_mode_set3,22),
669    Pin22: (pin22, gpio_cfgctl11, UartSig6, sig6, ss, scl, gpio_22, gpio_int_mode_set3,23),
670}