Reply by Paul Urbanus February 18, 20062006-02-18
Kris wrote:

> Mark Borgerson wrote: > >>If you want any more help, you're going to have to show us what is >>going on inside your wrapper functions. > > > Here are the functions from the Wrapper class: > > public class Wrapper > { > private static IntPtr m_USBhandler; > > [DllImport("FTD2XX.dll", EntryPoint="FT_Open")] > public static extern uint FT_Open(int iDevice, ref IntPtr ftHandle); >
<snip> I just finished solving a problem where I needed to call a vendor's dll from VB6 and perl. And I was having all sorts of problems. It turned out that the vendor's dll parameter passing used the _cdelc ('C' convention) for passing parameters instead of the _stdcall parameter passing convention. I ended up writing a wrapper dll in VC6 that used the _stdcall parameter passing convention, and this solved all of my problems. Since I'm mainly a hardware/VHDL guy, I've only dabbled in VC6, so it took lots of googling before I was able to make my wrapper dll work. But, I did. If FTDI supplies a C header file, you might be able to tell what parameter passing convention is used. I know that all of the Win32 API dlls, such as kernel32.dll, use the _stdcall convention. It is my understanding that any non-C programs linking to a dll require the _stdcall parameter passing convention. BTW, the difference betweeen the two calling conventions is that when using _cdecl, the calling program cleans up the stack after the call, but with _stdcall, the called (dll) program does the cleanup. Any of you real software guys out there, please feel free to chime in if my info is inaccurate. Urb _______________________________________________________________________________ Posted Via Uncensored-News.Com - Accounts Starting At $6.95 - http://www.uncensored-news.com <><><><><><><> The Worlds Uncensored News Source <><><><><><><><>
Reply by Andrew Jackson February 15, 20062006-02-15
Kris

 > [DllImport("FTD2XX.dll", EntryPoint="FT_Open")]
 > public static extern uint FT_Open(int iDevice, ref IntPtr ftHandle);

I'm not sure that it makes a difference but in my C# code I used out 
rather than ref.

> public static bool OpenDevice() > { > if (((FT_Status)Wrapper.FT_Open(1, ref m_USBhandler)) == > FT_Status.Ok) > { > return true; > } > else > { > return false; > } > }
Are you certain that there is just the one FTDI device on your system?
> public static void PurgeAll() > { > FT_Status opResult; > > if ((opResult = (FT_Status)Wrapper.FT_Purge(m_USBhandler, > (uint)FT_PurgeRXTX.TX & FT_PurgeRXTX.RX))) > != FT_Status.Ok) > { > throw new USBException("Could not purge the buffers.", > opResult); > } > }
Don't you mean or (|) rather than and (&) here? You won't be purging anything otherwise. Otherwise your functions look pretty reasonable. Andrew
Reply by Mark Borgerson February 15, 20062006-02-15
In article <1140017316.053269.264040@z14g2000cwz.googlegroups.com>, 
kris.robin@gmail.com says...
> Excuse me for the repeat, but I badly need somebody's help. > So, once again, just to draw attention: > > Mark Borgerson wrote: > > If you want any more help, you're going to have to show us what is > > going on inside your wrapper functions. > > > Here are the functions from the Wrapper class: > > public class Wrapper > { > private static IntPtr m_USBhandler;
<<SNIP CODE>
> > > For me, it seems to be ok, but may be there is some problem. >
It looks like you're doing the same things I do with the FT245, except that I never use the Purge or GetQueueStatus calls. I purge buffers by calling the Read function until there is no data left. I don't use GetQueueStatus, but just read until there is nothing left. in WinXP, I have set up and installed the FTDI driver using their Vendor ID and the product ID for my device. Here is the code to open the device: void __fastcall TFormLink::BTOpenClick(TObject *Sender) { // try to find and open a CF-1 interface char devstring[100]; DWORD numdevs, devindex = 0; if(FTH != 0) { // if already open, close first FT_Close(FTH); FTH = 0; } fts = FT_ListDevices( &numdevs, NULL, FT_LIST_NUMBER_ONLY); if(numdevs >0) fts = FT_Open(0, &FTH); strcpy(devstring, "No CF-1 Interface Found" ); EDDevice->Text = (const char *)devstring; // assume no device if(fts == FT_OK) { // if found change message, open device FT_ResetDevice(FTH); FT_SetTimeouts(FTH, 300,300); EDDevice->Text = "CF-1 USB Interface"; } } The code which traverses a directory list and copies each file from the data logger is this: void __fastcall TFormLink::BTXferClick(TObject *Sender) { char *fullstring, fnstring[15], cmdstring[16]; int i,spos; FILE *fp; static char spbuff[4098]; long bytecount; DWORD numwritten, num2read,numread; AnsiString str; char *fnp; if(FTH == 0) return; // exit if not open // transfer files that are selected for(i= 0; i < LBoxdir->Items->Count; i++){ if(LBoxdir->Selected[i]){ str = LBoxdir->Items->Strings[i]; fullstring = str.c_str(); strcpy(cmdstring, "s"); strncpy(&fnstring[0],fullstring,13); for(spos = 0; spos < 14; spos++){ if (fnstring[spos] == ' ') fnstring[spos] = 0; } // truncate string at trailing spaces strcat(cmdstring,fnstring); strcat(cmdstring, "\n"); // now collect the data from USB port bytecount = 0; num2read = 256; EDCount->Text = 0; EDFolder->Text = TCDO1->Directory+"\\" + / (const char *)fnstring; fnp = EDFolder->Text.c_str(); fp = fopen( fnp, "wb"); // now send the command //and file name to the cf-1 Application->ProcessMessages(); // catch up on windows //message handling FT_Write(FTH,cmdstring, strlen(cmdstring), &numwritten); //send the file name timeout = 50; // sets 5-second timeout to start file while(timeout > 0){ fts = FT_GetQueueStatus(FTH, &num2read); if((fts == FT_OK) && (num2read > 0)){ FT_Read(FTH,&spbuff[0],num2read,&numread); if(numread > 0){ if(fp != NULL) fwrite(&spbuff[0],numread,1, fp); bytecount+= numread; EDCount->Text = bytecount; timeout = 4; // reset timeout counter to 0.4 } } Application->ProcessMessages(); // catch up on windows //message handling } if(fp!= NULL) fclose(fp); } // end of if(selected... } // end of for(i= 0 .... } As you can see, it's pretty simple: Send a command and read the returned data until there is no more (as indicated by the timeout). No need for purges or GetQueueStatus() (Which may not even be valid for the FT245). In your code you use the apparent global variable (or object field) "m_USBhandler" in all your functions. I would suggest that you check that this handle is valid before using it. I'm always suspicious of object handles---especially if the handle is global. This could be even more of a problem in a multi-threaded application where another thread might be using the same handle. if m_USBhandler is an object field, try making it a static global. Can you simply link in the FTDI.sys driver and get the program working with normal C code, rather than using DLLImport and the wrapper functions? (I don't know C# well enough to know if this is possible. My C# system is still in its unopened box--waiting for a lull in the consulting schedule). Mark Borgerson
Reply by Kris February 15, 20062006-02-15
Excuse me for the repeat, but I badly need somebody's help.
So, once again, just to draw attention:

Mark Borgerson wrote:
> If you want any more help, you're going to have to show us what is > going on inside your wrapper functions.
Here are the functions from the Wrapper class: public class Wrapper { private static IntPtr m_USBhandler; [DllImport("FTD2XX.dll", EntryPoint="FT_Open")] public static extern uint FT_Open(int iDevice, ref IntPtr ftHandle); [DllImport("FTD2XX.dll", EntryPoint="FT_Close")] public static extern uint FT_Close(IntPtr ftHandle); [DllImport("FTD2XX.dll", EntryPoint="FT_Read")] public static extern uint FT_Read(IntPtr ftHandle, byte[] lpBuffer, uint dwBytesToRead, ref uint lpdwBytesReturned); [DllImport("FTD2XX.dll", EntryPoint="FT_Write")] public static extern uint FT_Write(IntPtr ftHandle, byte[] lpBuffer, uint dwBytesToWrite, ref uint lpdwBytesWritten); [DllImport("FTD2XX.dll", EntryPoint="FT_Purge")] public static extern uint FT_Purge(IntPtr ftHandle, uint dwMask); public static bool OpenDevice() { if (((FT_Status)Wrapper.FT_Open(1, ref m_USBhandler)) == FT_Status.Ok) { return true; } else { return false; } } public static bool CloseDevice() { if (((FT_Status)Wrapper.FT_Close(m_USBhandler)) == FT_Status.Ok) { return true; } else { return false; } } public static void PurgeAll() { FT_Status opResult; if ((opResult = (FT_Status)Wrapper.FT_Purge(m_USBhandler, (uint)FT_PurgeRXTX.TX & FT_PurgeRXTX.RX))) != FT_Status.Ok) { throw new USBException("Could not purge the buffers.", opResult); } } public static uint CheckQueue() { uint bytesToReceiveNum = 0; FT_Status opResult; if ((opResult = (FT_Status)Wrapper.FT_GetQueueStatus(m_USBhandler, ref bytesToReceiveNum)) != FT_Status.Ok) { throw new USBException("Could not check the USB device queue status.", opResult); } else { return bytesToReceiveNum; } } public static byte[] ReadData(uint bytesToReceiveNum) { uint readBytesNumber = 0; byte[] receivedBytes = new byte[bytesToReceiveNum]; FT_Status opResult; if ((opResult = (FT_Status)Wrapper.FT_Read(m_USBhandler, receivedBytes, bytesToReceiveNum, ref readBytesNumber)) != FT_Status.Ok) { throw new USBException("Could not read data from the USB device.", opResult); } else if (bytesToReceiveNum != readBytesNumber) { throw new USBException("Could not retreive the full data from the USB device.", FT_Status.OtherError); } else { return receivedBytes; } } public static void WriteData(byte[] data) { uint bytesToWriteNum = (uint)data.Length; uint writtenBytesNumber = 0; FT_Status opResult; if ((opResult = (FT_Status)Wrapper.FT_Write(m_USBhandler, data, bytesToWriteNum, ref writtenBytesNumber)) != FT_Status.Ok) { throw new USBException("Could not write the data into the USB device.", opResult); } else if (bytesToWriteNum != writtenBytesNumber) { throw new USBException("Could not write the full data into the USB device.", FT_Status.OtherError); } } } For me, it seems to be ok, but may be there is some problem. Thank you in advance, Kris
Reply by Kris February 12, 20062006-02-12
Mark Borgerson wrote:
> If you want any more help, you're going to have to show us what is > going on inside your wrapper functions.
Here are the functions from the Wrapper class: public class Wrapper { private static IntPtr m_USBhandler; [DllImport("FTD2XX.dll", EntryPoint="FT_Open")] public static extern uint FT_Open(int iDevice, ref IntPtr ftHandle); [DllImport("FTD2XX.dll", EntryPoint="FT_Close")] public static extern uint FT_Close(IntPtr ftHandle); [DllImport("FTD2XX.dll", EntryPoint="FT_Read")] public static extern uint FT_Read(IntPtr ftHandle, byte[] lpBuffer, uint dwBytesToRead, ref uint lpdwBytesReturned); [DllImport("FTD2XX.dll", EntryPoint="FT_Write")] public static extern uint FT_Write(IntPtr ftHandle, byte[] lpBuffer, uint dwBytesToWrite, ref uint lpdwBytesWritten); [DllImport("FTD2XX.dll", EntryPoint="FT_Purge")] public static extern uint FT_Purge(IntPtr ftHandle, uint dwMask); public static bool OpenDevice() { if (((FT_Status)Wrapper.FT_Open(1, ref m_USBhandler)) == FT_Status.Ok) { return true; } else { return false; } } public static bool CloseDevice() { if (((FT_Status)Wrapper.FT_Close(m_USBhandler)) == FT_Status.Ok) { return true; } else { return false; } } public static void PurgeAll() { FT_Status opResult; if ((opResult = (FT_Status)Wrapper.FT_Purge(m_USBhandler, (uint)FT_PurgeRXTX.TX & FT_PurgeRXTX.RX))) != FT_Status.Ok) { throw new USBException("Could not purge the buffers.", opResult); } } public static uint CheckQueue() { uint bytesToReceiveNum = 0; FT_Status opResult; if ((opResult = (FT_Status)Wrapper.FT_GetQueueStatus(m_USBhandler, ref bytesToReceiveNum)) != FT_Status.Ok) { throw new USBException("Could not check the USB device queue status.", opResult); } else { return bytesToReceiveNum; } } public static byte[] ReadData(uint bytesToReceiveNum) { uint readBytesNumber = 0; byte[] receivedBytes = new byte[bytesToReceiveNum]; FT_Status opResult; if ((opResult = (FT_Status)Wrapper.FT_Read(m_USBhandler, receivedBytes, bytesToReceiveNum, ref readBytesNumber)) != FT_Status.Ok) { throw new USBException("Could not read data from the USB device.", opResult); } else if (bytesToReceiveNum != readBytesNumber) { throw new USBException("Could not retreive the full data from the USB device.", FT_Status.OtherError); } else { return receivedBytes; } } public static void WriteData(byte[] data) { uint bytesToWriteNum = (uint)data.Length; uint writtenBytesNumber = 0; FT_Status opResult; if ((opResult = (FT_Status)Wrapper.FT_Write(m_USBhandler, data, bytesToWriteNum, ref writtenBytesNumber)) != FT_Status.Ok) { throw new USBException("Could not write the data into the USB device.", opResult); } else if (bytesToWriteNum != writtenBytesNumber) { throw new USBException("Could not write the full data into the USB device.", FT_Status.OtherError); } } } For me, it seems to be ok, but may be there is some problem. Kris
Reply by David Tweed February 10, 20062006-02-10
Kris wrote:
> Your experience with the FT245BM chips is very relevant in this case, I > think, because the DLP-2232PB module is based on FT2232C - "double" > FT245BM with some additions. > May be you can tell me, transfer of what amounts of data and at what > rate is involved in your applications. It could be the key to solution.
We have implemented a message protocol on top of the raw "byte stream" presented by the USB interface. Our primary traffic is a 38-byte message 200 times a second (about 8000 bytes/second) plus a few thousand bytes of other miscellaneous messages each second. It ends up being about 10K bytes/second on the average. Windows XP generally does a pretty good job of keeping up in real time, although we see occasional "hiccups" when it gets busy with something else. -- Dave Tweed
Reply by Andrew Jackson February 9, 20062006-02-09
[Sorry for previous post, over hasty key press]

 >> What is that, C#? Where did you get FTDIWrapper?

[deletia]

 > Yes, it's C#. FTDIWrapper is the namespace of my Wrapper class, that
 > uses PInvoke for communication between managed code and unmanaged
 > functions of the D2XX driver. These functions were tested before
 > through a couple of loopback tests, and it was ok.

I've used the FTDI device with both C++ and C# without problems. It 
would be useful to see what some of your wrapper functions look like. 
The code that I wrote for C#, after finding and opening the device, 
wrote a command and read a result back (similar to yours but without the 
flush).

     Andrew

Reply by Andrew Jackson February 9, 20062006-02-09
Kris wrote:
> David Tweed wrote: >> Kris wrote: >>> host side: >>> >>> using System; >>> using System.Collections.Generic; >>> using System.Text; >>> using FTDIWrapper; >> What is that, C#? Where did you get FTDIWrapper? >> >> All I can tell you is that I've been using FTDI chips (FT245BM, mainly) >> for a couple of years now in embedded projects. But on the host side, >> we just use the D2XX driver from FTDI via Visual C++, and it works >> pretty much the way the documentation says it does. >> >> I would also echo the thought that opening/closing the device on every >> iteration is probably a bad idea. >> >> -- Dave Tweed > > Hello, Dave. > Yes, it's C#. FTDIWrapper is the namespace of my Wrapper class, that > uses PInvoke for communication between managed code and unmanaged > functions of the D2XX driver. These functions were tested before > through a couple of loopback tests, and it was ok. > Now, the "opening/closing" issue is addressed in the code snippet > above. But, as I said before, this does not help - to leave the device > open. > Your experience with the FT245BM chips is very relevant in this case, I > think, because the DLP-2232PB module is based on FT2232C - "double" > FT245BM with some additions. > May be you can tell me, transfer of what amounts of data and at what > rate is involved in your applications. It could be the key to solution. > Regards, > Kris. >
Reply by Mark Borgerson February 9, 20062006-02-09
In article <1139496772.475156.255940@f14g2000cwb.googlegroups.com>, 
kris.robin@gmail.com says...
> David Tweed wrote: > > Kris wrote: > > > host side: > > > > > > using System; > > > using System.Collections.Generic; > > > using System.Text; > > > using FTDIWrapper; > > > > What is that, C#? Where did you get FTDIWrapper? > > > > All I can tell you is that I've been using FTDI chips (FT245BM, mainly) > > for a couple of years now in embedded projects. But on the host side, > > we just use the D2XX driver from FTDI via Visual C++, and it works > > pretty much the way the documentation says it does. > >
That's been my experience also. I haven't changed my host side software in several years.
> > I would also echo the thought that opening/closing the device on every > > iteration is probably a bad idea. > > > > -- Dave Tweed > > Hello, Dave. > Yes, it's C#. FTDIWrapper is the namespace of my Wrapper class, that > uses PInvoke for communication between managed code and unmanaged > functions of the D2XX driver. These functions were tested before > through a couple of loopback tests, and it was ok. > Now, the "opening/closing" issue is addressed in the code snippet > above. But, as I said before, this does not help - to leave the device > open. > Your experience with the FT245BM chips is very relevant in this case, I > think, because the DLP-2232PB module is based on FT2232C - "double" > FT245BM with some additions. > May be you can tell me, transfer of what amounts of data and at what > rate is involved in your applications. It could be the key to solution. > Regards, > Kris.
The source code for my windows host program uses the following to read a file transferred from the embedded system. The program is in Borland C++ builder. FTH is the handle for the FTDI FT245 device: void __fastcall TFormLink::BTXferClick(TObject *Sender) { char *fullstring, fnstring[15], cmdstring[16]; int i,spos; FILE *fp; static char spbuff[4098]; long bytecount; DWORD numwritten, num2read,numread; AnsiString str; char *fnp; if(FTH == 0) return; // exit if not open /// Snipped file opening code FT_Write(FTH,cmdstring, strlen(cmdstring), &numwritten); // //send the file name timeout = 50; // sets 5-second timeout to start file // at this point, the logger starts sending the file data while(timeout > 0){ fts = FT_GetQueueStatus(FTH, &num2read); if((fts == FT_OK) && (num2read > 0)){ FT_Read(FTH,&spbuff[0],num2read,&numread); if(numread > 0){ if(fp != NULL) fwrite(&spbuff[0], numread,1,fp); bytecount+= numread; EDCount->Text = bytecount; // show bytes sent timeout = 4; // reset timeout counter to 0.4 } } Application->ProcessMessages(); // check windows msgs } if(fp!= NULL) fclose(fp); } If you want any more help, you're going to have to show us what is going on inside your wrapper functions. You can find the logger-side source code at www.oes.to. Look for the USB-1 page. Mark Borgerson
Reply by Kris February 9, 20062006-02-09
David Tweed wrote:
> Kris wrote: > > host side: > > > > using System; > > using System.Collections.Generic; > > using System.Text; > > using FTDIWrapper; > > What is that, C#? Where did you get FTDIWrapper? > > All I can tell you is that I've been using FTDI chips (FT245BM, mainly) > for a couple of years now in embedded projects. But on the host side, > we just use the D2XX driver from FTDI via Visual C++, and it works > pretty much the way the documentation says it does. > > I would also echo the thought that opening/closing the device on every > iteration is probably a bad idea. > > -- Dave Tweed
Hello, Dave. Yes, it's C#. FTDIWrapper is the namespace of my Wrapper class, that uses PInvoke for communication between managed code and unmanaged functions of the D2XX driver. These functions were tested before through a couple of loopback tests, and it was ok. Now, the "opening/closing" issue is addressed in the code snippet above. But, as I said before, this does not help - to leave the device open. Your experience with the FT245BM chips is very relevant in this case, I think, because the DLP-2232PB module is based on FT2232C - "double" FT245BM with some additions. May be you can tell me, transfer of what amounts of data and at what rate is involved in your applications. It could be the key to solution. Regards, Kris.