ftdi-rs / ftdi-embedded-hal

Implementation of Rust Embedded HAL traits for FTDI devices
MIT License
36 stars 14 forks source link

Using bus B pins #25

Closed melvyn2 closed 1 year ago

melvyn2 commented 1 year ago

I'm looking to use this library with the Tigard, which uses both buses of the FT2232H. Specifically, AD0-6 are used for the UART and logic analyzer breakout, while BD0-6 are used for SWD/JTAG/I2C/SPI breakouts and more. However, this library seems to only provide access to pins ad0-7, which means that, for example, I would have to use the UART breakout for SPI and would not be able to use the other bus simultaneously. Is support for the B bus planned?

geomatsi commented 1 year ago

IIRC (e.g. see FTDI AN184) FT2232H ~ FT232H + FT232H. In fact, if you plug FT2232H board into your Linux machine, you will get two ttyUSB serial ports unless you disable ftdi_sio driver.

So you should be able to use this crate for both channels of FT2232. For channel A see ws2812 example. Channel B can be accessed along the same lines.

For example, create device for Channel A:

        if #[cfg(feature = "ftdi")] {
            let device_a = ftdi::find_by_vid_pid(0x0403, 0x6010)
                .interface(ftdi::Interface::A)
                .open()
                .unwrap();
        } else if #[cfg(feature = "libftd2xx")] {
            let device_a = libftd2xx::Ft2232h::with_description("Dual RS232-HS A").unwrap();
        } else {
            compile_error!("one of features 'ftdi' and 'libftd2xx' shall be enabled");
        }

And now device for Channel B:

        if #[cfg(feature = "ftdi")] {
            let device_b = ftdi::find_by_vid_pid(0x0403, 0x6010)
                .interface(ftdi::Interface::B)
                .open()
                .unwrap();
        } else if #[cfg(feature = "libftd2xx")] {
            let device_b = libftd2xx::Ft2232h::with_description("Dual RS232-HS B").unwrap();
        } else {
            compile_error!("one of features 'ftdi' and 'libftd2xx' shall be enabled");
        }

After that you should be able to use device_a and device_b independently, accessing D0..D7 lines (ADBUSx on Channel A and BDBUSx on Channel B) as ad0..ad7 on each channel and using them for gpio/i2c/spi.

What you can not do with this crate at the moment is to access higher GPIOH0..GPIOH7 lines which are ACBUSx on Channel A and BCBUSx on Channel B. It should be fairly straightforward to add support for them, e.g. see similar archived project ftdi-embedded-hal-archive. Though note that those lines can only be used as GPIO.

Regards, Sergey

melvyn2 commented 1 year ago

Thank you - I was using libftd2xx which didn't have the interface select option. Looking again, ftdi-rs using the open-source libftdi1 seems like a better choice anyways.

newAM commented 1 year ago

Yeah, in my experience if you're on Linux then the open source driver is better. The only advantage of libftd2xx is the ease of driver installation on Windows.

geomatsi commented 1 year ago

Thank you - I was using libftd2xx which didn't have the interface select option. Looking again, ftdi-rs using the open-source libftdi1 seems like a better choice anyways.

I would suggest to check my example above for the channel B:

        if #[cfg(feature = "ftdi")] {
            let device_b = ftdi::find_by_vid_pid(0x0403, 0x6010)
                .interface(ftdi::Interface::B)
                .open()
                .unwrap();
        } else if #[cfg(feature = "libftd2xx")] {
            let device_b = libftd2xx::Ft2232h::with_description("Dual RS232-HS B").unwrap();
        } else {
            compile_error!("one of features 'ftdi' and 'libftd2xx' shall be enabled");
        }

Probably "Dual RS232-HS B" will do the trick.

As for the choice between libftd2xx and libftdi, I would suggest to try both and make your choice for your hardware. In some cases libftd2xx behavior looks more predictable, e.g. see additional flushes.

Regards, Sergey

melvyn2 commented 1 year ago

Yes, I understand how to select bus with libftd2xx as well now - I simply meant to explain why I hadn't seen how to do so from the examples. I understand each driver/library has its advantages, but considering that I am developing on linux as well as usability features as shown, I will likely stick to libftdi for now. Thank you for the clarification.