July 28, 2018

1011 words 5 mins read

#TIL: Bit-Banging FTDI Breakout

#TIL: Bit-Banging FTDI Breakout

You don’t need Arduino to be able to learn about digital signal.

In the past I’ve been written about electrical engineering as a very valuable skill to be acquired in 2018. The role of electronic gadgets becomes more and more important as they are the “input” and “output” of the future.

Electrical Engineering is just one abstraction below the software. When you’re doing software you generally do not care about signals, voltage, current, analogue or digital. In EE, you need to understand them. My first dive into electronics was typical, I just bought some popular development board and code on it and finally I can write a wifi-connected blinky. Blinky is the ‘hello world’ of electronics.

The problem with that is it’s relatively expensive way of learning about digital signal. Writing code with boards like Arduino, Raspberry Pi, or ESP8266 may still worthwhile however I think I find a cheaper and simpler way by using only your PC and an affordable USB breakout board to learn about digital signal.

The problem with this approach is that the read and write rate is a magnitude slower than using ‘real’ GPIO as we’re actually doing something called bit-bang.

Bit banging - Wikipedia

Meet FTDI and libUSB

An FTDI breakout board can be bought for less that $5 nowadays. If you’re working with electronics you usually have this board to do serial communication.


FT232RL Breakout Board

With some cheap basic electronics components we can learn about electronics using your own computer. No cross compiling and flashing required all you need are two libraries: libUSB and libFTDI and your favourite programming language. I assume we’re using macOS or Linux here as they’re easier to work with. As for Windows, you may refer to this StackOverflow Q&A

pylibftdi missing libftdi libusb on Windows install

For Linux you can use apt-get or yum to install libftdi . On macOS, you can use port or brew and of course Xcode. If you’re like me, a macOS user, we need to unload the FTDI driver. sudo kextunload --bundle-id com.FTDI.driver.FTDIUSBSerialDriver

Here’s the simple ‘schematic’ and the photo of the components laid out in the breadboard. plug the USB to your PC to start coding.


Schematic and Breadboard component placement for Blinky

Getting Required Values

I’m using FTDI232R chip, the most common chip used on this breakout. The datasheet says these are the pins and bit number.


FTDI 232R pin assignment and bit-bang bus.

What we’ll do is called bit-banging which actually we can send and receive raw signal from a pin and control the data flow using software. In our example here, we’ll be reading and writing from CTS pin. The CTS pin is pin number 11 in the datasheet and it’s in bitbang bus bit 3. If we turn on bit 3 it’ll be : 001000b or the same with the number 8 both in decimal and hexadecimal. We’ll use the value on the program later.

Getting VID and PID

Every USB devices has If you’re using Linux you can use lsusb to get the VID and PID. Here’s the output of it from my computer.

$ lsusb  
Bus 020 Device 044: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC  
Bus 001 Device 024: ID 05e3:0612 Genesys Logic, Inc. Hub  
Bus 020 Device 009: ID 04d9:0269 Holtek Semiconductor, Inc.  
Bus 020 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver  
Bus 020 Device 002: ID 05e3:0610 Genesys Logic, Inc. 4-port hub

Those are all of my USB devices. There you can see that FTDI is on 0x0403 VID and 0x6001 PID.

On a macOS, you can use system_profiler SPUSBDataType and you’ll get the VID and PID.


Output on Mac

On Windows, there are more hoops you’ll need to do to get the VID and PID. So I think it’s better just to skip and trust my value.

Code Them Up

We’ll be using for this one. The reason was because this is the language used for creating firmware and also the easiest to get started after libftdi is installed.

We’ll be using C as our language of choice. We also assume we’re using somekind of Unix or Unix-like environments such as macOS or Linux. This code will not compile on Windows as it has no usleep function.

Here’s a fully-commented code, and we save it as blinky.c .

/* These are standard headers used in Unix systems */

#include <stdio.h>  
#include <unistd.h>  
#include <ftdi.h>

#define LED 0x08  /* CTS PIN */

int main()  {  
    unsigned char c = 0;
    /* ctx is the FTDI context, we'll use this to control the  
     * FTDI devices later. We'd need to initialise it first  
    struct ftdi_context ctx;  
    /*  Open FTDI Devices based on FTDI VID/PID */  

    if(ftdi_usb_open(&ctx, 0x0403, 0x6001) < 0) {  
        puts("Can't open device");  
        return 1;  
    /* Enable bitbang mode with a single output line */  
    ftdi_set_bitmode(&ctx, LED, BITMODE_BITBANG);

    /* Endless loop: invert LED state,   
     * write output, pause 1 second */  
    for(;;) {  
        c ^= LED; /* C = C XOR C which will flip the bits*/  
        ftdi_write_data(&ctx, &c, 1);  
        usleep(200000); /* pause for 200000 microseconds*/  

Let’s compile them using gcc . We assume that you have libftdi on standard path.

$ gcc blinky.c -o blinky -lftdi

This will output executable named blinky in the same folder. If your ftdi libraries and headers are in different directories you’d need to change the command slightly by add ngi -I and -L . For example, when you’re using Macports the library will be installed in /opt/local/include/libftdi1 and /opt/local/lib for the headers and library respectively. Therefore the command will be

gcc blinky.c -o blinky -I/opt/local/include/libftdi1 \  
  -L/opt/local/lib -lftdi1`

And then we’d need to execute it using ./blinky . And here’s blinky in its full glory:


Blinky in its full glory GIF


FTDI is very convenient piece of hardware. By utilising its capability of writing and reading from a digital signal pin to do bit-banging, we’re able to test sensors by emulating its peripheral communication such as SPI, UART, and I²C without cross compiling.

Happy Hacking!