HOWTO: FTDI bitbang mode on FreeBSD

Hello =)

I'd like to give a simple introduction on using FTDI chips in bitbang mode based on this post on Hack a Day.

For the hardware we will be using the "Breakout Board for FT232RL USB to Serial" from Sparkfun, of course you can use any flavor of FTDI ICs.

Also we will need to get the libftdi devel/libftdi if you don't have it already.
Code:
#cd /usr/ports/devel/libftdi
#make install clean

The documentation is very helpful when working with libftdi API in C++: libftdi docs

When you connect the FT232R breakout board via USB, you should be able to see your device as a virtual serial port in my case: /dev/cuaU0 and it was identified as a ugen1.2 device.
Code:
$dmesg | tail
ugen1.2: <FTDI> at usbus1
uftdi0: < FT232R USB UART > on usbus1

Next let's try the LED blinker example by Phil at Hack a Day.
I made some changes to the C++ code to be compatible with the latest libftdi 0.20

We will need an LED and a 330 Ohm resistor. Connect the Anode of LED (long lead +ve) to CTS pin on FTDI breakout, and the Cathode (short lead -ve) to the resistor, and the other lead of the resistor will be connected to GND.

Put the following code in a file named hello_ftdi.c
Code:
/* hello_ftdi.c: flash LED connected between CTS and GND.
   This example uses the libftdi API.
   Minimal error checking; written for brevity, not durability. */

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

#define LED 0x08  /* CTS */

int main()
{
    unsigned char c = 0;
    struct ftdi_context ftdic;

    /* Initialize context for subsequent function calls */
    ftdi_init(&ftdic);

    /* Open FTDI device based on FT232R vendor & product IDs */
    if(ftdi_usb_open(&ftdic, 0x0403, 0x6001) < 0) {
        puts("Can't open device");
        return 1;
    }

    /* Enable bitbang mode with a single output line */
     ftdi_set_bitmode(&ftdic, LED, BITMODE_BITBANG); 

    /* Endless loop: invert LED state, write output, pause 1 second */
    for(;;) {
        c ^= LED;
        ftdi_write_data(&ftdic, &c, 1);
        sleep(1);
    }
}

To compile the above code we use the following command:
# gcc -I/usr/local/include/ -L/usr/local/lib/ -o blink hello_ftdi.c -lftdi

This will generate an executable named hello, run it
# ./hello

You should see the LED blinking on and off with a period of 1 second.

We might need this pin mapping for the FTDI pins in future programming:

Code:
/*
 * bitbang I/O pin mappings 
 * 
 * #define PIN_TXD  0x01
 * #define PIN_RXD  0x02
 * #define PIN_RTS 0x04
 * #define PIN_CTS 0x08
 * #define PIN_DTR 0x10
 * #define PIN_DSR 0x20
 * #define PIN_DCD 0x40
 * #define PIN_RI  0x80
 */

For now you can have a look on Phil's post on Hack a Day he explains the code pretty well, the code above is modified and works well with libftdi 0.20, also I'll post here the PWM LED chaser code in that other article it's written using D2XX API instead. So I'll post below a modified version to work with libftdi API.

The hardware setup includes 4 LEDs and 4 330 Ohm resistors, I happened to use an LED bar that I had laying around.

Code:
/* pwmchase.c: 8-bit PWM on 4 LEDs using FTDI cable or breakout.
   This example uses the libftdi API.
   Minimal error checking; written for brevity, not durability. */

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ftdi.h>

#define LED1 0x08  /* CTS */
#define LED2 0x01  /* TXD  */
#define LED3 0x02  /* RXD */
#define LED4 0x14  /* RTS + DTR */

int main()
{
    int i,n;
    unsigned char data[255 * 256];
    struct ftdi_context ftdic;
    
    /* Generate data for a single PWM 'throb' cycle */
    memset(data, 0, sizeof(data));
    for(i=1; i<128; i++) {
        /* Apply gamma correction to PWM brightness */
        n = (int)(pow((double)i / 127.0, 2.5) * 255.0);
        memset(&data[i * 255], LED1, n);         /* Ramp up */
        memset(&data[(256 - i) * 255], LED1, n); /* Ramp down */
    }   

    /* Copy data from first LED to others, offset as appropriate */
    n = sizeof(data) / 4;
    for(i=0; i<sizeof(data); i++)
    {
        if(data[i] & LED1) {
            data[(i + n    ) % sizeof(data)] |= LED2;
            data[(i + n * 2) % sizeof(data)] |= LED3;
            data[(i + n * 3) % sizeof(data)] |= LED4;
        }
    }   

    /* Initialize context for subsequent function calls */
    ftdi_init(&ftdic);

    /* Open FTDI device based on FT232R vendor & product IDs */
    if(ftdi_usb_open(&ftdic, 0x0403, 0x6001) < 0) {
        puts("Can't open device");
        return 1;
    }

    /* Initialize, open device, set bitbang mode w/5 outputs */
    
    ftdi_set_bitmode(&ftdic, LED1 | LED2 | LED3 | LED4, BITMODE_BITBANG); 
    ftdi_set_baudrate(&ftdic, 9600);  /* Actually 9600 * 16 */

    /* Endless loop: dump precomputed PWM data to the device */
    for(;;) ftdi_write_data(&ftdic, data, sizeof(data));
}

To compile run:
# gcc -I/usr/local/include/ -L/usr/local/lib/ -o pwm pwmchase.c -lftdi -lm

then to run:
# ./pwm

You should now see the 4 LEDs chasing each other with the PWM (Pulse Width Modulation) effect.

I'm currently working on connecting a 20x4 LCD display, and will have it show some info.Will keep you posted.

I hope this would be of any help to you and have fun. :i

Draco ^^
 
wblock@ said:
An FTDI board can be used as an IR receiver with nox's port of comms/lirc.

This is interesting, I'm sure I'll play around with it =)

I'm also working on flashing some ATmega328 chips using devel/avrdude and the FTDI chip, still having some problems with avrdude.conf, but thanks to Joerg Wunsch he gave me some instructions in reply to my email yesterday, so I'll get working and update this Howto with the results.
 
Yes that would be great, I'd be very grateful if you could share it with me.

So the problem on my end when using the FT232R chip with avrdude I get this error:
Code:
Unknown type 3 (0x3)

Thanks to Joerg Wunsch he pointed out the following:
According to <ftdi.h>, type 3 is TYPE_R, i.e. you are using an FT232R.
I don't think this device offers the MPSSE feature which is required for
the SPI implementation.

Which is true. So I'm looking into this patch by David Brownell : http://lists.gnu.org/archive/html/avrdude-dev/2006-10/msg00011.html

David's patch is based on libftdi, which is unlike Johnathan Corgan's patch based on FTD2XX which is proprietary source.

I'll dig more into this, but I'm not sure if I can apply these changes to devel/avrdude or even if someone already ported them.

I also came across this article on AVR Freaks: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=103730&start=0
Some guy created a code to flash AVRs using FT232R (You need to be logged in to view the files, I'll upload it later somewhere).

A helpful link: http://doswa.com/2010/08/24/avrdude-5-10-with-ftdi-bitbang.html
 
burn_bootloader_328

Code:
#!/bin/sh

# based on http://www.arduino.cc/playground/uploads/Bootloader/Burn_Bootloader_168

avrdude="/usr/local/bin/avrdude"
options="-P /dev/cuaU0 -p atmega328p [color="Red"]-c avrisp[/color] -b 19200"
bootldr="/usr/local/arduino/hardware/arduino/bootloaders/atmega/ATmegaBOOT_168_atmega328.hex"

# erase chip write lock and fuses
${avrdude} ${options} -e -Ulock:w:0x3f:m -U lfuse:w:0xff:m -U hfuse:w:0xda:m -U efuse:w:0x05:m

# upload the bootloader
${avrdude} ${options} -D -V -U flash:w:${bootldr}:i

# lock the boot section
${avrdude} ${options} -V -U lock:w:0x0f:m
 
Back
Top