This project started by us, my father and me, buying a Diamond Lady pinball machine which had a defective display. We had to find out what exactly was broken to be able to fix it.
Background
Gottlieb, a pinball machine manufacturer active from 1927 to 1996, used the Rockwell 10941/10939 chips on their System 80B MA-644 display boards. These chips are used to control two 20 character, 16 segment displays. The MA-644 display board has one 10941 chip and two 10939 chips. The 10941 is responsible for driving the individual segments of a single character, while the 10939 chip is responsible for enabling one of the 20 characters.
The Rockwell 10941 and 10939 chips are no longer produced. That, in combination with the existing demand for these chips to repair devices still using them, makes them expensive to replace. Replacing all the chips on the display board would have been a waste of money.
Troubleshooting
We wanted to make sure the problem was actually on the MA-644 display board itself. We first verified that the voltages going into the display board were there. We checked the following voltages:
- +5V DC, used to supply power to the chips on the display board
- 32V AC, rectified to -45V DC and -15V DC for the displays
- 6.2V AC, used for the display filaments
All voltages checked out, so it was time to dig deeper. The next simple thing to try was to replace the 7417 Hex Buffer chip on the display board. This buffer is located between the data lines coming from the MPU board and the 10941/10939 chips. Replacing this buffer did not solve the problem.
The next thing we wanted to verify was the data coming from the MPU board. This can not be done with a multimeter as the signal levels change too fast for the multimeter to properly register them. An oscilloscope would have worked better for this, but we did not own one yet.
The CPU on the MPU board does not run at very high clock speeds. Because of that, I thought it would be possible to read the data sent to the display board with an Arduino board. The Arduino board would then be able to translate the data to something readable and send it to a PC via its serial connection. To do this, we made a small adapter board on which we could plug the existing display connector. This board then connected to an Arduino Nano with some wires.
I programmed the Arduino Nano to decode the commands which are normally sent to the 10941 and 10939 chips, effectively emulating the behavior of these chips.
Connecting the Arduino
Connecting the Arduino Nano to the MPU board was simple, as both systems use 5V logic. The connector from the MPU board carries eight data lines and two LD lines, amongst +5V DC, ground, and the higher AC voltages for the displays. We wired the Arduino Nano to the data lines as shown in the following table:
Pin number | Function | Arduino pin |
---|---|---|
1 | 6.2V AC | - |
2 | 6.2V AC return | - |
3 | 32V AC | - |
4 | 32V AC return | - |
5 | VCO (common) | - |
6 | RESET | - |
7 | VSS (+5V DC) | - |
8 | N.C. | - |
9 | LD1 | 2 |
10 | LD2 | 3 |
11 | DATA 0 | 8 |
12 | DATA 1 | 9 |
13 | DATA 2 | 10 |
14 | DATA 3 | 11 |
15 | DATA 4 | 4 |
16 | DATA 5 | 5 |
17 | DATA 6 | 6 |
18 | DATA 7 | 7 |
19 | GND | GND |
Operation of the chips
The Rockwell 10941 and 10939 chips receive the display data via eight data lines. Each 10939 chip had its own LD line. These are used to select which one of the 10939 chips should load the data present on the data lines into its Display Data buffer.
After loading the data into its buffer, the 10939 chip will check whether the data was character data or a command. Commands are used to configure the chips and move the cursor. The chips use their own protocol for communication between the 10939 and 10941 chips.
Code
To know when to read the data lines, I used the LD lines to trigger an interrupt. An interrupt is triggered by, for example, changing the state of a pin. An interrupt triggers a function, which in this case will read the data lines and save the state of these lines to a variable.
To enable interrupts for a specific pin on an Arduino board, call the attachInterrupt()
function:
// Attach interrupt
attachInterrupt(digitalPinToInterrupt(pinNumber), interruptFunction, RISING);
The attachInterrupt()
function needs three parameters. The first parameter is the pin number of the pin which should trigger the interrupt. The pin number expected here is not the same as the one printed on the board. You’ll need to call the digitalPinToInterrupt()
function to get the correct pin number. The second parameter is the function which should be called when the interrupt is triggered. The third parameter is used to determine in which case the interrupt is to be triggered.
Unfortunately, the ATMEGA328P does not have eight GPIO pins available on a single port when you also want to use the serial port (pins 0 and 1) and two interrupt pins (pins 2 and 3). If it had, reading all pins at once would have been easy, just read the port status register and be done with it.
I this case I had to work around it. Four data lines are connected to four pins of port B, and the other four data lines are connected to the pins of port D. With the help of some bitwise operators it is possible to “merge” the values read from the registers into one value.
incomingData = (PINB & B00001111) | (PIND & B11110000);
The (PINB & B00001111)
part gets the first 4 bits of from the PINB
register, which are pins 8 thru 11. The (PIND && B11110000)
part gets the last four bits of the PIBD
register, which are pins 4 thru 7. The bitwise |
(or) operator merges the read values together into a single byte.
I chose this approach to not have the overhead of calling the digitalRead()
function for each pin. I did not actually test whether that would have caused performance issues. Also, merging eight single values into a single byte is a bit more work than just using three bitwise operators. All of this is done in the interrupt function.
The code in the loop()
function checks if there is new data available. When new data is available, it will put the data in a display buffer. For debugging purposes, I discarded all the command codes. When the buffer is full, the contents of the buffer will be converted to ASCII characters and send to the PC over the serial connection. The character data corresponds to standard ASCII for the most part. All special 16 segment specific characters will be outputted as ~
.
Modding
This project and its code can also be used to mod your own pinball machine. The code can be altered to support other types of displays, like 16 segment LED displays. The data in the display buffer should be transformed into data suitable for another type of display, instead of sending it over the serial connection.