//! GPIO module. use super::memory_map::gpio::*; /// The number of pin for the raspberry 3. const NUMBER_PIN: usize = 54; /// Value to select the INPUT function of a PIN. const FSEL_INPUT: u32 = 0b000; /// Value to select the OUTPUT function of a PIN. const FSEL_OUTPUT: u32 = 0b001; /// Value to select the Alternate function 0 of a PIN. const FSEL_ALTF0: u32 = 0b100; /// Value to select the Alternate function 1 of a PIN. const FSEL_ALTF1: u32 = 0b101; /// Value to select the Alternate function 2 of a PIN. const FSEL_ALTF2: u32 = 0b110; /// Value to select the Alternate function 3 of a PIN. const FSEL_ALTF3: u32 = 0b111; /// Value to select the Alternate function 4 of a PIN. const FSEL_ALTF4: u32 = 0b011; /// Value to select the Alternate function 5 of a PIN. const FSEL_ALTF5: u32 = 0b010; /// The possible PIN functions. pub enum PinFunction { Input, Output, AltFunc0, AltFunc1, AltFunc2, AltFunc3, AltFunc4, AltFunc5, } /// The possible PIN state when in Output mode. pub enum PinOutputState { High, Low, } impl From for u32 { fn from(function: PinFunction) -> u32 { match function { PinFunction::Input => FSEL_INPUT, PinFunction::Output => FSEL_OUTPUT, PinFunction::AltFunc0 => FSEL_ALTF0, PinFunction::AltFunc1 => FSEL_ALTF1, PinFunction::AltFunc2 => FSEL_ALTF2, PinFunction::AltFunc3 => FSEL_ALTF3, PinFunction::AltFunc4 => FSEL_ALTF4, PinFunction::AltFunc5 => FSEL_ALTF5, } } } // TODO: remove Result and use an enum instead of usize /// Set the function of a Pin. /// /// # Result /// /// Return an error if the PIN does not exist. pub fn set_pin_fonction(n: usize, function: PinFunction) -> Result<(), &'static str> { if n >= NUMBER_PIN { return Err("The pin does not exist."); } let field = get_fsel(n); // TODO: SYNC let address = field.get_address(); let mut val = unsafe { core::ptr::read_volatile(address as *mut u32) }; val &= !field.get_mask(); val |= Into::::into(function) << field.get_offset(); unsafe { core::ptr::write_volatile(address as *mut u32, val); } Ok(()) } // TODO: remove Result and use an enum instead of usize /// Set the state of an output Pin. /// /// # Result /// /// Return an error if the PIN does not exist. pub fn set_pin_output_state(n: usize, state: PinOutputState) -> Result<(), &'static str> { if n >= NUMBER_PIN { return Err("The pin does not exist."); } let field = match state { PinOutputState::High => get_set(n), PinOutputState::Low => get_clr(n), }; let val = field.get_mask(); let address = field.get_address(); // 0 has no effect on this field: no nead to read-modify-write unsafe { core::ptr::write_volatile(address as *mut u32, val); } Ok(()) }