Ease/Dis-ease of Keystroke Programming


I know some would say our obsessions with calculators is evidence that our minds are a little "diseased".

That has certainly been true of me for the last couple of weeks. I have been caught and held hostage by a little electronic/mechanical device known as an HP-42S. I have been so enchanted with the little beast, that I have cranked over 1000 lines of calculator language in pursuit of the perfect embodiment of "YATZ," the game I use as a vehicle for learning about programming the old machines in my collection. It's certainly arguable whether I need so many lines to play that stupid (but fun) little dice game. But I want to use the features of each platform to the fullest extent possible. On the 42S, that means graphicl representations of the dice and scorecard, and that means lots of binary data. The initialization routine (not run every time) therefore takes over five hundred lines all by itself. The core of the game is currently at 530 lines or so, and will go higher before I'm through.

At that level, I've run into some scalability problems that I thought I'd share with this forum. Before getting into these, I have to praise the ergonomics of the 42S again. Program entry is very nice on this machine. The keystroke sequences you need in order to access common programming, matrix manipulation and alphanumeric functions is very regular and logical. It usually takes two to three keystrokes at worst to access the function you need.

The pickboard style of alpha entry is an example of this. Press [SHIFT] [ENTER] to get to alpha mode, or enter it via any function that can use or requires alphanumerics, and you see a menu of the uppercase alphabet spread over six keys. To get an upper case letter, press its menu key, then the key for the letter - two keystrokes. To get lowercase, press shift (orange key) before you press the letter key - that's three keystrokes. Since there are 6 menu keys and at most five letters per alphabet range, there is always a blank key in the letter pick menu. Pressing these always gives you a space. Less common letters are accessed from a secondary menu which you get to by pressing an arrow key at the main pick-board. You still only have three keystrokes on average, but it's not as straightforward and takes a little longer.

That lash up is a little awkward to describe but a breeze to use once you learn it. In fact. I find it to be the easiest system for alpha entry I know of, second to the qwerty keyboard that is burned into my synapses by a lifetime's use. The rest of the functions of the 42S are similarly well thought out, and I find I can crank code on the machine at nearly the speed of (careful, deliberate) thought.

But what I can't do is keep more than about five numeric labels and their meanings in my mind while I'm thinking about how to do some tricky piece of coding. Four labels I can manage, but five blows me out of the water. This is partly because numbers are not names, and partly because I can see at most two lines of code at a time in the calclator's display. "But the 42S has six character named labels!" I hear you protest. Yes. but multicharacter labels (and single character ones after "J") are global on the 42S. This means that after a certain point, they clutter up the XEQ and GTO menus to the point where the nice, easy structure is overwhelmed. In a program the size of YATZ42, however, numeric labels just don't cut it. So I've replaced many numeric labels with alpha globals. I may switch them back after I have the whole thing debugged.

A related problem has to do with the limited window on the program provided by the two line display. Often one section of code depends on one or more widely seperated other bits of code. You can't see the two sections side by side in that two line window. These all conspire to make that sort of coding difficult. I've adopted two different strategies for dealing with this. When the program was smaller, I would print it out to an HP 82240B printer. That was slow, but it worked. Since the program has grown larger, I've tended to print to INPRT running on an HP48GX instead. This is much slower, and requires extra transfer and conversion steps to get a listing in a form in which it can be viewed in an editor on the PC screen. Then, as I make changes, the version on the calculator and the one on the PC drift slowly apart, until the work of remembering which changes I've made recently exceeds the inconvenience of generating a new listing.

Finally, there's the fact that data - variables, registers, flags and the stack - are all global on the 42S. This makes it harder to have two significant apps loaded at the same time without collisions. I know the registers are accessible in a matrix called "REGS." and that you can rename and replace this matrix, thus giving you a way to implement local registers. But that doesn't work for named variables or the stack, and what if you bomb having made your local copy of REGS? There's no ON ERROR construct.

So there you have three barriers to scalability of keystroke programs on the HP42S. There are workarounds for some of them, but no outright solutions. Clearly, the machine wasn't designed to scale up very far. The programming model was born on smaller machines, and makes more sense when applied to smaller problems. But that raises an interesting question: is there value in extending keystroke programming to larger environments, meaning ones with a lot more memory and processor speed? It seems certain to me that just dropping the 42S environment down in the middle of such resources would be a dismal failure. The language and architecture would, at the very least, have to change to account for the deficiencies outlined above.

What sort of changes do you think might be necessary to acheive success in the larger environment? Here's my list:

  1. Real local scopes - local names should be possible, for labels variables, stacks and so forth.
  2. Two-way I/O - this to facilitate program editing off the calculator. Bonus points: make program editing on the PC transparent through to the target machine.

That's it. The points, few as they are, beg another question: how can you implement them without screwing up what is nice about keystroke programming? This is really the original question restated: whether keystroke programming can be scaled up at all, or should,


Edited: 30 Dec 2005, 2:26 p.m.


i agree with your sentiments regarding the scaling of keystroke programming. indeed, it’s a fast way to get results for short and easy to hold in one’s head sort of problems. but as the program gets larger, its gets nastier. as the program gets bigger i am forced to factor it into separate programs. even if this means loss of efficiency simply because otherwise it will go out of my control.

whilst writing large or moderate but tortuous keystroke programs, i have often yearned for some kind of higher level abstraction. i like to make an analogy between keystroke operations and assembler level programming; just like they were the machine instructions of a much larger architecture. it would be nice to have a sort of mini compiler that could take chunks of logic and generate keystroke ops.

when i say a compiler, i don’t mean ‘C’ into 42S or visual basic into 41c, this would be completely inappropriate. i think to some extent hp attempted this idea with the concept of RPL, although it didn’t compile into keystroke ops because really there wasn’t much point. but i don’t think the rpl experiment solved the problem, because pretty much the same difficulties arise when dealing with large rpl programs as do with large keystroke ones, albeit not quite so acute.

rather than a true compiler, i am hankering for some kind of macro processor and code block re-arranger. something that looks after the flow and allocation of real memories and lets me program in virtual ones. that also eliminates superfluous usages and overlaps true memories with virtual ones by scope analysis. i just want to think of each logical variable as a new name and have it allocate them to actual registers in an optimal way.

for block arrangement, i'd like to be able to rearrange blocks of code (ie segments of logic with no jumps out or into) so that i can tidy the program out of an increasingly spaghetti bowl of logic – and if that means reallocating the real vs virtual registers then, so be it!

the other idea would be to program in either a pure stack machine or a pure register machine (eg virtual register again) and have it transform into the ideal mixture of both for a given stack depth (eg 4). the hp keystroke programming paradigm is a strange mix of both. you keep stuff on the stack until you can’t, at which point you use registers but as few as you can get away with. then, a bit later, you need to change that bit of code, but all of a sudden, the bit of cleverness you did on the stack won’t fit on the stack anymore and you have to find a spare register to accommodate it, often knocking your allocation plan out of kilter. no, all of that should be done for me so i can concentrate on the algorithm itself.

that's what i want anyway :-)


Gents, I thought that RPN keystroke programming WAS INTENDED for simple quick programs; I haven't mastered RPL, but have gotten somewhat familiar with it and it seems to be better suited for larger, more complicated programs with more diverse routines.

Besides, RPN scientific programmables (most of our beloved HP vintage calcs) don't have the program memory capacity or data storage capacity for any programs requiring a bit complexity.

I wrote a program that would analyze any number of peaks from a x-ray powder pattern for my 48G series and 49G+ machines. For convenience' sake, I tried my hardest to port it to the 33S without loss of functionality, but because the program really taxed the capabilities of the 33S (four level only stack, twenty-six labels and twenty-six [and a half ;) ] registers, I limited the 33S version to only THREE data point inputs (as you said, so I didn't go crazy trying to track all the inputs and results as I wrote it)... plus a bit of revision of the program structure to adapt it to a limited stack depth and limited number of data registers. I think this 33S RPN keystroke version might even be a bit longer and slightly more complex than the original RPL version!!

(Off-Topic Department: as it turns out, the revised 33S version is all I need so far, but I can see easily that I might soon need the less limited version.)


Hi, Ed,

I think there's a bit of context missing. I'm thinking of the OpenRPN project, which has produced this PDF file of what they call a "IQ-43S" (IQ being like HAL in 2001, only backwards, er, forwards.) The "43S" part refers to the idea that this machine will be a succesor to the last great RPN keystroke programmable calculator: the HP-42S. The hardware feature set that project is developing include an ARM processor running at 80 MHz, 16MB of flash ROM, and 1MB of SRAM. This puts it in the ballpark I was describing in my previous post.

So yes, RPN keystroke programming grew up to solve smaller problems with shorter code. When William Wickes got a look at the problem of scaling it up, he chose instead to jettison the old programming model and helped to create RPL, a revolution in calculator design. A lot of folks feel something was lost in that transition. If you ask the average devotee of RPN keystroke programming, I suspect that simplicity would be high on the list of qualities they would list as lost in the transition to RPL. What I'm interested in is the question of whether this simplicity was solely due to the smaller problems tackled with RPN machines as compared with the RPL family, or if there were inherent simplicities in the older model that went out like the proverbial baby in the bathwater. I actually think that some baby did leave the scene, along with the admittedly murky bathwater.



Hi Howard,

so far I didn't know this German proverb also exists in English, so thanks for enlightenment!

Back to your topic: I fully agree on "something" being lost in translation, ummh, transition from RPN to RPL. Remembering the old manuals, programming was always explained in the very beginning as a simple way of storing keystrokes and recalling them later for repeated execution. I do not remember such an approach in the documentation of the 48s or 48g.

The point where RPN programming became awkward to me (pretty early) was with the loop control commands like ISG et.al. This was although I did a lot of (pdp) assembler programming at that time. I found the ISG-syntax difficult to remember and read correctly if not used everyday. In fact, I didn't write real programs on my 25c, 11c and 32s, but coded formulae for frequent use (most times).

Since I also own a 42s, I share your views you stated in your initial post. IMHO, RPN is great even/still today for straightforward automation of calculations, but it falls short in structures. Of course this is less important if you have just 100 steps available, but with 7200 it's a challenge. It reminds me of the FORTRAN (sic!) IV spaghetti code my professor used to write, with GOTOs in either direction - almost unreadable and eventually uncontrollable.

So, besides the 2 way I/O inevitably needed to enjoy comfortable editing in a PC, what about adding some (few!) structure commands like IF...THEN...ELSE, BEGIN...END, FOR...DO and the like (a bit like PASCAL)? To me, there is little to be added to create a new baby capable to win a triathlon. And to baptize it, swimming in the bathwater, I propose to call it RPS (RP Structured) d;-)


After months of programming RPL, I went back to pure RPN (41CX) because of what I perceive as a better programming environment. More direct access to the programming features and better debugging facilities was on top of the list. If only the HP-48 had keystroke programming, I would be in heaven.

As for the scalability, I would rather write a 1000 line program in pure RPN than in RPL. Maybe even more (I have an almost complete gladiator game for the 41 with more than 1800 lines).

For the OpenRPN project I would suggest to go with a combination of keystroke RPN and floating point Forth. That would do the trick for me. Rather than reinventing the wheel, Forth would give what RPL has, only better; Better managability of code through Lego-type building blocks, direct feedback on code execution (even the smallest parts, not just the whole program or a less-than-desirable SST), direct access to assembler coding, build-in editor (this should be improved from what most Forths have to offer) and an array of existing commands and building blocks to start off from.

Just my 2 øre (NOK 0.02)


So, besides the 2 way I/O inevitably needed to enjoy comfortable editing in a PC, what about adding some (few!) structure commands like IF...THEN...ELSE, BEGIN...END, FOR...DO and the like (a bit like PASCAL)?

You know, I thought about this for a while, and my conclusion was: why bother with the calculator? If you've got to use the computer to write and pre-process the program, why not use it to run the program as well?

I think if you're reliant on a computer for writing/editing the program, it rules out use of the calculator for those "exploratory" tasks that are often solved by keystroke programming. It relegates the calculator to programs that are used repetitively, perhaps in the field (not that there's anything wrong with that).

I've been investigating this area for myself, specifically looking at the use of a calculator as an aid to understanding simple physical problems (based on the mass on spring problem [dv/dt = -x] in Chapter 9 of The Feynman Lectures on Physics). Feynman himself takes a numerical approach to the problem, which I had only minimal difficulty in implementing in Perl and on the HP-41, but I haven't yet come up with a numerical solution on the HP-48GX. On the other hand, solving (and graphing) a differential equation is simplicity itself on the 48 - but I think one learns more from the programming exercise.

I'm part-way through writing this up, complete with listings. Just a few more days. . .


--- Les



Meanwhile, I found there is some structured control flow for RPN available already. MathU has IF-clauses and loops in its command set. Plus some additional stuff like ELSE and CONTINUE IF. Anyone here knows how they work exactly?

(Maybe it is explained in their documentation, but if you know it by heart you will be faster by far - and I do not have to search and read it all ;-) )

Edited: 5 Jan 2006, 1:01 p.m.


Hey, Howard, thanks for the clarification. It stinks to be shooting n the dark!

But in response to one of your questions (rhetorical??) I suspect that in those days, the '70s, the engineers who built the HP RPN calcs and the engineers who used them, along with the scientists, surveyors, programmers, accountants, managers, etc., probably DREAMED of having a simple keying interface yet providing powerful programming capabilities, but were limited by the technology available at the time due to the position of the cutting edge then or due to budgetary constraints.

I mean, how were they going to stuff more labels and registers on a breadboard 2.5" x 5"? Thus, I guess, this imposed natural limits as to the scope of problems it can be programmed to solve.

As to the Open RPN project, I hope I can afford whatever they end up with!


Hi, Ed,

I do think the RPN models did an awful lot with very little. Very little memory, very little processor speed, you name it. I also agree that the keystroke calculation programming model was designed to fit into this limited environment. Perhaps it isn't possible to remedy the scalability problems without erasing the nice things about RPN programming.

There have been several good suggestions, but mine included, they all tend to move the computation away from "nose-to-nose" interaction with the problem. That is to say, they all add abstraction to the model, which is the way to get generality. Add real scope to names, and you get better separation between the solution and the machine. But you have to know the scoping rules, and in particular, how they impact the limited resources a calculator provides.(Presumably without virtual memory! 8) Add real looping structures, and you start to want fancy indenting to reflect them. That means more overhead for the program editor. Program editor? Oh, you mean "program mode!" Well, no, I mean a real editor. More abstraction. At a certain point, I join Les in wondering what the calculator is doing in the mix at all.

So what about this: implement a very fancy, sophisticated programming model for those who want to do real computer science, functional programming, object oriented or what have you, but include as part of that environment a virtual RPN machine model. Define a flexible way to interface with this virtual machine, probably using an unlimited stack, and call the calculator to solve problems in the traditional RPN way.

-> [[
\\stack_size=2 \\stack_grow=fixed
\\regs=-1 \\result=X
01 X^2
02 X<>Y
03 X^2

Or something like that. The wrapping around the virtual RPN calculator would be visible or not as the user chose. In other words, the machine could look like a traditional RPN calculator, with lots of memory and nice support for engineering, scientific and business math, large conversion, constant and formula libraries and so forth. Or it could look like a mega-killer-über-calculator With RPFoS (Reverse Polish FORTH on Steroids). with all those features. Or it could look like both at the same time!

This solves the problem of complexity in the traditional geek way: by adding more. 8) Actually, the trick would be in engineering the environments so they were logical and self consistent when used seperately, but also when used together. That ought to mean that they'd be as intuitive and simple as possible, too.



Howard Owen wrote:

-> [[
\\stack_size=2 \\stack_grow=fixed
\\regs=-1 \\result=X
01 X^2
02 X<>Y
03 X^2

I realise that this is a hypothetical example, but if it was intended to be a Pythagorean hypotenutical hypothetical example, shoudn't line 04 be "04 +", then "05 SQRT"? See what happens when all that abstract fancy stuff enters the picture?



--- Les



Doh! 8)

But finding the error would have been much simpler for the dunderhead RPN-prejudiced author. 8)


Nice idea! And, I hope it can get implemented in some new ROM upgrade or compact, downloadable "library" or "aplet" written by one of us fanboys for the 48 and 49 series machines.

But one small aspect of it makes me wince:

it recalls to mind the use of DOSBOX or MO'SLO or some such Rube Goldberg type forced backwards compatibility device to make a Pentium IV or Athlon machine running WinXP able to run some old DOS program (read, most of the the time anyway, game [I do have one old DOS based plotting and fitting program some physicist wrote in-house over a decade ago, which I really liked]<-{--- self exculpation device}).

So, if you guys, or anyone ever does implement this, in itself, rather neat idea, I'd really rather prefer it to be seamless as the default mode, so as not to evoke some inaccurate "legacy" image of RPN keystroke programming, of which obviously I am fond!

Edited: 3 Jan 2006, 12:27 a.m.


Right, that's a bad connotation of "virtual machine." That was probably a bad choice in words not just because of the connection with old, slow legacy environments, but also because you wouldn't need a full-blown VM to do what I have in mind. My idea was to limit the RPN program from seeing more of the calling environment than it was explicitly allowed to. But there are lots of mechanisms for doing that sort of thing that don't involve creating byte code for an idealized processor the way Java does. I'd like the RPN environment to be capable of managing all the calculator's resources, at least to the degree the "whiz-bang" environment was. So one environment could call the other, or relinquish control of the complete machine to the other, with equal ease. There might well be a good reason to stick with one or the other for a particular problem, but it should be at least possible to do anything in either environment. They would have to be compatible, or have compatible glue, at least.

For example, if the "über" environment were RPL, then you would have to deal with the unlimited stack, and with how RPL consumes arguments placed on the stack. My example tried to show how that could work:

<< ..
-> X Y [[ # Two elements from the RPL stack are consumed
# and placed on RPN stack levels X and Y
\\stack_size=2 # "pragma" states only two stack levels
# needed.
\\stack_grow=fixed # Perhaps this is the default.
\\result=X # Single value returned in X. The
# glue will put this on the RPL stack
# level 1 on exit
\\regs=-1 # Signifies no registers used. This means no
# registers or other memory are visible to this routine.
01 .. # Correct Pythagorean thing here .. 8)

The \\regs pragma could be a lot more elaborate, mapping data structtures on one side to the other. It could be so elaborate that you might wish to maintain it outside the call preamble, and just refer to it there.

The stack pragmas allow you to have any sized stack, including an unlimited one, in your RPN program. The default for the RPN side would be a classic XYZT and L arrangement. This stack would be separate from the RPL stack, and it would have genuine RPN semantics. It would copy the top element down on stack drop, and it would allow you to drop an empty stack position. It could however contain the full bestiary of objects supported by he RPL environment. That's the default, but pragma's could enable lots of alternate stack behaviors in the local environment, according to the needs of the calculation, and/or the taste of the programmer.


So a macro facility, sort of like a macro assembler would work? Interesting idea.

Possibly Related Threads…
Thread Author Replies Views Last Post
  Most usable keystroke calculator? Sid Cave 32 7,291 01-07-2012, 03:49 PM
Last Post: Lutz Jacob
  Ren, you asked for keystroke calculations designnut 0 731 03-07-2009, 12:24 PM
Last Post: designnut
  HP 35s ENTER and keystroke skipping Luis Moreno 12 2,010 11-01-2008, 03:40 PM
Last Post: Brian Healy
  Keystroke Intensive Casio Hal Bitton in Boise 2 1,032 03-25-2008, 04:14 AM
Last Post: DaveJ
  HP-10 Dis-assembly Jeff Davis 2 1,141 03-24-2008, 09:20 AM
Last Post: Jeff Davis
  Keystroke programming worksheet Martin Pinckney 5 1,574 11-15-2007, 12:24 AM
Last Post: Forrest Switzer
  Keystroke Programming and Stacks DaveJ 14 3,402 09-10-2007, 02:57 PM
Last Post: Namir
  Keystroke recording on 50G (quite long...) Giancarlo (Italy) 0 657 02-27-2007, 09:53 AM
Last Post: Giancarlo (Italy)
  HP 50g Delayed Keystroke Paul 3 1,172 11-29-2006, 12:51 AM
Last Post: Tim Wessman
  HP-33s keystroke encoding and checksums [long] Ivan Nejgebauer 12 2,924 06-19-2006, 10:00 AM
Last Post: Eric Smith

Forum Jump: