avr-hal icon indicating copy to clipboard operation
avr-hal copied to clipboard

port: Add methods to temporarily switch a pin to a different mode

Open Rahix opened this issue 4 years ago • 11 comments

This allows temporarily making an output pin an input and vice versa:

let mut pin = pins.d0.into_output();

pin.with_pin_as_floating_input(|p| {
    // p is input here
    p.is_high();
});

Similarly:

  • pin.with_pin_as_pull_up_input()
  • pin.with_pin_as_output()
  • pin.with_pin_as_output_high()

TODO

  • [ ] Deduplicate implementation.
  • [ ] Check that all invariants are upheld and pin-state is always returned to what it was before.
  • [ ] Investigate whether we want the pin to be in the same state, or just the same mode - an alternative API could be one where a correct pin must be returned from the closure again:
    let pin = pins.d0.into_output();
    assert!(pin.is_set_low())
    pin.with_temporary(|p| {
      let p = p.into_floating_input();
      // ...
      p.into_output_high()
    })
    assert!(pin.is_set_high())
    

Rahix avatar Jul 28 '21 06:07 Rahix

FWIW, other HALs have come up with a very similar API. For example: https://docs.rs/stm32f4xx-hal/0.11.1/stm32f4xx_hal/gpio/struct.Pin.html#method.with_floating_input

Rahix avatar Jan 28 '22 23:01 Rahix

I wonder how this would behave if the pin were currently being used as the CS for an SPI transaction.

mutantbob avatar May 10 '22 20:05 mutantbob

Well, the CS pin must be managed manually anyway so you can do weird stuff in any case... I don't think this changeset here would make it worse than it already is, or am I missing something?

Rahix avatar May 10 '22 20:05 Rahix

Hello, I really need this for my project. Is there any way I can help? Should I fork it and then open a new PR?

haennes avatar Jul 20 '22 14:07 haennes

@haennes, giving me some feedback and testing this PR here is all I need. I just held off merging it because I wanted to hear from users first. Maybe you can comment on some of the open questions from the OP? What would be best for your usecase?

Rahix avatar Jul 20 '22 17:07 Rahix

It works on an Arduino Nano (from Elegoo) (Atmega m328p). I will test it on an Arduino Uno R3 (from Elegoo) (Atmega 328p) too. Although the 2nd implementations seems better at a first glance, the way it currently is is quite perfect, as it removes a lot of boilerplate code in the users project.

haennes avatar Jul 23 '22 16:07 haennes

Am I correct in saying that implementing the IoPin trait from embedded-hal would take care of this as well? https://docs.rs/embedded-hal/latest/embedded_hal/digital/v2/trait.IoPin.html

hiszd avatar May 18 '23 13:05 hiszd

@hiszd, not really. IoPin moves the pin to change its state more permanently while the methods in this PR only change the pin state for the duration of a closure.

Rahix avatar Jun 01 '23 00:06 Rahix

Hi,

I just finished implementing a driver for the DHT11 sensor on an Elegoo Arduino Uno R3. I had to use a pull up pin with temporary output mode to send the data request signal, and I can attest that it worked without any problem.

This might need a little refactoring before it is anywhere close to presentable, but it could eventually be integrated into the examples someday.

RenjiSann avatar Jul 14 '23 23:07 RenjiSann