HP 50g Calculator Programming

1 Introduction

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.

2 User RPL

2.1 Overview 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.2 Higher 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
  |»
  |»

2.3 Use 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»

3 Saturn assembly language

3.1 Overview 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.2 Control 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.

4 System RPL

4.1 Overview 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.2 More 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.3 Programming 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.