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

Closed
Ben-PH opened this issue Aug 17, 2023 · 4 comments · Fixed by #1659
Closed

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

Ben-PH opened this issue Aug 17, 2023 · 4 comments · Fixed by #1659
Assignees
Labels
peripheral:gpio GPIO peripheral status:needs-attention This should be prioritized
Milestone

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).

@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.

@MabezDev MabezDev assigned MabezDev and unassigned MabezDev May 29, 2024
@bjoernQ bjoernQ self-assigned this Jun 5, 2024
@MabezDev MabezDev added this to the 0.19.0 milestone Jun 5, 2024
@github-project-automation github-project-automation bot moved this from Todo to Done in esp-rs Jun 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
peripheral:gpio GPIO peripheral status:needs-attention This should be prioritized
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

5 participants