HP-29C Prefix Keys

How does the HP-29C remember that you’ve pressed a prefix key? When you press f, g, or even STO or GTO; what happens next is not the normal key function.

The f key

Here’s what the f key does:

key_f:
00467: if n/c goto 0245                    ;
00645: jsb 0000                            ;
00400: delayed rom 2                       ;
00401: if n/c goto 0167                    ;
01167: 0 -> s 4                            ;
01170: 0 -> s 0                            ;
01171: 0 -> s 14                           ;
01172: 0 -> s 6                            ;
01173: 0 -> s 7                            ;
01174: 0 -> s 8                            ;
01175: 0 -> s 10                           ;
01176: 0 -> s 13                           ;
01177: return                              ;
00646: 1 -> s 6                            ; S=...3.56..9.....F
00647: 1 -> s 4                            ; S=...3456..9.....F
00650: if n/c goto 0216                    ;
00616: 1 -> s 13                           ; S=...3456..9...D.F
00617: if n/c goto 0163                    ;
00563: if 1 = s 13 then goto 00124         ;

00124: ...


01167 clears a lot of existing flags, probably all existing prefix flags. You’ll see that subroutine a lot.
00124 is a common “after a function has completed” bit of code. I haven’t looked in detail yet, but it looks like it sorts out displaying the result and managing LastX.
s 13 will get cleared shortly after the next key gets pressed (00200, see HP-29C Keypress Routine) so pressing the f key sets s4 and s6.
There is more detail in f.txt.

The g key

Here’s what the g key does:

key_g:
00473: if 1 = s 4 then goto 00477          ;
00475: if 1 = s 7 then goto 00662          ;
00477: jsb 0000                            ;
00400: delayed rom 2                       ;
00401: if n/c goto 0167                    ;
01167: 0 -> s 4                            ;
01170: 0 -> s 0                            ;
01171: 0 -> s 14                           ;
01172: 0 -> s 6                            ;
01173: 0 -> s 7                            ;
01174: 0 -> s 8                            ;
01175: 0 -> s 10                           ;
01176: 0 -> s 13                           ;
01177: return                              ;
00500: if n/c goto 0247                    ;
00647: 1 -> s 4                            ; S=...345...9.....F
00650: if n/c goto 0216                    ;
00616: 1 -> s 13                           ; S=...345...9...D.F
00617: if n/c goto 0163                    ;
00563: if 1 = s 13 then goto 00124         ;

00124: ...


We see 01167 again. If we had pressed f before g, 01167 clears s4 and s6 so the g key overrides the earlier one.
We see 00124 again.
The g key sets s4 but not s6.
s13 is also set but, as explained earlier, it is short lived and doesn’t affect the behaviour of subsequent keys.
You can see more detail in g.txt.

The STO key

It is a little more complex for the other prefix keys as it also builds a hex code for a program step. Here’s the code for STO:

key_sto:
00425: if n/c goto 0266                    ;
00666: if 1 = s 4 then goto 00675          ;
00670: load constant 10                    ; C=000000000000A0 P= 0
00671: jsb 0000                            ;
00400: delayed rom 2                       ;
00401: if n/c goto 0167                    ;
01167: 0 -> s 4                            ;
01170: 0 -> s 0                            ;
01171: 0 -> s 14                           ;
01172: 0 -> s 6                            ;
01173: 0 -> s 7                            ;
01174: 0 -> s 8                            ;
01175: 0 -> s 10                           ;
01176: 0 -> s 13                           ;
01177: return                              ;
00672: 1 -> s 7                            ; S=...3.5.7.9.....F
00673: 1 -> s 6                            ; S=...3.567.9.....F
00674: if n/c goto 0216                    ;
00616: 1 -> s 13                           ; S=...3.567.9...D.F
00617: if n/c goto 0163                    ;
00563: if 1 = s 13 then goto 00124         ;

00124: ...


“g STO” leads to something else (DSZ) so the microcode first checks the s 4 flag.
We haven’t pressed the “g” key in this test run so we progress to 00670 which sets C[1,0] to “A0”. That is the first of a set of hex codes for instructions “STO 0” … “STO 9”, “STO .0” … “STO .5”.
We then clear all prefix flags (subroutine 01167 again) and set s6 and s7 (with s13 also being set temporarily).
By the time we get back to the wait loop, the “A0” has been tucked away in the M1 register.

If we now press “.”, we get:

key_dot:
00456: if n/c goto 0002                    ;
00402: if 0 = s 4 then goto 00407          ;
00407: if 0 = s 7 then goto 00404          ;
00411: if 0 = s 6 then goto 00575          ;
00413: jsb 0363                            ;
00763: m1 exch c                           ; C=050000000000A0 M1=05000000000000
00764: 0 -> s 7                            ; S=...3.56..9..C..F
00765: 1 -> s 8                            ; S=...3.56.89..C..F
00766: 0 -> s 10                           ;
00767: return                              ;
00414: 1 -> s 6                            ;
00415: p <- 0                              ; P= 0
00416: load constant 10                    ; C=050000000000AA P=13
00417: if n/c goto 0216                    ;
00616: 1 -> s 13                           ; S=...3.56.89..CD.F
00617: if n/c goto 0163                    ;
00563: if 1 = s 13 then goto 00124         ;

00124: ...


Because we pressed STO before this, you get the above combination of s4, s7 and s6.
s10 was already clear anyway but we also clear s7 and set s6 and s8 to note we’re now at “STO .”; instead of just “STO”.
You’ll also see our hex code of “A0” has been updated to “AA”. That is the starting point for the “STO . 0” … “STO . 5” series.

When we now press a digit, we get something that starts with this:

key_2:
00444: c + 1 -> c[x]                       ; C=05000000000001
00445: if n/c goto 0332                    ;
00732: c + 1 -> c[x]                       ; C=05000000000002
00733: if 1 = s 4 then goto 00745          ;
00735: if 1 = s 7 then goto 00747          ;
00737: if 1 = s 6 then goto 00756          ;
00756: if 0 = s 8 then goto 00747          ;
00760: if 1 = s 13 then goto 00745         ;
00762: if n/c goto 0347                    ;
00747: a exchange c[wp]                    ; A=05FFFFFFFFF202 C=05000000000040
00750: m1 exch c                           ; C=050000000000AA M1=05000000000040
00751: a + c -> c[wp]                      ; C=050000000000AC
00752: m1 exch c                           ; C=05000000000040 M1=050000000000AC
...


You can see that combination of s4, s6, s7 and s8 adds the “2” from “STO . 2” to the hex code “AA” to give hex code “AC” which is the code for that combination. A similar thing occurs if we pressed “0”, “1” or “3” to “5”.
The microcode continues on to clear all of the prefix keys (subroutine 01167) and to do the actual “STOre” action. It then goes via 00124 back to the wait loop.

If we’d pressed a digit instead of pressing the “.” key, it starts like this instead:

key_3:
00443: c + 1 -> c[x]                       ; C=05000000000001
00444: c + 1 -> c[x]                       ; C=05000000000002
00445: if n/c goto 0332                    ;
00732: c + 1 -> c[x]                       ; C=05000000000003
00733: if 1 = s 4 then goto 00745          ;
00735: if 1 = s 7 then goto 00747          ;
00747: a exchange c[wp]                    ; A=0500FFFFFFF203 C=05000000000030
00750: m1 exch c                           ; C=050000000000A0 M1=05000000000030
00751: a + c -> c[wp]                      ; C=050000000000A3
00752: m1 exch c                           ; C=05000000000030 M1=050000000000A3
...


With s4=0 and s7=1, it simply adds the “3” we pressed this time to the existing “A0” hex code to get “A3”. That is the hex code for “STO 3” so it makes a lot of sense.
It is interesting that it didn’t check s6 or other flags. There is a good chance that the same path gets followed for prefixes like “g LBL”, “GTO” and “GSB”. It may even also get used for “f FIX”, “f SCI”, “f ENG” and others.
Pressing a digit completes the key sequence so 01167 gets called here too and all of the prefix flags get cleared.

STO (op) [.] (n)

You can also press an operator (- + * /) after the STO key and then, optionally a “.” and, a digit key. That involves some additional prefix states. Here’s what “STO – 3” looks like, when you press “-“:

key_sub:
00441: if n/c goto 0053                    ;
00453: delayed rom 2                       ;
00454: if n/c goto 0000                    ;
01000: jsb 0025                            ;
01025: if 0 = s 4 then goto 01033          ;
01033: if 0 = s 6 then goto 01027          ;
01035: if 0 = s 7 then goto 01027          ;
01037: if 1 = s 10 then goto 01027         ;
01041: if 1 = s 8 then goto 01027          ;
01043: m1 exch c                           ; C=000000000000A0 M1=00000000000000
01044: return                              ;
01001: if p = 1 then goto 00773            ;
00773: c + 1 -> c[p]                       ; C=000000000000B0
00774: 1 -> s 8                            ; S=...3.56789.....F
00775: if n/c goto 0216                    ;
00616: 1 -> s 13                           ; S=...3.56789...D.F
00617: if n/c goto 0163                    ;
00563: if 1 = s 13 then goto 00124         ;

00124: ...


After STO, s4=0 s6=1 s7=1 s10=0 s8=0 so we put M1 into C then change the “A0” to “B0”. “B0” is the start of the hex codes for “STO – 0” … “STO – 9”, “STO – .0” … “STO – .5”.
We also set s8 (and temporarily s13).

If we press “.”, we get:

key_dot:
00456: if n/c goto 0002                    ;
00402: if 0 = s 4 then goto 00407          ;
00407: if 0 = s 7 then goto 00404          ;
00411: if 0 = s 6 then goto 00575          ;
00413: jsb 0363                            ;
00763: m1 exch c                           ; C=050000000000B0 M1=05000000000000
00764: 0 -> s 7                            ; S=...3.56.89.....F
00765: 1 -> s 8                            ;
00766: 0 -> s 10                           ;
00767: return                              ;
00414: 1 -> s 6                            ;
00415: p <- 0                              ; P= 0
00416: load constant 10                    ; C=050000000000BA P=13
00417: if n/c goto 0216                    ;
00616: 1 -> s 13                           ; S=...3.56.89...D.F
00617: if n/c goto 0163                    ;
00563: if 1 = s 13 then goto 00124         ;

00124: ...


With s4=0 s7=1 s6=1, we: get M1 to C, clear s7 and set s8 instead. s10 is already 0 and s6 is already 1. Like with “STO . n”, we change the hex code “B0” to “BA” so that we’re positioned at the start of the “STO – .0” … “STO – .5” hex codes.

For “STO + [.] n” it works very much the same way:

key_add:
00465: delayed rom 2                       ;
00466: if n/c goto 0004                    ;
01004: jsb 0025                            ;
01025: if 0 = s 4 then goto 01033          ;
01033: if 0 = s 6 then goto 01027          ;
01035: if 0 = s 7 then goto 01027          ;
01037: if 1 = s 10 then goto 01027         ;
01041: if 1 = s 8 then goto 01027          ;
01043: m1 exch c                           ; C=050000000000A0 M1=05000000000000
01044: return                              ;
01005: if p = 1 then goto 00772            ;
00772: c + 1 -> c[p]                       ; C=050000000000B0
00773: c + 1 -> c[p]                       ; C=050000000000C0
00774: 1 -> s 8                            ; S=...3.56789.....F
00775: if n/c goto 0216                    ;
00616: 1 -> s 13                           ; S=...3.56789...D.F
00617: if n/c goto 0163                    ;
00563: if 1 = s 13 then goto 00124         ;


STO was pressed so s4=0 s6=1 s7=1 s8=0 s10=0. We get the A0 from M1 to C. We then add 2 to the “A” part to move us to the hex codes starting with “C0” (“STO + 0” … “STO + 9”, “STO + .0” … “STO + .5”). s8 gets set.
If “.” is pressed, it behaves as for “STO – .” but “C0” becomes “CA” (for “STO + .0” … “STO + .5”).

“STO * [.] n” and “STO / [.] n” are also similar.
“STO * [.] n” adds 3 to “A” for hex codes “D0” … (“STO * 0” …). s8 also gets set.
“STO / [.] n” adds 4 to “A” for hex codes “E0” … (“STO / 0” …). s8 also gets set.

The Story so far

Prefix s4,6,7,8,10 hex code
f 11000 n/a
g 10000 n/a
STO 01100 A0
STO . 01010 AA
STO – 01110 B0
STO – . 01010 BA
STO + 01110 C0
STO + . 01010 CA
STO * 01110 D0
STO * . 01010 DA
STO / 01110 E0
STO / . 01010 EA

STO (op) has s4,6,7,8,10 = 01110. It may be followed by “.” or 0-9.
STO [(op)] . has s4,6,7,8,10 = 01010. It may only be followed by 0-5.

RCL

“RCL” sets s4,6,7,8,10 to 01101 and loads hex code “90”.
“RCL .” sets s4,6,7,8,10 to 01010 and updates the hex code to “9A”.
See rcl_dot_2.txt for more detail.

g LBL

“g LBL” sets s4,6,7,8,10 to 00001 and loads hex code “F0”. See g_lbl_0.txt.

GTO

“GTO” sets s4,6,7,8,10 to 00110 and loads hex code “80”. See gto_1.txt.

You can also do “GTO . n1 n2” to move to a specific program step. It is not a recordable program step but it is still another prefix sequence. The “.” clears s7 and sets s10 so s4,6,7,8,10 becomes 00011. M1 doesn’t change. Pressing the first digit (n1) doesn’t change any of the s flags (aside from s13) but M1[2,1,0] becomes “8(n1)0”. You can see the full sequence in gto_dot_23.txt

GSB

“GSB” sets s4,6,7,8,10 to 00100 and loads hex code “70”. See gsb_2.txt.

f FIX/SCI/ENG

“f FIX/SCI/ENG” sets s4,6,7,8,10 to 01000 and loads hex code “40/50/60”. See f_fix_3.txt, f_sci_4.txt and f_eng_3.txt.

Less Obvious Prefixes

There are some additional prefix combinations. These concern the indirect register, the “i” key (g Rolldown). You can use some prefixes with that key so you can get combinations like “STO – g i”. Here’s the prefixes:

Prefix s4,6,7,8,10 M1[2,1,0]
sto g 10100 0A0
sto sub g 10100 0B0 (others for other ops)
rcl g 10100 090
gto g 10100 080
gsb g 10100 070

The Digits 0-9

In the hp29rom.txt file, you can see the microcode converting a goto location for a key, to a value in C[x]. Pressing the “9” key causes the microcode to goto 00436 and the sequence there sets C[2,1,0] = “xx9”.

What is different with this calculator though, is s 13 gets set if the digit is outside the range 0-5. It looks like this:

00436: c + 1 -> c[x]                       ; key_9
00437: c + 1 -> c[x]                       ; key_8
00440: if n/c goto 00420                   ; key_7
00462: if n/c goto 00421                   ; key_6
00420: c + 1 -> c[x] 
00421: c + 1 -> c[x]
00422: 1 -> s 13
00423: if n/c goto 00463

00463: c + 1 -> c[x]                       ; key_5
00464: if n/c goto 00442                   ; key_4
00442: c + 1 -> c[x]
00443: c + 1 -> c[x]                       ; key_3
00444: c + 1 -> c[x]                       ; key_2
00445: if n/c goto 00732                   ; key_1
00457: if n/c goto 00733                   ; key_0
00732: c + 1 -> c[x]


This suggests that s13 will get checked if a prefix key sequence including a “.” was pressed. If s13 is set the number is out of range (not .0 through .5).

A lot of effort has gone into the choice of prefix flags, hex codes and the microcode for the digit keys. Regardless of which prefix, if any, was selected; and regardless of which digit gets pressed; every combination goes through a single sequence of microcode at 00733 which starts like:

00733: if 1 = s 4 then goto 00745
00735: if 1 = s 7 then goto 00747
00737: if 1 = s 6 then goto 00756
00741: if 1 = s 8 then goto 01045
00743: if 1 = s 10 then goto 00747


Whilst there are 32 possible combinations of the 5 s flags, there are only four possible actions for a digit key. These are: 00745, 00747, 00756 or 01045. Even if none of the flags are set, it “falls through” the tests to 00745 – one of the four actions. This makes 00745 the “normal action” (ie un-prefixed action) for a digit.

The 00756 action explains a little:

00756: if 0 = s 8 then goto 00747
00760: if 1 = s 13 then goto 00745
00762: if n/c goto 00747


If s13 is set, treat the digit as a normal digit. This means, for example, if you press “7” after a “STO .”; it will ignore the “STO .” part and act as if only “7” had been pressed. This makes sense because you can only “STO .” to “0”-“5”. There isn’t a “.7” data storage register. It may also mean that “STO .” then “.” will result in just “.”; but we’d have to check how the “.” microcode works – we’re only addressing digits for now.

We only get to 00756 if s4=0, s7=0 and s6=1. That means we are considering “{STO [op]|RCL} .” or “{FIX|SCI|ENG}”.
The “0 = s 8” line, 00756, means we’re dealing with “{FIX|SCI|ENG}” and we can skip the s13 (outside “0”-“5”) check. FIX/SCI/ENG can be followed by any digit 0-9.

For both “{STO [op]|RCL} .” and “{FIX|SCI|ENG}”, we need to merge the digit (0-5 or 0-9) into the hex code in M1 to get the hex code for the fully merged program step or operation. If 00756 decides the digit is valid for the prefix, it goes to 00747. We can also get to 00747 with other s flag combinations (see 00735 and 00743). That includes LBL, GTO and GSB. This all fairly clearly makes 00747 the microcode for “add a digit into the current hex code” (let’s call it upd_hex:). See above (“The STO key”), rcl_2.txt, or the GTO, GSB or LBL traces to watch how it works.

01045 has similar code to 00747. You get to 01045 if s4=0, s7=0, s6=0 and s8=1. That fits “GTO .” which isn’t going to create a hex code (it can’t be stored as a program step). Let’s call 01045 gto_dot:. You can see that in operation in gto_dot_23.txt

Summary

Pressing f or g sets s4, the “fg” flag. You can tell which by checking s6. If set it’s “f”.

For other prefixes or sequences, the current state is stored in a combination of s4,6,7,8,10 and M1. The combinations are:

s4,6,7,8,10 M1 prefix/sequence
00001 F0 LBL
00011 80/8(n1)0 GTO . [(n1)]
00100 70 GSB
00110 80 GTO
01000 40/50/60 FIX/SCI/ENG
01100 A0 STO
01101 90 RCL
01110 B0/C0/D0/E0 STO (op)
01010 AA/BA/CA/DA/EA/9A {STO [(op)]|RCL} .
10100 A0/B0/C0/D0/E0/90/80/70 {STO [(op)]|RCL|GTO|GSB} g

The s4,6,7,8,10 combination is a prefix code. s4 is “fg” but the others are harder to label separately.

s13 is used when a digit is pressed to flag a value outside the range 0-5.

Some significant microcode addresses are:
00745 digit:
00747 upd_hex:
01045 gto_dot:

Prefix keys in the HP-29C are a lot more complex than previous calculators.

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 *