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

Some useful Pin wrappers #1

Closed
wants to merge 1 commit into from
Closed

Conversation

bjoernQ
Copy link
Owner

@bjoernQ bjoernQ commented Aug 30, 2023

This is currently not intended to get merged - at least not as is. It's just here to sketch some ideas.
That's why it's not targeting the esp-hal repo

Basically, this adds a new module wrappers which contains wrappers and helpers for GPIO pins.

InterconnectPin

  • is a wrapper for Input + Output pins
  • can be used to connect one peripheral output to (multiple) peripheral inputs
  • might be useful for on-device / HIL tests
  • not sure how useful this is for regular users

e.g. the spi_loopback_dma example could be changed like this

let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
    let sclk = io.pins.gpio6;
    let miso = io.pins.gpio2;
    let cs = io.pins.gpio10;

    let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control);
    let dma_channel = dma.channel0;

    let mut descriptors = [0u32; 8 * 3];
    let mut rx_descriptors = [0u32; 8 * 3];

    let mosi_miso_interconnect_pin = InterconnectPin::new(miso);

    let mut spi = Spi::new(
        peripherals.SPI2,
        sclk,
        mosi_miso_interconnect_pin.get_output().unwrap(),
        mosi_miso_interconnect_pin.get_input(),
        cs,
        100u32.kHz(),
        SpiMode::Mode0,
        &mut system.peripheral_clock_control,
        &clocks,
    )
    .with_dma(dma_channel.configure(
        false,
        &mut descriptors,
        &mut rx_descriptors,
        DmaPriority::Priority0,
    ));

Then MISO reads MOSI without physically connecting the pins.

VirtualInputPin

  • doesn't wrap an existing pin
  • can be used to programmatically set a peripheral input to low / high
  • might be useful for on-device / HIL tests
  • might be useful for regular users

e.g. the spi_loopback_dma example could be changed like this

...
    let virtual_miso = VirtualInputPin::new();

    let mut spi = Spi::new(
        peripherals.SPI2,
        sclk,
        mosi,
        virtual_miso.input(),
        cs,
        100u32.kHz(),
        SpiMode::Mode0,
        &mut system.peripheral_clock_control,
        &clocks,
    )
    .with_dma(dma_channel.configure(
        false,
        &mut descriptors,
        &mut rx_descriptors,
        DmaPriority::Priority0,
    ));

    let mut delay = Delay::new(&clocks);

    // DMA buffer require a static life-time
    let mut send = buffer1();
    let mut receive = buffer2();
    let mut i = 0;

    for (i, v) in send.iter_mut().enumerate() {
        *v = (i % 255) as u8;
    }

    loop {
        send[0] = i;
        send[send.len() - 1] = i;
        i = i.wrapping_add(1);

        let transfer = spi.dma_transfer(send, receive).unwrap();

        for _ in 0..2000 {
            virtual_miso.set_high();
            virtual_miso.set_low();
        }
...

This will make it read MISO from a toggling virtual pin. Probably not a very good example since it's pretty much impossible to match SCLK but for other things it might be more useful (e.g. controlling an enable pin)

InvertedOutputPin

  • is a wrapper for OutputPin
  • can be used to invert the output level of a peripheral output mapped to GPIO
  • might not be too useful for HIL testing
  • might be useful for regular users ... at least there is a feature request in esp-hal

e.g. the spi_loopback_dma example could be changed like this

...
    let cs = io.pins.gpio10;
    let cs = InvertedOutputPin::new(cs);
...

This will invert the output of the CS pin.

Unfortunately, it's quite a lot of code. But at least it's living in its own module could be moved out of gpio.rs.

@jonored
Copy link

jonored commented Jun 23, 2024

InterconnectPin is immediately useful for users for bidirectional open-drain stuff like 1-wire, where we want to configure the RMT peripheral output side to an open-drain pin and read it back with the input side on the same pin.

I suspect there's a neat trick to get a no-hardware logic probe on another peripheral's output for debugging, as well.

@bjoernQ bjoernQ mentioned this pull request Sep 11, 2024
6 tasks
@bjoernQ bjoernQ closed this Sep 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants