#![no_std]
#![deny(missing_docs)]
pub use cortex_m;
#[cfg(feature = "rt")]
pub use cortex_m_rt;
pub use dw1000;
pub use embedded_hal;
pub use nrf52832_hal;
pub use embedded_timeout_macros::{block_timeout, repeat_timeout};
pub mod prelude {
pub use nrf52832_hal::prelude::*;
}
use cortex_m::{asm, interrupt};
use dw1000::DW1000;
use embedded_hal::blocking::delay::DelayMs;
use nrf52832_hal::{
gpio::{
p0::{self, P0_16, P0_17, P0_18, P0_20, P0_28, P0_29},
Disconnected, Floating, Input, Level, OpenDrainConfig, Output, PushPull,
},
pac::{self as nrf52, CorePeripherals, Interrupt, Peripherals, SPIM2, TWIM1},
spim, timer, twim,
uarte::{Baudrate as UartBaudrate, Parity as UartParity},
Spim, Timer, Twim,
};
#[cfg(feature = "dev")]
use nrf52832_hal::{
gpio::{
p0::{P0_05, P0_11},
Pin,
},
pac::UARTE0,
prelude::*,
uarte::{self, Uarte},
};
pub struct SpimConfig {
pub frequency: spim::Frequency,
pub mode: spim::Mode,
pub orc: u8,
}
#[cfg(feature = "dev")]
pub fn new_usb_uarte<TX, RX>(
uart0: UARTE0,
txd_pin: P0_05<TX>,
rxd_pin: P0_11<RX>,
config: UsbUarteConfig,
) -> Uarte<nrf52::UARTE0> {
Uarte::new(
uart0,
uarte::Pins {
txd: txd_pin.into_push_pull_output(Level::High).degrade(),
rxd: rxd_pin.into_floating_input().degrade(),
cts: None,
rts: None,
},
config.parity,
config.baudrate,
)
}
pub fn new_dw1000<SCK, MOSI, MISO, CS>(
spim: SPIM2,
sck: P0_16<SCK>,
mosi: P0_20<MOSI>,
miso: P0_18<MISO>,
cs: P0_17<CS>,
spim_opts: Option<SpimConfig>,
) -> DW1000<Spim<nrf52::SPIM2>, p0::P0_17<Output<PushPull>>, dw1000::Uninitialized> {
let cfg = spim_opts.unwrap_or_else(|| SpimConfig {
frequency: spim::Frequency::K500,
mode: spim::MODE_0,
orc: 0,
});
let spim = Spim::new(
spim,
spim::Pins {
sck: sck.into_push_pull_output(Level::Low).degrade(),
mosi: Some(mosi.into_push_pull_output(Level::Low).degrade()),
miso: Some(miso.into_floating_input().degrade()),
},
cfg.frequency,
cfg.mode,
cfg.orc,
);
DW1000::new(spim, cs.into_push_pull_output(Level::High))
}
pub fn new_acc_twim<SCL, SDA>(twim: TWIM1, scl: P0_28<SCL>, sda: P0_29<SDA>) -> Twim<nrf52::TWIM1> {
Twim::new(
twim,
twim::Pins {
scl: scl.into_floating_input().degrade(),
sda: sda.into_floating_input().degrade(),
},
twim::Frequency::K250,
)
}
pub struct UsbUarteConfig {
pub parity: UartParity,
pub baudrate: UartBaudrate,
}
impl Default for UsbUarteConfig {
fn default() -> UsbUarteConfig {
UsbUarteConfig {
parity: UartParity::EXCLUDED,
baudrate: UartBaudrate::BAUD115200,
}
}
}
#[allow(non_snake_case)]
pub struct DWM1001 {
pub pins: Pins,
#[cfg(feature = "dev")]
pub leds: Leds,
#[cfg(feature = "dev")]
pub uart: Uarte<nrf52::UARTE0>,
pub DW_RST: DW_RST,
pub DW_IRQ: DW_IRQ,
pub DW1000: DW1000<Spim<nrf52::SPIM2>, p0::P0_17<Output<PushPull>>, dw1000::Uninitialized>,
pub LIS2DH12: Twim<nrf52::TWIM1>,
pub CBP: nrf52::CBP,
pub CPUID: nrf52::CPUID,
pub DCB: nrf52::DCB,
pub DWT: nrf52::DWT,
pub FPB: nrf52::FPB,
pub FPU: nrf52::FPU,
pub ITM: nrf52::ITM,
pub MPU: nrf52::MPU,
pub NVIC: nrf52::NVIC,
pub SCB: nrf52::SCB,
pub SYST: nrf52::SYST,
pub TPIU: nrf52::TPIU,
pub FICR: nrf52::FICR,
pub UICR: nrf52::UICR,
pub BPROT: nrf52::BPROT,
pub POWER: nrf52::POWER,
pub CLOCK: nrf52::CLOCK,
pub RADIO: nrf52::RADIO,
#[cfg(not(feature = "dev"))]
pub UARTE0: nrf52::UARTE0,
pub UART0: nrf52::UART0,
pub SPIM0: nrf52::SPIM0,
pub SPIS0: nrf52::SPIS0,
pub TWIM0: nrf52::TWIM0,
pub TWIS0: nrf52::TWIS0,
pub SPI0: nrf52::SPI0,
pub TWI0: nrf52::TWI0,
pub SPIM1: nrf52::SPIM1,
pub SPIS1: nrf52::SPIS1,
pub TWIS1: nrf52::TWIS1,
pub SPI1: nrf52::SPI1,
pub TWI1: nrf52::TWI1,
pub NFCT: nrf52::NFCT,
pub GPIOTE: nrf52::GPIOTE,
pub SAADC: nrf52::SAADC,
pub TIMER0: nrf52::TIMER0,
pub TIMER1: nrf52::TIMER1,
pub TIMER2: nrf52::TIMER2,
pub RTC0: nrf52::RTC0,
pub TEMP: nrf52::TEMP,
pub RNG: nrf52::RNG,
pub ECB: nrf52::ECB,
pub CCM: nrf52::CCM,
pub AAR: nrf52::AAR,
pub WDT: nrf52::WDT,
pub RTC1: nrf52::RTC1,
pub QDEC: nrf52::QDEC,
pub COMP: nrf52::COMP,
pub LPCOMP: nrf52::LPCOMP,
pub SWI0: nrf52::SWI0,
pub EGU0: nrf52::EGU0,
pub SWI1: nrf52::SWI1,
pub EGU1: nrf52::EGU1,
pub SWI2: nrf52::SWI2,
pub EGU2: nrf52::EGU2,
pub SWI3: nrf52::SWI3,
pub EGU3: nrf52::EGU3,
pub SWI4: nrf52::SWI4,
pub EGU4: nrf52::EGU4,
pub SWI5: nrf52::SWI5,
pub EGU5: nrf52::EGU5,
pub TIMER3: nrf52::TIMER3,
pub TIMER4: nrf52::TIMER4,
pub PWM0: nrf52::PWM0,
pub PDM: nrf52::PDM,
pub NVMC: nrf52::NVMC,
pub PPI: nrf52::PPI,
pub MWU: nrf52::MWU,
pub PWM1: nrf52::PWM1,
pub PWM2: nrf52::PWM2,
pub RTC2: nrf52::RTC2,
pub I2S: nrf52::I2S,
}
impl DWM1001 {
pub fn take() -> Option<Self> {
Some(Self::new(CorePeripherals::take()?, Peripherals::take()?))
}
pub unsafe fn steal() -> Self {
Self::new(CorePeripherals::steal(), Peripherals::steal())
}
fn new(cp: CorePeripherals, p: Peripherals) -> Self {
let pins = p0::Parts::new(p.P0);
#[cfg(feature = "dev")]
let uarte0 = new_usb_uarte(p.UARTE0, pins.p0_05, pins.p0_11, UsbUarteConfig::default());
DWM1001 {
#[cfg(feature = "dev")]
uart: uarte0,
pins: Pins {
BT_WAKE_UP: pins.p0_02,
SPIS_CSn: pins.p0_03,
SPIS_CLK: pins.p0_04,
SPIS_MOSI: pins.p0_06,
SPIS_MISO: pins.p0_07,
RESETn: pins.p0_21,
READY: pins.p0_26,
GPIO_8: pins.p0_08,
GPIO_9: pins.p0_09,
GPIO_10: pins.p0_10,
GPIO_12: pins.p0_12,
GPIO_13: pins.p0_13,
GPIO_15: pins.p0_15,
GPIO_23: pins.p0_23,
GPIO_27: pins.p0_27,
#[cfg(not(feature = "dev"))]
UART_RX: pins.p0_11,
#[cfg(not(feature = "dev"))]
UART_TX: pins.p0_05,
#[cfg(not(feature = "dev"))]
GPIO_14: pins.p0_14,
#[cfg(not(feature = "dev"))]
GPIO_22: pins.p0_22,
#[cfg(not(feature = "dev"))]
GPIO_30: pins.p0_30,
#[cfg(not(feature = "dev"))]
GPIO_31: pins.p0_31,
IRQ_ACC: pins.p0_25,
},
#[cfg(feature = "dev")]
leds: Leds {
D9: Led::new(pins.p0_30.degrade()),
D10: Led::new(pins.p0_31.degrade()),
D11: Led::new(pins.p0_22.degrade()),
D12: Led::new(pins.p0_14.degrade()),
},
DW_RST: DW_RST::new(pins.p0_24),
DW_IRQ: DW_IRQ::new(pins.p0_19),
DW1000: new_dw1000(
p.SPIM2, pins.p0_16, pins.p0_20, pins.p0_18, pins.p0_17, None,
),
LIS2DH12: new_acc_twim(p.TWIM1, pins.p0_28, pins.p0_29),
CBP: cp.CBP,
CPUID: cp.CPUID,
DCB: cp.DCB,
DWT: cp.DWT,
FPB: cp.FPB,
FPU: cp.FPU,
ITM: cp.ITM,
MPU: cp.MPU,
NVIC: cp.NVIC,
SCB: cp.SCB,
SYST: cp.SYST,
TPIU: cp.TPIU,
FICR: p.FICR,
UICR: p.UICR,
BPROT: p.BPROT,
POWER: p.POWER,
CLOCK: p.CLOCK,
RADIO: p.RADIO,
#[cfg(not(feature = "dev"))]
UARTE0: p.UARTE0,
UART0: p.UART0,
SPIM0: p.SPIM0,
SPIS0: p.SPIS0,
TWIM0: p.TWIM0,
TWIS0: p.TWIS0,
SPI0: p.SPI0,
TWI0: p.TWI0,
SPIM1: p.SPIM1,
SPIS1: p.SPIS1,
TWIS1: p.TWIS1,
SPI1: p.SPI1,
TWI1: p.TWI1,
NFCT: p.NFCT,
GPIOTE: p.GPIOTE,
SAADC: p.SAADC,
TIMER0: p.TIMER0,
TIMER1: p.TIMER1,
TIMER2: p.TIMER2,
RTC0: p.RTC0,
TEMP: p.TEMP,
RNG: p.RNG,
ECB: p.ECB,
CCM: p.CCM,
AAR: p.AAR,
WDT: p.WDT,
RTC1: p.RTC1,
QDEC: p.QDEC,
COMP: p.COMP,
LPCOMP: p.LPCOMP,
SWI0: p.SWI0,
EGU0: p.EGU0,
SWI1: p.SWI1,
EGU1: p.EGU1,
SWI2: p.SWI2,
EGU2: p.EGU2,
SWI3: p.SWI3,
EGU3: p.EGU3,
SWI4: p.SWI4,
EGU4: p.EGU4,
SWI5: p.SWI5,
EGU5: p.EGU5,
TIMER3: p.TIMER3,
TIMER4: p.TIMER4,
PWM0: p.PWM0,
PDM: p.PDM,
NVMC: p.NVMC,
PPI: p.PPI,
MWU: p.MWU,
PWM1: p.PWM1,
PWM2: p.PWM2,
RTC2: p.RTC2,
I2S: p.I2S,
}
}
}
#[allow(non_snake_case)]
pub struct Pins {
pub BT_WAKE_UP: p0::P0_02<Disconnected>,
pub SPIS_CSn: p0::P0_03<Disconnected>,
pub SPIS_CLK: p0::P0_04<Disconnected>,
#[cfg(not(feature = "dev"))]
pub UART_TX: p0::P0_05<Disconnected>,
pub SPIS_MOSI: p0::P0_06<Disconnected>,
pub SPIS_MISO: p0::P0_07<Disconnected>,
#[cfg(not(feature = "dev"))]
pub UART_RX: p0::P0_11<Disconnected>,
pub RESETn: p0::P0_21<Disconnected>,
pub READY: p0::P0_26<Disconnected>,
pub GPIO_8: p0::P0_08<Disconnected>,
pub GPIO_9: p0::P0_09<Disconnected>,
pub GPIO_10: p0::P0_10<Disconnected>,
pub GPIO_12: p0::P0_12<Disconnected>,
pub GPIO_13: p0::P0_13<Disconnected>,
pub GPIO_15: p0::P0_15<Disconnected>,
pub GPIO_23: p0::P0_23<Disconnected>,
pub GPIO_27: p0::P0_27<Disconnected>,
#[cfg(not(feature = "dev"))]
pub GPIO_14: p0::P0_14<Disconnected>,
#[cfg(not(feature = "dev"))]
pub GPIO_22: p0::P0_22<Disconnected>,
#[cfg(not(feature = "dev"))]
pub GPIO_30: p0::P0_30<Disconnected>,
#[cfg(not(feature = "dev"))]
pub GPIO_31: p0::P0_31<Disconnected>,
pub IRQ_ACC: p0::P0_25<Disconnected>,
}
#[allow(non_snake_case)]
#[cfg(feature = "dev")]
pub struct Leds {
pub D9: Led,
pub D10: Led,
pub D11: Led,
pub D12: Led,
}
#[cfg(feature = "dev")]
pub struct Led(Pin<Output<PushPull>>);
#[cfg(feature = "dev")]
impl Led {
pub fn new<Mode>(pin: Pin<Mode>) -> Self {
Led(pin.into_push_pull_output(Level::High))
}
pub fn enable(&mut self) {
self.0.set_low().unwrap();
}
pub fn disable(&mut self) {
self.0.set_high().unwrap();
}
}
#[allow(non_camel_case_types)]
pub struct DW_RST(Option<p0::P0_24<Input<Floating>>>);
impl DW_RST {
pub fn new<Mode>(p0_24: p0::P0_24<Mode>) -> Self {
DW_RST(Some(p0_24.into_floating_input()))
}
pub fn reset_dw1000<D>(&mut self, delay: &mut D)
where
D: DelayMs<u32>,
{
let dw_rst = self
.0
.take()
.unwrap()
.into_open_drain_output(OpenDrainConfig::Standard0Disconnect1, Level::Low);
delay.delay_ms(2);
self.0 = Some(dw_rst.into_floating_input());
delay.delay_ms(5);
}
}
#[allow(non_camel_case_types)]
pub struct DW_IRQ(p0::P0_19<Input<Floating>>);
impl DW_IRQ {
pub fn new<Mode>(p0_19: p0::P0_19<Mode>) -> Self {
DW_IRQ(p0_19.into_floating_input())
}
pub fn wait_for_interrupts<T>(&mut self, gpiote: &mut nrf52::GPIOTE, timer: &mut Timer<T>)
where
T: timer::Instance,
{
gpiote.config[0].write(|w| {
let w = w.mode().event().polarity().lo_to_hi();
unsafe { w.psel().bits(19) }
});
gpiote.intenset.modify(|_, w| w.in0().set());
interrupt::free(|_| {
nrf52::NVIC::unpend(Interrupt::GPIOTE);
nrf52::NVIC::unpend(T::INTERRUPT);
unsafe {
nrf52::NVIC::unmask(Interrupt::GPIOTE);
}
timer.enable_interrupt();
asm::dsb();
asm::wfi();
nrf52::NVIC::mask(Interrupt::GPIOTE);
timer.disable_interrupt();
});
gpiote.events_in[0].write(|w| unsafe { w.bits(0) });
gpiote.intenclr.modify(|_, w| w.in0().clear());
}
pub fn free(self) -> p0::P0_19<Input<Floating>> {
self.0
}
}