-
Notifications
You must be signed in to change notification settings - Fork 297
AnyPin #384
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
AnyPin #384
Conversation
Seems like ESP32 with its One solution to this would be to have |
So I understand the need for the Maybe to make things simpler, something like this: enum ErasedPin<MODE> {
Gpio0(Gpio0<MODE>),
Gpio1(Gpio1<MODE>),
// ...
}
pub struct AnyPin<MODE> {
inner: ErasedPin<MODE>
}
// .. e-h and e-h-a impls on AnyPin |
Can we make it panic instead if you try to use them? |
Sorry, I probably made a bad job explaining the idea here - basically the idea is borrowed from https://crates.io/crates/enum_dispatch (but we can't use that or any of the similar macros I found, so I made our own) So, we have that enum like this: enum ErasedPin<MODE> {
Gpio0(Gpio0),
Gpio1(Gpio1),
} To dispatch calls we need something like this impl<MODE> SomeTraitAlreadyImplementedOnPin for ErasedPin<MODE> {
fn method_on_trait(&self) {
match self {
ErasedPin::Gpio0(target) => { target.method_on_trait() }
ErasedPin::Gpio1(target) => { target.method_on_trait() }
...
}
}
} That new macro generats a macro that handles all variants of the given enum. I like that
I would like that more than |
This makes things like this possible #![no_std]
#![no_main]
use esp32c3_hal::{
clock::ClockControl,
gpio::{AnyPin, Output, PushPull, IO},
peripherals::Peripherals,
prelude::*,
timer::TimerGroup,
Delay,
Rtc,
};
use esp_backtrace as _;
use esp_riscv_rt::entry;
#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
// Disable the watchdog timers. For the ESP32-C3, this includes the Super WDT,
// the RTC WDT, and the TIMG WDTs.
let mut rtc = Rtc::new(peripherals.RTC_CNTL);
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let mut wdt0 = timer_group0.wdt;
let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks);
let mut wdt1 = timer_group1.wdt;
rtc.swd.disable();
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();
// Set GPIO5 as an output, and set its state high initially.
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let mut led = io.pins.gpio3.into_push_pull_output();
let mut led1 = io.pins.gpio4.into_push_pull_output();
let mut led2 = io.pins.gpio5.into_push_pull_output();
let mut pins = [led.into(), led2.into()];
// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let mut delay = Delay::new(&clocks);
loop {
toggle_em(&mut pins);
delay.delay_ms(500u32);
}
}
fn toggle_em(pins: &mut [AnyPin<Output<PushPull>>]) {
for p in pins.iter_mut() {
p.toggle().unwrap();
}
} |
It's now very GPIO specific but shouldn't fail in CI anymore (besides currently crates.io seem to have trouble) |
I guess this is done so far. Would it make sense to add a simple example especially for this? |
I think I'm on board with this approach, another thing I have in my head is can we use these macros to hide the implementation details of the typed Gpio structs? Maybe this is asking too much of these macros :D. |
Yeah I think it would be worthwhile adding an example on this. I think there's a lot of use-cases for it. |
Maybe we could add a |
🎉 Currently I can't think of using this to hide the implementation details of the typed Gpio struct but maybe we'll explore ways to do that But for now I think this is useful and working fine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I was just getting ahead of myself :D.
LGTM! Nice to finally have something like this :)
I didn't have time to get to this over the last couple days so I guess I missed out on my chance for input, but had we not decided on |
The name |
|
Can we get some documentation for our GPIO then please? I don't even understand how it works anymore, apparently. |
Ah I think I remember we discussed pins that can change their mode dynamically - and there we discussed |
Do you mean API docs or developer docs? |
This is not necessarily meant to get merged but we can if we agree it's a good idea
This adds an
ErasedPin
type by having an enum and using the enum-dispatch pattern.The good thing is, it's easy to use this pattern also for other heavily typed types (e.g. SPI, I2C, I2S, ...) and doesn't need any refactoring of existing code. In other places we can even use an existing macro to implement
From
andTryInto
- but all macros I found didn't support generics which we need for the mode.It looks like a nice solution but maybe I forgot something that makes it actually a bad thing 🤷♂️
Closes #115
Closes #277