Just about a week ago, I encountered the same question as I was thinking about the idea of building a front panel for my homebrew computer, but I didn't understand how could one "move" the CPU to execute code at an user-specified address without affecting other components such as the content inside the RAM, I even searched at RC.SE! And so, I decided to take a look at Altair 8800. As I'm a bit late for the question, I'll just post some details from page 25 of the schematics to show the additional information.
The circuitry was surprisingly simple and clever.
- When the "Examine" button is pressed it generates a high pulse to
1CK below to activate a counter made from two 7473s. Also, at this point, there is no memory or I/O activity, the bus is free.
- (a) On the first count, the processor is started, and a logical "1" is sent to four 7405 inverter gates, which are connected to data line
D5. Thus, they are pulled to ground and became hardwired logical "0". The 7405 is used, because it has open-collector outputs, it either pulls a line down, or doesn't touch the line at all, avoid the need of tristate outputs.
- (b) On the other hand, the undriven pins
D7 are kept at logical "1", because the data lines have 4.7k ohm pull-up resistors.
(c) As a result, the opcode
11000011, generated from a completely hardwired circuit, is injected directly on the data bus. Also, the address bus is completely ignored - no matter what address the CPU wants to read from, it gets the ones and zeros we just injected, which is the opcode for
On the second count, another 8 gates of 7405 inverters are activated, correspond to the 8 toggle switches for address bits
A0-A7. If a switch is toggled, it completes the circuit and allows our 7405 to pull the line to logical "0". Otherwise, the lines are untouched and kept at logical "1" by pull-up resistors. Thus, the CPU gets the next byte from the data bus, still injected by us, which is the low 8-bit part of the 16-bit address.
- On the third count, another 8 gates of 7405 inverters are activated in the same way, this time, they correspond to the 8 toggle switches for address bits
Therefore, CPU gets the final byte we injected from the data bus. At this point, the CPU has fetched a complete instruction,
JMP is generated by our hardwired circuit, and XX and YY are derived from the toggle switches. Great, we have just modified the Program Counter without affecting anything else!
On the fourth count, the counter resets, which in turn pulls EXM line low, and causes PRDY to be low and stops the processor again.
Appendix I: How does Altair 8800 avoid bus conflicts?
Cautious readers would immediately notice a critical problem: The RAM is not disabled while we're injecting instructions to the data bus! It means, the RAM would also respond and start outputting data simultaneously, creating a bus contention.
How does Altair 8800 avoid this problem? First of all, it's important to notice that our code injection circuitry and the toggle switches from the front panel are not connected to the demultiplexed, buffered "normal" data bus, instead, it is connected directly to Intel 8080's bidirectional "raw" data bus, see page 24.
From this segment of the schematics, one can see that all the data from the CPU to the bus ("output") is buffered by a group of 8T97 tristate buffers, all the data from the bus to the CPU ("input") is buffered by another group. When the CPU needs to write data, the output buffer is enabled, driving the data from the CPU to the bus; when the CPU needs to read, the input buffer is enabled, driving the data from the bus to the CPU.
The key to our success is this part of the circuitry, which is connected to pin 1 of the 8T97 buffer, responsible for enabling/disabling the input buffer.
It will enable the input buffer and allow the data to flow towards the CPU, only if the following conditions are met (see page 4).
CPU needs to read data from the data bus (
DBIN), or the CPU releases data bus due to DMA (
The front panel is switched to Run (
RUN) or Single Step (
The buffer is not explicitly disabled by the
/SSW DSB signal from the front panel.
When the front panel is used for examining the memory, the RUN/STOP switch is flipped to
STOP. As a result, the Condition (2) is unsatisfied, the input buffers are disabled, effectively isolating the CPU from all RAM and I/O ports, leaving only the pull-up resistors and our front panel. Therefore, the bus contention problem is avoided without disabling the RAM explicitly.
Meanwhile, the RAM is not disabled for a good reason: we need to inspect them. To do this, indicator lights are simply connected to the "normal" bus lines (
The final conclusions:
When we need to examine the RAM: Instead of driving the address bus and generate the proper RAM-access signals by ourselves, we simply exploit the existing Intel 8080 CPU to do it for free, by injecting a
When we need to capture the data from RAM: Instead of latching the data by ourselves, we simply disable the input buffers, inject the instructions from one side, and watch the bits coming out from RAM to the indicator lights at the other side.
As a side-effect, this process also modifies current Program Counter of the CPU.
Using this simple circuit design and a minimum number of components, we hit three birds with one stone. This design is not without its limitation, which helped to explain the reason behind two oddities on the Altair 8800: (1) "EXAMINE" also modifies PC, (2) The indicator lights only shows input, not output.
The designers in Ed Roberts's company must have put great effort to reduce the cost and complexity of the Altair 8800 system.
Appendix II: What is
As you see, pulling the signal
/SSW DSB to ground will disable the input buffers as well. Why don't we use this signal? What is it?
The Altair 8800 has a special input port, 0xFF, which is the current position of the sense switch. As I mentioned, toggle switches are connected directly to the raw, unbuffered 8080 data bus. If we want to read the input from the sense switch, the input buffer must be switched off. The
/SSW DSB is used for this purpose.
/SSW DSB is generated to switch off the input buffer, when...
The CPU needs to read data from the data bus (
The source is an I/O port (
The address is 0xFF (255).