aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/gpio.rs116
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
88impl<'d, T: Pin> Output<'d, T> { 88impl<'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.
158pub struct OutputOpenDrain<'d, T: Pin> {
159 pin: T,
160 phantom: PhantomData<&'d mut T>,
161}
162
163impl<'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
158pub(crate) mod sealed { 240pub(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")]