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

Treat a Gpio pin as either input or output. #740

Open
Ben-PH opened this issue Aug 17, 2023 · 4 comments
Open

Treat a Gpio pin as either input or output. #740

Ben-PH opened this issue Aug 17, 2023 · 4 comments
Labels
enhancement New feature or request peripheral:gpio GPIO peripheral status:needs-attention This should be prioritized

Comments

@Ben-PH
Copy link

Ben-PH commented Aug 17, 2023

I'm trying to implement a bit-bang controller for a peripheral (ADNS5050, specifically), based an CPP arduino code.

The problem I've run into, is that I need to be able to use one of the pins as both input and output. If there's an ergonomic/intuitive way to do this as things already are, I've missed it.

Ideally, I'd be able to write something like this:

struct ADNSDriver<'a, MODE>
{
    sdio: &'a mut dyn IOPin<Error = Infallible, MODE>,
    srl_clk: &'a mut dyn OutputPin<Error = Infallible>,
    not_reset: &'a mut dyn OutputPin<Error = Infallible>,
    not_chip_sel: &'a mut dyn OutputPin<Error = Infallible>,
    pix: [u8; 360],
}

Reason being, is I have code a bit like this:

    fn read_reg(&mut self, addr: ADNSRegs, delay: &mut Delay) -> u8 {
        let stdio_writer = self.sdio.into_push_pull_output();
        let mut addr = addr as u8;
        for _ in 0..8 {
            // use bit-banging to write with the sdio pin as an output
            // in order to choose which memory address to read from
        }

        let mut res = 0u8;

        for i in 0..8 {
            // use bit-baning to read from the sdio-pin as an InputPin in order to get the value at
            // that memory address
        }

        res
    }

...the ADNSDriver can use the sdio field either an output pin XOR an input pin. If there's a way to dance between the two modes in a nice way, I been unable to come across it.

Context: rust-embedded/embedded-hal#357 in short: embedded-hal has the IoPin trait as well as some others, but is removing it for 1.0.0 (follow link for details).

@jessebraham jessebraham added the enhancement New feature or request label Aug 17, 2023
@bjoernQ
Copy link
Contributor

bjoernQ commented Aug 18, 2023

One thing that probably would work right now already is using our internal implementation details (I'm not sure if those should be kept public in future)

struct HoldGpioPin<P>
where
    P: esp32c3_hal::gpio::InputPin
        + esp32c3_hal::gpio::OutputPin
{
    pin: Option<P>,
}

impl<P> HoldGpioPin<P>
where
    P: esp32c3_hal::gpio::InputPin
        + esp32c3_hal::gpio::OutputPin
{
    fn do_output(&mut self) {
        let mut out = self.pin.take().unwrap();
        out.set_to_push_pull_output();
        out.set_output_high(true);
        self.pin.replace(out);
    }

    fn do_input(&mut self) -> bool {
        let mut inp = self.pin.take().unwrap();
        inp.set_to_input();
        let res = inp.is_input_high();
        self.pin.replace(inp);
        res
    }
}

... and use it like this

...
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

    let mut foo = HoldGpioPin {
        pin: Some(io.pins.gpio5),
    };

    foo.do_output();
    delay.delay_ms(3500u32);

    loop {
        println!("{}", foo.do_input());
        delay.delay_ms(500u32);
    }
...

This way certainly you cannot implement things in a HAL agnostic way

@bjoernQ
Copy link
Contributor

bjoernQ commented Aug 30, 2023

Not sure if we should implement the more or less deprecated IoPin or better wait for its return in EH-1.x

@jessebraham jessebraham added the peripheral:gpio GPIO peripheral label Sep 19, 2023
@SeTSeR
Copy link

SeTSeR commented Nov 22, 2023

Not sure if we should implement the more or less deprecated IoPin or better wait for its return in EH-1.x

Just hit into this, when tried to implement a driver for my segment display. Would be great to have a working implementation for current supported embedded_hal (which doesn’t mention deprecating IoPin in doc. However, I am not very familiar with its development flow). Or at least maybe document some workarounds for this? I have found two of them: either use open_drain_output, which implements both InputPin and OutputPin, or use push_pull_output with extra traits you mentioned.

@MabezDev MabezDev added the status:needs-attention This should be prioritized label May 20, 2024
@MabezDev
Copy link
Member

I think with our recent GPIO changes it should be easy to implement a Flexible pin type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request peripheral:gpio GPIO peripheral status:needs-attention This should be prioritized
Projects
Status: Todo
Development

No branches or pull requests

5 participants