A little while ago i wanted to play a couple of my pins, but I have fewer working DMD displays than I have games. I live in the beautiful South Africa where everything is plentiful apart from pinball parts. So I set out to be able to display the DMD images on a vga/hdmi display. I did not realize until recently that this idea is not unique. And that it has been done commercially. Oh well.
The project that I am about to share with you is not perfect, because there is things that I don't know about the Raspberry pi. So far I believe that I have accomplished what I have set out to do.
I have only tested this project on 2 BALLY machines('92 and '93), it worked nicely on both.
It is only tested on my Raspberry PI B+. Replicate at your own risk.
If you improve on the code please send me a copy.
If you have cool ideas or if you know how to solve the major issue plaguing the project let me know it will be greatly appreciated.
If you have any questions about the project I will do my best to answer.
OK let me tell you about the project.
First I i did the project on an Arduino due, very easy to capture the dmd data, because it can be set to be a Synchronous serial slave. Difficult to display in real time because the VGA timings were clashing with the interrupts for the serial data from the pinball machine. I realized that I needed something that has a graphics chip of some sort. I went and bought a Raspberry Pi, the shop only had B+. I know a bit of assembly language and c and so on. I just needed to get going with the Rpi.
I used Cambridge university raspberry pi tutorial screen01 to get started. the rest was blah.
here is a link.
Out of this tutorial I use the following files as they come. Thanks Cambridge.
and lastly I edited the makefile to work with windows
no need to reinvent the wheel.
the rest is all original.
WB Pinball machine.
The Williams/Bally DMD display receives a serial signal from the display board. It has a clock that ticks when data is being sent to the display. It has a data signal. It also has a signal that denotes the start of a new frame. It sends the data as 0(off) for a dead pixel and 1(on) for a lit pixel on the rising edge of the clock signal from left to right.
1 frame consist of 32 rows of 128 pixels.
It also has a row end signal, a latch signal and an screen enable signal, I only used clock, data and frame start in the end.
The dmd refreshes at about 120 times per second, it does shading by sending 3 frames per frame you see, a pixel that is on in all 3 frames is brightest and less so for only 2 1 or 0 frames. Thus black and 3 shades of colour. At 40 frames per second all frames should be present.
Interestingly enough you could get the data unserialised from the 74HC165 at U29 on the DMD controller board, but this would involve soldering 9 wires to your dmd board. Maybe easier to work with. Because the data will be available 8 times slower.
On the RPI one has to read the frame start signal, the clock and the data signal from its GPIO PINS at a rate higher than the pinball machine delivers it, save it to memory, interpret the signal, and then display it on a hdmi screen. Easy. BUT I did run into some issues doing this seemingly easy task. This lead to some hopefully temporary complexity in the final solution.
Silly little problem
Before I go further. I encountered a problem writing the captured dmd data to memory. It seems that the video chip of the RPI, refreshes the screen data every so often, this operation interferes with writing data to memory for very short periods of time, resulting in a small loss of data. At lower resolutions this problem is not so noticeable but at my intended resolution of 720P it is
quite noticeable but not a deal breaker for me. I have tried all sorts. If you know how to solve this issue please let me know. It will improve the frame rate and open new avenues for improvements, colourisation, frame injection, multiple machines on 1 screen etc.
I have implemented hardware and software fix for the loss of data but not all the missing data can be extrapolated from what there is, sadly a lot of the code and some hardware deals with this problem.
However the extra code and hardware will be redundant when I figure out how to solve this problem! And then more cool things will be worth pursuing! I obviously already have source code that does not implement any glitch filtering, but it is not included here, I have however included a version that does not use software "glitch" filtering.
Raspberry Pi B+ ( I only have this, sure it will work on A/B, cpu is same, pins might differ)
SD card fat 32
an electronics project board (optional)
a hex buffer chip CD4050
a ripple counter 74hct393 (will be redundant when the "glitch" issue is solved)
and obviously a hdmi display with a minimum of 640x480 resolution
For starters the RPI needs to capture the DMD data from the WPC machine. This can be accomplished in different ways.
Firstly one can poll, the GPIO pin levels. This is a straight forward logical method, but it has some draw backs mainly because of the "glitches" and it also seems to be slightly less predictable than other methods, and you have to wait for it to complete, but it could work.
Secondly one can poll the edges of the signals either synchronously (but you might miss some) or asynchronously, the asynchronous method is actually quite an elegant solution but it will require 2 extra GPIO pins 1 for rising and one for falling edge
on the data and clock pins. The major draw back of this method will come later when optimal frame rate will be an issue because you have to wait for this operation to complete before you can continue with the next.
Then there is the option of using the RPI DMA engine to record the levels of the GPIO pins, the DMA engine works separate from the cpu, could free up the cpu for other operations. This is the method I settled on in the end.
I use GPIO 2,3,4,(5,6,7 for 74hct393), so here we go
wait for the frame to start enable DMA ,capture the first byte of the GPIO address enough time to get at least 3 frames, and for now wait for this operation to end (this will change) then go through the data to find the rising edge of the clock signal and then read the data value there and save it as on or off in memory , yeah first pixel done. Then find the falling edge of the clock and then the rising edge, repeat until the clock stays low for longer than usual, that means the row of pixels is complete, next row 32(frame) times 3 etc.
This should've been all, but because of the glitches, 2 things need to happen, sometimes entire clock ticks gets missed this means pixels are gone and this shortens the row and cause pixels to be in the wrong place. So mostly one can go through the clock signal and if the ticks or tocks is too long, add a pixel because I know I should get on, off, on, off etc, so on , on or off, off means a tick or tock is missing. Sorted. Not entirely, because between the pixel rows the clock is off(low ),and if the first tick is gone there is no way of telling that there was one, because it starts normally with clock on (high) as expected. Enter the 74hct393 it counts ripples (or clock ticks in this case), 2 bit is enough, so it counts 0 1 2 3 0 1 2 3 etc. So at the beginning of the new row see what the value was on the q0 and q1 pins of the 393, look back , see what the value was a while before the row started, and if it is more than one less, add a blank pixel. yeaah. Not perfect but better.
Now that 3 frames has been captured, the state of each pixel is known(ish), all that is left to do is to add the values of the each pixel for the 3 frames, to get the shading.
0 is off, 1 is light,2 darker,3 darkest. Done
Then draw the DMD frame to the screen, with your selected colours.
repeat it all.
the short way ...
HARDWARE.jpg in docs folder shows the circuit.
build the circuit, format a SD card, copy the contents of one of the folders in the SD directory to your SD card. Hook up to 90's W/B pin. Should work.
the other way ...
Software you need for windows to use the source
arm-none-eabi get it here
make for windows get it here
some sort of text or code editor whatever you prefer.
The source is here
The firmware is
2015-05-05-raspbian-wheezy (you don't need to get it relevant files is include)
the docs folder includes all the documents I used plus a picture of the wiring, HARDWARE.jpg it is colour coded and big.
the source folder includes a couple off different versions(resolutions) with everything you need to build just run 00m it will build the kernel file.
The SD folder includes a couple of different builds, just copy the files onto a blank sd card.
The 720pminimal "build" only uses the 74hct393 for filtering, it's glitchy but it would be the easiest to mod if a solution is found for the glitches.
The 2 best builds is the 320x240 and 640x480
Change colours in drawfixdmd.s it is 24bit rgb,and compile, lots of room for improvement here, well all over but it's a start.
The code is not super clean some bits are marked as relic,some declarations are redundant. Some comments might be old.But it works.
HARDWARE bigger pic in DOCS folder