FTDI 2232H in MPSSE-SPI mode. Toil and Trouble. Example code needed - Page 1
Forum section: electronics / projects

author: free_electron
author_rank: Super Contributor
timestamp: January 25, 2013, 07:21:12 am
content: Does anyone have a working example using the FTDI MPSSE-SPI library ( version 1.1 , which apparently is the most recent one although there is a 2.0 which is older and has completely different functions... go figure... ) in a .NET language (C# or VB).That DLL is made using GCC and i cannot create a wrapper for .NET automatically since there is no manifest. GRRRRR !FTDI doesn't have anything available ...I managed to create the wrapper by hand (which is a pain as i need to marshall the code in. i'm not a coding guru. it took me 4 hours to figure out how to pass a fixed size string thru a structure... i gave up and simply created a structure with as many bytes in it as characters and i rebuild the string afterwards. .NET has marshalling tools specifically (p/invoke tool) for this but they don't work as it cannot retrieve the compilation manifest for the FTDI DLL)It works apart from 1 thing : i cannot toggle the CS line. no idea why.In short : all i need is the function prototypes for the MPSSE-SPI dll , the structure prototypes and a 5 line program- open device index 1- retrieve its information block in the information structure and give the serial number and description as strings. ( not 0 terminated strings, but .NET strings )i got the above working but it is UGLY. i need to know how to do the marshalling correctly. Google yielded tons of examples of people with the same problem and the answer is invariably use p/invok... if that can't help 'try all options until it works'. riiiight ...- initialize it at 100Khz, active low CS at pin db3 <- is suspect trouble here in my code- flunk 2 bytes out ( 0x55 and 0xaa for example ) <- or here- close deviceif i have this i can compare it with my code.

author: Bored@Work
author_rank: Super Contributor
timestamp: January 25, 2013, 10:56:32 am
content: If all else fails you could go down one level and directly use FTDI's normal D2XX device driver DLL. For this one they have a C# wrapper. And a chip's MPSSE can be configured and programmed via D2XX, although that requires a bit of coding and fiddling with bits.This way you wouldn't have to deal with the SPI lib, at the cost of having to code on a lower level.

author: free_electron
author_rank: Super Contributor
timestamp: January 25, 2013, 04:11:09 pm
content: Well the point was to avoid all the bit thumping ... I'm pressed for time.

author: marshallh
author_rank: Unknown
timestamp: January 25, 2013, 04:55:20 pm
content: built the DLL with MSVC2008... embedded manifestlet me know if this does the trick

author: free_electron
author_rank: Super Contributor
timestamp: January 25, 2013, 09:08:10 pm
content: ah that is the FTCspi . That's not the one i want... its the LibMPSSE one . it has both SPI and I2C on board and they don't release the source to that one. the FTCspi is no longer supported... ( besides it is a kludge to work with. i spent 3 days futsing around with it.... the LibMPSSE is easier to work with apart from having no demo code for .NETThanks for the effort though...I hacked it the hard way. I simply do not pass a structure, but a pointer to an array of bytes (for the DLL call it doesn't matter a pointer is a pointer as long as there is enough room to plunk its stuff.... i reconstruct the data by walking the array and picking the bytes i need. works like a charm.FTDI is a weird company. I email them , call them. Nobody ever answers the phone. they are always 'unavailable'. Email response is slow takes 3 days to get an answer. I have one direct number and the voice message says 'i am out until january 3' .. it's january 25 for crying out loud ....They have at lest 3 revisions of appnotes and none match the driver version. The appnotes are full of 'for explanation of this see document that' . It is one massive puzzle.If someone wants it : here is the NET code: (VB, but easily portable to C#)Code:Structure ChannelConfigDim clockrate As UInt32Dim latencytimer As ByteDim ConfigOptions As UInt32Dim Pins As UInt32Dim Reserved As UInt16End StructureDim ChannelConfiguration As ChannelConfigDim MPSSE_Status As UInt32Dim MPSSE_Handle As UInt32Private Declare Function MPSSE_SPI_GetChannels Lib "libmpsse" Alias "SPI_GetNumChannels" (ByRef NumberOfChannels As UInt32) As UInt32Private Declare Function MPSSE_SPI_GetChannelinfo Lib "libmpsse" Alias "SPI_GetChannelInfo" (ByVal Index As UInt32, ByRef DeviceInfo As DeviceInfoStructure) As UInt32Private Declare Function MPSSE_SPI_OpenChannel Lib "libmpsse" Alias "SPI_OpenChannel" (ByVal Index As UInt32, ByRef SPI_ProbeHandle As UInt32) As UInt32Private Declare Function MPSSE_SPI_InitChannel Lib "libmpsse" Alias "SPI_InitChannel" (ByVal SPI_ProbeHandle As UInt32, ByRef ChannelConfiguration As ChannelConfig) As UInt32Private Declare Function MPSSE_SPI_CloseChannel Lib "libmpsse" Alias "SPI_Closechannel" (ByVal SPI_ProbeHandle As UInt32) As UInt32Private Declare Function MPSSE_SPI_Read Lib "libmpsse" Alias "SPI_read" (ByVal SPI_ProbeHandle As UInt32, ByRef Readbuffer() As Byte, ByVal SizeToRead As UInt32, ByRef SizeRead As UInt32, ByVal TransferOptions As UInt32) As UInt32Private Declare Function MPSEE_SPI_Write Lib "libmpsse" Alias "SPI_Write" (ByVal SPI_ProbeHandle As UInt32, ByVal Writebuffer() As Byte, ByVal SizeToWrite As UInt32, ByRef SizeWritten As UInt32, ByVal TransferOptions As UInt32) As UInt32Private Declare Function MPSEE_SPI_ReadWrite Lib "libmpsse" Alias "SPI_ReadWrite" (ByVal SPI_ProbeHandle As UInt32, ByRef Readbuffer() As Byte, ByVal Writebuffer() As Byte, ByVal SizeTotransfer As UInt32, ByRef Sizetransferred As UInt32, ByVal TransferOptions As UInt32) As UInt32Private Declare Function MPSEE_SPI_CheckBusy Lib "libmpsse" Alias "SPI_IsBusy" (ByVal SPI_ProbeHandle As UInt32, ByRef State As Byte) As UInt32Private Declare Function MPSEE_SPI_ChangeCS Lib "libmpsse" Alias "SPI_ChangeCS" (ByVal SPI_ProbeHandle As UInt32, ByVal Options As UInt32) As UInt32Private Declare Function MPSEE_SPI_GPIOWrite Lib "libmpsse" Alias "FT_WriteGPIO" (ByVal SPI_ProbeHandle As UInt32, ByVal Direction As Byte, ByVal Value As Byte) As UInt32Private Declare Function MPSEE_SPI_GPIORead Lib "libmpsse" Alias "FT_WriteGPIO" (ByVal SPI_ProbeHandle As UInt32, ByRef Value As Byte) As UInt32Private Declare Function MPSSE_I2C_GetChannels Lib "libmpsse" Alias "I2C_GetNumChannels" (ByRef NumberOfChannels As UInt32) As UInt32Private Declare Function MPSSE_SPI_I2CChannelinfo Lib "libmpsse" Alias "I2C_GetChannelInfo" (ByVal Index As UInt32, ByRef DeviceInfo As DeviceInfoStructure) As UInt32Const Options_SPI_Mode0 As UInt32 = 0Const Options_SPI_Mode1 As UInt32 = 1Const Options_SPI_Mode2 As UInt32 = 2Const Options_SPI_Mode3 As UInt32 = 3Const Options_CS_DB3 As UInt32 = 0Const Options_CS_DB4 As UInt32 = 4Const Options_CS_DB5 As UInt32 = 8Const Options_CS_DB6 As UInt32 = 12Const Options_CS_DB7 As UInt32 = 16Const Options_CSmode_ActiveHigh As UInt32 = 0Const Options_CSmode_ActiveLow As UInt32 = 32Const TransferOptions_Inbits As UInt32 = 1Const TransferOptions_Inbytes As UInt32 = 0Const TransferOptions_CSAtStart As UInt32 = 2Const TransferOptions_CSAtStop As UInt32 = 4as soon as i got the i2c prototypes in there as well i will release that too together with helper functions ( like 'giveme alist of available chips, their device nemaes and port handles' 'connect to this porthandle at this channel'etc.It really shouldn't be that hard to interface with these things if their damn documentation would be right and complete and if they would use the right compiler.

author: Rob
author_rank: Newbie
timestamp: May 02, 2013, 08:34:23 am
content: Hey free_electron,I'm currently facing almost the same problems as you did. I try to use the I2C interface of a FT2232H via the libMPSSE in C# (Visual Studio 2008).Stuff like I2C_GetNumChannels(), I2C_GetChannelInfo() works fine. But I can't use the I2C_DeviceWrite() function. When I call that one, the program always gets stuck.I suppose the issue lies somewhere in my import of this function from the DLL. Did you finished your work on that and if so, can you give me a hint or maybe some code you wrote?Here is my code, I currently use for the import.[DllImportAttribute("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]private static extern UInt32 I2C_DeviceWrite(UInt32 handle, UInt32 deviceAddress, UInt32 sizeToTransfer,ref byte[] buffer, ref UInt32 sizeTransferred, UInt32 options);Thanks in advance for your response,Rob

author: free_electron
author_rank: Super Contributor
timestamp: May 02, 2013, 04:44:12 pm
content: Its not your code. The DLL is flawed.I have spi fully working now. Including the modes that they could not get glitch free. (Mode 1 and 3 od spi are not supported as it has glitches in the output... Some silicon bug.. I found a workaround and these modes are now also glitch free... )I am working on i2c. I have not got it fully working yet.. It freezes once in a while.The dll for spi and i2c is the same.I created extra functions in the dll that let me manipulate the commnad stream into the mpssee.It is just so annoying to have to use commnad line tools to edit that stupid code , compile it under mingw , lod it . I can't put breakpoints nor trace it... Shit like that should be prohibited.I am also working on code that eliminates the dll altogether. That dll is compiled using a compiler under mingw.. They produce both a dll and a linux library. The problem is there is no manifest and the produced dll loads only on 32 bit. There is no way to call it from a 64 bit environment. So i am moving code into native visual studio domain. That solves all this misery.I have built a set of functions i call packetbuilder. It uses a transmit and receive buffer that is exactly one usb frame long ( they have problems with multipacket streams. Byte 64 always gets corrupted...)You throw in commandsSendspistartSendspibyteSendi2cstartEtc...When you reach the maximum commnadlength the packet leaves. If your commnad is too short there is a closepacked command that forces a transmit.The same with receive. There is something weierd with the function te request the number of received bytes. Sometimes it falsely reports one more than there really is and then it locks up.The are obviously aware of these problems as the dll code dances around the real problem. They dont even 'pack' multiple commnads in a frame .This gives really weird things like a start condition followed by a long time nothing and then a byte followed by a long time nothing ...So there is no way you can race at full throttle on spi or i2c as you have random delays thrown in due to the usb transport only going out in bits and pieces as opposed to using full packet space.I have a few days off bow. I will post the code i have so far on monday.

author: DavidDLC
author_rank: Frequent Contributor
timestamp: May 02, 2013, 05:25:47 pm
content: I have used the class they provide: FTD2XX_NETclass.cs.I have the I2C fully operational. It is a pain on the butt to work with those functions they have.David.

author: shine98
author_rank: Newbie
timestamp: December 18, 2013, 09:50:38 am
content: Hi free_electron,could you attach your working spi-library so I can try so interface my SPI-Displays using VB.NET and my FT2232-Breakout.Thanks and regards,Jan

author: luky315
author_rank: Regular Contributor
timestamp: January 02, 2014, 01:05:49 pm
content: Same Problem here: Tried to use the FT4232 as SPI / I2C Master with Visual Studio 2013 but it is not working under 64bit Windows.

author: free_electron
author_rank: Super Contributor
timestamp: January 02, 2014, 02:47:04 pm
content: I know. That library is a pest.I will try to clean out my code over the weekend, remove proprietary stuff and release the source.

author: helge
author_rank: Regular Contributor
timestamp: January 12, 2014, 11:25:54 am
content: Hello free_electron,I gave the FT2232H a try and currently I'm stuck with the 32bit libmpsse.dll. Hope you can find the time to finish your lib. Any progress?edit:Hereyou can find a write-up on a little piece of code I wrote to be able to use libMPSSE with serial terminal programs like RealTerm and HTerm.

author: dbendov
author_rank: Newbie
timestamp: February 10, 2014, 09:17:01 pm
content: hi there free electron,I hahve just started looking into FTDI SPI dll when i crossed your post.any chance you upload your solution? this will be great help for us...

author: Digital Don
author_rank: Newbie
timestamp: May 26, 2014, 04:21:26 pm
content: I ran into a similar problem. Here is my code snippet that interfaces to the unmanaged libMPSSE.dll from C#. (If I knew how to upload a whole file, I could submit a full example program.) Enjoy!// Derived from FT_DEVICE_LIST_INFO_NODE in ftd2xx.h// With help from Microsoft's P/Invoke Interop Assistant[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]public struct FT_DEVICE_LIST_INFO_NODE{public uint Flags;public uint Type;public uint ID;public uint LocId;[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 16)]public string SerialNumber;[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 64)]public string Description;System.IntPtr ftHandle;}// Derived from ChannelConfig in libMPSSE_spi.h// With help from Microsoft's P/Invoke Interop Assistant[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]public struct ChannelConfig{public uint ClockRate;public byte LatencyTimer;public uint configOptions;public uint Pin;public uint reserved;}[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_GetNumChannels(out uint numChannels);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_GetChannelInfo(uint index, out FT_DEVICE_LIST_INFO_NODE chanInfo);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_OpenChannel(uint index, out System.IntPtr handle);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_InitChannel(System.IntPtr handle, ref ChannelConfig config);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_CloseChannel(System.IntPtr handle);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_Read(System.IntPtr handle, [MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint sizeToTransfer, ref uint sizeTransfered, uint options);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_Write(System.IntPtr handle, [MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint sizeToTransfer, ref uint sizeTransfered, uint options);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_ReadWrite(System.IntPtr handle, [MarshalAs(UnmanagedType.LPArray)] byte[] inBuffer, [MarshalAs(UnmanagedType.LPArray)] byte[] outBuffer, uint sizeToTransfer, ref uint sizeTransfered, uint options);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_IsBusy(System.IntPtr handle, out Boolean state);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern void Init_libMPSSE();[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern void Cleanup_libMPSSE();[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint SPI_ChangeCS(System.IntPtr handle, ChannelConfig config);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint FT_WriteGPIO(System.IntPtr handle, byte dir, byte value);[DllImport("libMPSSE.dll", CallingConvention = CallingConvention.Cdecl)]static extern uint FT_ReadGPIO(System.IntPtr handle, out byte value);

author: Cristalized
author_rank: Newbie
timestamp: June 18, 2014, 07:08:59 pm
content: Quote from: free_electron on January 02, 2014, 02:47:04 pmHello,I am using ft4232h and the library mpsse-spi.I am facing some problem with the spi mode1 which is not working properly.Surfing in internet I have found that you have already solved the problem.Can you please explain how?Did you finally release your source?Thanks in advance

author: cosminnci
author_rank: Regular Contributor
timestamp: November 27, 2014, 07:54:04 am
content: Hello,I try to use MPSSE-I2C lib for sending 6 bytes over i2c, modified the example they offer for eeprom.on win it sends ok for 5 loops then the i2c clock stays low, then after a few loops it recovers and does other 5 loops and so on.the speed on the bus is great, but when it looses clock it looses the i2c commands as well.same example on linux does 3 loops correctly, then it inserts 10 s delay between each loop.so none of them workany ideas what could cause the the i2c clock to stop at a regular interval?@free_electron did you encounter this behavior?thank you,regardsCosmin

author: aave
author_rank: Newbie
timestamp: May 18, 2018, 01:07:05 pm
content: Quote from: free_electron on January 02, 2014, 02:47:04 pmGood day! You promised to share youre code. It will be great help for people, because libmpsse.dll is not working under Windows 7 x64. I like your decision, but don't know how exactly it realize. Can you help me, please?