Post Reply 
Custom Menus on High-End RPL Machines
04-02-2019, 12:28 AM (This post was last modified: 02-15-2020 01:56 AM by Giuseppe Donnini.)
Post: #1
Custom Menus on High-End RPL Machines
Given the recent interest in custom menus, it might be worthwhile to take a quick overview of the development, and continuous improvement, of the custom menu system on high-end RPL machines.



A. FIRST APPEARANCE : ORLANDO 1988 (HP-28S)

The HP-28S's immediate precursor Paladin (HP-28C, 1987) didn't yet provide custom menus, though not due to an oversight on behalf of the development team (headed by Bill Wickes), but because it was not deemed worth the effort given the exceedingly small amount of RAM available to the user (2K).

In fact, Bill Wickes was forced by HP managament to either wait a couple of years to build his symbolic "dream machine", or to do it on the pre-existing Champion hardware (HP-18C, 1986). Although the very first calculator to use the new RPL operating system (also developed by the same team), its OS was actually hidden under an algebraic user interface, and it had only 2K of RAM. This made sense for a business model, but would be severely limiting for an advanced scientific calculator of the kind envisioned by Bill Wickes. Nevertheless, he felt it was better than nothing, and accepted.

Despite being "a crippled product in many respects" (quoting Bill Wickes himself), the HP-28C became a huge success, particularly in the mathematical community, and was able to finance its successor, the HP-28S, which was actually a complete redesign of the HP-28C. With sixteen times more RAM available to the user (32K), it was now possible to implement things conceptualized long before, like user graphics, sub-directories, and custom menus.

Considering the complexity of the subject, the following discussion will limit itself to a particular aspect of the custom menu system, which best exhibits HP's continuous efforts to improve it, namely menu keys defined by global names. Given that restriction, the custom menu system as implemented in the HP-28S could be summarized as follows:


 OUTPUT CUSTOM MENUS (White on Black Labels)
+------------+--------------------------------------------------------------+
| ENTRY MODE | PRESSING [id] WITH OR W/O SHIFT:                             |
+------------+--------------------------------------------------------------+
| IMMEDIATE  | (If a command line is present, executes it, then) executes   |
|            | the contents of the global variable named id. (*)            |
|            |                                                              |
| ALGEBRAIC  | Echoes the string "id" (without quotes) to the command line. |
|            |                                                              |
| ALPHA      | Echoes the string "id" (without quotes) to the command line, |
|            | surrounded by spaces.                                        |
+------------+--------------------------------------------------------------+
 (*) If the global name references a directory (whose label in the HP-28S
     still lacks the distinguishing tab), its execution consists of making
     that directory the current one.

 INPUT CUSTOM MENUS (Black on White Labels)
+------------+--------------------------------------------------------------+
| ENTRY MODE | PRESSING [id] WITH OR W/O SHIFT:                             |
+------------+--------------------------------------------------------------+
| IMMEDIATE  | (If a command line is present, executes it, then) stores the |
|            | object on stack level 1 in the global variable named id. (*) |
|            |                                                              |
| ALGEBRAIC  | Echoes the string "id" (without quotes) to the command line. |
|            |                                                              |
| ALPHA      | Echoes the string "id" (without quotes) to the command line, |
|            | surrounded by spaces.                                        |
+------------+--------------------------------------------------------------+
 (*) If the global name references a directory, a "Directory Not Allowed"
     error is generated.


We may note that:

  1. For custom menus, the HP-28S doesn't distinguish between shifted and unshifted menu keys.
     
  2. The distinction between output and input custom menus is only significant in immediate entry mode.
     
  3. Input custom menus are similar to the Solver menu—their non-shifted keys input, rather than output, values, and both have, for that very reason, inverted key labels (black on white)—but they are not quite the same:
            
    • The Solver menu only operates on variable names directly or indirectly included in the current equation, whereas input custom menus may operate on any names.
            
    • In the Solver, shifted menu keys trigger (in immediate entry mode) the root finding process, whereas a custom input menu does not differentiate between shifted and unshifted menu keys.




B. MAJOR IMPROVEMENT : CHARLEMAGNE 1990 (HP-48SX)

With one of the major design goals of the HP-48SX being enhanced customizability, it comes as no surprise that the custom menu system was greatly improved, merging the strengths of both output and input types into a single, unified structure:


+------------+--------------------------------------------------------------+
| ENTRY MODE | PRESSING [id] W/O SHIFT:                                     |
+------------+--------------------------------------------------------------+
| IMMEDIATE  | (If a command line is present, executes it, then) executes   |
|            | the contents of the global variable named id. (*)            |
|            |                                                              |
| ALGEBRAIC  | Echoes the string "id" (without quotes) to the command line. |
|            |                                                              |
| PROGRAM    | Echoes the string "id" (without quotes) to the command line, |
|            | surrounded by spaces.                                        |
|            |                                                              |
| ALG + PRG  | --- same as in ALGEBRAIC mode ---                            |
+------------+--------------------------------------------------------------+
 (*) If the global name references a directory (now displayed with the
     distinguishing tab), its execution consists of making that directory
     the current one.

+------------+--------------------------------------------------------------+
| ENTRY MODE | PRESSING LEFT SHIFT + [id]:                                  |
+------------+--------------------------------------------------------------+
| IMMEDIATE  | (If a command line is present, executes it, then) stores the |
|            | object on stack level 1 in the global variable named id. (*) |
|            |                                                              |
| ALGEBRAIC  | --- same as in IMMEDIATE mode ---                            |
|            |                                                              |
| PROGRAM    | --- DEAD KEY (low beep) ---                                  |
|            |                                                              |
| ALG + PRG  | --- DEAD KEY (low beep) ---                                  |
+------------+--------------------------------------------------------------+
 (*) If the global name references a directory, a "Directory Not Allowed"
     error is generated.

+------------+--------------------------------------------------------------+
| ENTRY MODE | PRESSING RIGHT SHIFT + [id]:                                 |
+------------+--------------------------------------------------------------+
| IMMEDIATE  | (If a command line is present, executes it, then) recalls    |
|            | the contents of the global variable named id.                |
|            |                                                              |
| ALGEBRAIC  | --- same as in IMMEDIATE mode ---                            |
|            |                                                              |
| PROGRAM    | --- DEAD KEY (low beep) ---                                  |
|            |                                                              |
| ALG + PRG  | --- DEAD KEY (low beep) ---                                  |
+------------+--------------------------------------------------------------+




C. FURTHER REFINEMENT : HAMMER 1993 (HP-48GX)

In the HP-48GX this scheme was further enhanced by placing additional typing aids on the dead key positions of the HP-48SX:


+------------+--------------------------------------------------------------+
| ENTRY MODE | PRESSING [id] W/O SHIFT:                                     |
+------------+--------------------------------------------------------------+
| IMMEDIATE  | (If a command line is present, executes it, then) executes   |
|            | the contents of the global variable named id. (*)            |
|            |                                                              |
| ALGEBRAIC  | Echoes the string "id" (without quotes) to the command line. |
|            |                                                              |
| PROGRAM    | Echoes the string "id" (without quotes) to the command line, |
|            | surrounded by spaces.                                        |
|            |                                                              |
| ALG + PRG  | --- same as in ALGEBRAIC mode ---                            |
+------------+--------------------------------------------------------------+
 (*) If the global name references a directory, its execution consists of
     making that directory the current one.

+------------+--------------------------------------------------------------+
| ENTRY MODE | PRESSING LEFT SHIFT + [id]:                                  |
+------------+--------------------------------------------------------------+
| IMMEDIATE  | (If a command line is present, executes it, then) stores the |
|            | object on stack level 1 in the global variable named id. (*) |
|            |                                                              |
| ALGEBRAIC  | --- same as in IMMEDIATE mode ---                            |
|            |                                                              |
| PROGRAM    | Echoes the string "'id' STO" (without double quotes) to the  |
|            | command line, surrounded by spaces.                          |
|            |                                                              |
| ALG + PRG  | --- same as in PROGRAM mode ---                              |
+------------+--------------------------------------------------------------+
 (*) If the global name references a directory, a "Directory Not Allowed"
     error is generated.

+------------+--------------------------------------------------------------+
| ENTRY MODE | PRESSING RIGHT SHIFT + [id]:                                 |
+------------+--------------------------------------------------------------+
| IMMEDIATE  | (If a command line is present, executes it, then) recalls    |
|            | the contents of the global variable named id.                |
|            |                                                              |
| ALGEBRAIC  | --- same as in IMMEDIATE mode ---                            |
|            |                                                              |
| PROGRAM    | Echoes the string "'id' RCL" (without double quotes) to the  |
|            | command line, surrounded by spaces.                          |
|            |                                                              |
| ALG + PRG  | --- same as in PROGRAM mode ---                              |
+------------+--------------------------------------------------------------+




D. CONCLUSION

As is readily apparent from the above, the HP-48's custom menu system is vastly superior to that of the HP-28S, especially considering the fact that we only focussed on global names as menu key objects, leaving aside the two dozens other object types which may trigger their own menu key actions.

But what's missing in the 48 are 28S-sytle input menu keys, with their inverted labels, and their ability to store values with a single, unshifted keystroke—while at the same time remaining completely disconnected from the Solver environment.

Now, given the unrivalled flexibility of the 48, nothing prevents us from adding this feature ourselves! And while we're at it, we could even go a step further and combine the best of both worlds and have the new input keys retain their added, 48-specific functionality, albeit in a different distribution: unshifted keys would then store, left-shifted keys execute, and right-shifted keys recall the corresponding variable's contents. In short, we want 48-style variable keys, but with black on white labels and with their no- and left-shift actions interchanged. The skeleton of such a custom menu would look like this:


{
 {
  :: TakeOver $ "A" MakeInvLabel ;     ( *MENU KEY 1 Label Object* )
  {
   :: TakeOver ' ID A StdMenuKeyLS ;   ( *MENU KEY 1 No-Shift Action Object* )
   :: TakeOver ' ID A StdMenuKeyNS ;   ( *MENU KEY 1 Left-Shift Action Object* )
   :: TakeOver ' ID A StdMenuKeyRS ;   ( *MENU KEY 1 Right-Shift Action Object* )
  }
 }
 {
  :: TakeOver $ "B" MakeInvLabel ;     ( *MENU KEY 2 Label Object* )
  {
   :: TakeOver ' ID B StdMenuKeyLS ;   ( *MENU KEY 2 No-Shift Action Object* )
   :: TakeOver ' ID B StdMenuKeyNS ;   ( *MENU KEY 2 Left-Shift Action Object* )
   :: TakeOver ' ID B StdMenuKeyRS ;   ( *MENU KEY 2 Right-Shift Action Object* )
  }
 }

 ( ... )

}


( StdMenuKeyRS is an unsupported, but stable entry point at #4021Fh. )

This code works equally well in an HP-48SX and in an HP-48GX, but the newly added typing aids of the GX will obviously not be available on an SX (although they can be added).

In a thorough implementation, however, several things would have to be reconsidered:

  1. Replacing every single global name in a menu list with the convoluted code above would be very inefficient, and even if the process was automated, would still lead to a massive overhead both in size and time. The solution of choice is to hook the key label and key action builders themselves, i.e. the system programs responsible for building the actual key labels and key objects from the information contained in the menu definition.
     
  2. The custom menu list as presented above will interchange the unshifted and left-shifted key actions across all four entry modes, which might not be what we want. In fact, in algebraic entry mode, it would be quite confusing to have to press LS+[id] to simply copy the string "id" into the current expression. One might be tempted to just press [id], which, in its new STO function, would terminate the command line and store whatever the result of the latter's evaluation happens to be in the global variable id. It would therefore be wiser to follow the Solver menu's example and restrict the new functionality to immediate entry mode alone. This would also have the benefit of remaining consistent with the conventions of the system.
     
  3. It would be convenient to extend the new look and functionality to keys defined by local names, so that a program could use a custom input menu to prompt the user for values that will merely be stored in temporary variables.
     
  4. It would perhaps also be useful to make a distinction between global names referencing directories and all other global names, so that directories may preserve their familiar aspect and behavior. For local names, this distinction would not be necessary or even useful, since they can only reference unrooted directories (in contrast to directories rooted in user memory, which have the additional ability to become the current context when executed, and which are accessible only through global names).
     
  5. Another enhancement one might consider is getting visual confirmation in the status area after each storing operation—exactly as in the Solver environment, where you are greeted with a "ABC: 123" message once the real number 123 has been successfully stored in the global variable ABC.


With these improvements in mind, an input key in immediate entry mode would then have the following functionality (as usual, any pending command line is executed beforehand):


+-------+
|  NS   |
+-------+----------------------------------------------------------------------+
| [id]  | + Stores the object on stack level 1 in the global variable named id |
|       |   within the current directory.  If the variable doesn't exist,      |
|       |   creates it in the current directory.  If it already exists in the  |
|       |   current directory, its contents are overwritten with the new       |
|       |   object from stack level 1.                                         |
|       | + If the storing operation was successful, displays a confirmation   |
|       |   message in the status area of the form "id: contents".             |
|       | + If the object on stack level 1 is an unrooted directory, stores it |
|       |   in the global variable id within the current directory, thereby    |
|       |   rooting it in the latter as its sub-directory.  As a consequence,  |
|       |   the key label changes from black on white to white on black with a |
|       |   tab, and the key actions revert to their standard behavior (as     |
|       |   long as the new sub-directory remains in the current path).        |
|       | + The menu key offers the same protection as the STO key against     |
|       |   accidental overwriting of a variable (LASTARG returns the old,     |
|       |   rather than the new contents of the variable, so that the sequence |
|       |   RS+ARG STO restores the variable to its prior state).              |
|       | + If the object on stack level 1 is the same as id, generates a      |
|       |   "Circular Reference" error.                                        |
|       | + If there is no object on stack level 1, generates a "Too Few       |
|       |   Arguments" error.                                                  |
|       |                                                                      |
| [dir] | + [Standard white on black label with a tab]  Makes dir the current  |
|       |   context.  Unlike in the VAR menu, dir may be anywhere in the       |
|       |   current path, as is the case for standard custom menus, too.       |
|       |                                                                      |
|       |......................................................................|
|       |                                                                      |
| [lam] | + Stores the object on stack level 1 in the temporary variable named |
|       |   lam, overwriting the old contents.  If the temporary variable      |
|       |   doesn't exist, generates an "Undefined Local Name" error.          |
|       | + If the storing operation was successful, displays a confirmation   |
|       |   message in the status area of the form "lam: contents".            |
|       | + The menu key offers the same protection as the STO key against     |
|       |   accidental overwriting of a variable.                              |
|       | + If the object on stack level 1 is the same as lam, generates a     |
|       |   "Circular Reference" error.                                        |
|       | + If there is no object on stack level 1, generates a "Too Few       |
|       |   Arguments" error.                                                  |
+-------+----------------------------------------------------------------------+

+-------+
|  LS + |
+-------+----------------------------------------------------------------------+
| [id]  | + Executes the object stored in the global variable named id.  The   |
|       |   search for id is not restricted to the current directory, but is   |
|       |   extended to the current path.  If the variable is not found in the |
|       |   current path, it is considered as not yet defined (formal variable)|
|       |   and the global name 'id' is returned to the stack.                 |
|       |                                                                      |
| [dir] | + [Standard white on black label with a tab]  Generates a "Directory |
|       |   Not Allowed" error.  Unlike in the VAR menu, dir may be anywhere   |
|       |   in the current path.                                               |
|       |                                                                      |
|       |......................................................................|
|       |                                                                      |
| [lam] | + Recalls the object stored in the temporary variable named lam to   |
|       |   stack level 1.  If the temporary variable doesn't exist, generates |
|       |   an "Undefined Local Name" error.                                   |
+-------+----------------------------------------------------------------------+

+-------+
|  RS + | [N.B. All right-shifted menu keys retain their standard behavior.]
+-------+----------------------------------------------------------------------+
| [id]  | + Recalls the object stored in the global variable named id to       |
|       |   stack level 1.  The search for id is not restricted to the current |
|       |   directory, but is extended to the current path.  If the variable   |
|       |   is not found in the current path, generates an "Undefined Name"    |
|       |   error.                                                             |
|       |                                                                      |
| [dir] | + [Standard white on black label with a tab]  Recalls dir as an      |
|       |   unrooted data object to stack level 1.  Unlike in the VAR menu,    |
|       |   dir may be anywhere in the current path.                           |
|       |                                                                      |
|       |......................................................................|
|       |                                                                      |
| [lam] | + Recalls the object stored in the temporary variable named lam to   |
|       |   stack level 1.  If the temporary variable doesn't exist, generates |
|       |   an "Undefined Name" error.                                         |
+-------+----------------------------------------------------------------------+




E. PRACTICAL EPILOGUE

In a bold break with tradition, I will not leave the implementation of such a menu system as an exercise for the reader, but rather offer my own try at it. Further details may be gleaned from the commented source code. Observations, suggestions, and criticism are welcome. Gaudete!



[Image: YHFDKRE.png]     [Image: Hh7f2RF.png]     [Image: PEceIjq.png]
Ex. Temporary custom menu for easy vector input with mixed input and output keys.



Code:

*******************************************************************************
** TMN2                                                         SX/GX rev. A-R
*******************************************************************************
** ABSTRACT : Alternative TMENU (Temporary Menu).  Displays a user-defined menu
**            specified by a list or by the name of a (global or local)
**            variable that contains a list.
**
**            Differences to TMENU:
**            + TMN2 will treat keys defined by global or local names in a
**              different way:
**              - Their labels will be inverted (black on white instead of
**                white on black).
**              - In immediate entry mode, they will have their no- and left-
**                shift actions interchanged.
**            + TMN2 does not handle built-in and library menus (specified by
**              real numbers), because the result would be the same as with
**              TMENU.
**
**            Note that, if the argument provided is not a list or a name of a
**            variable containing a list, TMN2 will display an empty menu (as
**            does the GX version of TMENU), rather than generate an error (as
**            does the SX version).
**
** STACK    : ( {list.definition} --> )
**            ( 'name.definition' --> )
**
** ERRORS   : "Too Few Arguments" if no argument provided.
**
** DETAILS  : + The menu list provided by the user is incorporated into a full-
**              fledged System RPL menu of the form:
**
**              :: <properties> {data} ;
**
**              where {data} is the user-provided list, and <properties> the
**              place where the menu's general properties are defined,
**              including, among many others, the label builder definition and
**              the definition of the key handlers for each shift plane (this
**              part of a menu is normally inaccessible to the user).
**
**              The secondary is then passed as an argument to InitMenu, which
**              first resets all menu properties to their default state, then
**              executes its argument, which is what gives <properties> the
**              chance to overwrite any of the default properties.  After
**              execution terminates, the user list remains on the stack and is
**              then stored in internal RAM (to be precise, the reference of
**              the list already present in TEMPOB is removed from DSKTOP* and
**              written to MenuData in IRAM).
**
**            + The system will feed only the following 5 object types to the
**              label builder (be it the default one or a custom one):
**
**              1. Character String
**              2. Global Name
**              3. TakeOver Secondary (normal secos are decompiled!)
**              4. Graphics Object
**              5. System Binary Integer
**
**              Any other object type will first be decompiled to a character
**              string, before being passed to the label builder.  This means
**              that, if we want to get a chance to change the label of a key
**              defined by a local name, we have to check the key *action*
**              definition, rather than the key *label* definition.
*******************************************************************************

ASSEMBLE

* Binary transfer header ; remove if compiled directly on the HP-48.

        NIBASC /HPHP48-A/

* Unsupported, but stable entry points:

=NotIDorLAM?  EQU #2E7A4
=StdLabelDef  EQU #3A260

RPL

::
 CK1NoBlame        ( *Clear saved command name ; require 1 argument* )

 ::                (  ------------ BEGIN ARGUMENT TYPE CHECKING ------------- )
  DUPTYPELIST?     ( *If argument is a list, ...* )
  ?SEMI            ( *... quit type checking* )
  NotIDorLAM?      ( *If argument neither global nor local name, ...* )
  casedrop NULL{}  ( *... supply empty list instead* )
  SAFE@            ( *If global or local variable not defined, ...* )
  NOTcase NULL{}   ( *... supply empty list instead* )
  DUPTYPELIST?     ( *If contents of global or local var. not a list, ...* )
  NOTcasedrop
  NULL{}           ( *... supply empty list instead* )
 ;                 (  ------------- END ARGUMENT TYPE CHECKING -------------- )

*******************************************************************************
* If one prefers error messages (as done by the SX version of TMENU), replace
* the secondary above with the following one:
* ::
*  DUPTYPELIST? ?SEMI
*  NotIDorLAM? case SETYPEERR
*  SAFE@ NcaseSIZEERR
*  DUPTYPELIST? NcaseSIZEERR
* ;
*******************************************************************************

 '
 ::                ( xxxxxxxxxxxxx BEGIN CUSTOM MENU DEFINITION xxxxxxxxxxxxx )

                   ( ============= BEGIN CUSTOM MENU PROPERTIES ------------- )
  '
  ::               ( ------------ BEGIN CUSTOM KEY LABEL BUILDER ------------ )

                   ( --- Local Names --- )
   INDEX@ GETPROC  ( *Get key action definition [INDEX@ returns #keynumber]* )
   TYPELAM? case   ( *If lam, the system has already decompiled it to a $* )
   ::
    MakeInvLabel   ( *Build inverted, black on white key label* )
    Grob>Menu      ( *Display key label* )
   ;
                   ( --- General Case --- )
   DUPTYPEIDNT?    ( *If key label not defined by global name, ...* )
   NOTcase
   StdLabelDef     ( * ... use standard key label builder* )

                   ( --- Global Names --- )
   DUP ID>$        ( *Copy id and convert it to a string* )
   SWAP @          ( *Try to recall contents anywhere in the current path* )
   ITE
   TYPERRP?        ( *If variable defined, check for dir. ; signal T or F* )
   FALSE           ( *If variable undefined, signal F* )
   ITE
   MakeDirLabel    ( *If directory, build standard directory label with tab* )
   MakeInvLabel    ( *If not, build inverted, black on white label* )
   Grob>Menu       ( *Display key label* )

  ;                ( ------------- END CUSTOM KEY LABEL BUILDER ------------- )

  LabelDef!        ( *Store as new key label builder* )

  '
  ::               ( -------- BEGIN CUSTOM NO-SHIFT MENU KEY HANDLER -------- )

                   ( --- General Case --- )
   NotIDorLAM?     ( *If key not defined by global or local name, ...* )
   ImmedEntry? NOT ( *... or if we are not in immediate execution mode ...* )
   ORcase
   StdMenuKeyNS    ( *... use standard no-shift menu key handler* )

                   ( --- Directories --- )
   DUPTYPELAM?     ( *If key defined by local name, ...* )
   ?SKIP           ( *... skip distinction betw. dir. and non-dir. contents* )
   ::
    DUP@           ( *Copy id, try to recall contents anywhere in curr. path* )
    ITE
    TYPERRP?       ( *If variable defined, check for dir. ; signal T or F* )
    FALSE          ( *If variable undefined, signal F* )
    case
    ::             ( *If global variable contains a directory, ...* )
     2RDROP        ( *... cancel all pending jobs in our custom handler ...* )
     StdMenuKeyNS  ( *... and use standard no-shift menu key handler instead* )
    ;
   ;

                   ( --- Local, Global Formal and Global Non-Dir. Vars --- )
   StdMenuKeyLS    ( *Do standard left-shift key action* )

  ;                ( --------- END CUSTOM NO-SHIFT MENU KEY HANDLER --------- )

  MenuKeyNS!       ( *Store as new no-shift menu key handler* )

  '
  ::               ( ------- BEGIN CUSTOM LEFT-SHIFT MENU KEY HANDLER ------- )

                   ( --- General Case --- )
   NotIDorLAM?     ( *If key not defined by global or local name, ...* )
   ImmedEntry? NOT ( *... or if we are not in immediate execution mode ...* )
   ORcase
   StdMenuKeyLS    ( *... use standard left-shift menu key handler* )

                   ( --- Directories --- )
   DUPTYPELAM?     ( *If key defined by local name, ...* )
   ?SKIP           ( *... skip distinction betw. dir. and non-dir. contents* )
   ::
    DUP@           ( *Copy id, try to recall contents anywhere in curr. path* )
    ITE
    TYPERRP?       ( *If variable defined, check for dir. ; signal T or F* )
    FALSE          ( *If variable undefined, signal F* )
    case
    ::             ( *If global variable contains a directory, ...* )
     2RDROP        ( *... cancel all pending jobs in our custom handler ...* )
     StdMenuKeyLS  ( *... and use std. left-shift menu key handler instead* )
    ;
   ;

                   ( --- Local, Global Formal and Global Non-Dir. Vars --- )
   DoKeyOb         ( *Do standard no-shift key action* )

  ;                ( -------- END CUSTOM LEFT-SHIFT MENU KEY HANDLER -------- )

  MenuKeyLS!       ( *Store as new left-shift menu key handler* )

                   ( ============== END CUSTOM MENU PROPERTIES ============== )

 ;                 ( xxxxxxxxxxxxxx END CUSTOM MENU DEFINITION xxxxxxxxxxxxxx )

 SWAP >TCOMP       ( *Append user-supplied menu data to menu definition* )

 InitMenu          ( *Activate menu properties and display menu* )
;
Find all posts by this user
Quote this message in a reply
04-02-2019, 12:55 AM
Post: #2
RE: Custom Menus on High-End RPL Machines
Very nice post, thanks!

Only one observation: I don't think that there's a low end RPL, that I remember

Cheers
Find all posts by this user
Quote this message in a reply
04-02-2019, 01:25 AM
Post: #3
RE: Custom Menus on High-End RPL Machines
Thanks for your kind reply!

What I mean by "high-end RPL" in this context, is that I don't take into consideration the high-end Pioneers (HP-17B, HP-17BII, HP-27S, HP-42S), which all are RPL machines (internally), have solver or input menus, and—in the case of the HP-42S—even real custom menus.
Find all posts by this user
Quote this message in a reply
04-02-2019, 01:32 AM
Post: #4
RE: Custom Menus on High-End RPL Machines
(04-02-2019 01:25 AM)Giuseppe Donnini Wrote:  high-end Pioneers (HP-17B, HP-17BII, HP-27S, HP-42S), which all are RPL machines (internally)

What is the RPL inside of the 42S used for? I thought it was all Saturn machine language inside (not that I've ever tried disassembling the ROM)...
Visit this user's website Find all posts by this user
Quote this message in a reply
04-02-2019, 02:07 AM
Post: #5
RE: Custom Menus on High-End RPL Machines
Well, for pretty much everything! It may be hard to believe at first, but to quote the most knowledgeable person I know of on that subject:

(06-07-2015 01:47 PM)Raymond Del Tondo Wrote:  The 42S actually is an RPL machine running a stripped-down version of the HP-48 OS.
Find all posts by this user
Quote this message in a reply
04-02-2019, 03:58 AM
Post: #6
RE: Custom Menus on High-End RPL Machines
(04-02-2019 02:07 AM)Giuseppe Donnini Wrote:  Well, for pretty much everything! It may be hard to believe at first, but to quote the most knowledgeable person I know of on that subject:

(06-07-2015 01:47 PM)Raymond Del Tondo Wrote:  The 42S actually is an RPL machine running a stripped-down version of the HP-48 OS.

That's tantalizingly vague. Smile

So if I were to try to disassemble the 42S ROM, I would find the floating-point routines in machine language, I guess, and perhaps the complex and matrix functionality as well, and the graphics primitives? With the command line interface, menu system, program editor, and program interpreter in (compiled?) RPL? Am I warm? Has anyone delved into this and written any articles about it?
Visit this user's website Find all posts by this user
Quote this message in a reply
04-02-2019, 10:54 AM
Post: #7
RE: Custom Menus on High-End RPL Machines
(04-02-2019 03:58 AM)Thomas Okken Wrote:  
(04-02-2019 02:07 AM)Giuseppe Donnini Wrote:  Well, for pretty much everything! It may be hard to believe at first, but to quote the most knowledgeable person I know of on that subject:

That's tantalizingly vague. Smile

So if I were to try to disassemble the 42S ROM, I would find the floating-point routines in machine language, I guess, and perhaps the complex and matrix functionality as well, and the graphics primitives? With the command line interface, menu system, program editor, and program interpreter in (compiled?) RPL? Am I warm? Has anyone delved into this and written any articles about it?
Yes and no.
Many years ago, I disassembled (and partly decompiled) a huge amount of the 42S ROM.
The RPL kernel is nearly the same as in the HP 48S series, lacking things like bank switching and some object types - things which are not used in the 42S.

There are similar (if not the same) math routines in ML, and math related routines in SysRPL. The latter are nearly the same as in the HP 48S series.
The user interface is different to that in the HP 48, so the associated display graphics routines and menu display routines are different, of course.

The stack registers incl. Alpha are stored in designated positions in system RAM, the registers are incarnated as a matrix object.

There is no User level RPL in the 42S, only SysRPL. So if you are in the 42S program editor, you'll only have access to FOCAL words, with some 42S extensions, of course.
The program "compiler" creates a FOCAL byte stream, which will be run through the FOCAL execution engine.
This FOCAL byte stream is binary compatible to that of the HP-41 and the HP41CV Emulator card for the HP 48SX.

The actual internal code behind the FOCAL words is RPL or Saturn ML, of course.

-- Ray
Find all posts by this user
Quote this message in a reply
04-02-2019, 07:17 PM
Post: #8
RE: Custom Menus on High-End RPL Machines
Fascinating. Thanks for the enlightenment!

I was always impressed with how much faster the 42S was than the 41. Now, even more so. Smile
Visit this user's website Find all posts by this user
Quote this message in a reply
04-02-2019, 11:53 PM
Post: #9
RE: Custom Menus on High-End RPL Machines
(04-02-2019 10:54 AM)Raymond Del Tondo Wrote:  There is no User level RPL in the 42S, only SysRPL. So if you are in the 42S program editor, you'll only have access to FOCAL words, with some 42S extensions, of course.
The program "compiler" creates a FOCAL byte stream, which will be run through the FOCAL execution engine.
This FOCAL byte stream is binary compatible to that of the HP-41 and the HP41CV Emulator card for the HP 48SX.

The actual internal code behind the FOCAL words is RPL or Saturn ML, of course.

Thanks for the detailed explanation Raymond; it's so interesting to still learn new things about the 42S so many years later!

Would you guess that the 42S FOCAL processing was actually based on the 41CV Emulator card code? Now that you've pointed out the similarity, it's an obvious method they could have used, but I never even thought about how similar these 2 are, and never gave it even a moment's thought that it could have been built from the emulator code.

--Bob Prosperi
Find all posts by this user
Quote this message in a reply
04-03-2019, 01:01 AM
Post: #10
RE: Custom Menus on High-End RPL Machines
(04-02-2019 11:53 PM)rprosperi Wrote:  Would you guess that the 42S FOCAL processing was actually based on the 41CV Emulator card code? Now that you've pointed out the similarity, it's an obvious method they could have used, but I never even thought about how similar these 2 are, and never gave it even a moment's thought that it could have been built from the emulator code.

Does the 41CV Emulator Card have the same numerical range as the 42S and the RPL machines, or is it 10-digit with 2-digit exponent like the real 41?

There could be more subtle clues as well, for example, in programs, the real 41 inserts a null byte (that doesn't disappear after PACKING) between two consecutive numbers, while the 42S inserts a null byte before every number, as in

Code:
00 { 2-Byte Prgm }
01 1
02 END
Visit this user's website Find all posts by this user
Quote this message in a reply
04-03-2019, 05:51 AM
Post: #11
RE: Custom Menus on High-End RPL Machines
Thanks for that explanation, Raymond.
How does the 42 handle garbage collection, then? It never seems to pause in any noticeable way.

Cheers, Werner

41CV†,42S,48GX,49G,DM42,DM41X,17BII,15CE,DM15L,12C,16CE
Find all posts by this user
Quote this message in a reply
04-03-2019, 06:21 AM
Post: #12
RE: Custom Menus on High-End RPL Machines
(04-03-2019 01:01 AM)Thomas Okken Wrote:  Does the 41CV Emulator Card have the same numerical range as the 42S and the RPL machines, or is it 10-digit with 2-digit exponent like the real 41?

I am at work now and cannot check, but I found this:

Quote:The range of valid values in the emulator is the same as for the
HP48 -- with exponents between -499 and +499. This is different from the
valid exponent range in the 41, between -99 and +99. Also, the emulator
uses 12 mantissa digits while the 41 uses only 10.

Greetings,
    Massimo

-+×÷ ↔ left is right and right is wrong
Visit this user's website Find all posts by this user
Quote this message in a reply
04-03-2019, 07:05 AM
Post: #13
RE: Custom Menus on High-End RPL Machines
(04-02-2019 07:17 PM)Thomas Okken Wrote:  Fascinating. Thanks for the enlightenment!

I was always impressed with how much faster the 42S was than the 41. Now, even more so. Smile
Back then I noticed that HP-42S was actually quite faster than the 48's on the same routines.
Find all posts by this user
Quote this message in a reply
04-03-2019, 10:26 AM
Post: #14
RE: Custom Menus on High-End RPL Machines
(04-03-2019 05:51 AM)Werner Wrote:  Thanks for that explanation, Raymond.
How does the 42 handle garbage collection, then? It never seems to pause in any noticeable way.

Cheers, Werner
As far as I can see, the garbage collection works in the same way as on the other RPL machines, which also includes the 17B(II) and the 19B(II) .
Creating objects consumes RAM as in the other RPL machines, and therefore the GARBAGECOL is invoked when there's not enough room for creating the new object.

One of the differences to the HP 48S series is that in the 42S, the memory layout is somewhat less complicated due to the lack of ban switching. Less memory is moved since the user stack (list of pointers) is of fixed size, the stack objects are real numbers in most cases, whose pointers have designated system RAM addresses, so expanding/shrinking of the internal data stack pointer list happens less often.
The user stack objects are not on the data stack normally, but recalled from the designated data area when needed, operated upon, then stored back into the location.

-- Ray
Find all posts by this user
Quote this message in a reply
04-03-2019, 10:34 AM
Post: #15
RE: Custom Menus on High-End RPL Machines
(04-02-2019 11:53 PM)rprosperi Wrote:  Would you guess that the 42S FOCAL processing was actually based on the 41CV Emulator card code?
AFAIK it's the other way round. The 42S had been developped before the HP41CV Emulator card.

I think I somewhere read about how Frank Wales and others from Zengrange went to Corvallis for the project.

I'm not exactly sure where I got that thought, be it either from RCL20, or Frank's web page, or in mails which we exchanged back then.

-- Ray
Find all posts by this user
Quote this message in a reply
04-03-2019, 12:53 PM (This post was last modified: 04-03-2019 02:54 PM by Giuseppe Donnini.)
Post: #16
RE: Custom Menus on High-End RPL Machines
(04-03-2019 10:34 AM)Raymond Del Tondo Wrote:  I think I somewhere read about how Frank Wales and others from Zengrange went to Corvallis for the project.

Exactly! Here's an excerpt from a transcript I made of Bill Wickes' talk in Philadelphia on November 11th, 1990 (warm thanks go to Jake Schwartz for sharing his video collection):

"I talked about times being different from the 41 time, and that's true in another way that I didn't mention before: In the 41, the plug-in modules were 4K of ROM and it was quite reasonable for an engineer at HP in those days to spend a month or so boning up on something like surveying, and write a little module that would exercise the 41 to its capacity on the topic of surveying. For the 48, that's just no longer practical. You can put so much into a plug-in card that it's just not reasonable to expect a mechanical engineer, or a software engineer, or anybody like that, to become expert in somebody else's field, and write a card that would stand on its own two feet in the world. So basically, the strategy with the 48 is, for the most part, to encourage other people to write cards—not for us necessarily, but for themselves, and we'll just sell the mainframes. Now, sometimes we will identify something as either being strategic or important, like in the case of the 41 emulator. We subcontracted that to Zengrange Co. out of England to write, because they have a lot of 41 expertise, and we actually brought them into our R&D lab, gave them a desk right across from mine, and they sat there for six months to develop that card right on our development systems."
Find all posts by this user
Quote this message in a reply
04-03-2019, 02:15 PM
Post: #17
RE: Custom Menus on High-End RPL Machines
Excuse the layman's question, but what do "immediate" and "algebraic" mean in the menu tables? Doesn't the 48GX only have RPN mode?
Find all posts by this user
Quote this message in a reply
04-03-2019, 03:14 PM (This post was last modified: 04-03-2019 03:17 PM by cdmackay.)
Post: #18
RE: Custom Menus on High-End RPL Machines
(04-03-2019 02:15 PM)Lode Wrote:  Excuse the layman's question, but what do "immediate" and "algebraic" mean in the menu tables? Doesn't the 48GX only have RPN mode?

Single-quotes ' allows a temporary algebraic-entry mode. See e.g. User's Guide 2-8 "Selecting Command-Line Entry Modes". Immediate is the normal mode.

Cambridge, UK
41CL/DM41X 12/15C/16C DM15/16 17B/II/II+ 28S 42S/DM42 32SII 48GX 50g 35s WP34S PrimeG2 WP43S/pilot
Casio, Rockwell 18R
Find all posts by this user
Quote this message in a reply
04-03-2019, 03:42 PM
Post: #19
RE: Custom Menus on High-End RPL Machines
(04-03-2019 10:34 AM)Raymond Del Tondo Wrote:  AFAIK it's the other way round. The 42S had been developped before the HP41CV Emulator card.

I think I somewhere read about how Frank Wales and others from Zengrange went to Corvallis for the project.

I'm not exactly sure where I got that thought, be it either from RCL20, or Frank's web page, or in mails which we exchanged back then.

Oh wow, you're right, about 2 years before the emulator, not at all how I seemed to recall things. Memory is a funny thing...

(04-03-2019 12:53 PM)Giuseppe Donnini Wrote:  
(04-03-2019 10:34 AM)Raymond Del Tondo Wrote:  I think I somewhere read about how Frank Wales and others from Zengrange went to Corvallis for the project.

Exactly! Here's an excerpt from a transcript I made of Bill Wickes' talk in Philadelphia on November 11th, 1990 (warm thanks go to Jake Schwartz for sharing his video collection):

Thanks for sharing that Giuseppe! There are also printed materials for that 1990 conference in Jake's splendid collection, including a Wickes presentation on vectored Enter, etc. but this seems to have been a reply to a question, so the video is the only record of that; I'm glad you watched it and made a transcript.

--Bob Prosperi
Find all posts by this user
Quote this message in a reply
04-03-2019, 04:22 PM
Post: #20
RE: Custom Menus on High-End RPL Machines
(04-03-2019 03:42 PM)rprosperi Wrote:  There are also printed materials for that 1990 conference in Jake's splendid collection, including a Wickes presentation on vectored Enter, etc.

You're talking about the big conference in Rolling Meadows, IL, that took place in June 1990, but the talk I'm referring to was a small meeting of the Philadelphia Area HP Handheld Club (PAHHC) later in November of the same year, where Bill Wickes addressed advanced HP-48 topics for nearly three hours and a half.
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 1 Guest(s)