HP 50g Calculator Programming

1Introduction

I got another HP 50g calculator. I heard it has an assembler install on the calculator, and it is much fun to program with Reverse Polish Lisp.

Indeed it is fun to play with RPL, but it is a burden to plan ahead the program, with the familiarity of HP 50g's library and the aid of pen and paper it might be easier. To help some new comers who already have plenty of programming experience in Forth and Assembly this article try to provide some quick-start example.

2User RPL

2.1Overview of User RPL

Traditionally Forth uses a separated data stack to handle local variables, while RPL only has one stack. Thus RPL has added the arrow () notation to declare local variables. In fact the notion is similar to the lambda notation in functional programming languages. The language itself is a bit slow compared to the System RPL that will be introduced later, however it is still a powerful language mixing concepts from Forth Lisp, BASIC.

2.2Higher order non-homogeneous differential equation

The original program was from TI BASIC. To be honest (or biased), the CAS of 50g is a bit inferior than Voyage 200.

The idea of algorithm is well known from any differential equation textbook.

This function produces the Wronskian from an input vector of independent terms from a homogeneous solution.

  |« DUP SIZE 1 GET → a s
  |« a 1 s 1 -
  |  START a DERVX DUP 'a' STO AUGMENT
  |  NEXT
5 |»
  |»

You can check the matrix determinant of the Wronskian for a test of existence of solutions.

Then, with the Wronskian as coefficient of the system and the right hand side of the homogeneous equation as inputs, this function produces the coefficient for the particular solution.

  |« 0 → f S
  |« DUP SIZE 1 GET 'S' STO S 1 - 1 SWAP
  |  START 0 NEXT
  |  NEXT f S →ARRY
5 |  SWAP / SIMPLIFY INTVX SIMPLIFY
  |»
  |»

The builtin LDEC can be used for solve non-homogeneous LDEs but the result is complicated because of the method it uses.

2.3Use inverse Laplace to solve initial value problem

The program below generates equation for the left hand side a linear differential equation of numeric coefficients, taking the list of coefficients from higher power to lower and initial values of the form { f ( 0 ) , f ( 0 ) , } .

  |« → c s
  |« 'F' 1 s SIZE
  |  FOR i
  |    'X^n' 'n' i 0 1 NEG SEQ
5 |    { 'F' } s 0 i SUB NEG + * ΣLIST
  |  NEXT
  |  c SIZE →LIST REVLIST c * ΣLIST
  |»
  |»

The second part solves the equation by applying inverse Laplace.

  |« SOLVE EQ→ SWAP DROP ILAP»

3Saturn assembly language

3.1Overview of Saturn assembly

At the first glance Saturn does not even look like assembly languages we would typically see today. It is more like so called "structured programming language". Well, there are examples from structured low level programming languages like PL/360. And although feels like 16bit computers, the registers are actually 64bits with BCD arithmetic support!

The HP50g ROM is running on the Saturn processor emulated on top of the ARM chip, so even the assembler supports embedding ARM assembly, interfacing the calculator stack is still done via Saturn machine language.1

3.2Control the buzzer

It is surprising that HP50g is with a speaker that is capable of producing complex sound. The BEEP command accept the first integer as the frequency in Hz and second float number as time in second.

In this section we will use the source file from qmc program on hpcalc.org as an example to demonstrate how to control the buzzer from Saturn Assembly.

   |SAVE                                                       
   |LC 0DF                                                     
   |LA 0006B                                                   
   |B=C.X  D=C.X
 5 | { LC 800  OUT=C                                           
   |   C=0.X  OUT=C
   | 
   |   { B-1.B  UPNC }
   |   C=D.X  B=C.X
10 |   A-1.A  UPNC }
   |LOADRPL                                                    

Save registers.

Pitch. 0DF is 233.

Length that will be used as loop counter.

Beginning of the loop, UPNC return up to the start of the brace. OUT=C will control the buzzer.

In pair with SAVE. Restore registers.

Entering the above program into a string, push to the stack, and call ASM from library 256. Store the result to a variable then you may recall the program from soft menu.

Unfortunately, the buzzer cannot be emulated by the ARM based calculators like 50g.

4System RPL

4.1Overview of SysRPL

Actually there is no fundamental difference between User System RPL as every User RPL is tokenized to a subset of System RPL after editing2. It is just that System RPL can access more internal features and does lesser safety checking, so it is not available to user by default to avoid causing damage to data.

As I have mentioned, System RPL is still running on top of the Saturn emulation layer for ARM based HP49 calculators, and a System RPL program is directly assembled to series of Saturn instructions.

4.2More buzzer

This simple program makes 4 beeps of different pitches.

  |::
  |  1200 440 1300 550 1000 470 1300 750
  |  4 #1+_ONE_DO setbeep LOOP
  |;

4.3Programming using PC

There is a set of tool chain that allows user to create System RPL/Saturn Assembly program and libraries on desktop computers. Unfortunately, ARM Assembly is not supported by this method.

This time we will create a bit more complex buzzer program with HPTools.

  |muse ( $ -> )

This program will convert each character in a string to a pitch and play it.

   |* Synth some music ( $ --> )
   |ASSEMBLE
   |        NIBASC /HPHP49-C/
   |RPL
 5 |::
   | CK1NOLASTWD
   | CK&DISPATCH0 str
   |  ::
   |   DUPLEN$ #1+_ONE_DO (DO)
10 |    DUP INDEX@ SUB$1# 48 #-
   |* n^(2/12)
   |    UNCOERCE %2 SWAP %^ %12 %1/ %^
   |    130E0 %* COERCE
   |    500 SWAP setbeep
15 |   LOOP
   |   DROP
   |  ;
   |;

The string HPHP49-C specify the ROM version of the target. In fact the final output produced by sload is a bare binary, that is a file only contains the machine code without any linking/loading format.

To compile this file to a standalone program, this example Makefile can be used:

  |all: muse
  |%.a: %.s
  |     rplcomp $< $@
  |%.o: %.a
5 |     sasm $<
  |muse: muse.o
  |     sload -H muse.m

Where the content of loader instruction muse.m is:

  |TITLE Muse
  |OUTPUT muse
  |LLIST muse.lr
  |SUPPRESS XREF
5 |SEARCH SUPROM49.o
  |REL muse.o
  |END

The SUPROM49.o is the entry table list created by running sasm assembler on the corresponding SUPROM49.a.

4.3.1Calling CAS functions

To handling ZINT objects, the functions provided by CAS in the form of flashpointers and their names are prefixed by ^, for example ^#>Z. On MASD the syntax for calling flashpointers is FPTR2 ^label, while RPLComp from HPTools uses a different syntax FLASHPTR label (note the ^ is omitted).

⚡︎
Warning

Do not call flashpointers directly, the assembler would not produce error message on such case but running such program would crash your calculator.

5Miscellaneous

5.1Step function in Laplace

It is common to have Laplace transform on step-wised functions. Although it is not explicitly mentioned in the manual, and the corresponding section from user manual is vague on that, 'Heaviside(X-1)*(X-1)' LAP for example works well.