aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-20 01:36:00 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-29 00:58:57 +0200
commit3d3e770b8dca9adb50b02f14d0087fe40ee1ce35 (patch)
tree60cf926885bbdbc4a2d43488e9570977a9a6e586
parentfcf6a63b5cf1d1505ec01ea42a1a75f33794b038 (diff)
nrf/gpio: add output drive config.
-rw-r--r--embassy-nrf/src/gpio.rs84
1 files changed, 65 insertions, 19 deletions
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 9f4604b0a..52cb57319 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -2,26 +2,12 @@ use core::convert::Infallible;
2use core::hint::unreachable_unchecked; 2use core::hint::unreachable_unchecked;
3 3
4use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; 4use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
5use gpio::pin_cnf::DRIVE_A;
5 6
6use crate::pac; 7use crate::pac;
7use crate::pac::p0 as gpio; 8use crate::pac::p0 as gpio;
8use crate::peripherals; 9use crate::peripherals;
9 10
10/// Represents a digital input or output level.
11#[derive(Debug, Eq, PartialEq)]
12pub enum Level {
13 Low,
14 High,
15}
16
17/// Represents a pull setting for an input.
18#[derive(Debug, Eq, PartialEq)]
19pub enum Pull {
20 None,
21 Up,
22 Down,
23}
24
25/// A GPIO port with up to 32 pins. 11/// A GPIO port with up to 32 pins.
26#[derive(Debug, Eq, PartialEq)] 12#[derive(Debug, Eq, PartialEq)]
27pub enum Port { 13pub enum Port {
@@ -33,6 +19,16 @@ pub enum Port {
33 Port1, 19 Port1,
34} 20}
35 21
22/// Pull setting for an input.
23#[derive(Debug, Eq, PartialEq)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub enum Pull {
26 None,
27 Up,
28 Down,
29}
30
31/// GPIO input driver.
36pub struct Input<T: Pin> { 32pub struct Input<T: Pin> {
37 pin: T, 33 pin: T,
38} 34}
@@ -80,18 +76,64 @@ impl<T: Pin> InputPin for Input<T> {
80 } 76 }
81} 77}
82 78
79/// Digital input or output level.
80#[derive(Debug, Eq, PartialEq)]
81#[cfg_attr(feature = "defmt", derive(defmt::Format))]
82pub enum Level {
83 Low,
84 High,
85}
86
87#[derive(Clone, Copy, Debug, PartialEq)]
88#[cfg_attr(feature = "defmt", derive(defmt::Format))]
89#[repr(u8)]
90pub enum OutputDrive {
91 /// Standard '0', standard '1'
92 Standard = 0,
93 /// High drive '0', standard '1'
94 HighDrive0Standard1 = 1,
95 /// Standard '0', high drive '1'
96 Standard0HighDrive1 = 2,
97 /// High drive '0', high 'drive '1'
98 HighDrive = 3,
99 /// Disconnect '0' standard '1' (normally used for wired-or connections)
100 Disconnect0Standard1 = 4,
101 /// Disconnect '0', high drive '1' (normally used for wired-or connections)
102 Disconnect0HighDrive1 = 5,
103 /// Standard '0'. disconnect '1' (also known as "open drain", normally used for wired-and connections)
104 Standard0Disconnect1 = 6,
105 /// High drive '0', disconnect '1' (also known as "open drain", normally used for wired-and connections)
106 HighDrive0Disconnect1 = 7,
107}
108
109/// GPIO output driver.
83pub struct Output<T: Pin> { 110pub struct Output<T: Pin> {
84 pin: T, 111 pin: T,
85} 112}
86 113
87impl<T: Pin> Output<T> { 114impl<T: Pin> Output<T> {
88 // TODO opendrain 115 pub fn new(pin: T, initial_output: Level, drive: OutputDrive) -> Self {
89 pub fn new(pin: T, initial_output: Level) -> Self { 116 match initial_output {
117 Level::High => pin.set_high(),
118 Level::Low => pin.set_low(),
119 }
120
121 let drive = match drive {
122 OutputDrive::Standard => DRIVE_A::S0S1,
123 OutputDrive::HighDrive0Standard1 => DRIVE_A::H0S1,
124 OutputDrive::Standard0HighDrive1 => DRIVE_A::S0H1,
125 OutputDrive::HighDrive => DRIVE_A::H0H1,
126 OutputDrive::Disconnect0Standard1 => DRIVE_A::D0S1,
127 OutputDrive::Disconnect0HighDrive1 => DRIVE_A::D0H1,
128 OutputDrive::Standard0Disconnect1 => DRIVE_A::S0D1,
129 OutputDrive::HighDrive0Disconnect1 => DRIVE_A::H0D1,
130 };
131
90 pin.conf().write(|w| { 132 pin.conf().write(|w| {
91 w.dir().output(); 133 w.dir().output();
92 w.input().disconnect(); 134 w.input().disconnect();
93 w.pull().disabled(); 135 w.pull().disabled();
94 w.drive().s0s1(); 136 w.drive().variant(drive);
95 w.sense().disabled(); 137 w.sense().disabled();
96 w 138 w
97 }); 139 });
@@ -195,11 +237,13 @@ pub(crate) mod sealed {
195} 237}
196 238
197pub trait Pin: sealed::Pin + Sized { 239pub trait Pin: sealed::Pin + Sized {
240 /// Number of the pin within the port (0..31)
198 #[inline] 241 #[inline]
199 fn pin(&self) -> u8 { 242 fn pin(&self) -> u8 {
200 self._pin() 243 self._pin()
201 } 244 }
202 245
246 /// Port of the pin
203 #[inline] 247 #[inline]
204 fn port(&self) -> Port { 248 fn port(&self) -> Port {
205 match self.pin_port() / 32 { 249 match self.pin_port() / 32 {
@@ -215,6 +259,7 @@ pub trait Pin: sealed::Pin + Sized {
215 self.pin_port() as u32 259 self.pin_port() as u32
216 } 260 }
217 261
262 /// Convert from concrete pin type PX_XX to type erased `AnyPin`.
218 fn degrade(self) -> AnyPin { 263 fn degrade(self) -> AnyPin {
219 AnyPin { 264 AnyPin {
220 pin_port: self.pin_port(), 265 pin_port: self.pin_port(),
@@ -222,12 +267,13 @@ pub trait Pin: sealed::Pin + Sized {
222 } 267 }
223} 268}
224 269
270// Type-erased GPIO pin
225pub struct AnyPin { 271pub struct AnyPin {
226 pin_port: u8, 272 pin_port: u8,
227} 273}
228 274
229impl AnyPin { 275impl AnyPin {
230 pub unsafe fn from_psel_bits(psel_bits: u32) -> Self { 276 pub unsafe fn steal_from_psel_bits(psel_bits: u32) -> Self {
231 Self { 277 Self {
232 pin_port: psel_bits as u8, 278 pin_port: psel_bits as u8,
233 } 279 }