Protecting the Pi
Through diodes and resistors, the schematic is protected against programming errors, where output pins set high and low could short each other out. So all currents stay well below the Pi's specifications whatever a programmer does.
Another point: the GPIO of the Raspberry Pi cannot deliver much current. As long as each led's current is limited by a 1K resistor, all is well. But that only delivers 1mA of current through the leds. Bright enough for a front panel, but just barely so. To let the leds burn brighter, all the ledRow pins on the GPIO connector are buffered through a UDN2981A driver chip. That way, resistors of around 390K can be used to light up the leds much brighter. The UDN2981A has 8 inputs, connected to the GPIO, and switches its 8 outputs based on the signal it receives from the 8 GPIO pins. This driver chip can deliver much more current, and is fed on the 5V power line from the GPIO connector (note that everything else on the Pi and on the front panel is 3.3V). The voltage drop from this chip, and from the leds behind it means the GPIO pins on the other end of the schematic do not get exposed to the dangerous 5V levels - in fact, no more than 1.7V or so reaches them.
Click on the picture below to see the full schematic, which is not much more than the above schematic wired through for 8 ledrows, 12 columns, and 3 (switch)rows. Two more things deserve mentioning: first, the UDN2981A can be left out completely, but then on the PCB, its pins 1-8 must be wired through to its pins 18-11. In that case the GPIO pins directly power the leds. Which is fine if you use 12 1K ohm resistors.
Click to expand
Opting for a serial port
The designers of the Pi decided to add 1.8K pull-up resistors to I/O pins 2 and 3 (Broadcom numbering, not GPIO pin numbering). That means these two pins cannot be used straight away for the PiDP's purposes.
But, the front panel needs pretty much all the I/O pins on the Pi. If 2 and 3 cannot be used, 14 and 15 must be used. Why does this matter? Because I/O pins 14 and 15 can either be used as I/O pins, or act as a serial port (TX and RX). It is - obviously - nice to use this serial port for the PiDP. It adds one more way to hook up terminals, next to WiFi and Ethernet.
So, the user has to choose one of two options. The default is to use an unmodified Raspberry Pi, and give up the serial port. Alternatively, remove the pull-up resistors on the Pi and have the serial port available.
So (in the final version of the PCB) users must choose the right jumper setting:
1. J1 and J2 jumpered to connect pins 1-2
--> I/O 2 and 3 are not used as column pins. I/O 14 and 15 are used instead.
2. J1 and J2 jumpered to connect pins 2-3
--> I/O 2 and 3 are used as column pins. So I/O 14 and 15 can be used for the serial port.
--> the 1.8K pull-up resistors R23 and R24 must be removed from the Raspberry Pi.
The Resulting PCB
The placing of LEDs and switches on the PCB is an exact 2:3 replica of the original PDP-8/I front panel:
A 2*20 pin header provides access to those signal lines that may be useful for peripheral devices. In fact, it serves as two identical single-row expansion connectors.
The 12 column pins are brought out, as well as the 2 row pins (for switches/inputs) and 1 ledrow pin (for LEDs/outputs) which are not fully occupied by switches/leds on the PiDP. For instance, row2 only has six PiDP switches attached to it. Six external switches, or inputs, can still be added. Take care with the ledrow pin. It comes straight out of the UDN2981A driver and has about 4 volts on it. Use a diode, maybe, to drop the voltage if a 3.3V device is attached to it.
Also brought out are the 5V and 3.3V power lines and of course GND. Most important, though, is the one single gpio pin that is left unused on the PiDP. This pin can be input, output, or both, under program control.
One obvious idea is to attach a spacewar controller/joystick to the expansion port. Look at gpio.c to understand how you can reach the in/output signals from software.
The software setup is as follows: when SimH starts up, it starts a second 'multiplexing' process which runs in parallel to SimH and which is set to be a high-priority 'Real Time' process. The main SimH program thread starts emulating the PDP-8, and that means there are a couple of variables containing the register values inside the PDP-8.
The multiplexing process, in gpio.c, does nothing more than continuously cycle through reading these register values, lighting up the 8 rows of LEDs accordingly, and sensing the 3 rows of switches.
The main SimH program meanwhile continues to emulate the PDP-8. This happens in pdp8_cpu.c, and the main function in there basically goes through the sequential logical operations as they are done in real PDP-8 hardware too.
The above description results in a SimH version that happily blinks the lights on the front panel without any modification to the SimH code itself. The multiplexing process just listens in and blinks its leds according to internal PDP-8 register values.
Some code has to be added in the main emulation function to read the front panel switch settings, and interrupt the instruction execution sequence accordingly. I.e., stop execution when the STOP switch is toggled.
Modifications to the SimH emulator
In the startup part of SimH, scp.c, you'll see the multiplex process being started, and being closed down when the user exits SimH.
In the actual emulator core, pdp8_cpu.c, you'll see code added to make the PDP-8 registers visible to the multiplexing process, and code added to handle the switches on the front panel.
At the end of the pdp8_cpu.c, you'll see code that mounts image files from USB sticks. What is done here is nothing more than scan for image files on USB sticks, and mount them by sending an 'attach <dev> <filename> instruction to SimH, just like what a user could do manually on the command line.
Lastly, gpio.c is added to the SimH source code base. It contains the multiplexing process, with some initialisation of the I/O ports done before it enters its main loop.
The above should give you the background to understand the code modifications to SimH. Note that all modifications to SimH are added lines, clearly demarcated by lines to show where the added code starts and ends.
Changes to the standard Raspbian Linux distribution
See 'PiDP setup.doc' in the source code. Not much: you need to install mountusb so USB sticks get mounted automatically. WiringPi is recommended for debugging because its gpio utility is helpful. But WiringPi's libraries are not used, they are too slow for the PiDP's purpose. All I/O access is done directly by writing GPIO registers.
Observations on Raspberry Pi GPIO
I almost discarded the Raspberry Pi as a basis for the PiDP because almost anytime the topic of real-time multiplexing on the Pi is mentioned, the consensus is that the Pi is too slow/Unix is unfit for running led multiplexing.
Those comments turned out to be complete rubbish. Linux on a Pi is plenty fast enough to run a process that flips pin settings every 30ms with good consistency. In fact, that takes so little of the Pi's CPU power that you can not only run a PDP emulator concurrently, but also just use the Pi's GUI and run any other program you want. Even surf the web whilst the PDP emulator is running and the front panel blinks away.
Another point is the idea that the GPIO port cannot provide enough mA to drive more than a few leds. Rubbish: leds run on small amounts of current (1 mA is often enough), and as the PiDP (if you run it without the UDN2981A) proves: the GPIO ports has no problem driving **89** leds bright enough to use. Still, adding the UDN2981A allows the leds to be brighter, and that's nice enough to add that IC to the schematic.
Lesson learned: there's a lot of rubbish sold as received wisdom on the Raspberry Pi fora. I guess I should not have needed that lesson. With hindsight. But I wonder how many good projects never saw the light of day because of the false 'experts' on Raspberry fora!
The download links below contain the manual and schematic/PCB/artwork files.
Manual - this old document refers to the 2015 version. Since then, the software has been updated quite drastically. The manual is still useful for the hardware description. But please refer to the Building Instructions page, and the Tangentsoft site that it refers to for the newest software updates.
Hardware and graphics - Final versions.
The PiDP-8/I: Details
From a hardware perspective, the PiDP is just a frontpanel for a Raspberry PI. In the hardware section below, the technical details of the front panel are explained. In fact, the front panel could just as easily be driven by any microcontroller, it only lights the leds and scans the switch positions.
From a software perspective, the PiDP is just a Raspberry Pi, running Raspbian, which automatically logs in to the SimH emulator. SimH is modified to drive the front panel - meaning it has instructions added to reflect the state of the PDP-8 CPU registers through the leds, and responds to the switch settings.
At the bottom of this page, you'll find the download section with software, hardware (Kicad) and artwork (Inkscape).
The Raspberry Pi (any version from Pi Zero to Pi 4 is fine) has a 40-pin GPIO connector with just enough I/O pins to drive the front panel. The PiDP schematic is actually taken from the venerable KIM-1 single board computer, and I used it for my earlier KIM-1 replica too. A multiplexing scheme is used to quickly light up alternating rows of leds in sequence. Doing so approximately 60 times per second, with the switch positions scanned in-between, the human eye sees the whole front panel light up.
Because the GPIO I/O pins are closely tied into the Pi's CPU chip, it only takes a few instructions to drive the front panel. The front panel is driven by a parallel process that reads the CPU status from SimH whilst it is running independently, and reflects the register states onto the front panel leds.
The figure below gives the basic idea. Three groups of GPIO pins are used:
8 'ledRow' pins, each of which provides a collective power line ('+') to a row of 12 LEDs.
12 'column' pins, which are connected to the cathodes ('-') of the individual 12 LEDs across all ledRows. So a row of LEDs is powered up when a ledRow pin is set to Output High. Which of the 12 LEDs actually lights up depends on whether its column pin is set to Output High (LED off) or Output Low (current flows, so LED lights up).
3 'row' pins each provide a power sink (0V) to a row of 12 switches. The column pins above, when flipped to Input mode with pullup resistors, can then sense which of the switches is 'on' (because that causes a short from row to its column pin overriding its weak pullup resistor).
The software quickly cycles through the 8 ledRows, setting each them High in sequence. Do it fast enough and the human eye sees all rows light up consistently without flickering. Then, the 12 column pins are quickly flipped over to being input pins to sense their attached switches, and the cycle starts afresh.
PiDP-8/I: RECREATING THE PDP-8/I
CELEBRATING 50 YEARS OF PROGRAMMED DATA PROCESSING