Building an SPI Port

It’s been some time since my last post. Last week I got inspired and revisited my yad2xx project over on Source Forge. Managed to get an SPI interface working as well as a bunch of cleanup work.

The Serial Peripheral Interface Bus (SPI) was originally introduced by Motorola as a low pin count bus for chip interconnect. Its main competitor is Philips’ (now NXP) I2C interface. Whilst having a lower pin count, I2C is a little more complicated to implement. SPI is commonly used with serial RAM/ROM chips as well as being forming the basis for the MMC/SD memory card interface. A PC to SPI interface is a handy tool to have!

I’m not going to cover the details of SPI here, there are plenty of other sites that provide that information such as Wikipedia. I’m going to assume that you are familiar with the port and terminology.

Certain FTDI serial chips contain a Multi Purpose Synchronous Serial Engine (MPSSE). The MPSSE can be used as the core of an SPI interface, as per FTDI application notes AN108 and AN114.


My SPI interface is based on the FTDI FT2232H USB/Serial chip. Dangerous Prototypes sell a convenient break out board with this chip mounted. For testing I used a CAT93C46 Flash ROM chip. This is a 1024 bit memory which can be organised as either 8 or 16 bit words depending on the level of a device pin.

I left the ORG pin disconnected which results in 64×16 bit words (internal tie high). Pin connections between the FT2232H and CAT93C46 are as follows:

FTDI Pin SPI Pin Comments
ADBUS0 SCK Serial clock – idles low for CAT93C46
ADBUS1 MOSI Master out
ADBUS2 MISO Master in
ADBUS3 CS Chip select – active high for CAT93C46

Generic SPI Interface

The nice thing about standards is that you have so many to choose from – Andrew S Tannenbaum

SPI in its current form tries to be all things to all people. The clock (SCK) can idle low or high (CPOL). Data can be valid on the clocks leading or trailing edges (CPHA). Data can be shifted out either LSB or MSB first. There are no restrictions as to the number of bits per exchange, bits are not required to be byte aligned. The chip select (CS) can be either active low or high. In other words, expect the unexpected.

To make sense of all this some of the above variables can be restricted to make implementation easier.

Due to limitations in the MPSSE, only SPI modes 0 and 2 are supported (AN114 pg 3). This simplifies one of the above variables, the CPHA setting must always be zero. This means that data is always sampled on the clocks (SCK) leading edge, regardless of the idle state. The clock can idle low (Mode 0) or idle high (Mode 2).

For simplicity, I decided to restrict the code to MSB first only. This is an arbitrary restriction and will be something I revisit as soon as I encounter a device that requires LSB first.

CAT93C46 commands are bit variable and can 9-11 bits long. The implemented interface supports variable bit commands.

Chip Select (CS) on the CAT93C46 is active high. As plenty of other devices are active low I decided to implement this as a configurable value from the start.

One other variable I’ve neglected to mention is clock period. This also needs to be an interface variable.


Source code is located under the yad2xx project at Source Forge. The relevant packages are net.sf.yad2xx.mpsse and net.sf.yad2xx.mpsse.samples.

The command line example, SpiEEPROMSample, uses the SPI interface to read and write to the attached ROM device.



  1. FTDI – AN108 – Command Processor For MPSSE and MCU Host Bus Emulation Modes
  2. FTDI – AN114 – Interfacing FT2232H Hi-Speed Devices To SPI Bus
This entry was posted in FTDI, OS X, USB. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s