diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-05-03 00:43:04 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-05-03 00:52:48 +0200 |
| commit | 29402fa76be8088b637c21dcaaa9c3b0a1ea9f99 (patch) | |
| tree | 679198073f4d67d5c9ff8c291f255b94af8d6926 | |
| parent | b1afe54c5fd7589e07af5e87d149892bc25582ef (diff) | |
nrf/gpio: add input+output to Flex, for OpenDrain.
| -rw-r--r-- | embassy-nrf/src/gpio.rs | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index c33cca64b..f5212c6af 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -7,10 +7,10 @@ use core::marker::PhantomData; | |||
| 7 | use cfg_if::cfg_if; | 7 | use cfg_if::cfg_if; |
| 8 | use embassy::util::Unborrow; | 8 | use embassy::util::Unborrow; |
| 9 | use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; | 9 | use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; |
| 10 | use gpio::pin_cnf::DRIVE_A; | ||
| 11 | 10 | ||
| 12 | use crate::pac; | 11 | use crate::pac; |
| 13 | use crate::pac::p0 as gpio; | 12 | use crate::pac::p0 as gpio; |
| 13 | use crate::pac::p0::pin_cnf::{DRIVE_A, PULL_A}; | ||
| 14 | 14 | ||
| 15 | use self::sealed::Pin as _; | 15 | use self::sealed::Pin as _; |
| 16 | 16 | ||
| @@ -129,9 +129,30 @@ impl<'d, T: Pin> Output<'d, T> { | |||
| 129 | } | 129 | } |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | fn convert_drive(drive: OutputDrive) -> DRIVE_A { | ||
| 133 | match drive { | ||
| 134 | OutputDrive::Standard => DRIVE_A::S0S1, | ||
| 135 | OutputDrive::HighDrive0Standard1 => DRIVE_A::H0S1, | ||
| 136 | OutputDrive::Standard0HighDrive1 => DRIVE_A::S0H1, | ||
| 137 | OutputDrive::HighDrive => DRIVE_A::H0H1, | ||
| 138 | OutputDrive::Disconnect0Standard1 => DRIVE_A::D0S1, | ||
| 139 | OutputDrive::Disconnect0HighDrive1 => DRIVE_A::D0H1, | ||
| 140 | OutputDrive::Standard0Disconnect1 => DRIVE_A::S0D1, | ||
| 141 | OutputDrive::HighDrive0Disconnect1 => DRIVE_A::H0D1, | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | fn convert_pull(pull: Pull) -> PULL_A { | ||
| 146 | match pull { | ||
| 147 | Pull::None => PULL_A::DISABLED, | ||
| 148 | Pull::Up => PULL_A::PULLUP, | ||
| 149 | Pull::Down => PULL_A::PULLDOWN, | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 132 | /// GPIO flexible pin. | 153 | /// GPIO flexible pin. |
| 133 | /// | 154 | /// |
| 134 | /// This pin can either be a disconnected, input, or output pin. The level register bit will remain | 155 | /// This pin can either be a disconnected, input, or output pin, or both. The level register bit will remain |
| 135 | /// set while not in output mode, so the pin's level will be 'remembered' when it is not in output | 156 | /// set while not in output mode, so the pin's level will be 'remembered' when it is not in output |
| 136 | /// mode. | 157 | /// mode. |
| 137 | pub struct Flex<'d, T: Pin> { | 158 | pub struct Flex<'d, T: Pin> { |
| @@ -158,17 +179,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 158 | self.pin.conf().write(|w| { | 179 | self.pin.conf().write(|w| { |
| 159 | w.dir().input(); | 180 | w.dir().input(); |
| 160 | w.input().connect(); | 181 | w.input().connect(); |
| 161 | match pull { | 182 | w.pull().variant(convert_pull(pull)); |
| 162 | Pull::None => { | ||
| 163 | w.pull().disabled(); | ||
| 164 | } | ||
| 165 | Pull::Up => { | ||
| 166 | w.pull().pullup(); | ||
| 167 | } | ||
| 168 | Pull::Down => { | ||
| 169 | w.pull().pulldown(); | ||
| 170 | } | ||
| 171 | } | ||
| 172 | w.drive().s0s1(); | 183 | w.drive().s0s1(); |
| 173 | w.sense().disabled(); | 184 | w.sense().disabled(); |
| 174 | w | 185 | w |
| @@ -180,22 +191,31 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 180 | /// The pin level will be whatever was set before (or low by default). If you want it to begin | 191 | /// The pin level will be whatever was set before (or low by default). If you want it to begin |
| 181 | /// at a specific level, call `set_high`/`set_low` on the pin first. | 192 | /// at a specific level, call `set_high`/`set_low` on the pin first. |
| 182 | pub fn set_as_output(&mut self, drive: OutputDrive) { | 193 | pub fn set_as_output(&mut self, drive: OutputDrive) { |
| 183 | let drive = match drive { | ||
| 184 | OutputDrive::Standard => DRIVE_A::S0S1, | ||
| 185 | OutputDrive::HighDrive0Standard1 => DRIVE_A::H0S1, | ||
| 186 | OutputDrive::Standard0HighDrive1 => DRIVE_A::S0H1, | ||
| 187 | OutputDrive::HighDrive => DRIVE_A::H0H1, | ||
| 188 | OutputDrive::Disconnect0Standard1 => DRIVE_A::D0S1, | ||
| 189 | OutputDrive::Disconnect0HighDrive1 => DRIVE_A::D0H1, | ||
| 190 | OutputDrive::Standard0Disconnect1 => DRIVE_A::S0D1, | ||
| 191 | OutputDrive::HighDrive0Disconnect1 => DRIVE_A::H0D1, | ||
| 192 | }; | ||
| 193 | |||
| 194 | self.pin.conf().write(|w| { | 194 | self.pin.conf().write(|w| { |
| 195 | w.dir().output(); | 195 | w.dir().output(); |
| 196 | w.input().disconnect(); | 196 | w.input().disconnect(); |
| 197 | w.pull().disabled(); | 197 | w.pull().disabled(); |
| 198 | w.drive().variant(drive); | 198 | w.drive().variant(convert_drive(drive)); |
| 199 | w.sense().disabled(); | ||
| 200 | w | ||
| 201 | }); | ||
| 202 | } | ||
| 203 | |||
| 204 | /// Put the pin into input + output mode. | ||
| 205 | /// | ||
| 206 | /// This is commonly used for "open drain" mode. If you set `drive = Standard0Disconnect1`, | ||
| 207 | /// the hardware will drive the line low if you set it to low, and will leave it floating if you set | ||
| 208 | /// it to high, in which case you can read the input to figure out whether another device | ||
| 209 | /// is driving the line low. | ||
| 210 | /// | ||
| 211 | /// The pin level will be whatever was set before (or low by default). If you want it to begin | ||
| 212 | /// at a specific level, call `set_high`/`set_low` on the pin first. | ||
| 213 | pub fn set_as_input_output(&mut self, pull: Pull, drive: OutputDrive) { | ||
| 214 | self.pin.conf().write(|w| { | ||
| 215 | w.dir().output(); | ||
| 216 | w.input().connect(); | ||
| 217 | w.pull().variant(convert_pull(pull)); | ||
| 218 | w.drive().variant(convert_drive(drive)); | ||
| 199 | w.sense().disabled(); | 219 | w.sense().disabled(); |
| 200 | w | 220 | w |
| 201 | }); | 221 | }); |
