The 1608G DAQ (Driver)

For the past few months I have been using the 1608G DAQ from measurement computing to perform data collection on a microphone array. There have been a few hickups with using the device, though those were mostly figured out. The main issue with the DAQ and the reason why I am writing this is that the driver software was a a constant annoyance.

When working with this device, there were two driver options, a C API for windows with no source or a portable C# interface with source. As the intended platform was Linux, I had to go with the C# code. Now I do not know C#, nor do I intend to learn the language, as the only niche it would fill would be working with this library, so I looked for the basic documentation and examples with the driver’s library.

I found sparse documentation and example code using undocumented commands, but I did have source code up to where the hardware began. Starting from the C# examples, C slowly started to consume the C#. First I started with C# calling a C library, then I had C calling a mono vm, lastly I decided I was fed up with any amount of C#. The heterogeneous environment was too prone to bugs and too difficult to debug for my tastes.

So I started to read page after page of source code, looking for the magic commands to control this hardware. Eventually I get to the calls out to libusb. I figure that I should be able to get the sequence of calls fairly easily. First I try to see if gdb has some form of glob based break point system, as that would let me inspect all of the data originating within the bowels of the library, but there is no support for this. Then I tried to see if mono had some verbose debug level, but the debugging support within embedded programs was not sufficiently verbose. Lastly I found ltrace and found out that whatever magic lied inside mono’s dll execution hid and evidence of libusb getting called from this tool as well.

So, with all of these tools struck down, I reverted to the basics, grep and reading code in vim. After trudging through partial classes and copy-pasta code, I find a basic initialization routine and I see the outgoing calls to ibusb_control_transfer. After reading up on the basic functionality, I sent the device a simple query for its firmware version. Surprisingly I get a response and it makes sense. Now I get to the point where I can even ask it to start scanning its analog input ports, yet it response with a simple "INVALID" message. Perplexed I try again and again finally finding the oddity of the fpga version, the device claims the version is "ff.ff", yet if I run the command from one of the example programs it clearly responds with a number.

A few Console.Writes and a few hours later and I had the fpga image written to the device and I had samples streaming back. While this may seem like a fairly minor project, there is a great feeling with seeing bits stream back from an external device. If one sends the wrong bits it would act like an abyss, dropping all bytes into nothingness, but it worked, it responded and even gave back the desired data quickly and in a (as of so far) bug free manner.

If anyone has one of these devices or a similar model, you should be able to modify my code to have a basic libusb based interface. The code is availiable "here":http://fundamental-code.com/log/daqflex/1608g.tar under the MIT license.