HP-28 Utilities


by Eric L. Hernes I., hernes@plains.nodak.edu

This file contains the format of my hp-28. This setup is the result of a
eagerly awaited 'memory lost'. The directory structure is basically the same
as what has been described here by a number of people. My two most
significant modifications to this system are (1) the use of 'weird' names
and (2) the use of a '.profile' for each main directory. The philosophy
behind the use of 'wierd' names is that the commonly used directories and
custom menus will be available with as few key presses as possible, and
most of these keys will be as close together as possible. For example, to
get to the main directory it's custom menu of subdirs and procedures you
only need to type '.' (plus enter). The reason behind the use of a
'.profile' for each subdir is so that different directories will have
different modes. For example if I am in a 'hacking' directory, I want to
be in custom-menu-mode, but if i am in an engineering directory, I want to
be in letter-mode.

Last fall I discovered how to use SYS to create 'weird' names such as '.'
and '..'. I never found time to write a program to totally automate this
process, but Craig Lien did, he will probably be posting most of his hacks
later this week.

The directory structure is as follows:

HOME ==> contains system stuff
|
..1 ==> contains more system stuff
|
..2 ==> contains the calendar/time stuff
|
..3 ==> contains the math stuff
|
..4 ==> contains the .commands/menus
|
`5
_________________________|_______________________________________
| | | | |
.econ .engin .rolodex .graf .hack
| | | | |
`econ `engin `rolodex `graf `hack
________________|________________
| | | | |
.optics .emag .circuts .comm .electronics
| | | | |
`optics `emag `circuts `comm `electronics

HOME contains the following:

mem-> :(procedure) recalls the current directory recursively
displaying the all objects and their names.
(Written by Craig Lien)

.profile :(procedure) contains the main profile for the hp.

CM :(list) contains the objects that will appear in all of the
custom menus.

`5 :(procedure) follows the path to go to the main directory.

..1 :(subdirectory) HOME's only subdirectory.

. :(procedure) pseudo-alias to `5

OFF :(procedure) puts the hp into 'SLOW' mode then powers down
goes into 'FAST' mode when turned back on

SLOW :(procedure) the complement of 'FAST'

FAST :(procedure) speeds up the hp described in numerous places

SPEED :(procedure) adjusts the speed of the hp.

.P :(procedure) returns the name '.profile' on the stack to allow
you to visit, recall, or purge the current '.profile'

moff :(procedure) takes the hp out of menu-mode.

mon :(procedure) puts the hp into menu-mode. The MENUS_on syseval
listed by Eric Toonen, should really read MENUS_toggle.

.A :(procedure) a pseudo-alias to go to '..1'

RCLD :(procedure) Alonzo's recall directory

S->O :(procedure) Craig Lien's string to name (object)

O->S :(procedure) (object) name to string

dopath :(procedure) traverse a path

ND :(string) suffix required for S->O
ND is made up of the characters whose ascii values are:
# 90h # 2Fh # 0h

BG :(string) prefix required for O->S
BG is made up of the characters whose ascii values are:
# 96h # 2Ah # 20h # D1h # 2h
where,

| 'mem->' is: | '`5' is: | '.A' is:
| << PATH DUP SIZE GET | << { HOME ..1 ..2 ..3| << ..1 .profile
| ->STR "BEG - - " + | ..4 `5 } dopath | >>
| VARS { } -> O M | .profile |
| << O " - - - - - " | >> | 'RCLD' is:
| IF O SIZE | | << DUP DEPTH -> d
| THEN 1 O SIZE | '.' is: | << # 1E737h SYSEVAL
| FOR J O J GET | << HOME `5 | DROP
| DUP | >> | IF DEPTH d ==
| IFERR RCL | | THEN SWAP DROP
| THEN DROP M | 'OFF' is: | ELSE RCL
| + 'M' STO | << SLOW # 18E58h | END
| END | SYSEVAL FAST | >>
| NEXT | >> | >>
| WHILE M SIZE | |
| REPEAT M DUP 2 | 'SLOW' is: | 'S->O' is:
| OVER SIZE SUB 'M' | << # 0h SPEED | << ->STR PATH SWAP BG
| STO 1 GET -> DD | >> | OVER SIZE CHR + SWAP
| << DD EVAL | | + ND + HOME 'AbC'
| mem-> DD ->STR | 'FAST' is: | DUP PURGE STO
| " - - END " + up1 | << # Fh SPEED | # D0000h AbC SIZE 2
| >> | >> | * - SYSEVAL 1 GET 1
| END | | ->LIST LIST-> DROP
| END | 'SPEED' is: | 'AbC' PURGE SWAP
| >> | << RR RL | dopath
| >> | System Object | >>
| | >> |
| '.profile' is: | | 'O->S' is:
| << CM MENU | '.P' is: | << # 4567h SYSEVAL
| >> | << { .profile } 1 GET| >>
| | >> |
| 'CM' is: | | 'dopath' is:
| { `5 ..1 } | 'moff' is: | << # C784h SYSEVAL
| | << # 186BDh SYSEVAL | >>
| | >> |
| | | 'ND' is:
| | 'mon' is: | *see above*
| | << # 186BDh SYSEVAL |
| | # 186ACh SYSEVAL | 'BG' is:
| | >> | *see above*


Directory '..1' contains the following:

RPG :(procedure) recursively purges the current directory and all of its
subordinates.

.profile :(procedure) default profile for all subdirectories.

..2 :(directory) ..1's only subdirectory.

cm :(list) the objects that are specific to ..1 that will appear in
the custom menu.

HIDE :(procedure) moves a stored object up one subdirectory. Does
not work on subdirectories (yet).

CM. :(procedure) calls up the custom menu for the current directory.

CM :(list) portion of the custom menu that will appear in all
of the following custom menus.

MKDIR :(procedure) makes two subdirectories, one of which is
pseudo-hidden.

up1 :(procedure) moves to the current parent directory.

->CM :(procedure) adds a name to the current custom menu.

.. :(procedure) moves up to the next non-pseudo-hidden directory.

[mu]os :(procedure) calls the custom menu for the
pseudo-operating-system.


| 'RPG' | 'CM.' | '->CM'
| << VARS -> z | << cm CM + MENU | <<
| << 1 z SIZE | >> | IF VARS 'cm' POS
| FOR x z x GET | 'CM' | THEN cm
| DUP | { FAST OFF [mu]os } | ELSE { }
| IFERR PURGE | 'MKDIR' | END + 'cm' STO
| THEN EVAL RPG | << -> n | >>
| up1 | << "." n + S->O DUP | '..'
| END PURGE | CRDIR "`" n + DUP | << up1 PATH DUP SIZE
| NEXT | " .profile >>" + STR-> | GET O->S 1 1 SUB
| >> | OVER S->O STO SWAP | IF "." ==
| >> | EVAL S->O CRDIR up1 | THEN ..
| '.profile' | >> | ELSE .profile
| << mon STD CM. | >> | END
| >> | 'up1' | >>
| 'cm' | << PATH 1 OVER SIZE | '[mu]os'
| { `D } | OVER - SUB dopath | << { MKDIR ->CM CM.
| 'HIDE' | >> | HIDE O->S S->O } MENU
| << PATH SWAP DUP RCL | | >>
| SWAP DUP PURGE up1 | |
| STO dopath | |
| >> | |

Directory '..2' contains the following:

All of this stuff was previously posted by assorted authors.
Strauss Erez wrote this implement of the perpetual calendar

I believe that Eric Zmyslowski wrote the rest of the stuff here.

MTHLST
NDAYS
PCAL :(procedure) the main program, calles everything else
DAYS
DOW
CJ
LDISP
KEYS
procs
KY
->in
MTHS
..3 :(directory) ..2's only subdirectory.

| 'MTHLST' | 'NDAYS' | 'KEYS'
| << RCLF STD -> f | { 31 28 31 30 31 30 | { "UP" "DOWN" "STO"
| << DUP FP SWAP IP | 31 31 30 31 30 31 } | }
| DUP | |
| IF 100 < | 'PCAL' | 'procs'
| THEN 1900 + | << FAST MTHLST 0 SWAP | >>
| END SWAP 100 * | 1 LDISP | << 1 +
| SWAP -> mm yy | DO KY | >>
| << yy mm 1 DOW | IF KEYS SWAP POS | << ROT DROP 1 3 ROLLD
| DROP -> dow | DUP | >> }
| << " " -> s | THEN 'procs' |
| << { } s MTHS | SWAP GET EVAL | 'KY'
| mm GET + " " + yy | ELSE DROP | <<
| ->STR + s + + | END LDISP | DO
| " S M T W R F S" | UNTIL 3 PICK | UNTIL KEY
| + -> ml | END DROP DROP DROP | END
| << "" | CLMF | >>
| IF dow 0 | >> |
| != | | '->in'
| THEN 1 | 'DAYS' | << DISP 1 40
| dow | { "Sun" "Mon" "Tues" | START KEY '->in'
| START " " + | "Wed" "Thur" "Fri" | IFT
| NEXT | "Sat" } | NEXT
| END | | >>
| END 1 | 'DOW' |
| NDAYS mm GET | << CJ 1 + 7 MOD DUP 1 | 'MTHS'
| IF mm 2 | + DAYS SWAP GET | { "Jan " "Feb "
| == yy 4 MOD 0 == AND | >> | "Mar " "Apr " "May "
| THEN 1 + | | "June" "July" "Aug "
| END | 'CJ' | "Sept" "Oct " "Nov "
| FOR x | << | "Dec " }
| " " + | << 2.85 - 12 / + |
| IF x | >> -> y m d yp |
| 10 < | << 367 y m yp EVAL |
| THEN | * IP y m yp EVAL IP |
| " " + | - .75 y m yp EVAL IP |
| END x | * - d + IP .75 y m |
| ->STR + | yp EVAL 100 / IP * - |
| NEXT DUP | IP 1721115 + |
| SIZE -> dl s | >> |
| << 0 s 21 | >> |
| / IP | |
| FOR x | 'LDISP' |
| ml dl x 21 * 1 + DUP | << DUP2 OVER SIZE -> l |
| 20 + SUB + 'ml' STO | i s |
| NEXT | << |
| ml " " + | IF i 3 + s >= |
| >> | THEN 1 - DUP 'i' |
| >> | STO |
| >> | END l i GET 1 |
| >> | DISP l i 1 + GET 2 |
| >> f STOF | DISP l i 2 + GET 3 |
| >> | DISP l i 3 + GET 4 |
| >> | DISP |
| | >> |
| | >> |


Directory '..3' contains the following:

The Fraction program is a combination of a couple of
programs, one was written by Thomas Affinito, the
other was written by Jurjen N.E. Bos.

The D[pi] and the DSQ programs were written by
Wayne Scott.

I cannot remember who wrote 'line' and 'PLANE', but
it wasn't me.

Fract :(procedure) turns a decimal into a fraction.

D[pi] :(procedure) takes a factor of pi out of a number.

DSQ :(procedure) puts a number in terms of n*sqrt(m).

fact :(procedure) factors a number into a list of prime factors.

line :(procedure) takes two points and calculates the equation
of the line between them.

EXCO :(procedure) from TFM.

IRT :(procedure) is used by DSQ.

POLOP :(procedure) performs addition, subtraction, multiplication,
or division on two polar numbers (phasors).

plane :(procedure) takes three points and calculates the equation
of the plane through them.

fr1 :(procedure) is used by Fract.

fa1 :(procedure) is used by fact.

MULTI :(procedure) from TFM.

| 'Fract' | 'EXCO' | 'plane'
| << fr1 "'" ROT ->STR | << FAST | << -> a b c
| "/" + SWAP ->STR + | << EXPAN | << a b - a c -
| "'" + STR-> | >> MULTI | CROSS a ARRY-> DROP ->
| >> | << COLCT | x0 y0 z0
| | >> MULTI | << ARRY-> DROP -> p
| 'D[pi]' | >> | q r
| << 3.14159265359 / | | << 'Z' r * 'Y'
| fr1 SWAP '[pi]' * SWAP| 'IRT' | q * + 'X' p * + x0 p
| / | << | * y0 q * z0 r * + +
| >> | IF DUP 1 != | -
| | THEN fact -> a | >>
| 'DSQ' | << 1 | >>
| << DUP SIGN SWAP ABS | IF a SIZE 1 > | >>
| SQ fr1 SWAP IRT SWAP | THEN 1 a SIZE | >>
| IRT / * | 1 - | 'fr1'
| >> | FOR i | << FAST 12 NEG ALOG
| | IF a i GET | .5 * 1 0 4 ROLL DUP
| 'fact' | a i 1 + GET == | ABS 5 ROLLD SIGN -> X
| << 2 1 -> n f i | THEN a i | P A B S
| << { } | GET * i 1 + 'i' STO | << X ABS
| DO | END | WHILE 'ABS(FLOOR
| IF n f / FP 0 | NEXT | (X*A+.5)-X*A)>=P*A'
| == | END DUP 1 1 a | EVAL
| THEN f + n f / | SIZE | REPEAT INV DUP
| 'n' STO | FOR i a i GET | IP ABS A * B + A 'B'
| ELSE f i + 'f' | * | STO 'A' STO FP
| STO 2 'i' STO | NEXT SWAP SQ / | END DROP 'FLOOR(
| END | >> -> a b | X*A+.5)' EVAL S * A
| > | << "'" | >>
| END n + CLMF | IF a 1 != | >>
| >> | THEN a ->STR + |
| >> | END | 'fa1'
| | IF a 1 != b 1 !=| FLOOR
| 'line' | AND | FOR f
| << -> b a | THEN "*" + | IF DUP f / DUP
| << a b - ARRY-> DROP| END | IP SAME
| SWAP / -> m | IF b 1 != | THEN f SWAP OVER
| << m 'X' * a | " + b | / fa1
| ARRY-> DROP SWAP m * | ->STR + | END
| - + | END STR-> | NEXT
| >> | | >>
| >> | 'POLOP' |
| >> | << DUP2 P->R SWAP P->R| 'MULTI'
| | SWAP 0 | << -> p
| | DO DROP | <<
| | DO | DO DUP p EVAL
| | UNTIL KEY | UNTIL DUP ROT
| | END | SAME
| | UNTIL { "/" "*" | END
| | "-" "+" } OVER POS | >>
| | END STR-> R->P 3 | >>
| | ROLLD DROP2 |
| | >> |

directory '..4' contains the following

math :(list) contains the objects in the math menu.

.M :(procedure) calls up the math menu.

.C :(procedure) pseudo-alias to the 'PCAL' program
in ..2.

engin :(list) contains the objects in the engineering menu.

.E :(procedure) calls up the engineering menu

'math'
{ DSQ fact CM. }

'.M'
<< math MENU
>>

'.C'
<< PCAL >>

'engin'
{ POLOP . CM. }

'.E'
<< engin MENU >>