Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No way to switch an analog pin back to digital mode #490

Closed
QuinnFreedman opened this issue Jan 12, 2024 · 7 comments · Fixed by #493
Closed

No way to switch an analog pin back to digital mode #490

QuinnFreedman opened this issue Jan 12, 2024 · 7 comments · Fixed by #493
Labels
hal-api API design for the different components of avr-hal hal-generic Related to MCU generic parts of avr-hal

Comments

@QuinnFreedman
Copy link
Contributor

If I set an pin to a digital input/output, I can later change it to a different input/output config:

let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let a0_input = pins.a0.into_pull_up_input();
a0_input.is_low();                      // use pin
let a0_output = a0_input.into_output();
a0_output.set_high();                   // use pin as output

But, if I change it to an analog input, I cant figure out how to use it as an output afterwards:

let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let mut adc = arduino_hal::Adc::new(dp.ADC, Default::default());
let a0 = pins.a0.into_analog_input(&mut adc);

// Error: the method `into_output` exists for struct `Pin<Analog, PC0>`, but its trait bounds were not satisfied
let a0_output = a0.into_output();

Am I missing something? Is there a different way to read from a pin and get it back?

My only current workaround is to start an unsafe block, get a second copy of arduino_hal::Peripherals with steal(), and use a second copy of the pin. But that is not a great solution for something that should be safe to do.

@stappersg
Copy link
Contributor

stappersg commented Jan 13, 2024 via email

@Rahix
Copy link
Owner

Rahix commented Jan 13, 2024

@stappersg this is entirely besides the point. There are certainly usecases where a pin is used with the ADC and digital I/O at the same time.

@Rahix
Copy link
Owner

Rahix commented Jan 13, 2024

Am I missing something? Is there a different way to read from a pin and get it back?

No, unfortunately you are not missing anything. We simply don't have this implemented yet. The problem is that we can't just reuse the .into_...() methods that are used to convert a pin between different digital I/O modes because they don't reset the ADC configuration. I am not sure how this can be best plumbed into our codebase. Maybe the easiest solution is simply a .into_digital() method on ADC pins which always just makes the pin a floating input - and then you can further convert the pin into any digital I/O as you please. What do you think?

@Rahix Rahix added hal-api API design for the different components of avr-hal hal-generic Related to MCU generic parts of avr-hal labels Jan 13, 2024
@QuinnFreedman
Copy link
Contributor Author

Maybe the easiest solution is simply a .into_digital() method on ADC pins which always just makes the pin a floating input.

Could you just add another impl for Pin<mode::Analog, PIN> that implements all the into... methods and resets the ADC in each one? If that doesn't work, an into_digital method would also be fine by me. On a related note, it looks like an Adc::disable_pin method might be missing.

I am happy to work on a PR for this next week if you don't have the bandwidth to take it on.

@QuinnFreedman
Copy link
Contributor Author

@stappersg My current usecase is that I have several pullup inputs connected to buttons, but I want to read their floating value before setting them to pullup in order to seed my PRNG. But you could also have situations where you want to switch between input modes based on what is connected to your device, user configuration, etc.

@stappersg
Copy link
Contributor

stappersg commented Jan 13, 2024 via email

@Rahix
Copy link
Owner

Rahix commented Jan 13, 2024

Could you just add another impl for Pin<mode::Analog, PIN> that implements all the into... methods and resets the ADC in each one?

No, unfortunately, Rust doesn't allow multiple inherent impls on the same type to define methods of the same name, even if the generics don't overlap. That's why I suggested the into_digital() approach...

I am happy to work on a PR for this next week if you don't have the bandwidth to take it on.

I'd certainly welcome a PR :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hal-api API design for the different components of avr-hal hal-generic Related to MCU generic parts of avr-hal
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants