Calculator Coding

Once upon a time, long time ago, an exquisite-yet-useful object came into life, called the HP-15C. Millennials will not remember, even can likely not imagine that there was such a time as the pre-internet era, and a bit further back, even a pre-personal-computer era. The HP-15C was born in those years, 1982 to be exact. I got mine on September 23rd 1987, exactly the time I needed a more advanced scientific calculator, because that’s what it was.

Proud owner of the HP-15C, serial number 2707A25331, since 23/09/1987

I had been the almost-as-proud owner of a HP-11C already for 3 years, but my dad — who, being an electronics engineer, went over such household-logistics decisions as calculator distribution — made the wise decision that my 2 years younger brother, should inherit from me the 11C (to replace his TI) and I instead should get a brand new 15C, a bit like clothes are passed on to younger siblings, but then infinitely more interesting. I am still grateful for that, because amongst other things, the 15C had more memory for programming: a total of 448 bytes! That surely should be enough for anyone! :)

I loved the 15C for many reasons.

I guess that, back in 1987, there was a 5% to 95% split between people with HPs and people with the omnipresent TIs. At least, in each class of about 20 to 30 people there was only one or max two students with a HP-11C or HP-15C. It made me feel quite special already. :)

But it ran deeper than that.

For the obvious visible-from-far part, I liked its different wider-than-high case form factor compared to other calculators. HP also came from the vertical case aspect ratio as can be seen in this HP calculator collection poster, reproduced here.

HP calculators of the 70s and 80s (1970s and 1980s that is, millennials, and yes, we had calculators on our watch already!)

The Voyager series, of which the HP-15C was a family member, clearly wanted to be different.

Its similarly wide buttons were particular in that they felt rigid and had a very pleasant solid rubbery click, called haptic by some. TI buttons were wobbly and moving in all directions when touched and felt too light.

Another feature is that the HP 15C smelled really new-plastically-nice. Was it marketed-in consciously or just a consequence of choice of materials resulting from a spec-list not including any smell-related requirements? In any case, the HP Voyager series smell is an olfactory sensation which still clearly clings to my temporal lobe.

Apart from all its sensory satisfactions, there were some more brainy ones.

In particular, HP used RPN (Reverse Polish Notation) rather than the traditional version. If you calculate 3 + 4, a TI operator would tap just those ‘3’ then ‘+‘ then ‘4‘ and then ‘=‘ and the result would appear. On a HP calculator one would tap the keys: ‘3‘ ‘Enter’ ‘4’ ‘+’. The operator always comes at the end i.o in between its operands, and is called postfix i.o infix for that reason. The Enter is just there to separate the two operands. The advantage is not visible yet for this single operation. However, when one has to do some nested computations like (3 + 4) * 5 a TI device takes 7 key strokes ‘(‘ ‘3‘ ‘+’ ‘4’ ‘)’ ‘*’ ‘5‘ while an RPN HP gets it done in 5 keystrokes: ‘3’ ‘enter’ ‘4’ ‘+’ ‘5’ ‘*’. Brilliant! There are no brackets keys on an RPN machine. There is no equal sign on a RPN machine. There is no need for those. The ENTER key replaces both. I remember the “hmm, nice”-feeling and a sense of appreciation. The beauty is of course in the minimalism, or otherwise put: the optimisation. HP just thought a little harder about it than TI. Well, it did not invent RPN, but at least dared to walk on the less crowded RPN side.

But my favourite HP-15C’s related memory is that I wrote my very first assembly programs on it.

For about 2 years, I had already enjoyed programming PCs in GW-Basic, some Borland Turbo Pascal and some more Turbo C/C++, which was easy in comparison. But from programming the HP-15C, I really learned how machines work at the lowest instruction level.

ReCalL value in register 8 (RCL 8), store this address value in index register I (STO I), add 10 (10 STO + I), get register with address stored in I and add 3 to that register, (3 STO(i) +) which in — to be avoided, since even too low pointer & address level — C is just *(&r8+10)+=3.

At the time, a non-programming uncle (yes, I keep and cherish two categories of uncles :), told me to not occupy myself too much with Basic, since it was ‘not structured programming’ and so the ‘wrong kind’ of low level programming with GOTOs and whatnot. I see his point, but disagree with that, since all of the high level programming relies on the low level programming constructs like: goto, gosub.

Does one not want to know how machines manage to run the higher level constructs of a for & while loop, or how they remember where they came from after a subroutine and can jump back, how arguments are passed to a subroutine (via pushing them on a stack) and — nicely symmetrically — how local variables ‘automatically’ disappear without harming functionality (via popping them from the stack)? How recursion can work? Of course one does!

So I loved to play with and program on this calculator and was looking for a challenge.

2 A Coding Challenge

With my 3 other siblings at home, we used to play “Kleur bekennen”. The cardboard box looked like this.

The game “Kleur bekennen” from Clipper a.k.a. Master Mind

The game, outside the Dutch-speaking world, is more generally known as Master Mind, where one person, the CodeMaker, thinks of a combination of a number (in “Kleur bekennen” 3 and in “Master Mind” 4 to 6) coloured pegs, which apart from colour are entirely identical, and the other person, the CodeBreaker, has to guess the CodeMaker’s pegs, both their colours as well as their positions in fewer turns that the opponent can guess your coloured peg combination.

Back at 16, I thought it would be fun to be able to play Master Mind against the 15C. In other words, the human, mostly me, would play CodeBreaker, the challenging part, against the CodeMaker, the program I would write for the 15C.

In the manual, I rushed through the 63 pages of Chapter 1, called ‘Basic Characteristics of the HP-15C’ before arriving at part II, called ‘Programming the 15C’, where I learned what I needed.

The manual cover, which I found very inspiring in becoming an engineer :)

Since the HP-15C had a monochrome display (even computers had at the time!), pegs would have to become their digital twins: digits. For Master Mind, I needed the program to randomly generated a N digit number, each digit representing one out of N colours. Then the user would do an N digit guess and then the program would have to score this guess by replying with two answer digits. The first answer digit (correct_digits_in_correct_position, from 0 to N) should count how many digits of the user’s guess were the correct ones in the correct place and from the leftover guess digits. The second answer digit (correct_digits_in_wrong_position, from 0 to N) should count (amongst the leftover digits) how many were occurring in the solution but in the wrong place. Surely correct_digits_in_correct_position + correct_digits_in_wrong_position ≤ N always should hold.

I also want to return the number of guesses done and back then chose the answer format to be <#guesses>,<correct_digits_in_correct_position><correct_digits_in_wrong_position>, so like “3,14” for third turn, 1 correctly positioned digit and the 4 others correct but in the wrong place, like a guess 12345 for a secret number to be guessed 15432.

End of 1987 flash back.

3 An HP-15C Simulator

Intermediate stop 11 years later in 1998: Google was founded.

Back in 2020: Googling a bit on HP-15C, I quickly bumped into a simulator on which shows some HP-15C programs, nicely rendered into what marketing would call the brand- book-style of the HP-15C. Now, that’s an exquisite setting to render my 33 year old program in! Thanks Torsten! :)

3. 1 Entering a Program into the Simulator

This simulator now allows in fact for anyone, say you, the reader, even when you do not have the privilege of owning of a HP-11/15C calculator, to execute the programs mentioned here by first downloading the officially published simulator from here and then downloading the example programs here. My programs, developed and discussed in this article, are contained in there. They’re called HigherLower_v1987.15c and MasterMindGuessScoring.15c.

Before delving into ‘the making of’ the latter, we’ll first explain, by the use of two small demo programs, how a program is stored in a HP-15C calculator, by use of the HP-15C simulator and then do the same for my Master Mind program.

The simulator nicely renders the calculator as shown in the below snapshot.

Showing the calculator in the programming mode. 001 for program line, 42 for key in row 4, column 2 (f), 21 (GTO) and 11 (A).

In this case, the calculator is shown in the programming mode. You get it there by pressing g P/R, where P stands for Program and R for Run. So it is a toggle action. On the display, 001 stands for the program line 1, 42 for the key on row 4 (rows are numbered from top (1) to bottom (4)), column 2 (columns are numbered from left (1) to right (0!:)), (so key f), 21 (key GTO) and 11 (key A).

As such the user has display feedback on the pressed keys. Note that back in 1982, LCD displays still were 7-segment displays only meant to show digits from 0 to 9 and not any alphabetic character yet, so they could not show letters like ‘GTO’ on the display. So I found this was a smart next-best way out as a key coding scheme.

Actually, there were some nice exceptions for when the HP-15C was running a program and working hard on it, one could see this.

making up the words “running”with only 7 LCD segments per letter

or when the programmer had not worked hard enough yet, one would see this

making up the word “Error” with only 7 LCD segments per letter

I now even wonder if this key mapping is why HP went for the wide case format. Given our convention on reading from left to right in most of the world, it is more natural to number keys from left to right than from top to bottom.

According to this system, the key 4 should appear, in program mode, as key 27, but in fact HP made exceptions for the numeric keys and just makes them appear as their actual value, so 4 for 4, 7 for 7. Logical right? Yes, but wait, can that not lead to two keys mapping to the same number? Nah, since the digits are 1, 2, … 9 and 0, they can be considered to be mapped to the line 0, so nicely separated from the rows 1 to 4 with keys 1* to 4*. So we can all map the keys to a logical row-column number and the 0 to 9 digits in an even more intuitive way, to themselves.

It’s elegant design choices and solutions like these, even to the little puzzles engineers faced, when designing an innovating and off-beam calculator, that makes one appreciate the obvious care and effort they made in bringing the HP-15C to life.

We now how an instruction looks and the way to enter it is just applying the keystrokes. The calculator automatically divides the keystrokes up into program lines, each containing 1,2 or 3 keystrokes, not a trivial task I guess.

One, two or three numbers on the display, one instruction at a time. This was all there was to see, back in 1987. And one had to debug ones program by single-stepping (SST) and back-stepping (BST) through the program. Keeping SST/BST pressed would show the program line and instruction, releasing it would show the result. It was elegantly executed, but still, the display offered only a very small keyhole view on a full program. And when one wanted a full program listing, one had to write it down on paper, pressing SST copying an instruction, repeat until done.

I am glad we have the simulator now to generate in a second a full program list of what is in the memory, print it out and edit or restructure from there.

How does a program listing look? Let’s inspect a small example.

3.2 Extracting a Program from the Simulator

The first program mentioned in the HP-15C manual is one calculating the number of seconds it takes for an object to fall when given to it as input, the height in meter above earth’s surface at which it is released. This program looks like this.

HP-15C program from the HP 15C handbook to return the number of seconds for an object to fall as a function of height in meters.

We obtained this nice representation by first entering this instruction sequence in the simulator (really by mouse clicking the keys of the realistically rendered calculator) and then, still in the simulator entering “File > Save program …” and then entering FallingSeconds.15C as the filename. After that, “File > Export program to HTML” generates the file FallingSeconds.htm. Loading the HTML file in a browser, I inserted the screen capture of it above.

The way to run the program, in the HP-15C simulator as well (as on the real HP-15C of course) is to type a number and then call the program on it by typing “f LBL A”, since that is the ‘name’ under which the program is stored. The program just calculates

time in seconds for object to fall on planet Earth depending on height h in meters of release above surface

on the h value stored in the X register, which is always the register which you see in your HP-15C display. Of course, this program also easily fitted in the HP-11C’s memory.

4 A Coding Celebration

4.1 Higher Lower Game

In fact, digging up my scribblings, I found out I also wrote up a higher lower game on my 11C, 3 years earlier. It could serve as a good intermediary step up to the Master Mind program. Compared to the previous program in 3.1, the higher lower game has at least a loop construct and does some conditional branching.

So we just need code for the calculator to invent a random secret number between, say 1 and 100, and then need to just construct one loop, where the player will enter a number as a guess and the calculator will answer, say ‘+1’ to mean the secret number is higher than the guess and say ‘-1’ to mean the secret number is lower, and say, show the guessed number blinking on and off, when the number is guessed. An easy enough specification.

Using the HP-15C simulator, the code for that looks like this.

Code and usage description for playing the higher lower game on a HP-11C (or HP-15C) calculator, Peter’s 1984 code with a much nicer formatting from Torsten Manz’s simulator.

On line 1, the label A is given to the program. Line 2 generates a random number x where 0 ≤x<1. The next lines multiply it with 100, take the integer part only and add 1 to get a number in [1,100] as required. On line 10 this is in the x register and put in register 6, called R[6] in HP calculator speak. Line 11 erases the register so that the user does not see the secret number to be guessed.

Line 12 puts label 1 here, because this is the start point of each guess for the user and so we need to be able to return to it — most likely — multiple times. Line 13 shows a pause, called ‘PSE’ which makes the display blink for a second or so. Line 14 contains the R/S instruction meaning ‘Run/Stop’, which will make the program stop, so that the user can enter digits representing his guessed number. No enter is required. Instead the user needs to press R/S so that running is resumed. Line 15 has ‘ENTER’ meaning that the user given number will be pushed up from X to Y in the X,Y,Z,T 4-register stack. Line 16 then fetched/recalls the secret number stored in register X6 to X and will next do comparisons with the Y register containing the guess.

Line 17 tests if x≤y. If that is the case, the program goes to the next line, line 18 where we jump to label 2 (which is on line 22). More on that branch later. But if x>y, the guess y is too low and we end up on line 19, where a +1 is put in the x register (so in the display) and is blinked once on line 20 (by f PSE) and then on line 21 we jump to label 1 (on line 12) and blink the 1 once more on line 13 and stop execution on line 14, so that the user can enter a new number.

If x≤y, we jumped from line 17 to line 22 using label 2. We have the guess still in Y and the to be guessed value in X. We subtract X from Y in line 23, and test for equality on line 24 by the test: ‘g x=0’. If that’s the case, the player guessed right and line 25 makes us go to label 3 on line 30. Line 31 then fetched the to be guessed number (which we lost by subtraction) from register X6 and blink it twice (on lines 32 and 33) and line 34 makes us jump to label 1 again. The game is finished then. Well the user could guess again but that’s a bit useless.

If on line 24, the test ‘g x=0’ failed, we know the guess is too high and indicate the player to lower it by showing ‘-1’ in the display and blinking it twice (lines 26 to 29) and then jump back to label 1 on line 12 to let the user enter a new guess via the R/S on line 14.

You now understand the basic primitives to make simple programs on the HP-11C and 15C calculators. Let’s go for the bigger challenge now, the Master Mind program.

4.2 Master Mind Memory

What’s the best road to a working program that is also ultimately satisfying?

4.2.1 Trying to Reverse Engineer my 1987 Program

And now for our own Master Mind program. From my own 1987 notes, I could enter the program into the simulator and let the simulator output the 234 lines code neatly.

However, after some testing, it appeared that it mostly works, but also sometimes, in having to come up with the number of digits in the right place and used digits but in the wrong place, errs on only the latter.

I considered debugging and improving it for a few minutes, but looking at the code above, seeing the kind of ‘ugly’ loop-unrolled lines from 64–73, 97–106 and 190–199, I quickly decided it would not lead to satisfactory code, which then kills the plan for me. One learning here is that one should write understandable code. Since understanding comes from seeing structure, in particular for assembly level code, which flattens and concatenates every subpart to a seemingly unstructured whole at the very low machine level, parsing structure back out of it, certainly years later, is simply too hard for a human. At least it was for me.

So I decided to entirely rewrite it.

4.2.2 A 2020 Rewrite, …. v2020_1.

Some days later … I made a new fully working version. However, it had some ‘suboptimalities’, so I avoid discussing the code itself here. Only:

Mainly, it does not fit in my HP-15C real machine. The simulator allows to use the DM-15 mode with a choice of number of registers. I had to select 128 registers for the combination of the program instructions and the used registers to fit together in the memory. The DM-15 is a clone made by a Swiss company in credit format, but I do not possess a physical DM-15. So I have to somehow reengineer the program to use fewer resources, in terms of number of used

  1. program lines or/and
  2. registers.

In fact both optimisations are still possible.

  1. I figured out that by (affine) loop (index) transformation, one can perform the two loops (or the two functions, producing c and d) in one combined loop. Have a look at the explanation for that principle in my other Medium article called Data Dependencies.
  2. I used the N registers from 21 to 2N to store matched_secret array and the N registers from 31 to 3N to store the matched_guess array. (Both arrays serve as a way to keep record of which pegs/digits are already matched to others and should, after that, not be compared anymore to other pegs/digits.) In fact we could store these boolean variables together with their respective secret and guess numbers, say as the fractional part of the numbers or digits. Each register seems to take up 7 bytes in a HP-15C and in 7 bytes one can put quite some program instructions instead, since each program instruction takes between 1 and 3 bytes on a 15C.

Apart from that, we do not display yet the number of turns a user needed to get to the final correct guess, for the same reason that we have no registers available yet. Keeping track of it somewhere high up in the XYZT stack is possible, but harder to get right than by use of a simple register where we can store and retrieve it at any time.

So here we go again.

4.2.3 A 2020 Rewrite, v2020_2

Ok, so following what has been described in Data Dependencies, we can transform the two sequential loops (one single loop for checking equal positioned and one checking any positioned guess versus secret digits) from

into a single loop (be it two nested ones) to

The modulo function on line L7 is a nice notation, but in HP-15C assembly code, we do not have an operator for that. However since the argument the modulo function is applied to is always between 0 and 2N-2, we can simply test if it is ≥N and if so, subtract N and we come to the same result.

Experimenting in a high level language and getting it right/optimal there and only then translating the guaranteed to work code to assembly is a much better practice than immediately coding in assembly, since debugging a conceptual or other error at a low level just takes 5 to 50 times more time there.

So third time, good time. Here is the result, as anything beautiful and true, in three parts.

MasterMind v2020_2 game program listing. You guess, the HP 15C scores your guesses.

If you’re an assembly genius, you may have mentally parsed the structure out of it already.

For the rest of the attentive readers I explain the main structure a bit, by the figure below. I marked the sub- and sub-sub-sections and added some arrows representing up and down jumps as well as subroutine calls.

Same MasterMind v2020_2 game program listing, but with structure, backward and forward jumps and subroutine calls indicated.

The first orange rectangle asks the user for N (<7), which is the number of digits in the secret and guess words as well as the maximum value of each digit.

The second rectangle, starting at line L018, indicates code that generates N digits between 1 and N and sores this secret in registers R[1] to R[N].

The third rectangle, starting at line L035, lets the user enter his guess (for secret). It’s stored in 1 register (R[.0]) for now.

The fourth rectangle, starting at line L042, takes the user’s guess number from R[.0] and divides it into digits (using Horner’s algorithm), storing them into R[.1] to R[.N]. As such they will be more easily comparable with the similarly stored digits from the secret number in registers R[1] to R[N] later.

Rectangle five, starting at line L072, clears some counters and bookkeeping indices. This has to be done at each new guess the user enters.

Orange rectangle six, starting at line L087, starts the main outer loop. The blue rectangle inside, starting at line L090, represents the inner loop. Inside, there are 7 sections, marked in grey dashed rectangles, which represent:

  1. starting at line L093, represents the second index transformation expression, so the second part of: (j=R[8]=row number, k=( R[.8]=(R[7]+R[8]-1) modulo N(in R[0]) ) = column number). In there the modulo is simplified to subtraction of N (in the called subroutine by GSB .4 on line L101). The test needed for this is (R[7]+R[8]-1) > N, but in the code it is constructed as ([x=R[7]+R[8])] > [y=(1+N)], which is equivalent. Lines L201 to L104 store the transformed value in R[.8]. Note that the first part of the transformation: j=R[8]=row number, needs no code, since R[8] can be directly reused.
  2. starting at line L105, this section is the first of three ‘condition-test and-if-so-skip-(double)-loop-body’ code pieces. Note that the conditions are the negation of the ones in Python, since in the HP-15C code it is the condition for skipping rather than for executing (in Python code) the body code. Skipping happens by GTO (LBL) .2. This first one tests: “if matched_secret[j] != ‘0’ ”.
  3. starting at line L112, this code tests-and-if-true-jump-to-LBL.2 “if matched_guess[j] != ‘0’ ”.
  4. starting at line L120, this code tests-and-if-true-jump-to-LBL.2 “if secret[j] != guess[k]”.
  5. starting at line L136, we have found new matching digits, so we set
    1. matched_secret[j] = ‘1’ :
    getting j by RCL 8 and then STO I and .1 STO + (i) since we keep the matched boolean info as ‘,1’ in the same register as the digit it applies to,
    2. matched_guess[k] = ‘1’:
    getting k by RCL .8 and then 10 +; STO I ‘coz in the guess i.o secret case, we need to store in register 11 to 1N and then STO I and .1 STO + (i)
    3. either c+=1 (L153) if j==k or d+=1 (L154 and L155), otherwise
  6. from lines L157 to L159, we, conditionally on R[.7] being different from 0, will show the j and k indices, so that the user can follow that indices advance first on the main diagonal from 11, 22, 33, … etc and only after that along shorter diagonals parallel to the right of it and then to the left of it.
  7. starting at line L160, we have the end of the inner loop lines, which increment the (untransformed) inner loop variable k in R[8] and jumps back up to LBL 7 to repeat the inner loop body if still R[8] ≤ N or otherwise continues after the inner loop body.
  8. starting at line L167, we have the end of the outer loop lines, which increment the (untransformed) outer loop variable j in R[7] and jumps back up to LBL 6 to repeat the outer loop body if still R[7] ≤ N or otherwise continues after the outer loop body.

The orange rectangle starting at line L176, is the part right after the scoring of the guess number ‘cd’ has been constructed in R[9]. So we construct the answer ‘g,cd ’to be displayed to the user. This happens up to L182. The remaining code compares c to N, and if equal calls the celebration subroutine at LBL .3. To show the answer an extra time. In any case at the end line L193, we do GTO 2 to show the answer to the user at least once there and let him enter a new guess.

A grey rectangle indicates a real subroutine. This is a code piece where we auto-return from by the RTN (return) statement, back to one line after the GSB (go subroutine) call line.

The grey rectangle starting at line L194 is just a wrapper subroutine for the result displaying subroutine with LBL .7. It pulls down the stack and calling the LBL .7 subroutine and then pushes up the stack again. This routine makes that the displaying subroutine can be used in more than one context: showing the end result as such and showing the end result an extra time when guess equals secret, as a small victory-for-guessing-the-secret celebration.

The grey rectangle starting at line L199, is a subroutine called by the modulo calculation used in the loop index transformation. It just decrements the stack x register by N (stored in R[0]), when in adding two indices in the transforming expression, we get a results ≥ N.

The orange rectangle starting at line L203, increments c with 1. Since cd is stored in R[9], this works by adding 10 to this register (10; STO + 9). We jump back to LBL .2, which ends up after the else branch (which does (1; STO +9 to increment d by 1). The condition of the branch selection is j==k, which indeed makes the difference between correctly and displaced digit positions.

The grey rectangle at line L208, constructs ‘jk,cd’, from j via RCL 8, k via RCL .8 and cd via RCL 9. It aligns these three number by the proper by 10, 1 and .01 factors and sums them up. f PSE shows the number for a second. This subroutine is only called in debug mode. Note that the ‘cd’ value is the one being under construction during the scoring algorithm at index-couple step jk. So you can see ‘cd’ evolving as ‘jk’ is making its journey through the matrix indices along diagonals.

They grey rectangle at line L223, shows the number of turns as ‘t,’ and then the guess concatenated with the score as ‘g,cd’, where g is the guessed number and c and d the number of correctly positioned digits and d the number of displaced digits (excluding the correct ones). It assumes that before it’s called, the x register contains the ‘g,cd’ value. The ‘t’ it gets from RCL R[.9].

If you want even more information. Here is the nitty-gritty info spit out by the simulator as HTML documentation. Of course, someone has first put it into the simulator. This information is then stored in the binary of the program itself.

Labels documentation output as HTML by the HP-15C simulator from the binary
Storage Registers documentation output as HTML by the HP-15C simulator from the binary

Here is the usage documentation, also contained in the program binary the simulator stores.

Usage documentation output as HTML by the HP-15C simulator from the binary

4.2.4 A HP-15C Master Minding

Well, we did all this effort. So now, how does this program look in action?

Here is a video of MasterMind_v2020_2 in action in the simulator. Of course it behaves the same as on a physical HP-15C device.

Demoing playing the Master Mind game against the HP-15C Calculator

4 A Machine Memory

In my computational profession (as well as free time :), Google spreadsheets and programming are all the rule. Surely, these are both very ingenious inventions of mankind. So I rarely have a need for a ‘manual’ calculation. Yet, sometimes, in a forlorn weekend, when facing a small calculation job for which a spreadsheet, let alone start coding, is overkill, my deeply rooted HP-15C reflex comes back and I’ll eagerly dig up the thingy from the cupboard.

I’ll remove the black leather cover and try to detect the smell. Hmm, that one has regrettably faded after 33 years.

I’ll press the ON, which, insightfully ¹ ², is the OFF at the same time.

I’ll see the crisp-as-ever letter markings on every single key, none even faded in the least. ³

I’ll be again surprised at the 0.0000 numbers, all coming up in full LCD blackness. Does the battery triplet never die? It’s 25 years now since I last replaced them! The decades long battery life is in fact caused by the extremely low consumption of the HP-15C: only 25mW when used! ⁴

And I’ll again enjoy the general robustness⁵ and the key’s initial solid resistance and the then sudden and satisfactory rubbery haptic — still-gives-me-butterflies — . They all still work after a third of a century! ⁵

To check a tax-inclusive amount from an invoice, I press: 156 ENTER 1.21 x (or, from memory, in program key-positional notation 1 5 6 36 1 48 2 1 20). HP-15C RPN ⁶ … RIP? … Some legends never die.⁷


  1. The more mainstream TIs had a separate on and off button, both of them too light and wiggly.
  2. Someone, much later, was also strongly convinced of the idea that, no two buttons but just one, is required both for switching from off to on and from on to off, simply because the machine knows its own state. This guy even let the two buttons open/close on the door to the cockpit of his private jet replace by one. This guy was Steve Jobs.
  3. My current MacBook Pro has, just like my previous one, 3 fading letter marks after a few months already.
  4. Nowadays an Apple iPhone as well as an Apple watch has to be charged every day! That’s a factor 8900 advantage in number of times to think and act on maintenance!
  5. As for robustness, claims this story about the 12C. “One HP-12C was used by a zoo keeper to calculate feed mixtures. The zoo keeper dropped the calculator and it was consumed by a hippopotamus. The calculator survived the hippo’s digestive process as well as the washing that followed.”
  6. Contrary to that, on a product design of a third of a century later, my previous Apple MacBook ‘Pro’, I had 3, three!, be it free, repairs done on due to failing/loosening ‘butterfly keys’, which includes replacing the glued to the keyboard battery.
  7. In fact, I later learned in Electronics and Computer Science courses about the widely useful concept stack, also called FILO (First In Last Out) in contrast with a queue or FIFO (First in First Out) and realised that RPN implements exactly that. Try to imagine how the calculator matches brackets? Well, that’s via a stack as well, hidden for the user internally! Why not expose it? It pushes a ‘(‘ bracket on a stack and pops the result inside the brackets from the stack when the matching bracket ‘)’ occurs. But in fact, the bracket entry is entirely unneeded and wasteful since by using the operator as a suffix i.o as an infix, the calculator knows the order in which calculations should be performed and the user can dictate that without brackets.
    In fact the bracket obsession originates from overly focussing on the convention how humans traditionally write down expressions, which does not need to be the same as how humans efficiently perform calculations on a pocket calculator. Here is a one pager from HP to show “the RPN advantage”.
  8. Luckily, I seem not to be alone in my admiration for the HP-15C. HP stopped producing it after 10 years in 1992. But even many years later, quite some people were still petitioning HP to “bring back the HP-15C”. In 2011, so 29(!) years after its birth, HP started making a HP-15C Limited Edition version, which come in a nice case with a window, like one would do for a precious precambrian fossil. Only … this fossil from the previous millennium has an ON button that will bring it back to life, guaranteed! They go for around $299,99 on Amazon.


[1] The HP-15C owners handbook.

[2] The HP-15C got to the market in 1982 (the time IBM brought out their first personal computer called the IBM XT).

[3] A collection of programs, entered into the HP-15C simulator software and nicely rendered by it, including care to even stay within the color scheme of the calculator.

To understand in detail the loops index transformations, see my other Medium article at Data Dependencies. The Python code mentioned this article is available as an executable notebook on Github at or as a gist already containing all output at

The HP-15C code binaries of the HigherLower game and MasterMind game are available at Thanks to Torsten Manz.

Peter Sels, May 9th 2020. From a ‘programming-uncle’, to my millennial nephew Edward, whom I hope will still enjoy understanding machines down to the ‘bare metal’.

Copyright © 2020 Logically Yours BV.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store