|
From: Kyle M. (qDot) <ky...@no...> - 2008-04-27 22:06:56
|
Stephen Sinclair wrote: > I've heard of this 16 ms / 64 byte thing regarding FTDI chips. It > always made me wonder how they managed to do high-speed stuff using > these chips actually. Glad to know it can be set to 1. I think I > figured that they were instead just padding the data to get it to fill > the 64-byte buffer and transmit faster. > If you want all the reasoning behind why handshaking and latency work like they do, check out http://www.ftdichip.com/Documents/AppNotes/AN232B-04_DataLatencyFlow.pdf This explains it all, and is actually how I figured out what I was doing wrong this morning. > That's pretty much haptic speed now... One tricky thing being that > there is a lot of jitter. > Yeah, I'm not sure how much you could possibly do with a moving average filter or something to fix that. I also just implemented double buffering of received data, because at > ~350hz, the packets start to fall off per-frame alignment and you have to assemble them across multiple frames. Right now nifalcon_test_fw_get_struct and get_raw are considered to be polls for this functionality, as most of the time, it's assumed we'll bridge across a maximum of 2 frames for a full set of data. However, this also leads to about a 5-9% error rate in data construction, which I honestly believe is on-par with what the falcon experiences using Novint's code. If you look at the FalconTest GUI that comes with the real falcon drivers, it manages to clock up a similar error rate, too. > Does the D2XX driver really perform faster than that? I know it > should really be 1000 Hz. > Yup, the D2XX drivers run at 1khz for I/O. This is where we hit the next wall, synchronous versus asynchronous transmission. libftdi is built on libusb 0.1, which only gives you synchronous transmission. This means that even though we're sending and receiving ~18bytes (2 status + 16 user from the FTDI) per frame, well under the 64 byte maximum for the endpoint, we're still locked to one transaction per frame, and USB frames are 1ms. So, we're stuck with a 2ms control loop, hence the 500hz for libftdi. The way to fix this is to do simultaneous requests for both input and output and then hope to receive them back on the same frame, which requires an asynchronous library. libusb-1.0 (http://libusb.wiki.sourceforge.net/Libusb1.0) does this, but at the moment, is unfortunately at pre-alpha stage. I've been working with a checkout of the dev branch of it for the past week (I initially figured the speed issue was an synchronous limitation), and if I get it actually up to 1khz, I'll check in all of my specialized code (I have my own little fork of libftdi at the moment to handle the status calls, just had to convert their control message calls from the 0.1 to 1.0 API) so others can use it. |