eldruin / xca9548a-rs

Platform-agnostic Rust driver for the TCA954xA and PCA954xA I2C switch/multiplexer family.
Apache License 2.0
3 stars 8 forks source link

Using with I2C drivers that take ownership? #1

Closed marikka closed 5 years ago

marikka commented 5 years ago

Thank you for a great crate!

Many drivers for i2c devices take ownership of the i2c instance. Do you have an example of using such drivers? It would seem that switching channels is not possible after the i2c instance is moved into the driver.

My exact use case is taking subsequent measurements from a number of these sensors: https://crates.io/crates/vl53l0x

eldruin commented 5 years ago

Glad to hear that you find this crate useful. You should be able to do that using shared-bus. I will publish an example of doing this soon and will notify you here.

marikka commented 5 years ago

Thanks! I was able to use shared-bus to make it work. However, I think this is not the best possible abstraction, as one needs to manually switch between channels. Have you considered an alternative API for this crate, where the end-user would supply the channel information during initialization, and the channel switching would be automatically done just before reading/writing?

eldruin commented 5 years ago

Yes, I want to add a split() method that returns several virtual I2C devices. Then you can use these devices as if there was no switch in between. This is what I did in the pcf857x crate. Here an example of the split() method. I was waiting on https://github.com/rust-embedded/embedded-hal/issues/119 to avoid implementing my own Mutex. Maybe this could be implemented in some better way (see https://github.com/rust-embedded/wg/issues/294 ) but it would be a start.

Kintaro commented 5 years ago

I also tried to use it with shared-bus, but how am I still able to call select_channels on just the handle?

eldruin commented 5 years ago

@Kintaro I am not sure I understand the problem. Is your question referred to the split() method?

eldruin commented 5 years ago

Ok it took some work but I implemented splitting. I think it turned out quite like you would expect. Here an extract of the example in the docs passing slave (virtual) I2C devices to other drivers:

/// Some driver defined in a different crate. Defined here for completeness.
struct Driver<I2C> {
    i2c: I2C,
}

impl<I2C, E> Driver<I2C>
where I2C: Write<Error = E> + Read<Error = E> + WriteRead<Error = E> {
    pub fn new(i2c: I2C) -> Self {
        Driver { i2c }
    }
}

let i2c_switch = TCA9548A::new(dev, address);
let parts = i2c_switch.split();

let mut my_driver = Driver::new(parts.i2c0);
let mut my_other_driver = Driver::new(parts.i2c1);
eldruin commented 5 years ago

I have released this in version 0.2.0. Closing. cc: @marikka @Kintaro