nrf/gpio: add output drive config.

This commit is contained in:
Dario Nieuwenhuis 2021-03-20 01:36:00 +01:00
parent fcf6a63b5c
commit 3d3e770b8d

View File

@ -2,26 +2,12 @@ use core::convert::Infallible;
use core::hint::unreachable_unchecked; use core::hint::unreachable_unchecked;
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
use gpio::pin_cnf::DRIVE_A;
use crate::pac; use crate::pac;
use crate::pac::p0 as gpio; use crate::pac::p0 as gpio;
use crate::peripherals; use crate::peripherals;
/// Represents a digital input or output level.
#[derive(Debug, Eq, PartialEq)]
pub enum Level {
Low,
High,
}
/// Represents a pull setting for an input.
#[derive(Debug, Eq, PartialEq)]
pub enum Pull {
None,
Up,
Down,
}
/// A GPIO port with up to 32 pins. /// A GPIO port with up to 32 pins.
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum Port { pub enum Port {
@ -33,6 +19,16 @@ pub enum Port {
Port1, Port1,
} }
/// Pull setting for an input.
#[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Pull {
None,
Up,
Down,
}
/// GPIO input driver.
pub struct Input<T: Pin> { pub struct Input<T: Pin> {
pin: T, pin: T,
} }
@ -80,18 +76,64 @@ impl<T: Pin> InputPin for Input<T> {
} }
} }
/// Digital input or output level.
#[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Level {
Low,
High,
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum OutputDrive {
/// Standard '0', standard '1'
Standard = 0,
/// High drive '0', standard '1'
HighDrive0Standard1 = 1,
/// Standard '0', high drive '1'
Standard0HighDrive1 = 2,
/// High drive '0', high 'drive '1'
HighDrive = 3,
/// Disconnect '0' standard '1' (normally used for wired-or connections)
Disconnect0Standard1 = 4,
/// Disconnect '0', high drive '1' (normally used for wired-or connections)
Disconnect0HighDrive1 = 5,
/// Standard '0'. disconnect '1' (also known as "open drain", normally used for wired-and connections)
Standard0Disconnect1 = 6,
/// High drive '0', disconnect '1' (also known as "open drain", normally used for wired-and connections)
HighDrive0Disconnect1 = 7,
}
/// GPIO output driver.
pub struct Output<T: Pin> { pub struct Output<T: Pin> {
pin: T, pin: T,
} }
impl<T: Pin> Output<T> { impl<T: Pin> Output<T> {
// TODO opendrain pub fn new(pin: T, initial_output: Level, drive: OutputDrive) -> Self {
pub fn new(pin: T, initial_output: Level) -> Self { match initial_output {
Level::High => pin.set_high(),
Level::Low => pin.set_low(),
}
let drive = match drive {
OutputDrive::Standard => DRIVE_A::S0S1,
OutputDrive::HighDrive0Standard1 => DRIVE_A::H0S1,
OutputDrive::Standard0HighDrive1 => DRIVE_A::S0H1,
OutputDrive::HighDrive => DRIVE_A::H0H1,
OutputDrive::Disconnect0Standard1 => DRIVE_A::D0S1,
OutputDrive::Disconnect0HighDrive1 => DRIVE_A::D0H1,
OutputDrive::Standard0Disconnect1 => DRIVE_A::S0D1,
OutputDrive::HighDrive0Disconnect1 => DRIVE_A::H0D1,
};
pin.conf().write(|w| { pin.conf().write(|w| {
w.dir().output(); w.dir().output();
w.input().disconnect(); w.input().disconnect();
w.pull().disabled(); w.pull().disabled();
w.drive().s0s1(); w.drive().variant(drive);
w.sense().disabled(); w.sense().disabled();
w w
}); });
@ -195,11 +237,13 @@ pub(crate) mod sealed {
} }
pub trait Pin: sealed::Pin + Sized { pub trait Pin: sealed::Pin + Sized {
/// Number of the pin within the port (0..31)
#[inline] #[inline]
fn pin(&self) -> u8 { fn pin(&self) -> u8 {
self._pin() self._pin()
} }
/// Port of the pin
#[inline] #[inline]
fn port(&self) -> Port { fn port(&self) -> Port {
match self.pin_port() / 32 { match self.pin_port() / 32 {
@ -215,6 +259,7 @@ pub trait Pin: sealed::Pin + Sized {
self.pin_port() as u32 self.pin_port() as u32
} }
/// Convert from concrete pin type PX_XX to type erased `AnyPin`.
fn degrade(self) -> AnyPin { fn degrade(self) -> AnyPin {
AnyPin { AnyPin {
pin_port: self.pin_port(), pin_port: self.pin_port(),
@ -222,12 +267,13 @@ pub trait Pin: sealed::Pin + Sized {
} }
} }
// Type-erased GPIO pin
pub struct AnyPin { pub struct AnyPin {
pin_port: u8, pin_port: u8,
} }
impl AnyPin { impl AnyPin {
pub unsafe fn from_psel_bits(psel_bits: u32) -> Self { pub unsafe fn steal_from_psel_bits(psel_bits: u32) -> Self {
Self { Self {
pin_port: psel_bits as u8, pin_port: psel_bits as u8,
} }