Friday, September 19, 2008

FTCI2C DLL functionalities

Nothing received on my last mail. So the FDTI support is not that friendly if you ask me. Nevertheless I modified the DLL code so I now have access to the ADBUS and ACBUS bus GPIO. Although the ADBUS access is limited. But as I promised, this post will be dedicated to the API calls you can use when the FT2232 device is in MPSSE mode. The next post I will show some results on timings from several tests I did to get a better idea on the capabilities of this chip using it for other purposes than usb to serial conversions.

Mainly two possible ways to work with this device. You can pick the VCP (virtual com port) or the D2XX (low level design and special modes). In my case I downloaded the D2XX package. I took the windows based package but also linux , windows CE and even MAC are possible. Resources are available on the following site:

http://www.ftdichip.com/Drivers/D2XX.htm

The FTDI software comes with a zip file archive with following components:

- ftdi driver
- ftd2xx.dll
- ftd2xx.lib
- ftd2xx.h

These are the minimum components you need to start making your programs using visual studio. If you choise to interface an I2C bus peripheral than you must download an ectra development package to be able to work easier with the internal command structure of the FT2232. This can be found :

http://www.ftdichip.com/Projects/MPSSE/FTCI2C.htm

Components included are :

- ftci2c.h
- ftci2c.dll
- ftci2c.lib

Basically you can do pretty much with the default API functions the DLL exports and are quit simple to use. Here is the list of APIs:

FTCI2C_API
FTC_STATUS WINAPI I2C_GetNumDevices(LPDWORD lpdwNumDevices);

FTCI2C_API
FTC_STATUS WINAPI I2C_GetDeviceNameLocID(DWORD dwDeviceNameIndex, LPSTR lpDeviceNameBuffer, DWORD dwBufferSize, LPDWORD lpdwLocationID);

FTCI2C_API
FTC_STATUS WINAPI I2C_OpenEx(LPSTR lpDeviceName, DWORD dwLocationID, FTC_HANDLE *pftHandle);

FTCI2C_API
FTC_STATUS WINAPI I2C_Open(FTC_HANDLE *pftHandle);

FTCI2C_API
FTC_STATUS WINAPI I2C_Close(FTC_HANDLE ftHandle);

FTCI2C_API
FTC_STATUS WINAPI I2C_InitDevice(FTC_HANDLE ftHandle, DWORD dwClockDivisor);

FTCI2C_API
FTC_STATUS WINAPI I2C_GetClock(DWORD dwClockDivisor, LPDWORD lpdwClockFrequencyHz);

FTCI2C_API
FTC_STATUS WINAPI I2C_SetClock(FTC_HANDLE ftHandle, DWORD dwClockDivisor, LPDWORD lpdwClockFrequencyHz);

FTCI2C_API
FTC_STATUS WINAPI I2C_SetLoopback(FTC_HANDLE ftHandle, BOOL bLoopbackState);

FTCI2C_API
FTC_STATUS WINAPI I2C_SetMode(FTC_HANDLE ftHandle, DWORD dwCommsMode);

FTCI2C_API
FTC_STATUS WINAPI I2C_Write(FTC_HANDLE ftHandle, PWriteControlByteBuffer pWriteControlBuffer,
DWORD dwNumControlBytesToWrite, BOOL bControlAcknowledge, DWORD dwControlAckTimeoutmSecs,
BOOL bStopCondition, DWORD dwDataWriteTypes, PWriteDataByteBuffer pWriteDataBuffer, DWORD NumDataBytesToWrite,
BOOL bDataAcknowledge, DWORD dwDataAckTimeoutmSecs, PFTC_PAGE_WRITE_DATA pPageWriteData);

FTCI2C_API
FTC_STATUS WINAPI I2C_Read(FTC_HANDLE ftHandle, PWriteControlByteBuffer pWriteControlBuffer,
DWORD dwNumControlBytesToWrite, BOOL bControlAcknowledge, DWORD dwControlAckTimeoutmSecs,
DWORD dwDataReadTypes, PReadDataByteBuffer pReadDataBuffer, DWORD dwNumDataBytesToRead);

FTCI2C_API
FTC_STATUS WINAPI I2C_GetDllVersion(LPSTR lpDllVersionBuffer, DWORD dwBufferSize);

FTCI2C_API
FTC_STATUS WINAPI I2C_GetErrorCodeString(LPSTR lpLanguage, FTC_STATUS StatusCode,
LPSTR lpErrorMessageBuffer, DWORD dwBufferSize);


As you can see quit a complete list of functions that you can call almost directly. The principe is based on dividing the i2c commands into a ControlBuffer and a DataBuffer. This is done to simplify the internal calls to the FTDI2232 command set available. Here is an example out of my library I write to prepare a command for the PCA device:

FTDI_API FTC_STATUS FTDI_I2C_PCA_WRITE_ALL ( UCHAR adr , PCHAR buf )
{
FTC_STATUS stat;

PageWriteData.dwNumBytesPerPage = PCA9698_MAX_DATA;
PageWriteData.dwNumPages = PCA9698_MAX_PAGE;

WriteControlBuffer[0] = adr;
WriteControlBuffer[1] = PCA9698_WRITE_ALL;

memcpy ( WriteDataBuffer , buf , PCA9698_MAX_DATA );

stat = I2C_Write( hI2C,
&WriteControlBuffer,
PCA9698_CONTROL_BYTES,
FTDI_WANT_ACK,
FTDI_TIME_OUT,
FTDI_WANT_ACK,
PAGE_WRITE_TYPE,
&WriteDataBuffer,
PCA9698_MAX_DATA,
FTDI_WANT_ACK,
FTDI_TIME_OUT,
&PageWriteData
);I2C_RETURN_ERROR;

I2C_RETURN_SUCCES;
}

So in fact you can organize your calls in seperate functions library for readability or you can of course also call it directly within your main logic. Due to the fact I modified the FTDI DLL code I better add my functions directly in the code of the DLL. This has an extra advantage in using only one single device handle. If you need the GPIO calls together with I2C you need to call functions out of the basic ftd2xx.dll and you need to open up an other handle. This means that if you work like that you simply can't let open two handles in your program. I show you the lines that I changed to be able to access the ACBUS:

In function FT2232cMpsseI2c::InitDataInOutClockFrequency I commented out these lines:

// outputs on GPIO21-24
// FTC_AddByteToOutputBuffer(SET_HIGH_BYTE_DATA_BITS_CMD, false);
// FTC_AddByteToOutputBuffer('\x0F', false);
// FTC_AddByteToOutputBuffer('\x0F', false);

If you don't do that every time the device gets initialized the ACBUS is set to output and the 4 lines become high. Another thing I did was changing the WriteProtectEnable flag. This flag is related to pin 4 of the ADBUS and not documented in the specifications. It's not quit clear to me why they use it but I guess to make the internal command calls save for multihreading.

In function FT2232cMpsseI2c::ReadDataFromExternalDevice I modified the flag to false :

Status = WriteAddressExternalDevice(ftHandle, (*pWriteControlBuffer)[0], ControlAckType, dwControlAckTimeoutmSecs, false);

I needed to that because my PCA OE was connected to pin 4. After these changes the OE was working properly and the ACBUS was available for input as well as for output whitout any changes when calling the InitDevice function.

I went not into great details regarding the code and of course I assume that you know how to build a DLL and use third party DLLs from within visual studio. The purpose of this post is just showing you the fact that FDTI device can be put into other modes than the widly used VCP mode. Next I will tell you bit more on the results of my tests. For the ones interested in reading some hardware specifications

http://www.ftdichip.com/Documents/DataSheets.htm

I can't attach the DLL source code here in this google blog which is a pitty but if you're interested just give me a reaction on this post.

7 comments:

Unknown said...

Hello,

I had the same problem here. Is it possible to send me the modified DLL source code and DLL? Many Thanks.

Kind regards,
Xin
my email: xinyin8 at_gmail_com

guyvo said...

Sorry for the delay but I didn't checked my comments.

I will send you to the source code this evening at your address:

xinyin8_at_gmail.com

regards
-G

Gordon said...

Hello,

I'm using a FT232BM device. Do you know how to use the commands in ftd2xx.dll to interface with an I2C device?

Thank you very much,
Gordon

yu said...

How do you access this dll and use the functions inside?
I write VC++ program for accessing and always have runtime error.
Coould you please send me the C source code?

Very appreciated~
yuyuyuyu176@gmail.com

yves said...

Hello,

Very good job.
Could you send me the C source code ?

Thank you.

Unknown said...

Hello,
I have problems using FT2232D as an I2C Master to control the oscillator Si570. could you help me and send me the dll file or suggest some suggestions?
Thanks alot hope u would read this command
Ahed

Unknown said...

Hello Please send me the modified FTCI2C.dll,

mail id: harinidece25@gmail.com
Regards,
Harini