Driving a Pinball DMD with an Arduino Microcontroller
For quite some time now I’ve been interested in developing my own pinball machine. Obviously this is a massive endeavor. Before I happened across the P-ROC project, over the course of several days in April of 2007 I did some work on driving a pinball dot matrix display (DMD) with an Arduino microcontroller. Here’s what I made; read on for the details of how.
How It Works
Before we get too technical, a brief disclaimer: I am a computer scientist, not a digital design engineer. I’m self-taught when it comes to practical digital I/O knowledge, so some of my terminology may be a bit fuzzy. Also, and very importantly, I cannot take any responsibility for the crazy things you do to your pinball (or computer) hardware. You’re working with a high voltage peripheral here and while I seem to have escaped any ill results, you may not be so lucky. Be sure to ground the Arduino to the pinball machine ground, and keep your finger near the on/off switch. You may need to cut the power a few times before you get it right!
Let’s summarize what’s in the video:
- A dot matrix display in a Shadow pinball machine. The game is powered up and running, but the DMD’s ribbon cable has been detached from the display controller board and is attached to…
- An Arduino microcontroller, strapped to a solderless breadboard, and wired to the ribbon cable via the breadboard. I don’t recall exactly how it was wired up, but you can get an idea from the sketch source below. I do recall that there was at least a pull-down resistor on the Display Enable. This is important because if the DMD is left drawing the same row for a long time I suspect it will burn it in. (It shines extremely brightly in a rather bad sort of way.)
- The Arduino is completely controlling the contents of the display (rudimentary pong in this case).
- The Arduino is plugged into my Powerbook via USB for 5V power.
- The DMD is powered by the pinball machine’s high voltage board. It would be possible to run this independent of the pinball machine if you had an appropriate DMD power supply.
The DMD is controlled by six digital I/O lines:
- Display Enable
- Row Data
- Row Clock
- Column Latch
- Column Clock
- Column Data
It’s essentially a serial interface (serial data via Row Data, clocked in with Row Clock), using the other I/Os to control the column position. The DMD works like a CRT. It has no onboard frame buffer; instead it has latches for one row’s worth of data. The Arduino must write these rows of data out constantly in order to maintain a picture. Here’s what the Arduino sketch I wrote does, in pseudocode:
for each row: for each 8 columns in this row: clock out dot data from bitmap at (column, row) latch in the row we just wrote update bitmap repeat
My initial implementation clocked out the dot data manually, but this ended up being much too slow. Thankfully the Arduino has a hardware SPI interface on pins 10-13 (although only the clock and data pins are needed). This allows you to rapidly clock out 8 bits of data with one call in Arduino C code (done by assigning to the SPDRvariable/register, in UpdateDMD() in the sample code). So the actual code is more like:
for each row: for each 8 columns in this row: write out those 8 columns all at once via SPI latch in the row we just wrote update bitmap repeat
You can see the source code for my Arduino sketch here: DMDTest.c. It’s very much a sketch; hopefully you can glean the important parts. Again, UpdateDMD() has the important stuff. I derived the background image with the UNIX banner program and a perl script to generate the bitmap array.
This project was a lot of fun to do, and very rewarding when I finally got it right. It took a lot of trial and error to get it working correctly. The question is, though, is this a practical means for driving your homebrew pinball machine’s display?
Frankly I suspect not. My experimentation showed that the Arduino I was using (ATMega 128, I believe) was just barely fast enough to do a reasonable job of keeping the picture bright enough and flicker-less. The DMD is very sensitive to the timing of its driver (the Arduino in this case), so it would prove very tricky (in my estimation) to a) drive the image consistently and b) do something else useful, like read any considerable amount of data off the serial lines (such as new frames), much less do something more involved like drive a lamp matrix, too. You may be much more of an embedded wizard than I am, however, and be able to figure it out.
There’s a very good reason that Williams et al had dedicated hardware to perform this function. Once I realized these limitations I began to imagine the ideal solution to be something like an FPGA driving the DMD off of some sort of shared memory setup. FPGA work is a bit beyond my skills at this point, so that was the end of the trail for me.
I did end up finding a solution that’s essentially done that, and more. It’s more expensive than an Arduino, but is a great fit for my interests (writing high level code on a PC to control a pin): P-ROC. Full disclosure: I have contributed a lot of open source software to this project in the form of pyprocgame and libpinproc. I hope to write a bit more about my work with P-ROC here in the future.
If you do end up implementing your own DMD controller, even on an Arduino, drop me a line about it!