Vintage Computer Festival wrote:
On Mon, 16 May 2005, Jim Battle wrote:
(4) I recently wanted to capture the contents of a
ROM that was soldered
into a board. I didn't want to unsolder it, so I used by HP 1631D logic
analyzer to monitor all the pins while the computer was driving it with
a test program that made sure every address was getting hit. I used my
hp87 to drive the logic analyzer via HPIB and repeatedly sampled the
pins, analyzed what was captured and repeated until I had seen all
addresses. Finally I dumped the final ROM image to my PC via the serial
adapter. It took me about four hours to figure out how to program
everything, having never done it before. it would have been very useful
for me to have seen other such code before I tried mine. I'd be happy
to give you my program in case somebody else finds such a thing useful.
Wow, cool technique! Would definitely like to see this in the KB.
OK, the details.
The machine is the compucolor II. There are two 2708-equivalent ROMs to
hold character generator data (they are mask programmed ROMs, not actual
2708s). Because compucolors are so scarce, I didn't want to risk
damaging anything by taking the ROMs out and putting them back in, even
if it is a relatively simple job.
I wrote a program on the compucolor to fill the display RAM with all the
characters. One ROM is just the bitmapped graphics mode, yielding the
256 possible combitions of fat pixels in a 2x4 pixel grid. There was no
need to dump that. Recreating the program on the compucolor, it was
something like this:
10 B=4096*6:REM BASE ADDRESS OF DISPLAY RAM
20 FOR I=1 TO 16
30 FOR C=0 TO 127
40 POKE B,C:REM ASCII CHARACTER VALUE
50 POKE B+1,7:REM WHITE CHAR ON BLACK BACKGROUND
60 B=B+2
70 NEXT C,I
80 GOTO 80
The compucolor display is a 64x32 character cell grid with two bytes per
character. The even byte is the ascii value; the odd byte is the
attribute byte including fg/bg colors, blink, and plot mode. The MSB of
the ascii value tells the logic to line double the character rows,
showing the top half if in an even row and the bottom half in an odd row
such that double heights characters can be intermixed with single height
charactes. None of that matters to the character ROM, so the above code
just draws the 128 unique character values. There are eight rows per
character cell, so a 1KB ROM is enough to hold the information.
The 1631 is set up to monitor the 10 address lines, the 8 data lines,
and a clock signal elsewhere in the logic that fires when the ROM output
is being sampled. Fortunately, you can set up all the logic analyzer
stuff manually before entering HP-IB controlled mode. My original fear
was that I was going to have to set everything up via the HP-IB
interface. Make sure the 1631 is in HP-IB slave mode. In my case I
made it address 02, so that from the HP-87 it appears as device 702
(which will be evident in the code below).
I had to hook up a serial port adapter to the hp87 to get the data to my
PC. The initial part of the program below sets up the right bits &
rates to allow that to happen. The serial port is device address 10.
It would have been possible to program the logic analyzer to look for a
specific address and then capture it, but it was easier for me to be
statistical. When I tell the logic analyzer to RUN, it could start
sampling at just about any phase in the process. The depth of the trace
memory is only 1024 samples, and not all clocks have valid data, so a
single run will never catch all 1024 ROM adddresses. Instead my program
keeps track of which addresses have been capture already and just keeps
sampling until all values have been seen.
Now the hp-87 code. To prove that I'm not an aesthete, note the liberal
use of GOTO below. :-)
10 DIM ROM(1024)
20 DIM DONE(1024)
30 FOR I=0 TO 1023 @ DONE(I)=0 @ NEXT I
40 LEFT=1024
50 !
60 !
70 ! set up the serial port
80 STATUS 10,0 ; S@ IF S=2 THEN 100
90 DISP "Device 10 isn't a serial port" @ STOP
100 CONTROL 10,1 ; 0 ! no interrupts
110 CONTROL 10,3 ; 15 ! 9600 bps
120 CONTROL 10,4 ; 3 ! no parity, 8b
130 CONTROL 10,5 ; 48@ REM hw flow control
140 !
150 !
160 CAPTURE:
170 OUTPUT 702 ;"LM" ! LIST menu
180 OUTPUT 702 ;"RN" ! RUN
190 WAIT 1000 ! sleep one second
200 OUTPUT 702 ;"SB2" ! status byte
210 ENTER 702 USING "#,B" ; ST
220 IF BIT (ST,1)=1 THEN 240
230 DISP "Waiting on capture" @ GOTO 190
240 OUTPUT 702 ;"TS" ! dump trace state
250 ENTER 702 USING "#,2A,W,7X,1X,B" ; C$,BYTES,FMT
260 IF C$="RS" THEN 280
270 DISP "Response RS expected" @ STOP
280 IF FMT=0 THEN 300
290 DISP "Format 0 expected" @ STOP
300 ENTER 702 USING "#,X,W,2X" ; SAMPLES
310 DISP "SAMPLES:";SAMPLES
320 FOR I=1 TO SAMPLES
330 ENTER 702 USING "#,B,B,B,B,2X" ; B0,B1,B2,B3
335 GOSUB 500
340 NEXT I
350 ENTER 702 USING "#,X,2X" ! skip revision code and CRC
370 IF LEFT>0 THEN CAPTURE
380 !
390 !
400 ! dump results to the serial port
410 FOR I=0 TO 1023
420 H$=DTH$ (ROM(I))
425 FOR J=1 TO 8 @ IF BIT (ROM(I),8-J) THEN I$[J]="#" ELSE I$[J]="."
426 NEXT J
430 OUTPUT 10 USING "4X,2A,4X,4D,4X,6A" ; H$[3,4],I,I$
440 NEXT I
450 GOTO 1000
460 !
470 !
500 ! pick apart the data
520 POD4=BINAND (B0,7)*64+B1 DIV 4
530 POD3=BINAND (B1,3)*128+B2 DIV 2
540 POD2=BINAND (B2,1)*256+B3
550 DAT=BINAND (POD4,255)
560 ADDR=BINAND (POD2,3)*256+POD3 DIV 16*8+BINAND (POD3,7)
570 IF DONE(ADDR) THEN 600
580 DONE(ADDR)=1 @ ROM(ADDR)=DAT @ LEFT=LEFT-1
590 DISP "ADDR ";ADDR;"=";DAT;", LEFT=";LEFT
600 RETURN
1000 END