esp-hal icon indicating copy to clipboard operation
esp-hal copied to clipboard

Inverting GPIOs

Open har7an opened this issue 3 years ago • 1 comments
trafficstars

Why?

Today I came across a SPI device that has an inverted CS line. With the current HAL implementation, this situation cannot easily be handled: The SpiDevice trait as implemented on SpiBusDevice requires an IO that implements the OutputPin trait from the esp-hal, hence something like inverted-pin doesn't work. This leaves me with having to forego SpiBusDevice in favor of manually handling the CS line which isn't nice.

What to do about it?

The esp32 has hardware support for inverting both input and output GPIOs in hardware, via the GPIO_FUNCx_(OUT|IN)_INV_SEL bit. Hence, I think it would be possible to add GPIO inversion at zero cost by extending the Pin trait from esp-hal. What are your thoughts on this? Would you accept a PR that implements this?

har7an avatar Sep 02 '22 11:09 har7an

I think in general if the hardware supports it we will accept PRs, so go nuts :)

Just as a note I am in the process of completely rewriting the GPIO module, however I'm not sure how long this will take so you can likely implement this and get it merged before I'm done. I will of course propagate your changes to my rewrite if this does happen.

jessebraham avatar Sep 02 '22 13:09 jessebraham

We have everything needed to do that in

  • https://github.com/esp-rs/esp-hal/blob/9fa59fe12754b367cb0b75668dbd896e8a78fba8/esp-hal-common/src/gpio.rs#L158-L163
  • https://github.com/esp-rs/esp-hal/blob/9fa59fe12754b367cb0b75668dbd896e8a78fba8/esp-hal-common/src/gpio.rs#L196-L203

Only thing we are missing is a way to expose it in the API. That is everywhere we want to have this feature we need a special constructor for the peripheral driver that allows to specify if a pin should be inverted or not.

bjoernQ avatar Feb 17 '23 13:02 bjoernQ

@bjoernQ How we can invoke the inversion?

E.g. here it's used in SmartLED which should have inverted signal: https://github.com/georgik/esp32-buddy-rs/blob/feature/update-hal-2023-05/examples/rainbow.rs#L89

  // Configure RMT peripheral globally
    let pulse = PulseControl::new(
        peripherals.RMT,
        &mut system.peripheral_clock_control,
        ClockSource::APB,
        0,
        0,
        0,
    )
    .unwrap();


    let mut led = <smartLedAdapter!(1)>::new(pulse.channel1, io.pins.gpio25);

Should be just GPIO25 womehow wrapped or do we need to make whole driver inverted?

georgik avatar May 22 '23 13:05 georgik

Pins get passed into the drivers and the drivers configure the pins accordingly (e.g. here https://github.com/esp-rs/esp-hal/blob/7b3e19c4c6bbca778f3ac77c036635bb1a919e75/esp-hal-common/src/pulse_control.rs#L761-L763 )

In this case we would need to call connect_peripheral_to_output_with_options instead and set the options to invert the pin.

This then needs to be reflected in the user-facing API (e.g. alternative constructors with an option to invert a pin)

bjoernQ avatar May 22 '23 13:05 bjoernQ