avr-hal
avr-hal copied to clipboard
port: Add methods to temporarily switch a pin to a different mode
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())
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
I wonder how this would behave if the pin were currently being used as the CS for an SPI transaction.
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?
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, 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?
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.
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, 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.
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.