So, you bought an old calculator; or a new one a very long time ago. You press a button and an answer pops out. How does it get from the first thing, to the second? This’ll answer the “getting from” part. I’ll leave the “getting to” part to later (get the HP-65 book if you’re not good at waiting). Here’s what happens …
Pressing a key results in the s15 flag inside the calculator getting set and a scancode being passed to its processor. (See HP-29C Wait Loop and HP-29 Scan Codes).
The Wait Loop is waiting for something to happen, such as s15 getting set. This article covers what the microcode inside the calculator does as a result.
Here’s part of the Wait Loop:
00173: if 0 = s 15 then goto 00152 00152: ... 00166: ... then goto 00173
It checks that there isn’t a key press, goes to 00152, checks some other things, and then ends up back at 00173 again.
Here’s what happens is s15 isn’t 0:
(press the "x<->y" key, scan code 0x43) (s 15 gets set, shown here as "S= ..F") 00156: if 0 = s 11 then goto 00165 ; S=...3.5...9.....F 00165: 0 -> s 5 ; 00166: if 1 = s 5 then goto 00173 ; 00173: if 0 = s 15 then goto 00152 ; it's not, so we're not going 00175: ... ;
We’re no longer in the loop – we didn’t go to 00152. The “if (something) then goto (somewhere)” instruction is a two-word instruction. We went instead, to the next instruction after 00173 – to 00175. That makes 00175 the “keypressed” address. It looks like:
00175: display off ; 00176: b exchange c[w] ; B=00000000000000 C=29000000000000 00177: keys to a ; A=0000FFFFFFF430 00200: 0 -> s 13 ;
It turns the display off and we see that as a blink when we press a key. It saves anything in the C register, by putting it in B for now, because it is about to use A and C to work some things out. The keys to a” instruction puts the current scan code in A[2] and A[1]. You can see 43 there. Remember that we pressed the “x<->y” key which has a scan code of 0x43. It also clears s13. I don’t know why as yet.
The next thing it does is multiply the scan code row (the 4) by 5 and add the scan code column. This is a simple way of reducing the range down to something smaller. If you look at the HP-29 scan code article, you’ll see that column numbers are all within 0-4 so multiplying row by 5 and adding column makes sense. In theory, you could reduce a range of (potentially) 00-FF down to 35 keys. Scan codes are easier for hardware. A short list of possible keys is easier for software. In practice, the row numbers range from 4-D(=13) so it isn’t quite as neat as it could be; but it does reduce the span of the jump table.
The row*5+col code looks like this:
00201: binary ; 00202: 0 -> c[x] ; 00203: c + 1 -> c[x] ; C=29000000000001 00204: a - 1 -> a[xs] ; A=0000FFFFFFF330 00205: if n/c goto 0203 ; 00203: c + 1 -> c[x] ; C=29000000000002 00204: a - 1 -> a[xs] ; A=0000FFFFFFF230 00205: if n/c goto 0203 ; 00203: c + 1 -> c[x] ; C=29000000000003 00204: a - 1 -> a[xs] ; A=0000FFFFFFF130 00205: if n/c goto 0203 ; 00203: c + 1 -> c[x] ; C=29000000000004 00204: a - 1 -> a[xs] ; A=0000FFFFFFF030 00205: if n/c goto 0203 ; 00203: c + 1 -> c[x] ; C=29000000000005 00204: a - 1 -> a[xs] ; A=0000FFFFFFFF30 00205: if n/c goto 0203 ; 00206: c - 1 -> c[x] ; C=29000000000004 c[0]= was a[2] 00207: 0 -> a[xs] ; A=0000FFFFFFF030 00210: shift right a[x] ; A=0000FFFFFFF003 a[0]= was a[1] 00211: a + c -> a[x] ; A=0000FFFFFFF007 a[x]= was a[2]+a[1] 00212: c + c -> c[x] ; C=29000000000008 c[0]= 2x was a[2] 00213: c + c -> c[x] ; C=29000000000010 c[0]= 4x was a[2] 00214: a + c -> a[x] ; A=0000FFFFFFF017 a[x]= 5x was a[2] + was a[1]
00203-00205 is a loop reducing the row number by 1 each time and adding 1 to C[0]. It is like doing “a -> c [xs]” then “shift right a[x]” twice (A[2]->C[2]; C[2]->C[1]->C[0]). We end up with the 4 from 0x43 in C[0].
We still have the 3 from 0x43 in A[1] so 00210 moves it into A[0].
As shown, the sequence 00211-00214: adds row+col (4+3=7), sets C[x] to 4*row (4*4=0x10), and adds that too. We get (row+col + 4*row = 5*row+col). For 0x43, row=4, col=3, 5*4+3= 23= 1*16+7=) 0x17 in A[x].
The next bit looks a little confusing; but it is really just a jump to 00400 + 5*row+col
00215: shift left a[x] ; A=0000FFFFFFF170 00216: p <- 1 ; P= 1 00217: m1 -> c ; C=00000000000000 00220: 0 -> c[x] ; 00221: delayed rom 1 ; to 00400-00777 00222: a -> rom address ; 0x17 = 10111 = 027 ; scancode 043 -> row4,col3 -> 5*4+3 = 23 ; 23= 1*16+7 so hex = 0x17 ; 23= 2* 8+7 so octal= 027 00427: if n/c goto 0151 ; 00400 + 5*row + col
You end up with:
Keycode | Key | Scan Code | Goto |
11 | SST | 0xb3 | 00472 |
12 | GSB | 0xb2 | 00471 |
13 | GTO | 0xb1 | 00470 |
14 | f | 0xb0 | 00467 |
15 | g | 0xb4 | 00473 |
21 | x<->y | 0x43 | 00427 |
22 | Rv | 0x42 | 00426 |
23 | STO | 0x41 | 00425 |
24 | RCL | 0x40 | 00424 |
25 | SUM | 0x44 | 00430 |
31 | ENTER | 0xd3 | 00504 |
33 | CHS | 0xd1 | 00502 |
34 | EEX | 0xd0 | 00501 |
35 | CLx | 0xd4 | 00505 |
41 | – | 0x63 | 00441 |
42 | 7 | 0x62 | 00440 |
43 | 8 | 0x61 | 00437 |
44 | 9 | 0x60 | 00436 |
51 | + | 0xa3 | 00465 |
52 | 4 | 0xa2 | 00464 |
53 | 5 | 0xa1 | 00463 |
54 | 6 | 0xa0 | 00462 |
61 | x | 0x73 | 00446 |
62 | 1 | 0x72 | 00445 |
63 | 2 | 0x71 | 00444 |
64 | 3 | 0x70 | 00443 |
71 | / | 0x93 | 00460 |
72 | 0 | 0x92 | 00457 |
73 | . | 0x91 | 00456 |
74 | R/S | 0x90 | 00455 |