Reverse Engineering at -17V and 200kHz
Warning: Rabbit Holes ahead
I have a Rockwell 920/3 calculator.
It's from about 1975, and is a pretty impressive beast. It's programmable and has 960 steps in its fully expanded form, a printer and a magnetic card reader/writer as well as a sixteen digit display. It can store data on cards as well as programs. The one I have (well the first one I got) ran the payroll at a large catalogue company in the UK.
The card reader didn't work when I got it, which was a shame. I had several cards which had programs on them and I wanted to get them off the cards somehow. When a second calculator came up for sale I bought it. I swapped the card reader into my first machine and it worked. If you want to see it working there's a video here:
I printed the programs and will look at transcribing them later. Of course when a third machine came up for sale I bought that as well. It turned out to be a 920/2 rather than a 920/3, which was a variant with less memory than the /3, but more than the base /1 model. Internally the machines have a common base board which comes with a small amount of RAM. This is one of them with some of my debug connections attached.
The architecture of the calculator is really what we would call a single board computer. There's a processor, RAM and ROM together with some general purpose IO (GPIO) devices. The processor is an early one, the Rockwell PPS-4, a four bit processor used in quite a few devices in the 1970s, notably calculators and pinball machines. It runs from a pretty non-standard, at least these days, -17V supply. It's negative logic so a zero is -17V and a one is 0V. Not something that can easily be attached to my logic analyser or even oscilloscope. The clock rate is one you don't see a lot these days: 200kHz. The second and third machines don't run at the moment, so I decided to have a go at fixing them. As it would be useful to know what the code was doing I decided to instrument the bus signals with a view to watching code execute and also hopefully build up a ROM dump. I could desolder the devices (all of which are in an uncommon 42 pin staggered QIP package) but then I'd need a ROM dump machine that runs at -17V. I may build one of these later if I can't dump all the ROM by bus capture on a working machine. If I run the machine through all of it's features while I have a scanner attached I should be able to slowly capture the contents of ROM. The executed parts anyway. i made a test circuit to see if I could get something working at -17V, the result is in this video:
That worked well, so I went on and made a PCB with enough inputs that I can capture the relevant signals to allow code execution flow to be examined. It turned out that a simple (and cheap, useful if I make a mistake at -17V) blue pill (STM32F103C8) had just enough GPIOs to handle the address bus (A/B in PPS-4 speak), data bus (or I/D bus), and bus control signals.
A datasheet for the PPS-4 is available on the web, and I found some example code in a patent. That gives me something to test my disassembler and any object code I find against as a sanity check. I f you look at the processor bus you find it is a bit of a monster, at least compared with something like the Z80. It is a multiplexed, interleaved two phase type of thing. There are four clock phases (my terminology). ROM addresses come out on the address bus in phase 1 while RAM or IO data is on the data bus. Then in phase 3 the RAM or IO address comes out on the address bus while the ROM data is on the data bus. This diagram from the datasheet should make things clearer:
No? If you look at it for about 10 minutes it starts to make sense. Yes, the processor has two clock inputs, at two frequencies and slightly out of phase with each other. There's a special IC just to generate these clock signals. You can see that de-soldering the ROM chips to read them is the easy bit. Once de-soldered you have to dump the ROMs using this bus arrangement, not forgetting that the logic levels are 0V and -17V.
What is useful about the bus scheme is the pair of 'bus clear' phases. It gives a simple handle on the bus phases when looking at traces. You'd have thought that was straightforward, but the PPS-4 throws another spanner in the works by inverting clock B and also inverting some (just some) of the data on the bus before it is used. Sometimes it inverts a nibble, sometimes a byte. A blank phase is a piece of driftwood to cling on to.
After some simple tests with the blue pill I ended up with a sketch that capture the bus signals as fast as it can manage. I added a pretrigger delay of a number of clock cycles from the reset signal going inactive so that the window of captured bus signals can be moved about with the aim of capturing the inital code execution. Hopefully this will provide some insight into why the board does not work.
The bus traces look like this:
A:000 D:04 CLKA:0 CLKB:1 WOL:0 DO:0 - 0
A:000 D:00 CLKA:0 CLKB:1 WOL:0 DO:0 - 1
A:000 D:00 CLKA:0 CLKB:1 WOL:0 DO:0 - 2
A:000 D:00 CLKA:0 CLKB:1 WOL:0 DO:0 - 3
A:003 D:00 CLKA:0 CLKB:0 WOL:0 DO:0 - 0
A:003 D:00 CLKA:0 CLKB:0 WOL:0 DO:0 - 1
A:003 D:07 CLKA:1 CLKB:0 WOL:0 DO:0 - 2
A:000 D:0F CLKA:1 CLKB:1 WOL:0 DO:0 - 0
A:000 D:00 CLKA:1 CLKB:1 WOL:0 DO:0 - 1
A:000 D:00 CLKA:1 CLKB:1 WOL:0 DO:0 - 2
A:000 D:00 CLKA:1 CLKB:1 WOL:0 DO:0 - 3
A:003 D:1C CLKA:1 CLKB:0 WOL:0 DO:0 - 0
A:FFF D:1C CLKA:1 CLKB:0 WOL:0 DO:0 - 1 1C
A:FFF D:1C CLKA:1 CLKB:0 WOL:0 DO:0 - 2
A:6AB D:1C CLKA:0 CLKB:0 WOL:0 DO:0 - 3
You an see address 3 in the second block, that's a ROM address, and then in the fourth block the data from the ROM is put on the bus. The contents of the data bus when the ROM address is presented is the RAM or IO data from a previous IO or read instruction.
The captured data is copied to text files, one per pretrigger 'window'. A series of scripts extract the ROM information. This is sparse data, as obviously only ROM addresses that are either executed or accessed by instructions is captured. One key sequence is the startup code:
000 0x81 t 0x1
001 0x82 t 0x2
002 0x74 ldi 0xB
003 0x1C iol 0x1E
005 0x7E ldi 0x1
006 0x1C iol 0x1D
The processor starts at address 000 when reset, so we have a sensible trace. The next instruction is a jump (t : transfer) from address 000 to address 001. This is a bit odd, but sort of makes sense. Then there's a jump from address 001 to address 002. Again, odd, but maybe the processor has to do some setup in the first instruction cycles, or the program counter gets 'finalised' or something by doing this. I did find some PPS4 code in a patent and the start of that looks like this:
0000 81 T #1
*SET O/P TO ZERO
0001 7F LDI 0
0002 10 0E IOL #E
0004 7F LDI 0
0005 10 0D IOL #D
0007 7F LDI
0008 10 07 IOL 1
There's the same jump instruction at 000, so we have another flag that we have a sensible trace. The second jump from 001 to 002 isn't there, though. I've not found an explanation of why they are there.
The IOL instruction sends a command to one of the GPIO chips. These aren't memory mapped or IO mapped but instead have hardwired device numbers. The IOL 0x1E sends command 0xE to device 1. This is setting up the keyboard/display scanning signals. I have traced enough signals on the PCB to determine the device numbers for the GPIO chips. I've called the PPS4 processor chip a processor up until now, but this isn't quite right. The chip does, in fact, have input and output ports. They aren't GPIO ports as they are fixed inputs or outputs. So the chip is close to being a microcontroller in some ways. The output port is used in the 920 to drive the demultiplexor that drives each display digit. The inputs are used to sense the keyboard matrix (the scan signals for the keyboard are the same scan signals used to drive the display digits).
Instruction Set
I'm familiar with the 8 bit processors, the Z80 and 6502 and the ARM instruction set. I've also programmed in PIC assembly, and Z8, and 6301, and 8086, and 8051, and 4 bit microcontrollers, and so on. But I was still a bit surprised when I saw some of the PPS-4 instruction. They seem to be from a time before people had worked out the rules. Here's an example, the load immediate instruction:
Ok, it's 4 bit, fair enough, and the immediate value is a nibble in the opcode, fine. Then you see on the right hand side that it refers to a note 3 lower on. Let's look at that:
Ok, so for these instructions (not all instructions), the nibble that is the immediate data is inverted in ROM and hence on the bus. Hmm, a bit odd, but a disassembler or assembler will handle that. Then you notice that a note is mentioned in the fourth box from the left. Is it referring to the same note 3? No it's not, it's this one it is pointing to:
Right, now we have some oddness. If you load the accumulator with 6 and then load it with 4, it ends up with the value 6. This struck me as downright bizarre when I first saw it, but after seeing some code and thinking about it it is useful. If you want to enter a routine with various different parameters then you can do this sort of thing:
Enter6 LDI 6
Enter7 LDI 7
Enter 8 LDI 8
* Do something with A
RTN
If you jump to Enter6 then the accumulator is loaded with 6, the next loads are ignored and you do something with 6. If you jump to Enter7 then the accumulator is loaded with 7 and the next load is ignored and you do something with 8. I can see how that could be useful.
This instruction:
shows the use that is made of data tables in ROM at the instruction level.
Next...
I now need to trace the code execution through to the loop it ends up in so I can maybe work out what isn't right... I also need to draw up a schematic. The PCBs are fairly low density so it probably isn't a massive job.
Memory Expansion
An aside.The 920/2 has one plug-in memory expansion board, the 920/3 has two:
Rather surprisingly the /2 RAM board has four RAM chips, the /3 boards have six chips each. Another surprise is that the two six chip boards in the /3 are different from each other. It looks to me that the connector pinouts on the cards are different, even though they carry the same amount of RAM. So rather than using the same PCB for both memory expansion configurations (part populating the 920/2 board), there are three different PCBs.
4 comments:
I was a Rockwell representative and sold the PPS-4 chips that went into the Litton microwave oven, the Silent Knight home security system, the Weightronix scale, some Honeywell as well as 3M products such as their 1200 baud Fax machine.
I am glad we have connected and you can have access to all my documents.
I was a Rockwell representative and sold the PPS-4 chips that went into the Litton microwave oven, the Silent Knight home security system, the Weightronix scale, some Honeywell as well as 3M products such as their 1200 baud Fax machine.
I am glad we have connected and you can have access to all my documents.
Actually, the clock has two phases as shown in the timing diagram. The Rockwell chips might use several clock pulses to complete an operation, thus the confusion of a 2-phase clock with a 4-cycle operation.
@Microguy: Well, yes, there are two clocks, if that is what you mean, but they do run at different frequencies and slightly out of phase with each other, so it's not a single clock with two phases. The instructions are all performed in a cycle or two. The really odd thing about the 'four cycle' bus accesses is that the address for a ROM byte goes out in phase 1 but isn't returned to the processor until phase 3, the RAM addresses go out in phase 2 and come back in phase 4. This is not like a modern bus like a Z80, or a multiplexed bus. I think the P in PPS stands for parallel and this parallel fetching of RAM and ROM bytes is what it is denoting. Also, you can't read ROM as data, if you want to do that you have to have a special ROM chip made that responds to the RAM accesses. So no data tables in ROM with code.
Post a Comment