pitaya_go_bsp/
lib.rs

1//! Board support crate for the Makerdiary Pitaya Go
2//!
3//! UARTE, SPIM and TWI should be functional,
4//! but might miss some features.
5#![no_std]
6
7pub use cortex_m;
8pub use embedded_hal;
9pub use nrf52840_hal as hal;
10
11/// Exports traits that are usually needed when using this crate
12pub mod prelude {
13    pub use nrf52840_hal::prelude::*;
14}
15
16// TODO: Maybe we want a debug module like in the DWM1001-Dev implementation.
17// pub mod debug;
18
19use nrf52840_hal::{
20    gpio::{p0, p1, Disconnected, Input, Level, Output, Pin, PullUp, PushPull},
21    pac::{self as nrf52, CorePeripherals, Peripherals},
22    spim::{self, Frequency, Spim, MODE_0},
23    uarte::{self, Baudrate as UartBaudrate, Parity as UartParity, Uarte},
24};
25
26use embedded_hal::digital::v2::{InputPin, OutputPin};
27
28/// Provides access to all features of the Pitaya Go board
29#[allow(non_snake_case)]
30pub struct Board {
31    /// The nRF52's pins which are not otherwise occupied on the Pitaya Go
32    pub pins: Pins,
33
34    /// The Pitaya Go UART which is wired to the virtual USB CDC port
35    pub cdc: Uarte<nrf52::UARTE0>,
36
37    /// The Pitaya Go SPI which is wired to the SPI flash
38    pub flash: Spim<nrf52::SPIM2>,
39    pub flash_cs: Pin<Output<PushPull>>,
40
41    /// The LEDs on the Pitaya Go board
42    pub leds: Leds,
43
44    /// The buttons on the Pitaya Go board
45    pub buttons: Buttons,
46
47    pub nfc: NFC,
48
49    /// Core peripheral: Cache and branch predictor maintenance operations
50    pub CBP: nrf52::CBP,
51
52    /// Core peripheral: CPUID
53    pub CPUID: nrf52::CPUID,
54
55    /// Core peripheral: Debug Control Block
56    pub DCB: nrf52::DCB,
57
58    /// Core peripheral: Data Watchpoint and Trace unit
59    pub DWT: nrf52::DWT,
60
61    /// Core peripheral: Flash Patch and Breakpoint unit
62    pub FPB: nrf52::FPB,
63
64    /// Core peripheral: Floating Point Unit
65    pub FPU: nrf52::FPU,
66
67    /// Core peripheral: Instrumentation Trace Macrocell
68    pub ITM: nrf52::ITM,
69
70    /// Core peripheral: Memory Protection Unit
71    pub MPU: nrf52::MPU,
72
73    /// Core peripheral: Nested Vector Interrupt Controller
74    pub NVIC: nrf52::NVIC,
75
76    /// Core peripheral: System Control Block
77    pub SCB: nrf52::SCB,
78
79    /// Core peripheral: SysTick Timer
80    pub SYST: nrf52::SYST,
81
82    /// Core peripheral: Trace Port Interface Unit
83    pub TPIU: nrf52::TPIU,
84
85    /// nRF52 peripheral: FICR
86    pub FICR: nrf52::FICR,
87
88    /// nRF52 peripheral: UICR
89    pub UICR: nrf52::UICR,
90
91    /// nRF52 peripheral: ACL
92    pub ACL: nrf52::ACL,
93
94    /// nRF52 peripheral: POWER
95    pub POWER: nrf52::POWER,
96
97    /// nRF52 peripheral: CLOCK
98    pub CLOCK: nrf52::CLOCK,
99
100    /// nRF52 peripheral: RADIO
101    pub RADIO: nrf52::RADIO,
102
103    /// nRF52 peripheral: UART0
104    pub UART0: nrf52::UART0,
105
106    /// nRF52 peripheral: SPIM0
107    pub SPIM0: nrf52::SPIM0,
108
109    /// nRF52 peripheral: SPIS0
110    pub SPIS0: nrf52::SPIS0,
111
112    /// nRF52 peripheral: TWIM0
113    pub TWIM0: nrf52::TWIM0,
114
115    /// nRF52 peripheral: TWIS0
116    pub TWIS0: nrf52::TWIS0,
117
118    /// nRF52 peripheral: SPI0
119    pub SPI0: nrf52::SPI0,
120
121    /// nRF52 peripheral: TWI0
122    pub TWI0: nrf52::TWI0,
123
124    /// nRF52 peripheral: SPIM1
125    pub SPIM1: nrf52::SPIM1,
126
127    /// nRF52 peripheral: SPIS1
128    pub SPIS1: nrf52::SPIS1,
129
130    /// nRF52 peripheral: TWIM1
131    pub TWIM1: nrf52::TWIM1,
132
133    /// nRF52 peripheral: TWIS1
134    pub TWIS1: nrf52::TWIS1,
135
136    /// nRF52 peripheral: SPI1
137    pub SPI1: nrf52::SPI1,
138
139    /// nRF52 peripheral: TWI1
140    pub TWI1: nrf52::TWI1,
141
142    /// nRF52 peripheral: NFCT
143    pub NFCT: nrf52::NFCT,
144
145    /// nRF52 peripheral: GPIOTE
146    pub GPIOTE: nrf52::GPIOTE,
147
148    /// nRF52 peripheral: SAADC
149    pub SAADC: nrf52::SAADC,
150
151    /// nRF52 peripheral: TIMER0
152    pub TIMER0: nrf52::TIMER0,
153
154    /// nRF52 peripheral: TIMER1
155    pub TIMER1: nrf52::TIMER1,
156
157    /// nRF52 peripheral: TIMER2
158    pub TIMER2: nrf52::TIMER2,
159
160    /// nRF52 peripheral: RTC0
161    pub RTC0: nrf52::RTC0,
162
163    /// nRF52 peripheral: TEMP
164    pub TEMP: nrf52::TEMP,
165
166    /// nRF52 peripheral: RNG
167    pub RNG: nrf52::RNG,
168
169    /// nRF52 peripheral: ECB
170    pub ECB: nrf52::ECB,
171
172    /// nRF52 peripheral: CCM
173    pub CCM: nrf52::CCM,
174
175    /// nRF52 peripheral: AAR
176    pub AAR: nrf52::AAR,
177
178    /// nRF52 peripheral: WDT
179    pub WDT: nrf52::WDT,
180
181    /// nRF52 peripheral: RTC1
182    pub RTC1: nrf52::RTC1,
183
184    /// nRF52 peripheral: QDEC
185    pub QDEC: nrf52::QDEC,
186
187    /// nRF52 peripheral: COMP
188    pub COMP: nrf52::COMP,
189
190    /// nRF52 peripheral: LPCOMP
191    pub LPCOMP: nrf52::LPCOMP,
192
193    /// nRF52 peripheral: SWI0
194    pub SWI0: nrf52::SWI0,
195
196    /// nRF52 peripheral: EGU0
197    pub EGU0: nrf52::EGU0,
198
199    /// nRF52 peripheral: SWI1
200    pub SWI1: nrf52::SWI1,
201
202    /// nRF52 peripheral: EGU1
203    pub EGU1: nrf52::EGU1,
204
205    /// nRF52 peripheral: SWI2
206    pub SWI2: nrf52::SWI2,
207
208    /// nRF52 peripheral: EGU2
209    pub EGU2: nrf52::EGU2,
210
211    /// nRF52 peripheral: SWI3
212    pub SWI3: nrf52::SWI3,
213
214    /// nRF52 peripheral: EGU3
215    pub EGU3: nrf52::EGU3,
216
217    /// nRF52 peripheral: SWI4
218    pub SWI4: nrf52::SWI4,
219
220    /// nRF52 peripheral: EGU4
221    pub EGU4: nrf52::EGU4,
222
223    /// nRF52 peripheral: SWI5
224    pub SWI5: nrf52::SWI5,
225
226    /// nRF52 peripheral: EGU5
227    pub EGU5: nrf52::EGU5,
228
229    /// nRF52 peripheral: TIMER3
230    pub TIMER3: nrf52::TIMER3,
231
232    /// nRF52 peripheral: TIMER4
233    pub TIMER4: nrf52::TIMER4,
234
235    /// nRF52 peripheral: PWM0
236    pub PWM0: nrf52::PWM0,
237
238    /// nRF52 peripheral: PDM
239    pub PDM: nrf52::PDM,
240
241    /// nRF52 peripheral: NVMC
242    pub NVMC: nrf52::NVMC,
243
244    /// nRF52 peripheral: PPI
245    pub PPI: nrf52::PPI,
246
247    /// nRF52 peripheral: MWU
248    pub MWU: nrf52::MWU,
249
250    /// nRF52 peripheral: PWM1
251    pub PWM1: nrf52::PWM1,
252
253    /// nRF52 peripheral: PWM2
254    pub PWM2: nrf52::PWM2,
255
256    /// nRF52 peripheral: RTC2
257    pub RTC2: nrf52::RTC2,
258
259    /// nRF52 peripheral: I2S
260    pub I2S: nrf52::I2S,
261}
262
263impl Board {
264    /// Take the peripherals safely
265    ///
266    /// This method will return an instance of `Board` the first time it is
267    /// called. It will return only `None` on subsequent calls.
268    pub fn take() -> Option<Self> {
269        Some(Self::new(CorePeripherals::take()?, Peripherals::take()?))
270    }
271
272    /// Steal the peripherals
273    ///
274    /// This method produces an instance of `Board`, regardless of whether
275    /// another instance was create previously.
276    ///
277    /// # Safety
278    ///
279    /// This method can be used to create multiple instances of `Board`. Those
280    /// instances can interfere with each other, causing all kinds of unexpected
281    /// behavior and circumventing safety guarantees in many ways.
282    ///
283    /// Always use `Board::take`, unless you really know what you're doing.
284    pub unsafe fn steal() -> Self {
285        Self::new(CorePeripherals::steal(), Peripherals::steal())
286    }
287
288    fn new(cp: CorePeripherals, p: Peripherals) -> Self {
289        let pins0 = p0::Parts::new(p.P0);
290        let pins1 = p1::Parts::new(p.P1);
291
292        // The Pitaya Go has an 64MB SPI flash on board which can be interfaced through SPI or Quad SPI.
293        // As for now, only the normal SPI mode is available, so we are using this for the interface.
294        let flash_spim = Spim::new(
295            p.SPIM2,
296            spim::Pins {
297                sck: pins1.p1_04.into_push_pull_output(Level::Low).degrade(),
298                mosi: Some(pins1.p1_06.into_push_pull_output(Level::Low).degrade()),
299                miso: Some(pins1.p1_01.into_floating_input().degrade()),
300            },
301            Frequency::K500,
302            MODE_0,
303            0,
304        );
305
306        let flash_cs = pins1.p1_03.into_push_pull_output(Level::High).degrade();
307
308        // The Pitaya Go features an USB CDC port.
309        // It features HWFC but does not have to use it.
310        // It can transmit a flexible baudrate of up to 1Mbps.
311        let cdc_uart = Uarte::new(
312            p.UARTE0,
313            uarte::Pins {
314                txd: pins0.p0_26.into_push_pull_output(Level::High).degrade(),
315                rxd: pins0.p0_27.into_floating_input().degrade(),
316                cts: None, // Some(pins0.p0_07.into_floating_input().degrade()),
317                rts: None, // Some(pins0.p0_05.into_push_pull_output(Level::High).degrade()),
318            },
319            UartParity::EXCLUDED,
320            UartBaudrate::BAUD115200,
321        );
322
323        Board {
324            cdc: cdc_uart,
325            flash: flash_spim,
326            flash_cs,
327
328            pins: Pins {
329                _RESET: pins0.p0_19,
330                P13: pins0.p0_13,
331                P14: pins0.p0_14,
332                P15: pins0.p0_15,
333                P16: pins0.p0_16,
334                P17: pins0.p0_17,
335                P20: pins0.p0_20,
336                P21: pins0.p0_21,
337                P22: pins0.p0_22,
338                P23: pins0.p0_23,
339                P24: pins0.p0_24,
340                P25: pins0.p0_25,
341                A1: pins0.p0_03,
342                A2: pins0.p0_04,
343                A3: pins0.p0_05,
344                A4: pins0.p0_28,
345                A5: pins0.p0_29,
346                A6: pins0.p0_30,
347                A7: pins0.p0_31,
348            },
349
350            leds: Leds {
351                led_r: Led::new(pins1.p1_10.degrade()),
352                led_g: Led::new(pins1.p1_11.degrade()),
353                led_b: Led::new(pins1.p1_12.degrade()),
354            },
355
356            buttons: Buttons {
357                button_1: Button::new(pins1.p1_00.degrade()),
358            },
359
360            nfc: NFC {
361                nfc_1: pins0.p0_09,
362                nfc_2: pins0.p0_10,
363            },
364
365            // Core peripherals
366            CBP: cp.CBP,
367            CPUID: cp.CPUID,
368            DCB: cp.DCB,
369            DWT: cp.DWT,
370            FPB: cp.FPB,
371            FPU: cp.FPU,
372            ITM: cp.ITM,
373            MPU: cp.MPU,
374            NVIC: cp.NVIC,
375            SCB: cp.SCB,
376            SYST: cp.SYST,
377            TPIU: cp.TPIU,
378
379            // nRF52 peripherals
380            FICR: p.FICR,
381            UICR: p.UICR,
382            ACL: p.ACL,
383            POWER: p.POWER,
384            CLOCK: p.CLOCK,
385            RADIO: p.RADIO,
386
387            UART0: p.UART0,
388            SPIM0: p.SPIM0,
389            SPIS0: p.SPIS0,
390            TWIM0: p.TWIM0,
391            TWIS0: p.TWIS0,
392            SPI0: p.SPI0,
393            TWI0: p.TWI0,
394            SPIM1: p.SPIM1,
395            SPIS1: p.SPIS1,
396            TWIM1: p.TWIM1,
397            TWIS1: p.TWIS1,
398            SPI1: p.SPI1,
399            TWI1: p.TWI1,
400            NFCT: p.NFCT,
401            GPIOTE: p.GPIOTE,
402            SAADC: p.SAADC,
403            TIMER0: p.TIMER0,
404            TIMER1: p.TIMER1,
405            TIMER2: p.TIMER2,
406            RTC0: p.RTC0,
407            TEMP: p.TEMP,
408            RNG: p.RNG,
409            ECB: p.ECB,
410            CCM: p.CCM,
411            AAR: p.AAR,
412            WDT: p.WDT,
413            RTC1: p.RTC1,
414            QDEC: p.QDEC,
415            COMP: p.COMP,
416            LPCOMP: p.LPCOMP,
417            SWI0: p.SWI0,
418            EGU0: p.EGU0,
419            SWI1: p.SWI1,
420            EGU1: p.EGU1,
421            SWI2: p.SWI2,
422            EGU2: p.EGU2,
423            SWI3: p.SWI3,
424            EGU3: p.EGU3,
425            SWI4: p.SWI4,
426            EGU4: p.EGU4,
427            SWI5: p.SWI5,
428            EGU5: p.EGU5,
429            TIMER3: p.TIMER3,
430            TIMER4: p.TIMER4,
431            PWM0: p.PWM0,
432            PDM: p.PDM,
433            NVMC: p.NVMC,
434            PPI: p.PPI,
435            MWU: p.MWU,
436            PWM1: p.PWM1,
437            PWM2: p.PWM2,
438            RTC2: p.RTC2,
439            I2S: p.I2S,
440        }
441    }
442}
443
444/// The nRF52 pins that are available on the Pitaya Go
445#[allow(non_snake_case)]
446pub struct Pins {
447    _RESET: p0::P0_19<Disconnected>,
448    pub P13: p0::P0_13<Disconnected>,
449    pub P14: p0::P0_14<Disconnected>,
450    pub P15: p0::P0_15<Disconnected>,
451    pub P16: p0::P0_16<Disconnected>,
452    pub P17: p0::P0_17<Disconnected>,
453    pub P20: p0::P0_20<Disconnected>,
454    pub P21: p0::P0_21<Disconnected>,
455    pub P22: p0::P0_22<Disconnected>,
456    pub P23: p0::P0_23<Disconnected>,
457    pub P24: p0::P0_24<Disconnected>,
458    pub P25: p0::P0_25<Disconnected>,
459    pub A1: p0::P0_03<Disconnected>,
460    pub A2: p0::P0_04<Disconnected>,
461    pub A3: p0::P0_05<Disconnected>,
462    pub A4: p0::P0_28<Disconnected>,
463    pub A5: p0::P0_29<Disconnected>,
464    pub A6: p0::P0_30<Disconnected>,
465    pub A7: p0::P0_31<Disconnected>,
466}
467
468/// The LEDs on the Pitaya Go board
469pub struct Leds {
470    pub led_r: Led,
471    pub led_g: Led,
472    pub led_b: Led,
473}
474
475/// An LED on the Pitaya Go board
476pub struct Led(Pin<Output<PushPull>>);
477
478impl Led {
479    fn new<Mode>(pin: Pin<Mode>) -> Self {
480        Led(pin.into_push_pull_output(Level::High))
481    }
482
483    /// Release the inner Pin to be used directly
484    pub fn release(self) -> Pin<Output<PushPull>> {
485        self.0
486    }
487
488    /// Enable the LED
489    pub fn enable(&mut self) {
490        self.0.set_low().unwrap()
491    }
492
493    /// Disable the LED
494    pub fn disable(&mut self) {
495        self.0.set_high().unwrap()
496    }
497}
498
499/// The Buttons on the Pitaya Go board
500pub struct Buttons {
501    pub button_1: Button,
502}
503
504/// A Button on the Pitaya Go board
505pub struct Button(Pin<Input<PullUp>>);
506
507impl Button {
508    fn new<Mode>(pin: Pin<Mode>) -> Self {
509        Button(pin.into_pullup_input())
510    }
511
512    /// Release the inner Pin to be used directly
513    pub fn release(self) -> Pin<Input<PullUp>> {
514        self.0
515    }
516
517    /// Button is pressed
518    pub fn is_pressed(&self) -> bool {
519        self.0.is_low().unwrap()
520    }
521
522    /// Button is released
523    pub fn is_released(&self) -> bool {
524        self.0.is_high().unwrap()
525    }
526}
527
528/// The NFC pins on the Pitaya Go board
529pub struct NFC {
530    /// Pitaya Go: NFC1, nRF52: P0.09
531    pub nfc_1: p0::P0_09<Disconnected>,
532
533    /// Pitaya Go: NFC2, nRF52: P0.10
534    pub nfc_2: p0::P0_10<Disconnected>,
535}