Today the parallel printer port is on the brink of extinction (and good riddance, some would say). Largely rendered obsolete by USB, few (if any) new peripherals even include a parallel connector, and today’s shrinking computers — nettops, netbooks, media center PCs — wouldn’t have space for it anyway. That’s great for tidy desks, but not so good if you enjoyed the dirt-cheap hacks that the legacy parallel port made possible.

Fear not, for there’s a viable USB alternative that can resurrect many of these classic hacks! And if you’ve done much work with Arduino, there’s a good chance it’s already lurking in your parts drawer.

A recurring element among many recent hacks is the use of an Arduino or other USB-connected microcontroller as an intermediary between a PC and an external circuit. Code running on the microcontroller will poll some sensor to detect a change (for example, an empty coffee pot), then send a message over USB to a host PC where another program then acts on it (updating a web page to tell the world there’s no coffee). This is a reasonable approach, the parts are affordable and simple to program, but for many projects we can get by with just half the code, complexity and expense…and some folks will be thrilled to hear, no Arduino!

When the microcontroller on an Arduino board talks to a host PC over USB, all of the heavy lifting of USB communication is done by a separate chip: the FTDI FT232R USB to serial UART interface. This allows code on both the host and microcontroller to use much simpler asynchronous serial communication. As a size- and cost-cutting measure, some Arduino variants place this chip on a separate board to be attached only when programming the microcontroller, allowing it to be re-used for the next project.

This default USB-to-serial mode of the FT232R is what usually draws all the attention and gets all the girls. An alternate mode, less talked about but no less useful, is bitbang mode. This gives us independent software control of up to eight I/O lines, similar to the classic parallel port or the digital I/O lines of a microcontroller.

Acquiring the Hardware

If one isn’t already in your stash, FT232R breakout boards are easy to come by. Any shop that carries the Arduino Pro or LilyPad, or some of the bargain-priced Arduino derivatives (e.g. Boarduino), will also offer a programming cable that breaks out four of the FT232R I/O lines:

Above: The SparkFun FTDI Basic Breakout board (around $14) is surrounded by the FTDI TTL-232R converter cable (around $20). Both break out four data lines that can be used for general-purpose I/O.

Four data lines may seem constraining, but for many tasks this is sufficient; projects using SPI communication, shift registers and port expanders will be well served. If you need the full complement of I/O lines, more sophisticated breakout boards are available:

Above: just a few of the available full breakout boards. Clockwise from top: SparkFun Breakout Board for FT232RL (around $15), Modern Device USB-BUB ($12), DLP Design DLP-USB232R ($18) and DLP-USB1232H ($25), and FTDI’s own FT4232HQ Mini Module ($30). The latter two are based on more capable chips, the FT2232H and FT4232H, backwardly compatible but with additional features far exceeding the scope of this article.

Setting Up for Development

Another encouraging aspect of the FTDI interface is cross-platform software support; the same hacks can be created whether you’re using Windows, Linux or Mac OS X. Two software components are required to begin development: a device driver, which operates behind the scenes to handle all the low-level USB communication, and an API library, which is linked with your own code and forwards requests to the driver. Complicating matters slightly, there are two different APIs to choose from, and the setup process is a little different for each OS.

FTDI’s own API is called D2XX. This library is proprietary and closed source, but they do not charge for its use, even in commercial situations. An alternate API, libftdi, is community-developed and fully open source. This library has similar capabilities, but different function names and syntaxes. Conversion between the two APIs is very straightforward, and we’ll provide an example for each.

Linux users: most current Linux distributions already have the necessary driver present as a kernel module. The D2XX library for Linux can be downloaded from the FTDI driver page, but libftdi is easier to install: simply locate libftdi-dev in your favorite package manager and have it take care of the dependencies when installing. In either case, FTDI programs for Linux need to be run as root, e.g.

sudo ./hello-ftdi

Mac OS X users:download the D2XX library from the FTDI download page. The included ReadMe file will explain how to install this library. If you’d prefer to use libftdi, download the source for libusb (legacy 0.1.12 version) and libftdi from their respective sites, then use the following commands in a Terminal window to build and install each of the two libraries:

./configure
make
sudo make install

If you’ve used Arduino in the past or have the FTDI Virtual Com Port (VCP) driver installed for any other reason, this needs to be disabled before bitbang mode will work on the Mac; the two cannot coexist. In a Terminal window, type:

sudo kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext

To restore the driver and resume using Arduino or other FTDI serial devices:

sudo kextload /System/Library/Extensions/FTDIUSBSerialDriver.kext

Other operating systems: drivers for several other platforms are available. Please see the FTDI drivers page for details and links.

Most of the FTDI sample code is written in C, and that’s what we’ll use here. Bindings for other languages are available on the FTDI web site.

Hello World: Flash an LED

The standard introductory program for nearly every microcontroller is the LED flasher, so let’s give that a try. You’ll need an FTDI cable or any of the breakout boards, one LED and a 220 Ohm resistor.

Connect the resistor to either leg of the LED, but keep note of which leg is the positive (anode) side. Then insert the LED/resistor pair into the socket on the end of the FTDI cable as shown below, with the negative leg connected to the GND line (the black wire on the FTDI cable) and the positive leg to the CTS line (brown wire).

Here’s the C source code, using the libftdi API. If you plan on using D2XX, have a look at the second listing a bit later; the relationship between functions should be fairly obvious.

If the program successfully compiles (all of the required headers and libraries in the appropriate locations, and properly linked with our own code), the LED should flash slowly.

The code is largely self-explanatory, but there are a couple of points worth highlighting:

Note the second parameter to ftdi_enable_bitbang(). This is an 8-bit mask indicating which lines should be outputs (bit set) vs. inputs (bit clear). As we’re only using a single output line (CTS in this case), we set just the one bit corresponding to that line (0x08). For additional outputs, we can OR the bit values together. The bitbang I/O pin mappings aren’t defined in either API’s header, so you might find it helpful to keep around a header such as this:

Notice that the second parameter to ftdi_write_data() is a pointer to an 8-bit variable. The function normally expects an array (and the second example will demonstrate this), but for this simple case only one value is required. When issuing a single byte like this, remember to always pass by reference (a pointer), not a numeric constant. The last parameter to the function is the number of bytes.

The value(s) passed to ftdi_write_data() indicate the desired state of the output lines: a set bit indicates a logic high state (3.3 or 5 volts, depending on the FTDI adapter used), and a clear bit indicates logic low (0 volts). The mapping of bits to I/O pins is exactly the same as for ftdi_enable_bitbang(), so the prior #defines may be helpful in that regard.

More Bells and Whistles

There are many project ideas that only occasionally need to toggle an I/O line: ring a bell when a web counter increments, flash a light when email arrives, send a Tweet when the cat uses the litter box. The code for such tasks will often be just as simple as the example above. But when communicating with more complex devices and protocols, this byte-at-a-time approach becomes very inefficient. Every call to ftdi_write_data(), even a single byte, issues a USB transaction that will be padded to a multiple of 64 bytes, and there can be latencies of a full millisecond or more before this request is actually sent down the wire. To efficiently send complex data streams, it’s necessary to pass an entire array to the ftdi_write_data() function.

Bitbang mode operates very differently than the chip’s default serial UART mode. In the serial configuration, one simply calls fwrite() to issue a block of data to the serial port, and the chip manages all the details of the transmission protocol: word length, start, stop and parity bits, and toggling the logic state of the TX line at the required baud rate. In Bitbang mode there is no implied protocol; this is raw access to the data lines, and we must take care to construct a meaningful signal ourselves, essentially creating an image map of the data lines over time:

Suppose we want to communicate with a device that uses the SPI protocol (Serial Peripheral Interface, also sometimes called Microwire, synchronous serial or three- or four-wire serial, depending on the implementation). The required output would resemble the waveform in the illustration above: one output line provides a clock signal, another represents the data bits (in sync with the clock), and a third issues an end-of-data latch signal. If sending 8 bits of data, our output array would need to be twice that size (to represent the high and low state of each clock tick), plus two additional bytes for the latch high/low at the end. 8 * 2 + 2 = 18 bytes in the output array (possibly a few extra bytes, if a specific device requires a short delay before the latch signal).

SPI might be too esoteric for an introductory article; not everyone will have the right components around. Instead, let’s make something visually gratifying: we’ll drive a group of LEDs using pulse width modulation. This is of dubious utility but it’s flashy and hints at the speed and fine control that’s possible using this port.

The hardware setup is similar to the first example, but repeated four times: four LEDs, four 220 Omh resistors (we’re limiting it to four in order to work with the FTDI cable or SparkFun Basic Breakout, but it’s easily expandable to eight with the other boards). The negative legs are all connected in common to the GND line (black wire on the FTDI cable), while the positive legs are connected to CTS, TX, RX and RTS (brown, orange, yellow and green wires, respectively). The SparkFun Basic Breakout has DTR in place of RTS for the last pin, but the example code will work the same with either one…we’ll explain how shortly.

Here’s how the components look on a breadboard. Notice that the +5V line (red wire on FTDI cable) is skipped:

And here’s the source code, using the D2XX API. Adapting this to libftdi is straightforward; see the first example for the different syntaxes.

When successfully compiled and run, the LEDs should slowly pulsate in a repeating “chaser” cycle. There are some notable differences from the first example:

LED4 is defined by two bits, a logical OR of both RTS and DTR, and the two bits are always toggled in unison. This isn’t a mandatory requirement, it simply makes the program compatible with different hardware: the FTDI cable and the SparkFun Basic Breakout use a different signal on the last pin, and toggling both bits makes it work the same regardless.

The baud rate is explicitly set to 9600 bps (bitbang mode will actually run at 16 times the baud rate). This is so the PWM speed will be the same whether using libftdi or D2XX. The former library normally initializes the port to 9600 baud by default, while the latter API (used here) opens the port at maximum speed and we need to slow it down to match. In practice, at maximum speed we’re able to get about 650,000 8-bit samples per second out this port.

In Mac OS X 10.6, you may find it necessary to pass the -m32 flag to gcc in order to compile and link with the D2XX library. And Windows programmers using Cygwin may need some additional header files:

Pulse width modulation makes for a nice visual demonstration of speed but unfortunately can’t really be put to serious use. In addition to the previously-mentioned I/O latency, other devices may be sharing the USB bus, and the sum total is that we can’t count on this technique to behave deterministically nor in realtime. PWM with an LED looks just fine to the eye…the timing is close enough…but trying to PWM-drive a servo is out of the question. For a synchronous serial protocol such as SPI, where a clock signal accompanies each data bit, this method works perfectly, and hopefully that can be demonstrated in a follow-up article.

Not a Panacea

FTDI bitbang mode comes in handy for many projects, but it’s not a solution to every problem. There are many situations where a microcontroller is still preferable:

For extended standalone use, it’s a no-brainer: a microcontroller board costs less than a fancy meal and runs for days on a 9-volt battery. Only when a project is going to involve a full-on PC anyway should bitbang mode be considered.

If a task involves basic analog-to-digital conversion, you’re almost certainly better off using a USB-connected microcontroller with built-in ADC. It’s just less hassle than the alternative.

For tasks that require continual high-speed polling of a sensor, bitbang mode will needlessly gobble USB bandwidth and CPU cycles. Most microcontrollers have an interrupt-on-change feature that avoids polling entirely, using resources only when a change actually occurs.

Post navigation

77 thoughts on “Introduction to FTDI bitbang mode”

Comment navigation

I’m having trouble with 10.6 Snow Mac OS X. FTDI D2xx driver installed properly.. bout FT_openEx() gives error.. after debugging found that I need to do lsmode to find the usb modules that are loaded and remove them using rmmod..

But there is no equivalent command to rmmod in mac os x.
kext stat is the equivalent for lsmod..
I’m stuck at this point.. please suggest what else am I missing?

The fact that kextstat is listing the FTDI driver at all indicates that the VCP driver has NOT been fully purged from the system. With both the VCP and D2XX drivers installed, if I build and run the ‘simple’ program, I’m seeing the same error you show.

However, if I first run the command as given in my prior instructions:

sudo kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext

The ‘simple’ program then runs without error. Please try that command first rather than trying to delete the VCP driver.

Thank you very much for the wonderful article. It has been very helpful for amateurs like me!
I would like to ask somehing if I may, I am using the FT2232H mini mod to generate a PPS with a dutycycle of 20/980. You (and the DS) mentioned that the baud gets x16. But its not the case for me. I am writing 120 bytes to a pin with a baud of 1200 which means I should send the data in 6.25ms (with effective baud of (x16 = 19200) but it takes exactly 20ms (x5 = 6000)! Has it happened to anybody else too?

I have been experimenting with FTDI bit-bang on Windows-7 Pro and I thought I would pass on an interesting phenomenon I have noticed. I am using FTDI FT230x and “CBUS” bit-bang, which only sends 4 bits per USB packet (as opposed to FT_Write/FT_Read that can use a buffer). This is probably similar to any “tiny” USB packet (like FT_Read/FT_Write with a small length).

While testing I noticed some PCs were about 7 times faster than others (of a similar type). After experimenting I found that having a USB hub made the bit-bang MUCH faster. For example, toggling a clock line I can toggle at ~3.5Khz with a hub and only .5Khz without a hub (i.e., exactly 1 packet per millisecond). My friend suspects the hub makes Windows use “micro-frames” or some such.

So, take away is a hub can make a huge increase in USB packet transmission rate (when packets have a small payload).

A somewhat counter-intuitive, but an interesting find. Since this was a very helpful article for FTDI bit-banging (even though not exactly about CBUS mode), I thought I would pass on this info here.

tnx for good article.
what is maximum speed on pins of ft232r in gpio mode (toggling) ?
I make a pwm generator with ft232r , I want to know maximum carrier frequency of my design.
can any body help me?
is there any sample code in c# or labview?

I think this tutorial missed out a huge chunk when skipping the build of libftdi. Could annyone help me with how to do that? There’s seems to be zero information on how to do it. I’m using Eclipse and just can’t get anything work, it won’t compile.

Your information sparked an idea in my mind to interface a Noritake SPI interface VFD (vacuum fluorescent display) to an FDTI breakout board. Your code samples provided enough guidance to get it working in 30 minutes and the program finished in a few hours. My code read from standard input and sends the text to the VFD. If the link works, here’s a photo of it working: http://www.hobbytent.com/other/files/vfd_ftdi.jpg