//! A not-very-useful abstraction of GPIOs in Rust #![allow(dead_code)] use core::sync::atomic::{AtomicBool, Ordering::SeqCst}; const REG_P0_PIN_CNF_BASE: *mut u32 = 0x5000_0700 as *mut u32; const REG_P0_OUT_SET: *mut u32 = 0x5000_0508 as *mut u32; const REG_P0_OUT_CLR: *mut u32 = 0x5000_050C as *mut u32; const PIN_CNF_DIR_OUTPUT: u32 = 0x0000_0001; const PIN_CNF_INPUT_CONNECT: u32 = 0x0000_0000; const PIN_CNF_PULL_DISABLED: u32 = 0x0000_0000; const PIN_CNF_DRIVE_S0S1: u32 = 0x0000_0000; const PIN_CNF_SENSE_DISABLED: u32 = 0x0000_0000; /// A struct that represents an nRF52 Pin pub struct Pin(u8); impl Pin { /// Set a pin to be a push pull output pub fn set_push_pull_output(&mut self, level: Level) { // set level match level { Level::High => self.set_high(), Level::Low => self.set_low(), } let set_val = PIN_CNF_DIR_OUTPUT | PIN_CNF_INPUT_CONNECT | PIN_CNF_PULL_DISABLED | PIN_CNF_DRIVE_S0S1 | PIN_CNF_SENSE_DISABLED; unsafe { core::ptr::write_volatile(REG_P0_PIN_CNF_BASE.offset(self.0 as isize), set_val); } } /// Set a pin to output level low pub fn set_low(&mut self) { unsafe { core::ptr::write_volatile(REG_P0_OUT_SET, 1 << (self.0 as u32)) } } /// Set a pin to output level high pub fn set_high(&mut self) { unsafe { core::ptr::write_volatile(REG_P0_OUT_CLR, 1 << (self.0 as u32)) } } } /// The level of a GPIO #[derive(Copy, Clone)] pub enum Level { Low, High, } /// A struct that represents P0 of the nRF52 pub struct Pins { pub p0_31: Pin, } impl Pins { /// A function to obtain a Port 0 singleton structure pub fn take() -> Self { static TAKEN: AtomicBool = AtomicBool::new(false); // Enforce this as a singleton assert!(!TAKEN.swap(true, SeqCst)); Self { p0_31: Pin(31) } } }