Casio CQ-1 Recreation Information
Until I tidy up the github repository, here's some snippets relating to the Casio CQ-1 recreation.
The first PCB is really a prototype as well, it just fits in the case better than the first prototype.
Casio CQ-1 Recreation Information
Until I tidy up the github repository, here's some snippets relating to the Casio CQ-1 recreation.
The first PCB is really a prototype as well, it just fits in the case better than the first prototype.
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.
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: