Initialize i2c and return handle

I've got some i2c code working and reading/writing the SX1509. But now I'd like to refactor the code into functions and I'm having some trouble.

Working code:

    let per = Peripherals::take().unwrap();
    // init::i2c_peripheral(&per);
    let sda = per.pins.gpio4.into_input_output().unwrap();
    let scl = per.pins.gpio5.into_output().unwrap();
    let i2c = per.i2c0;

    let config = <i2c::config::MasterConfig as Default>::default().baudrate(400.kHz().into());
    let mut i2c =
        i2c::Master::<i2c::I2C0, _, _>::new(i2c, i2c::MasterPins { sda, scl }, config).unwrap();

    let mut expander = sx1509::Sx1509::new(&mut i2c, sx1509::DEFAULT_ADDRESS);
    expander.borrow(&mut i2c).software_reset().unwrap();
    expander.borrow(&mut i2c).set_bank_a_direction(0).unwrap();
    expander
        .borrow(&mut i2c)
        .set_bank_b_direction(0xFF)
        .unwrap();

Non-working i2c init function:

use crate::helpers;
use esp_idf_hal::i2c;
use esp_idf_hal::prelude::*;
use esp_idf_hal::units::FromValueType;

pub fn i2c_peripheral(
    per: &Peripherals,
) -> i2c::Master<
    i2c::I2C0,
    esp_idf_hal::peripherals::Peripherals::pins::gpio4,
    esp_idf_hal::peripherals::Peripherals::pins::gpio5,
> {
    let sda = per.pins.gpio4.into_input_output().unwrap();
    let scl = per.pins.gpio5.into_output().unwrap();
    let i2c = per.i2c0;

    let config = <i2c::config::MasterConfig as Default>::default().baudrate(400.kHz().into());
    let i2c =
        i2c::Master::<i2c::I2C0, _, _>::new(i2c, i2c::MasterPins { sda, scl }, config).unwrap();

    helpers::ptype(&i2c);
    i2c
}

Thanks for any advice or comments.

In what way does it not work, exactly?

i2c_peripheral() results in the error:

error[E0223]: ambiguous associated type
  --> src/init.rs:10:5
   |
10 |     esp_idf_hal::peripherals::Peripherals::pins::gpio4,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<esp_idf_hal::peripherals::Peripherals as Trait>::pins`

error[E0223]: ambiguous associated type
  --> src/init.rs:11:5
   |
11 |     esp_idf_hal::peripherals::Peripherals::pins::gpio5,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<esp_idf_hal::peripherals::Peripherals as Trait>::pins`

esp_idf_hal::peripherals::Peripherals appears to be a struct. You can't refer to the type of fields in a struct with a path like that, you just need to use the actual type.

In this case I believe it should be

pub fn i2c_peripheral(
    per: &Peripherals,
) -> i2c::Master<
    i2c::I2C0,
    esp_idf_hal::gpio::Gpio4<esp_idf_hal::gpio::Unknown>,
    esp_idf_hal::gpio::Gpio5<esp_idf_hal::gpio::Unknown>,
> {
2 Likes

Thank you @semicoleon! That worked, except I had to add the InputOutput and Output type to the gpio's or I get the error:

i2c
   |       ^^^ expected struct `esp_idf_hal::gpio::Unknown`, found struct `InputOutput`

The code that works ended up being:

pub fn i2c_peripheral(
    per: Peripherals,
) -> i2c::Master<
    i2c::I2C0,
    esp_idf_hal::gpio::Gpio4<esp_idf_hal::gpio::InputOutput>,
    esp_idf_hal::gpio::Gpio5<esp_idf_hal::gpio::Output>,
> {
    // init::i2c_peripheral(&per);
    let sda = per.pins.gpio4.into_input_output().unwrap();
    let scl = per.pins.gpio5.into_output().unwrap();
    let i2c = per.i2c0;

    let config = <i2c::config::MasterConfig as Default>::default().baudrate(400.kHz().into());
    let i2c =
        i2c::Master::<i2c::I2C0, _, _>::new(i2c, i2c::MasterPins { sda, scl }, config).unwrap();
    i2c
}

Oh yeah if your function is initializing the pins that makes sense that you needed to change that type!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.