rpsp/
pin.rs

1// Permission is hereby granted, free of charge, to any person obtaining a copy
2// of this software and associated documentation files (the "Software"), to deal
3// in the Software without restriction, including without limitation the rights
4// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5// copies of the Software, and to permit persons to whom the Software is
6// furnished to do so, subject to the following conditions:
7//
8// The above copyright notice and this permission notice shall be included in
9// all copies or substantial portions of the Software.
10//
11// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17// SOFTWARE.
18//
19
20#![no_implicit_prelude]
21
22extern crate core;
23
24use core::cell::UnsafeCell;
25use core::clone::Clone;
26use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
27use core::convert::{From, TryFrom};
28use core::fmt::{self, Debug, Formatter};
29use core::marker::{Copy, PhantomData};
30use core::option::Option::{self, None, Some};
31use core::result::Result::{self, Err, Ok};
32use core::unreachable;
33
34use crate::asm::nop;
35use crate::int::Acknowledge;
36use crate::pac::pads_bank0::GPIO;
37use crate::pac::{ADC, IO_BANK0, PADS_BANK0, RESETS, SIO, SYSCFG};
38use crate::pin::gpio::{Input, Output};
39use crate::pin::pwm::{PwmID, PwmPin};
40use crate::{Pico, write_reg};
41
42#[path = "pin/boards/lib.rs"]
43mod boards;
44
45#[cfg_attr(rustfmt, rustfmt_skip)]
46pub use self::boards::pins::*;
47
48pub mod adc;
49pub mod led;
50pub mod pwm;
51
52pub enum PinPull {
53    Up,
54    Down,
55    None,
56}
57#[repr(u8)]
58pub enum PinSlew {
59    Slow = 0u8,
60    Fast = 1u8,
61}
62#[repr(u8)]
63pub enum PinState {
64    Low  = 0u8,
65    High = 1u8,
66}
67#[repr(u8)]
68pub enum PinStrength {
69    Drive2ma  = 0u8,
70    Drive4ma  = 1u8,
71    Drive8ma  = 2u8,
72    Drive12ma = 3u8,
73}
74#[repr(u8)]
75pub enum PinFunction {
76    JTag  = 0x00u8,
77    Spi   = 0x01u8,
78    Uart  = 0x02u8,
79    I2c   = 0x03u8,
80    Pwm   = 0x04u8,
81    Sio   = 0x05u8,
82    Pio0  = 0x06u8,
83    Pio1  = 0x07u8,
84    Clock = 0x08u8,
85    Usb   = 0x09u8,
86    None  = 0x1Fu8,
87}
88#[repr(u8)]
89pub enum PinDirection {
90    In  = 0u8,
91    Out = 1u8,
92}
93#[repr(u8)]
94pub enum PinInterrupt {
95    Low      = 0x1u8,
96    High     = 0x2u8,
97    EdgeLow  = 0x4u8,
98    EdgeHigh = 0x8u8,
99    All      = 0xFu8,
100}
101
102pub struct Pin<F: PinIO> {
103    i:  PinID,
104    _p: PhantomData<UnsafeCell<F>>,
105}
106pub struct PinInvalidError;
107
108pub trait PinIO {
109    const INPUT: bool;
110}
111
112pub type PinInput = Pin<Input>;
113pub type PinOutput = Pin<Output>;
114
115#[allow(unused)]
116// In case any boards don't use all I2C busses.
117pub(super) enum I2cID {
118    I2C0,
119    I2C1,
120}
121#[allow(unused)]
122// In case any boards don't use all SPI busses.
123pub(super) enum SpiID {
124    Spi0,
125    Spi1,
126}
127#[allow(unused)]
128// In case any boards don't use all UART busses.
129pub(super) enum UartID {
130    Uart0,
131    Uart1,
132}
133
134impl PinID {
135    #[inline]
136    pub(super) fn set_pio(&self, pio0: bool) {
137        let v = unsafe { &*IO_BANK0::PTR }
138            .gpio(*self as usize)
139            .gpio_ctrl()
140            .read()
141            .funcsel()
142            .bits();
143        match (v, pio0) {
144            (0x6, true) => return,
145            (0x7, false) => return,
146            _ => (),
147        }
148        self.ctrl().modify(|_, r| {
149            r.slewfast()
150                .set_bit()
151                .schmitt()
152                .set_bit()
153                .slewfast()
154                .set_bit()
155                .ie()
156                .set_bit()
157                .od()
158                .clear_bit()
159                .pue()
160                .clear_bit()
161                .pde()
162                .clear_bit()
163                .drive()
164                .bits(3)
165        });
166        self.set_function(if pio0 { PinFunction::Pio0 } else { PinFunction::Pio1 });
167    }
168    #[inline]
169    pub(super) fn set_input(&self) {
170        unsafe { &*SIO::PTR }
171            .gpio_oe_clr()
172            .write(|r| unsafe { r.bits(self.mask()) });
173        self.ctrl().modify(|_, r| r.ie().bit(true).od().bit(false));
174    }
175    #[inline]
176    pub(super) fn set_output(&self) {
177        unsafe { &*SIO::PTR }
178            .gpio_oe_set()
179            .write(|r| unsafe { r.bits(self.mask()) });
180        self.ctrl().modify(|_, r| r.ie().bit(true).od().bit(false));
181    }
182    #[inline]
183    pub(super) fn set_function(&self, f: PinFunction) {
184        unsafe { &*IO_BANK0::PTR }
185            .gpio(*self as usize)
186            .gpio_ctrl()
187            .modify(|_, r| unsafe { r.funcsel().bits(f as u8) });
188        self.ctrl().modify(|_, r| r.ie().bit(f as u8 != 0x1F))
189    }
190
191    #[inline(always)]
192    fn mask(&self) -> u32 {
193        1 << (*self as u32)
194    }
195    #[inline(always)]
196    fn is_odd(&self) -> bool {
197        (*self as u8) % 2 != 0
198    }
199    #[inline(always)]
200    fn offset(&self) -> usize {
201        (*self as usize) % 8 * 4
202    }
203    #[inline]
204    fn into_input(self) -> PinID {
205        self.set_input();
206        self.set_function(PinFunction::Sio);
207        self
208    }
209    #[inline]
210    fn into_output(self) -> PinID {
211        self.set_output();
212        self.set_function(PinFunction::Sio);
213        self
214    }
215    #[inline]
216    fn ctrl<'a>(&self) -> &'a GPIO {
217        unsafe { &*PADS_BANK0::PTR }.gpio(*self as usize)
218    }
219    fn inter_set(&self, i: PinInterrupt, en: bool) {
220        let (p, n) = (unsafe { &*IO_BANK0::PTR }, (*self as usize) / 8);
221        write_reg(
222            if on_core0() { p.proc0_inte(n).as_ptr() } else { p.proc1_inte(n).as_ptr() },
223            (i as u32) << self.offset(),
224            !en,
225        )
226    }
227    fn inter_status(&self, i: PinInterrupt) -> bool {
228        let (p, n) = (unsafe { &*IO_BANK0::PTR }, (*self as usize) / 8);
229        let r = if on_core0() { p.proc0_ints(n).read().bits() } else { p.proc1_ints(n).read().bits() } >> self.offset();
230        let m = i as u32;
231        r & m == m
232    }
233    fn inter_enabled(&self, i: PinInterrupt) -> bool {
234        let (p, n) = (unsafe { &*IO_BANK0::PTR }, (*self as usize) / 8);
235        let r = if on_core0() { p.proc0_inte(n).read().bits() } else { p.proc1_inte(n).read().bits() } >> self.offset();
236        let m = i as u32;
237        r & m == m
238    }
239    #[inline]
240    fn dorm_wake_set(&self, i: PinInterrupt, en: bool) {
241        let p = unsafe { &*IO_BANK0::PTR };
242        write_reg(
243            p.dormant_wake_inte((*self as usize) / 8).as_ptr(),
244            (i as u32) << self.offset(),
245            !en,
246        )
247    }
248    #[inline]
249    fn dorm_wake_status(&self, i: PinInterrupt) -> bool {
250        let (p, m) = (unsafe { &*IO_BANK0::PTR }, i as u32);
251        (p.dormant_wake_ints((*self as usize) / 8).read().bits() >> self.offset()) & m == m
252    }
253    #[inline]
254    fn dorm_wake_enabled(&self, i: PinInterrupt) -> bool {
255        let (p, m) = (unsafe { &*IO_BANK0::PTR }, i as u32);
256        (p.dormant_wake_inte((*self as usize) / 8).read().bits() >> self.offset()) & m == m
257    }
258}
259impl PinPull {
260    #[inline(always)]
261    fn sets(&self) -> (bool, bool) {
262        match self {
263            PinPull::Up => (true, false),
264            PinPull::Down => (false, true),
265            PinPull::None => (false, false),
266        }
267    }
268}
269impl Pin<Input> {
270    #[inline]
271    pub fn is_low(&self) -> bool {
272        unsafe { &*SIO::PTR }.gpio_in().read().bits() & self.i.mask() == 0
273    }
274    #[inline(always)]
275    pub fn is_high(&self) -> bool {
276        !self.is_low()
277    }
278    #[inline]
279    pub fn get_state(&self) -> bool {
280        self.i.ctrl().read().ie().bit_is_set()
281    }
282    #[inline]
283    pub fn is_enabled(&self) -> bool {
284        self.i.ctrl().read().ie().bit_is_set()
285    }
286    #[inline]
287    pub fn set_state(&self, en: bool) {
288        self.i.ctrl().modify(|_, r| r.ie().bit(en))
289    }
290    #[inline]
291    pub fn into_output(self) -> Pin<Output> {
292        Pin {
293            i:  self.i.into_output(),
294            _p: PhantomData,
295        }
296    }
297    #[inline]
298    pub fn into_pwm(self) -> Option<PwmPin<Input>> {
299        let i = pins_pwm(&self.i);
300        if i.is_b() {
301            return None;
302        }
303        self.i.set_function(PinFunction::Pwm);
304        i.set_state(true);
305        Some(PwmPin::<Input>::new(i))
306    }
307}
308impl Pin<Output> {
309    #[inline]
310    pub fn get(_p: &Pico, i: PinID) -> Pin<Output> {
311        // NOTE(sf): We require the Board struct to make sure the Pins are
312        // initialized first.
313        let v: Pin<Output> = Pin {
314            i:  i.into_output(),
315            _p: PhantomData,
316        };
317        v.low();
318        v.set_pull_type(PinPull::None);
319        v
320    }
321
322    #[inline]
323    pub fn low(&self) {
324        unsafe { &*SIO::PTR }
325            .gpio_out_clr()
326            .write(|r| unsafe { r.gpio_out_clr().bits(self.i.mask()) })
327    }
328    #[inline]
329    pub fn high(&self) {
330        unsafe { &*SIO::PTR }
331            .gpio_out_set()
332            .write(|r| unsafe { r.gpio_out_set().bits(self.i.mask()) })
333    }
334    #[inline]
335    pub fn toggle(&self) {
336        unsafe { &*SIO::PTR }
337            .gpio_out_xor()
338            .write(|r| unsafe { r.gpio_out_xor().bits(self.i.mask()) })
339    }
340    #[inline]
341    pub fn set_on(&self, en: bool) {
342        if en {
343            self.high();
344        } else {
345            self.low();
346        }
347    }
348    #[inline]
349    pub fn get_state(&self) -> bool {
350        self.i.ctrl().read().od().bit_is_set()
351    }
352    #[inline]
353    pub fn is_enabled(&self) -> bool {
354        self.i.ctrl().read().od().bit_is_set()
355    }
356    #[inline]
357    pub fn is_set_low(&self) -> bool {
358        unsafe { &*SIO::PTR }.gpio_out().read().bits() & self.i.mask() == 0
359    }
360    #[inline(always)]
361    pub fn is_set_high(&self) -> bool {
362        !self.is_set_low()
363    }
364    #[inline]
365    pub fn set_state(&self, en: bool) {
366        self.i.ctrl().modify(|_, r| r.od().bit(!en))
367    }
368    #[inline(always)]
369    pub fn into_input(self) -> Pin<Input> {
370        Pin {
371            i:  self.i.into_input(),
372            _p: PhantomData,
373        }
374    }
375    pub fn into_pwm(self) -> PwmPin<Output> {
376        let i = pins_pwm(&self.i);
377        self.i.set_function(PinFunction::Pwm);
378        i.set_state(true);
379        PwmPin::<Output>::new(i)
380    }
381    #[inline]
382    pub fn output_high(self) -> Pin<Output> {
383        self.high();
384        self
385    }
386    #[inline]
387    pub fn output(self, high: bool) -> Pin<Output> {
388        if high {
389            self.high()
390        } else {
391            self.low()
392        }
393        self
394    }
395}
396impl<F: PinIO> Pin<F> {
397    #[inline(always)]
398    pub fn id(&self) -> &PinID {
399        &self.i
400    }
401    #[inline]
402    pub fn get_schmitt(&self) -> bool {
403        self.i.ctrl().read().schmitt().bit_is_set()
404    }
405    #[inline]
406    pub fn get_slew(&self) -> PinSlew {
407        if self.i.ctrl().read().slewfast().bit_is_set() { PinSlew::Fast } else { PinSlew::Slow }
408    }
409    #[inline]
410    pub fn set_slew(&self, s: PinSlew) {
411        self.i.ctrl().modify(|_, r| r.slewfast().bit(s as u8 == 1));
412    }
413    #[inline]
414    pub fn pull_type(&self) -> PinPull {
415        let v = self.i.ctrl().read();
416        match (v.pue().bit_is_set(), v.pde().bit_is_set()) {
417            (true, false) => PinPull::Up,
418            (false, true) => PinPull::Down,
419            _ => PinPull::None,
420        }
421    }
422    #[inline]
423    pub fn set_schmitt(&self, en: bool) {
424        self.i.ctrl().modify(|_, r| r.schmitt().bit(en));
425    }
426    #[inline]
427    pub fn is_sync_bypass(&self) -> bool {
428        let i = self.i.mask();
429        unsafe { SYSCFG::steal() }.proc_in_sync_bypass().read().bits() & i == i
430    }
431    #[inline(always)]
432    pub fn is_pwm_avaliable(&self) -> bool {
433        !F::INPUT || (F::INPUT && self.i.is_odd())
434    }
435    #[inline]
436    pub fn pull(self, p: PinPull) -> Pin<F> {
437        self.set_pull_type(p);
438        self
439    }
440    #[inline]
441    pub fn set_pull_type(&self, p: PinPull) {
442        let (x, y) = p.sets();
443        self.i.ctrl().modify(|_, r| r.pue().bit(x).pde().bit(y))
444    }
445    #[inline(always)]
446    pub fn set_drive(&self, s: PinStrength) {
447        self.i.ctrl().modify(|_, r| r.drive().bits(s as _));
448    }
449    #[inline]
450    pub fn get_strength(&self) -> PinStrength {
451        match self.i.ctrl().read().drive().bits() {
452            0 => PinStrength::Drive2ma,
453            1 => PinStrength::Drive4ma,
454            2 => PinStrength::Drive8ma,
455            3 => PinStrength::Drive12ma,
456            _ => unreachable!(),
457        }
458    }
459    #[inline(always)]
460    pub fn set_function(&self, f: PinFunction) {
461        self.i.set_function(f)
462    }
463    #[inline]
464    pub fn interrupt_clear(&self, i: PinInterrupt) {
465        unsafe { &*IO_BANK0::PTR }
466            .intr((self.i as usize) / 8)
467            .write(|r| unsafe { r.bits((i as u32) << self.i.offset()) })
468    }
469    #[inline(always)]
470    pub fn interrupt_set(&self, i: PinInterrupt, en: bool) {
471        self.i.inter_set(i, en)
472    }
473    #[inline(always)]
474    pub fn interrupt_status(&self, i: PinInterrupt) -> bool {
475        self.i.inter_status(i)
476    }
477    #[inline(always)]
478    pub fn interrupt_enabled(&self, i: PinInterrupt) -> bool {
479        self.i.inter_enabled(i)
480    }
481    #[inline(always)]
482    pub fn dormant_wake_set(&self, i: PinInterrupt, en: bool) {
483        self.i.dorm_wake_set(i, en)
484    }
485    #[inline(always)]
486    pub fn dormant_wake_status(&self, i: PinInterrupt) -> bool {
487        self.i.dorm_wake_status(i)
488    }
489    #[inline(always)]
490    pub fn dormant_wake_enabled(&self, i: PinInterrupt) -> bool {
491        self.i.dorm_wake_enabled(i)
492    }
493
494    #[inline]
495    pub unsafe fn set_sync_bypass(&self, en: bool) {
496        write_reg(
497            unsafe { SYSCFG::steal() }.proc_in_sync_bypass().as_ptr(),
498            self.i.mask(),
499            !en,
500        );
501    }
502}
503
504impl PinIO for Input {
505    const INPUT: bool = true;
506}
507impl PinIO for Output {
508    const INPUT: bool = false;
509}
510
511impl<F: PinIO> Clone for Pin<F> {
512    #[inline(always)]
513    fn clone(&self) -> Pin<F> {
514        Pin { i: self.i, _p: PhantomData }
515    }
516}
517
518impl Eq for PinID {}
519impl Ord for PinID {
520    #[inline(always)]
521    fn cmp(&self, other: &PinID) -> Ordering {
522        (*self as u8).cmp(&(*other as u8))
523    }
524}
525impl Copy for PinID {}
526impl Clone for PinID {
527    #[inline(always)]
528    fn clone(&self) -> PinID {
529        *self
530    }
531}
532impl PartialEq for PinID {
533    #[inline(always)]
534    fn eq(&self, other: &PinID) -> bool {
535        (*self as u8).eq(&(*other as u8))
536    }
537}
538impl PartialOrd for PinID {
539    #[inline(always)]
540    fn partial_cmp(&self, other: &PinID) -> Option<Ordering> {
541        (*self as u8).partial_cmp(&(*other as u8))
542    }
543}
544impl TryFrom<u8> for PinID {
545    type Error = PinInvalidError;
546
547    #[inline]
548    fn try_from(v: u8) -> Result<PinID, PinInvalidError> {
549        match v {
550            0 => Ok(PinID::Pin0),
551            1 => Ok(PinID::Pin1),
552            2 => Ok(PinID::Pin2),
553            3 => Ok(PinID::Pin3),
554            4 => Ok(PinID::Pin4),
555            5 => Ok(PinID::Pin5),
556            6 => Ok(PinID::Pin6),
557            7 => Ok(PinID::Pin7),
558            8 => Ok(PinID::Pin8),
559            9 => Ok(PinID::Pin9),
560            10 => Ok(PinID::Pin10),
561            11 => Ok(PinID::Pin11),
562            12 => Ok(PinID::Pin12),
563            13 => Ok(PinID::Pin13),
564            14 => Ok(PinID::Pin14),
565            15 => Ok(PinID::Pin15),
566            16 => Ok(PinID::Pin16),
567            17 => Ok(PinID::Pin17),
568            18 => Ok(PinID::Pin18),
569            19 => Ok(PinID::Pin19),
570            20 => Ok(PinID::Pin20),
571            21 => Ok(PinID::Pin21),
572            22 => Ok(PinID::Pin22),
573            26 => Ok(PinID::Pin26),
574            27 => Ok(PinID::Pin27),
575            28 => Ok(PinID::Pin28),
576            _ => Err(PinInvalidError),
577        }
578    }
579}
580
581impl Copy for PinSlew {}
582impl Clone for PinSlew {
583    #[inline(always)]
584    fn clone(&self) -> PinSlew {
585        *self
586    }
587}
588
589impl Copy for PinState {}
590impl Clone for PinState {
591    #[inline(always)]
592    fn clone(&self) -> PinState {
593        *self
594    }
595}
596
597impl Copy for PinStrength {}
598impl Clone for PinStrength {
599    #[inline(always)]
600    fn clone(&self) -> PinStrength {
601        *self
602    }
603}
604
605impl Copy for PinFunction {}
606impl Clone for PinFunction {
607    #[inline(always)]
608    fn clone(&self) -> PinFunction {
609        *self
610    }
611}
612
613impl Copy for PinInterrupt {}
614impl Clone for PinInterrupt {
615    #[inline(always)]
616    fn clone(&self) -> PinInterrupt {
617        *self
618    }
619}
620
621impl Copy for PinDirection {}
622impl Clone for PinDirection {
623    #[inline(always)]
624    fn clone(&self) -> PinDirection {
625        *self
626    }
627}
628
629impl From<Pin<Output>> for Pin<Input> {
630    #[inline(always)]
631    fn from(v: Pin<Output>) -> Pin<Input> {
632        v.into_input()
633    }
634}
635
636impl<F: PinIO> Acknowledge for Pin<F> {
637    #[inline]
638    fn ack_interrupt(&mut self) -> bool {
639        let r = self.interrupt_status(PinInterrupt::All);
640        self.interrupt_clear(PinInterrupt::All);
641        r
642    }
643}
644
645#[cfg(feature = "debug")]
646impl Debug for PinInvalidError {
647    #[inline]
648    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
649        f.write_str("PinInvalidError")
650    }
651}
652#[cfg(not(feature = "debug"))]
653impl Debug for PinInvalidError {
654    #[inline(always)]
655    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
656        Ok(())
657    }
658}
659
660#[inline]
661pub fn emergency_pin_on(i: PinID) {
662    let v = i.into_output().mask();
663    unsafe { &*SIO::PTR }
664        .gpio_out_set()
665        .write(|r| unsafe { r.gpio_out_set().bits(v) })
666}
667
668pub(crate) fn setup_pins() {
669    let s = unsafe { SIO::steal() };
670    let r = unsafe { RESETS::steal() };
671    let b = unsafe { PADS_BANK0::steal() };
672    r.reset().modify(|_, r| r.pads_bank0().set_bit());
673    r.reset().modify(|_, r| r.io_bank0().set_bit());
674    unsafe {
675        s.gpio_oe().write_with_zero(|r| r.bits(0));
676        s.gpio_out().write_with_zero(|r| r.bits(0));
677    }
678    r.reset().modify(|_, r| r.io_bank0().clear_bit());
679    while r.reset_done().read().io_bank0().bit_is_clear() {
680        nop();
681    }
682    r.reset().modify(|_, r| r.pads_bank0().clear_bit());
683    while r.reset_done().read().pads_bank0().bit_is_clear() {
684        nop();
685    }
686    r.reset().modify(|_, r| r.pwm().clear_bit());
687    while r.reset_done().read().pwm().bit_is_clear() {
688        nop();
689    }
690    // Enable all pins by default.
691    b.gpio(0).modify(|_, r| r.od().clear_bit().ie().set_bit());
692    b.gpio(1).modify(|_, r| r.od().clear_bit().ie().set_bit());
693    b.gpio(2).modify(|_, r| r.od().clear_bit().ie().set_bit());
694    b.gpio(3).modify(|_, r| r.od().clear_bit().ie().set_bit());
695    b.gpio(4).modify(|_, r| r.od().clear_bit().ie().set_bit());
696    b.gpio(5).modify(|_, r| r.od().clear_bit().ie().set_bit());
697    b.gpio(6).modify(|_, r| r.od().clear_bit().ie().set_bit());
698    b.gpio(7).modify(|_, r| r.od().clear_bit().ie().set_bit());
699    b.gpio(8).modify(|_, r| r.od().clear_bit().ie().set_bit());
700    b.gpio(9).modify(|_, r| r.od().clear_bit().ie().set_bit());
701    b.gpio(10).modify(|_, r| r.od().clear_bit().ie().set_bit());
702    b.gpio(11).modify(|_, r| r.od().clear_bit().ie().set_bit());
703    b.gpio(12).modify(|_, r| r.od().clear_bit().ie().set_bit());
704    b.gpio(13).modify(|_, r| r.od().clear_bit().ie().set_bit());
705    b.gpio(14).modify(|_, r| r.od().clear_bit().ie().set_bit());
706    b.gpio(15).modify(|_, r| r.od().clear_bit().ie().set_bit());
707    b.gpio(16).modify(|_, r| r.od().clear_bit().ie().set_bit());
708    b.gpio(17).modify(|_, r| r.od().clear_bit().ie().set_bit());
709    b.gpio(18).modify(|_, r| r.od().clear_bit().ie().set_bit());
710    b.gpio(19).modify(|_, r| r.od().clear_bit().ie().set_bit());
711    b.gpio(20).modify(|_, r| r.od().clear_bit().ie().set_bit());
712    b.gpio(21).modify(|_, r| r.od().clear_bit().ie().set_bit());
713    b.gpio(22).modify(|_, r| r.od().clear_bit().ie().set_bit());
714    b.gpio(26).modify(|_, r| r.od().clear_bit().ie().set_bit());
715    b.gpio(27).modify(|_, r| r.od().clear_bit().ie().set_bit());
716    b.gpio(28).modify(|_, r| r.od().clear_bit().ie().set_bit());
717    PwmID::Pwm0A.set_defaults();
718    PwmID::Pwm1A.set_defaults();
719    PwmID::Pwm2A.set_defaults();
720    PwmID::Pwm3A.set_defaults();
721    PwmID::Pwm4A.set_defaults();
722    PwmID::Pwm5A.set_defaults();
723    PwmID::Pwm6A.set_defaults();
724    PwmID::Pwm7A.set_defaults();
725    unsafe { ADC::steal() }.cs().write(|r| r.en().clear_bit());
726}
727
728#[inline]
729fn on_core0() -> bool {
730    unsafe { (*SIO::ptr()).cpuid().read().bits() == 0 }
731}
732
733pub mod gpio {
734    pub struct Input;
735    pub struct Output;
736}