Continuous Memory Error

Hewlett-Packard produced calculators in the late 1970s which came with “Continuous Memory”. This retained programs and data in the calculator even when it was switched off.

The mechanism is the forerunner to modern BIOSes with CMOS settings so it was another very successful innovation.

I have recently been developing a microcode emulator for one of HP’s Continuous Memory calculators, the HP-29C. Unlike its predecessor, the HP-29 only came with continuous memory – there was only the “C” model – and the microcode includes instructions specifically for continuous memory. I had actually been tinkering with my microcode emulator for the HP-67 and the idea crossed my mind, “if this is an accurate match to the original processor, how well does it run other programs for the processor?” It was at that was the point I plugged in the microcode for the HP-29C.

There are some hardware aspects that changed between the two calculator models: different things wired up to different pins and a 12 digit display instead of a 15 digit one; but internally both calculators use the same processor chip. There isn’t a HP-67 variant of the Woodstock chip and a HP-29C variant. The idea seemed sound.

After some tweaks for the hardware, I plugged in the HP-29C microcode and ran it. The calculator (emulation) came up with “Error” in the display.

Now, whilst you might consider the outcome disappointing (and I definitely would have preferred to see “0.00”), it is impressive that it understood enough and functioned well enough to be able to create “Error” in the A and B registers and display it. It was actually a pretty good starting point for test 1.

Why would it say, “Error” at power up?

I did own a real HP-29C at one point a long time ago, and I did read the manual from cover to cover at the time. There was a vague recollection that there was something about a continuous memory failure. It was something I’d never seen; but I did think the manual mentioned it. I sure didn’t have continuous memory in the HP-67 emulator so perhaps it was something related to that.

Guesses are all very good but what was more important was what was actually happening. It was one of my emulator so it had microcode logging. Here’s what the log said:

>>> dr
A=00000000000000 D=00000000000000 M1=00000000000000 P= 0
B=00000000000000 E=00000000000000 M2=00000000000000
C=00000000000000 F=00000000000000 S =................
>>> dp
00000: nop
>>> ts1000
00000: nop                                   ;
00001: nop                                   ;
00002: delayed rom 12                        ;
00003: if n/c goto 0303                      ;
06303: cpu woodstock                         ;
06304: 0 -> c[w]                             ;
06305: m1 exch c                             ;
06306: 0 -> c[w]                             ;
06307: m2 exch c                             ;
06310: clear s                               ;
06311: binary                                ;
06312: delayed rom 4                         ;
06313: jsb 0235                              ;
02235: p <- 1                                ; P= 1
02236: load constant 2                       ; C=00000000000020 P= 0
02237: c -> addr                             ;
02240: data register -> c 14                 ; C=00000000000000
02241: return                                ;
06314: c -> a[w]                             ;
06315: jsb 0360                              ;
06360: p <- 12                               ; P=12
06361: load constant 3                       ; C=03000000000000 P=11
06362: load constant 4                       ; C=03400000000000 P=10
06363: load constant 9                       ; C=03490000000000 P= 9
06364: load constant 3                       ; C=03493000000000 P= 8
06365: load constant 4                       ; C=03493400000000 P= 7
06366: load constant 2                       ; C=03493420000000 P= 6
06367: load constant 8                       ; C=03493428000000 P= 5
06370: load constant 4                       ; C=03493428400000 P= 4
06371: return                                ;
06316: a - c -> a[m]                         ; A=0CB6CBD7C00000
06317: if a[m] # 0 then goto 00334           ;
06334: 0 -> c[w]                             ; C=00000000000000
06335: p <- 1                                ; P= 1
06336: load constant 3                       ; C=00000000000030 P= 0
06337: p <- 1                                ; P= 1
06340: delayed rom 2                         ;
06341: jsb 0372                              ;
01372: if n/c goto 0141                      ;
01141: a exchange c[w]                       ; A=00000000000030 C=0CB6CBD7C00000
01142: binary                                ;
01143: 0 -> c[w]                             ; C=00000000000000
01144: a - 1 -> a[wp]                        ; A=0000000000002F

01145: a exchange c[w]                       ; A=00000000000000 C=0000000000002F
01146: c -> addr                             ;
01147: a exchange c[w]                       ; A=0000000000002F C=00000000000000
01150: c -> data                             ;
01151: a - 1 -> a[wp]                        ; A=0000000000002E
01152: if n/c goto 0145                      ;

01145: (2E -> addr, 0->mem[addr], 2E->2D)    ; C=00000000000000 A=0000000000002D
...
01152: if n/c goto 0145                      ;

01145: (0 -> mem[2D])
01145: (0 -> mem[2C])
...
01145: (0 -> mem[1])                         ; C=00000000000000 A=00000000000001
...
01151: a - 1 -> a[wp]                        ; A=00000000000000
01152: if n/c goto 0145                      ;

01145: a exchange c[w]                       ; (both 0 so neither change)
01146: c -> addr                             ;
01147: a exchange c[w]                       ; (ditto)
01150: c -> data                             ;
01151: a - 1 -> a[wp]                        ; A=000000000000FF
01152: if n/c goto 0145                      ;
01153: return                                ;

06342: 0 -> c[w]                             ;
06343: jsb 0360                              ;
06360: p <- 12                               ; P=12
06361: load constant 3                       ; C=03000000000000 P=11
06362: load constant 4                       ; C=03400000000000 P=10
06363: load constant 9                       ; C=03490000000000 P= 9
06364: load constant 3                       ; C=03493000000000 P= 8
06365: load constant 4                       ; C=03493400000000 P= 7
06366: load constant 2                       ; C=03493420000000 P= 6
06367: load constant 8                       ; C=03493428000000 P= 5
06370: load constant 4                       ; C=03493428400000 P= 4
06371: return                                ;
06344: p <- 2                                ; P= 2
06345: load constant 2                       ; C=03493428400200 P= 1
06346: jsb 0352                              ;
06352: a exchange c[w]                       ; A=03493428400200 C=000000000000FF
06353: p <- 1                                ;
06354: load constant 2                       ; C=0000000000002F P= 0
06355: c -> addr                             ;
06356: a exchange c[w]                       ; A=0000000000002F C=03493428400200
06357: return                                ;
06347: c -> data register 14                 ; mem[46]=03493428400200
06350: delayed rom 2                         ;
06351: if n/c goto 0374                      ;
01374: if n/c goto 0231                      ;
01231: 0 -> a[w]                             ; A=00000000000000
01232: 0 -> c[w]                             ; C=00000000000000
01233: 0 -> s 1                              ; S=...3............
01234: 0 -> s 2                              ;
01235: p <- 13                               ; P=13
; About to load "Error"
01236: load constant 14                      ; C=E0000000000000 P=12
01237: load constant 10                      ; C=EA000000000000 P=11
01240: load constant 10                      ; C=EAA00000000000 P=10
01241: load constant 12                      ; C=EAAC0000000000 P= 9
01242: load constant 10                      ; C=EAACA000000000 P= 8
01243: binary                                ;
01244: c - 1 -> c[wp]                        ; C=EAACAFFFFFFFFF
01245: a exchange c[w]                       ; A=EAACAFFFFFFFFF C=00000000000000
01246: b exchange c[w]                       ;
01247: display off                           ;
01250: display toggle                        ; display ON
01251: p <- 2                                ; P= 2
01252: load constant 4                       ; C=00000000000400 P= 1
01253: c - 1 -> c[x]                         ; C=000000000003FF
01254: if n/c goto 0253                      ;
01253: ...
>>>


You can see “Error” being loaded into the A register and the B mask being set to display all digits from address 01236.

There are a lot of instructions (shown as “…” above) zeroing memory (06334-01153) before “Error” is loaded.

The key decision point before both of those is 06317. If mem[46] mantissa isn’t 3493428400, the microcode clears memory and displays “Error”.

If I had continuous memory and I powered up the calculator then I might have a value in mem[46] and it might be the correct one. However, if my continuous memory failed and I have zeros in mem[46], or part of it failed and the content of mem[46] isn’t correct, then the calculator will clear the lot and warn you of the problem. It looks like my guess was correct.

You can see, just after it zeros memory, the first thing it does is put 3493428400 in the mantissa of mem[46]. That starts happening right from address 06342.

If mem[46] had the correct value at power up, the sequence would have been different. Given we’re in an emulator, we can see what would have happened. The steps are:

>>> sd46 03493428400200
>>> srpc 0
>>> dp
00000: nop
>>> g
>>> dr
A=0000FFFFFFFF00 D=00000000000000 M1=00000000000000 P= 8
B=29000000000000 E=00000000000000 M2=00000000000000
C=00000000000000 F=00000000000000 S =...3.....9......
>>> dp
00347: if 1 = s 15 then goto 00175
>>>


We set data 46 to a value which included the required mantissa, set register pc back to 0, confirmed we were at the starting step, “go”ed (run) the program, “broke” back to the emulator (not shown above – it happens from the calculator window; not the monitor one), and then displayed the registers and current program step.

The display is showing “0.00”. You can see that from the A and B register values (0/2 shows as a blank sign digit, 0/9 shows as “0.” then two 0/0s show as “0” each). It is even easier to tell by looking at the calculator window.

Obviously the monitor is a bit different to what you’ve seen in my earlier emulators as it clearly has some new features. You’ll see updated emulators with the new monitor shortly.

I did manage to find a HP-29C manual online. At the bottom of page 183 it says, “If you drop or traumatize your calculator, or if power to the Continuous Memory is interrupted whether the calculator is off or on, the contents of program memory and the data storage registers may be lost. If this occurs, when the calculator is then turned on, the display will show Error. To restore the display , ensure that the battery is charged, or connect the ac adapter/recharger, and press any key.”

There is more information on the HP-29 Topic page.

It's only fair to share...Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUponDigg thisPin on PinterestEmail this to someone

Leave a Reply

Your email address will not be published. Required fields are marked *