OT: FTDI MPSSE: USB-SPI interface

425 views
Skip to first unread message

Douglas Miller

unread,
Feb 28, 2021, 5:01:44 PM2/28/21
to retro-comp
(MPSSE: Multi-Protocol Synchronous Serial engine)
Seems like a lot of devices these days have SPI interfaces, and are being interfaced to retro computers. I've always wished I had an easier way to evaluate and debug these devices than actually connecting them to a Z80 and writing CP/M software. Especially since I don't have any working CP/M machines that are "real hardware".

I ran across this device: http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_C232HM_MPSSE_CABLE.pdf which looks promising, and got a 5V and 3.3V version. While not perfect, there is example software and reasonable documentation, and I was able to get a simple program for generic SPI access working, and running with a 25LC512 NVRAM chip (for the most part).

I'm wondering if anyone else has used these devices, and has software for them?

They still require some interfacing in order to plug into an SPI device, mostly pull-ups on appropriate pins, but seems to be a fairly simple way to get "hands on" on a device and learn how to use it, while sitting in the comfort of your Linux box.

FWIW, my software thus far is here: https://github.com/durgadas311/ftdi_mpsse

Jay Cotton

unread,
Mar 1, 2021, 9:49:35 PM3/1/21
to retro-comp
Wondering if this could be driven by a Z80 machine.  Without access to the DLL source code, I really can't 
judge the scope of effort.    Then there is the problem of h/w.      Maybe not...

Douglas Miller

unread,
Mar 1, 2021, 10:32:22 PM3/1/21
to retro-comp
My guess is that the overhead of implementing the USB protocol on a Z80 would negate any benefits from having the MPSSE. I am looking at it as a way to experiment with SPI devices on a Linux box, in preparation of writing CP/M software for the device. And possibly for reproducing and debugging issues that might appear on the CP/M machine.

I didn't think of this before, but for retro computers it might be possible to use a synchronous serial chip to access SPI devices. There's probably some kinks in that idea, but I did use a Z80-SIO on my Kaypro to read infrared remote control signals and decipher them, and then generate the signals back out an IR LED, turning my Kaypro into a really heavy and bulky, but powerful, "universal remote control". I think the issue with the Z80-SIO and SPI is that you need to ensure that the clock signal stops when there is no data. I'm pretty sure it is capable of full-duplex, though.

Alan Cox

unread,
Mar 2, 2021, 8:51:26 AM3/2/21
to retro-comp
On Tue, 2 Mar 2021 at 03:32, Douglas Miller <durga...@gmail.com> wrote:
My guess is that the overhead of implementing the USB protocol on a Z80 would negate any benefits from having the MPSSE. I am looking at it as a way to experiment with SPI devices on a Linux box, in preparation of writing CP/M software for the device. And possibly for reproducing and debugging issues that might appear on the CP/M machine.

The master end of USB is very complex and has a lot of very tight timing requirements. The device end (especially when talking USB 1) is mindbogglingly simple and was designed so it could be implemented with an 8051/68HC08 style mouse or keyboard controller. It does however still have very tight timing requirements so usually there is a simple FIFO and a hard protocol engine. There are SPI<->USB interfaces designed to provide basic USB to an SPI capable system even in USB master mode but they are all modern surface mount logic.

I didn't think of this before, but for retro computers it might be possible to use a synchronous serial chip to access SPI devices. There's probably some kinks in that idea, but I did use a Z80-SIO on my Kaypro to read infrared remote control signals and decipher them, and then generate the signals back out an IR LED, turning my Kaypro into a really heavy and bulky, but powerful, "universal remote control". I think the issue with the Z80-SIO and SPI is that you need to ensure that the clock signal stops when there is no data. I'm pretty sure it is capable of full-duplex, though.

You can also easily do SPI over a Z80 PIO for general playing around, and with carefully optimized code it's fine for SD cards and CP/M. For experimenting if you have a PC with a good old parallel port there are trivial interfaces for bigbanging SPI over parallel port. You can also just use something like a Raspberry PI running Linux for experimental end stuff.

There are also a bunch of SPI controllers such as the 65SPI which are implemented in small programmable logic devices to give you an SPI port on a chip or just use a 68HC11 CPU card instead of a Z80 one 8)

Alan

Bill McMullen

unread,
Mar 5, 2021, 11:23:16 AM3/5/21
to retro-comp
Since your original issue was to test and evaluate SPI devices, I came upon a unique device that may serve your purpose.  I haven't done any followup nor do I own one ... simply an alternative and food for thought.  There's also a similar device for I2C.

You can check it out at https://spidriver.com/

Douglas Miller

unread,
Mar 5, 2021, 11:44:27 AM3/5/21
to retro-comp
That's a very sweet looking device. If I'd found that first, I probably would not have pursued the FTDI MPSSE. I suspect the MPSSE is more flexible, but I'm only interested in SPI. The MPSSE has some rough edges like requiring root privileges and removal of usbserial drivers (cannot be used at the same time as standard usbserial devices).

Jay Cotton

unread,
Mar 5, 2021, 1:44:29 PM3/5/21
to retro-comp

I ordered the spidriver, but the i2cdriver is out of stock.

jc

Douglas Miller

unread,
Mar 5, 2021, 5:08:14 PM3/5/21
to retro-comp
I see one limitation of SPIDriver, it is limited/fixed to about 500KHz bit rate on the SPI. The FTDI MPSSE can be set to run almost any speed up to 30MHz. Of course, the general USB overhead limits overall throughput, but the MPSSE can slew up to 64K bytes at a time at full speed. SPIDriver appears to bit-bang 64 bytes at a time at ~500KHz.

Matt Callow

unread,
Mar 5, 2021, 10:46:47 PM3/5/21
to retro...@googlegroups.com
You might want to look at the Bus Pirate. http://dangerousprototypes.com/docs/Bus_Pirate

Matt

On Sat, 6 Mar 2021, 09:08 Douglas Miller, <durga...@gmail.com> wrote:
I see one limitation of SPIDriver, it is limited/fixed to about 500KHz bit rate on the SPI. The FTDI MPSSE can be set to run almost any speed up to 30MHz. Of course, the general USB overhead limits overall throughput, but the MPSSE can slew up to 64K bytes at a time at full speed. SPIDriver appears to bit-bang 64 bytes at a time at ~500KHz.

--
You received this message because you are subscribed to the Google Groups "retro-comp" group.
To unsubscribe from this group and stop receiving emails from it, send an email to retro-comp+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/retro-comp/8f81d739-caf2-4bf9-a31d-8dc55c50bc48n%40googlegroups.com.

Nigel Kendrick

unread,
Mar 6, 2021, 1:54:49 AM3/6/21
to retro-comp
This FT232H-based project, or some of the resource links, might be useful...

Tom Storey

unread,
Mar 6, 2021, 9:39:57 AM3/6/21
to Douglas Miller, retro-comp
If its of any use or interest, Ive created a "SPI master" that loads into an ATF1502 CPLD.


Parallel data bus, just OUT a byte to it (in Z80 parlance) and it will shift it at the clock frequency you feed into it (6MHz in my case, same as the CPU), producing the SCK and MOSI signals itself.

It only transmits serial data at the moment because that was all I needed when I created it, but with a little work it could be modified to receive, and probably also support more SPI modes and maybe supply some chip selects too.

It will complete its shifting quickly enough that you can continue to push data into it with OTIR, I use it to load a shift register chain to drive a display. I believe I measured 18 clocks for each OTIR cycle, and the shifter only needs 8, so potentially you could even divide the clock by 2 and still scrape in. But if you need to also read data then youre probably going to need a software loop and that'll make it a bit slower. I am having ideas about maybe a setting that would automatically shift another byte each time you read one, so you could OTxR out the command to the device, and then INxR the result back in. Might need a bigger CPLD (ATF1504), but should be doable.

Bill McMullen

unread,
Mar 6, 2021, 10:52:36 AM3/6/21
to retro-comp
"I see one limitation of SPIDriver, it is limited/fixed to about 500KHz bit rate on the SPI."

That was my initial reaction until I stopped to think about the initial question and objective which was to experiment with different SPI devices.  Because of their nature, all SPI devices I've used have a command / response architecture with a unique protocol for different classes of devices.  In my experience, the vast majority of development time is spent working with the protocol.  SPI CLK is simply a matter of understanding the limitations of the host and the device.

A SPI interface requires a host controller whether that be bit-banging, a CPLD / FPGA or a dedicated controller, plus in many (most?) cases a way to read/write a data stream to/from memory.  With newer fast SPI devices and retro systems, controller speed and memory bandwidth become the speed limitations.  Assuming zero controller overhead delays, DMA on a Z180 at 33 MHz limits the effective SPI speed to about 38 MHz.  I've also used dual 104 MHz capable QSPI devices in a byte-wide configuration ... a full speed DMA controller requires a cycle time just under 10ns, as does main memory.

Douglas Miller

unread,
Mar 6, 2021, 11:06:28 AM3/6/21
to retro-comp
For my purposes, the speed testing is also important - although secondary. Being able to ramp-up to the effective speed on the target system can be valuable in evaluating the device. Bit rate can be as important as throughput, but they are different issues. Many of these devices have limitations on the SPI clock frequency, so being able to test where those limits are being approached will be nice.

I'm not sure I follow how a 33MHz CPU can achieve 38MHz SPI clock rate. The target hardware I'm currently interested in uses the CPU clock as the SPI clock (only gating it for 8 bits at a time). Such interfaces can use INIR/OUTIR instructions to get the best possible throughput (without DMA). A DMA interface would be another matter, as it would require some sort of overclocking to make 8 SPI clock pulses in 3 CPU cycles, or else generate DREQ and do the DMA on-demand. Not sure that sort of performance is warranted, although it might make an SDCard *scream*.

Bill McMullen

unread,
Mar 6, 2021, 1:45:13 PM3/6/21
to retro-comp
The 38 MHz SPI on a 33 MHz Z180 reference is based on a DMA controller which takes 7T states or 210ns per cycle.  Given 8 SPI clocks per byte, the max theoretical SPI rate is 210ns /8 = 26.5ns or just under 38MHz.  Of course that assumes the SPI controller is fast enough to change states and receive/send data at full rates.

My MinZ boards have a dual-rate DMA-capable SPI controller in a CPLD: 5 MHz for the RTC and 25 MHz for SD.  Once I had the CPLD tested, I didn't go back to fully optimize it since all the CPLD macrocells had been used and it's VERY sensitive to changes.  As a result, my state diagram has a few extra states and throughput is a bit reduced.  Without going back to the scope, it's about 400ns / Byte and requires wait states on a 36.864 MHz Z180 with it's 190ns DMA cycle.  Regardless, it's still about a 2.5 MB/sec SPI interface to SD.  On the "to-do" list is to go back and test the CPLD at 50 MHz which would allow close to the full 5+ MB/sec DMA rate.

I've also been using the eZ80 internal SPI controller for SD interfacing but it's controller is limited to a maximum of 8.33 MHz.  At this time I'm not ready to dive into an FPGA for native SD mode transfers.

I'm not sure I follow your timing.  The INIR instruction only holds IORQ active for 3 PHI clocks.  if you're using PHI to clock SPI then it would require either wait states for reads or delaying the read of actual data by one iteration.  Writes are much simpler.

Douglas Miller

unread,
Mar 6, 2021, 1:53:09 PM3/6/21
to retro-comp
The hardware I'm looking at uses the CPU clock to clock the SPI. So, after the /WR latches the data, the next 8 CPU cycles clock out the data over SPI. Same for read (SPI does differentiate - a read requires that you write 8 bits). Since the fasted I/O instruction on a Z80 is 11 cycles, you have plenty of time to clock out the byte on the SPI. INIR/OUTIR gives even more time.

I am assuming your CPLD is clocking the SPI independent of the CPU clock, thus it must be overclocking in order to meet the DMA timing. 7 cycles for a DMA operation seems slow, as typically they will perform the operation in 3 cycles. Perhaps you have WAIT states or a different DMA controller.

On Saturday, March 6, 2021 at 12:45:13 PM UTC-6 Bill McMullen wrote:
...

Bill McMullen

unread,
Mar 6, 2021, 3:01:18 PM3/6/21
to retro-comp
Per my previous comment, I think your design works for writes but if I understand correctly, reads first require a write and thus INIR isn't quite as simple.  If INIR were to trigger your 8 clocks it can work but actual data received by the host is delayed one byte frame.  In order to prevent read data corruption, read triggers need to be trailing edge oriented whereas writes can occur as soon as the data is latched.  I've also found that different SPI devices have various setup/hold times before/after the clock signals.

My MinZ SPI CPLD uses a separate clock at 50 MHz to drive it's state machine which also requires a synchronizer to avoid metastability.

MinZ DMA is via the Z180 integrated DMA controller which uses separate read/write cycles and requires 7T for I/O <-> memory.  I've also implemented CPLD-based fly-by DMA controllers in other designs *BUT* the I/O device requires unique select and R/W signals since they can't be used simultaneously for memory and I/O.

Douglas Miller

unread,
Mar 6, 2021, 3:19:58 PM3/6/21
to retro-comp
Both of the interfaces I'm referring to work quite well. They do require a "dummy" read before the block I/O, but that's all manageable. An input on the adapter causes 0xff to be sent on the SPI, and the resulting data sent back is shifted-in and latched and available to a subsequent input instruction. One of the adapters allows for a "read without shift", although the devices being used in that case don't need it.

On Saturday, March 6, 2021 at 2:01:18 PM UTC-6 Bill McMullen wrote:
Per my previous comment, I think your design works for writes but if I understand correctly, reads first require a write and thus INIR isn't quite as simple. ...

Bill McMullen

unread,
Mar 6, 2021, 4:55:10 PM3/6/21
to retro-comp
Seems it took awhile for my morning coffee to kick in and understand your design.  I went the CPLD & separate clock route to obtain a 25 MHz SPI rate for SD regardless of PHI from 6.144 to 36.864 MHz.  Both ways can work and are MUCH faster than bit-banging on a Z80 or Z180.

Tom Storey

unread,
Mar 8, 2021, 5:24:59 PM3/8/21
to Douglas Miller, retro-comp
I had a go at creating a better "SPI master" with a programmable auto-shift function after a read. It is using just over 40 macrocells so far.

First operation is a write to address 1 to write to the configuration register setting auto-shift (d7) and asserting a built-in slave select pin (d2).

Then I do a read from address 1 just to test the contents of the config register.

Next is a write to address 0 with a value of 0xED which causes that value to be shifted out once CS/ is deasserted. The value 0xB7 is shifted in at the same time.

Then I do a read of address 0 to retrieve the value that was shifted in, after which the auto-shift occurs to shift in another byte, 0xE7.

Then I write again to the config register to deassert the SS and disable auto-shift.

And finally a read from address 0 to retrieve the final value that was shifted in. And since auto-shift was disabled you can see that nothing happens afterwards.

Quite pleased with that. Yes it was written in CUPL. :-)

I did also implement CPOL, and Ive been scratching my head about how I could implement CPHA.

There is probably room for one or two more SS signals, and perhaps also an ability to tri-state MOSI when no SS is asserted.

Im also sort of inspired by Bills CPLD, perhaps using a separate clock for the shifter, enabling higher speed shifting independent of the CPU clock which is used for the internal state machine so that it is synchronous with the CPU, but this wouldn't be strictly necessary if the external clock was at least as fast as the CPU clock, phasing issues aside.
Screen Shot 2021-03-08 at 22.07.10.png

Bill Shen

unread,
Mar 8, 2021, 6:10:08 PM3/8/21
to retro-comp
FYI,
Daryl Rictor has published a SPI master for 6502.  This is the discussion about that SPI. http://forum.6502.org/viewtopic.php?f=4&t=1265&start=75

It has a nice data sheet and the CUPL source code is released.  https://sbc.rictor.org/download/65spi2.zip

My little contribution to 65SPI is converting the CUPL design file to Altera Quartus schematic and ported the design to EPM7064S, https://www.retrobrewcomputers.org/doku.php?id=builderpages:plasmo:protorc3:65spi_proto
  Bill

Tom Storey

unread,
Mar 9, 2021, 10:38:48 AM3/9/21
to Bill Shen, retro-comp
Very nice.

I'll keep working on mine because it has the auto-shift function which will play well with INIR/INDR instructions.

Plus I have a habit of re-inventing the wheel for my own projects, mostly for the experience of doing things and understanding how they work. :-)

--
You received this message because you are subscribed to the Google Groups "retro-comp" group.
To unsubscribe from this group and stop receiving emails from it, send an email to retro-comp+...@googlegroups.com.

Bill McMullen

unread,
Mar 9, 2021, 12:05:10 PM3/9/21
to retro-comp
Re CPOL & CPHA: One of the advantages of a fixed design with known SPI devices is that you also know the requirements for CPOL & CPHA.  The devices I'm using all accept CPOL=0 & CPHA=0 which makes life easier.  These devices don't have a problem with extra reads when MOSI=FFh and indeed the SanDisk SD cards I tested actually require this extra dummy read at one point in initialization whereas Kingston cards didn't.

The separate clock works *BUT* it creates two clock domains (processor & CPLD) which goes against good design practices.  A synchronizer has to be carefully designed to avoid metastability.  Even though I thought I'd done that I got caught and had to rework it.  The error only happened once in perhaps 30+MB of transfer and was EXTREMELY difficult to identify.

When going to faster processors (i.e. Z8S180 at 33+MHz) you'll find that INIR at 30*14=420ns might exceed a 25+MHz SPI byte frame (320ns) when you add in extra states for the synchronizer.  On one design I had to use an INI loop rather than INIR.  That was solved with an upgraded controller that can issue processor waits which also enabled the use of Z180 DMA with it's cycle time of 30*7 = 210ns.

Re CUPL: I haven't used that in a long time but as an assembler programmer from way back, I use ABEL and prefer it to VHDL or Verilog which I find quite verbose.

Douglas Miller

unread,
Mar 9, 2021, 12:30:11 PM3/9/21
to retro-comp
Well, this topic has gone off the rails completely. Anyone interested in the FTDI C232HM devices can look in on the github repo https://github.com/durgadas311/ftdi_mpsse and use the "issues" there for problems/discussion.

Tom Storey

unread,
Mar 10, 2021, 3:26:04 AM3/10/21
to retro-comp
Guilty. :-)

One last thing to say, I did eventually notice that 65SPI has an auto-shift mode as well, just called something that I didnt catch/expect during my initial skim of the datasheet (fast receive mode). So it seems to be quite a capable little device. Anyhow, onwards with my wheel reinventing. :-)

On Tue, 9 Mar 2021 at 17:30, Douglas Miller <durga...@gmail.com> wrote:
Well, this topic has gone off the rails completely. Anyone interested in the FTDI C232HM devices can look in on the github repo https://github.com/durgadas311/ftdi_mpsse and use the "issues" there for problems/discussion.

--
You received this message because you are subscribed to the Google Groups "retro-comp" group.
To unsubscribe from this group and stop receiving emails from it, send an email to retro-comp+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages