diff options
| -rw-r--r-- | embassy-rp/src/gpio.rs | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 5fdb2b0c6..12b9f6aca 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs | |||
| @@ -86,7 +86,6 @@ pub struct Output<'d, T: Pin> { | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | impl<'d, T: Pin> Output<'d, T> { | 88 | impl<'d, T: Pin> Output<'d, T> { |
| 89 | // TODO opendrain | ||
| 90 | pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level) -> Self { | 89 | pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level) -> Self { |
| 91 | unborrow!(pin); | 90 | unborrow!(pin); |
| 92 | 91 | ||
| @@ -155,6 +154,89 @@ impl<'d, T: Pin> Drop for Output<'d, T> { | |||
| 155 | } | 154 | } |
| 156 | } | 155 | } |
| 157 | 156 | ||
| 157 | /// GPIO output open-drain. | ||
| 158 | pub struct OutputOpenDrain<'d, T: Pin> { | ||
| 159 | pin: T, | ||
| 160 | phantom: PhantomData<&'d mut T>, | ||
| 161 | } | ||
| 162 | |||
| 163 | impl<'d, T: Pin> OutputOpenDrain<'d, T> { | ||
| 164 | #[inline] | ||
| 165 | pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level) -> Self { | ||
| 166 | unborrow!(pin); | ||
| 167 | |||
| 168 | unsafe { | ||
| 169 | let val = 1 << pin.pin(); | ||
| 170 | pin.io().ctrl().write(|w| { | ||
| 171 | w.set_funcsel(pac::io::vals::Gpio0CtrlFuncsel::SIO_0.0); | ||
| 172 | }); | ||
| 173 | pin.sio_out().value_clr().write_value(val); | ||
| 174 | |||
| 175 | match initial_output { | ||
| 176 | Level::High => { | ||
| 177 | // For Open Drain High, disable the output pin. | ||
| 178 | pin.sio_oe().value_clr().write_value(val); | ||
| 179 | } | ||
| 180 | Level::Low => { | ||
| 181 | // For Open Drain Low, enable the output pin. | ||
| 182 | pin.sio_oe().value_set().write_value(val); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | Self { | ||
| 188 | pin, | ||
| 189 | phantom: PhantomData, | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 193 | /// Set the output as high. | ||
| 194 | #[inline] | ||
| 195 | pub fn set_high(&mut self) { | ||
| 196 | // For Open Drain High, disable the output pin. | ||
| 197 | unsafe { | ||
| 198 | self.pin | ||
| 199 | .sio_oe() | ||
| 200 | .value_clr() | ||
| 201 | .write_value(1 << self.pin.pin()); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | /// Set the output as low. | ||
| 206 | #[inline] | ||
| 207 | pub fn set_low(&mut self) { | ||
| 208 | // For Open Drain Low, enable the output pin. | ||
| 209 | unsafe { | ||
| 210 | self.pin | ||
| 211 | .sio_oe() | ||
| 212 | .value_set() | ||
| 213 | .write_value(1 << self.pin.pin()); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | /// Is the output level high? | ||
| 218 | #[inline] | ||
| 219 | pub fn is_set_high(&self) -> bool { | ||
| 220 | let val = 1 << self.pin.pin(); | ||
| 221 | unsafe { (self.pin.sio_oe().value().read() & val) == 0 } | ||
| 222 | } | ||
| 223 | |||
| 224 | /// Is the output level low? | ||
| 225 | #[inline] | ||
| 226 | pub fn is_set_low(&self) -> bool { | ||
| 227 | !self.is_set_high() | ||
| 228 | } | ||
| 229 | |||
| 230 | /// Toggle pin output | ||
| 231 | #[inline] | ||
| 232 | pub fn toggle(&mut self) { | ||
| 233 | let val = 1 << self.pin.pin(); | ||
| 234 | unsafe { | ||
| 235 | self.pin.sio_out().value_xor().write_value(val); | ||
| 236 | } | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 158 | pub(crate) mod sealed { | 240 | pub(crate) mod sealed { |
| 159 | use super::*; | 241 | use super::*; |
| 160 | 242 | ||
| @@ -322,6 +404,38 @@ mod eh02 { | |||
| 322 | Ok(self.toggle()) | 404 | Ok(self.toggle()) |
| 323 | } | 405 | } |
| 324 | } | 406 | } |
| 407 | |||
| 408 | impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for OutputOpenDrain<'d, T> { | ||
| 409 | type Error = Infallible; | ||
| 410 | |||
| 411 | #[inline] | ||
| 412 | fn set_high(&mut self) -> Result<(), Self::Error> { | ||
| 413 | Ok(self.set_high()) | ||
| 414 | } | ||
| 415 | |||
| 416 | #[inline] | ||
| 417 | fn set_low(&mut self) -> Result<(), Self::Error> { | ||
| 418 | Ok(self.set_low()) | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for OutputOpenDrain<'d, T> { | ||
| 423 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 424 | Ok(self.is_set_high()) | ||
| 425 | } | ||
| 426 | |||
| 427 | fn is_set_low(&self) -> Result<bool, Self::Error> { | ||
| 428 | Ok(self.is_set_low()) | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | impl<'d, T: Pin> embedded_hal_02::digital::v2::ToggleableOutputPin for OutputOpenDrain<'d, T> { | ||
| 433 | type Error = Infallible; | ||
| 434 | #[inline] | ||
| 435 | fn toggle(&mut self) -> Result<(), Self::Error> { | ||
| 436 | Ok(self.toggle()) | ||
| 437 | } | ||
| 438 | } | ||
| 325 | } | 439 | } |
| 326 | 440 | ||
| 327 | #[cfg(feature = "unstable-traits")] | 441 | #[cfg(feature = "unstable-traits")] |
