[comp.sys.handhelds] Assorted HP48 questions

ferris@tcville.HAC.COM (06/13/90)

I am another quite happy HP48SX owner, having just recently acquired one.
I am especially delighted as my previous calculator, which I still
proudly own, is a 1980 vintage HP41C. Comparing the two, it's astounding
to realize how much the technology has grown in the past ten years.  And
I'm still impressed by what my 41 can do (especially with the PPC ROM
installed)!

So kudos to all the folks up in Corvallis!

I have run up with a couple of questions that puzzle me, though.

I have the distinct impression, and I have a sinking feeling that it is
because it is correct, that for an object to be globally accessable,
it must reside in the HOME directory.  If this is indeed true, it is
unfortunate there isn't a path variable the user can create.  The situation
in which this creates the most trouble is having a program in a lower
directory assigned to a key.  When in another directory and in USER mode,
pressing that key places on the stack the name of the program, which EVALs
to only itself.  Is there a _system provided_ way to make a key assignment
inactive when not in the directory that the object assigned to that key
resides?  What this boils down to is having different key assignments for
each directory. Is this possible?

I have noticed when using the BYTES command, that 100% of the time, the
number of bytes returned is _lower_ than the amount specified either in
the manual or by other people when keying their programs.  The checksums
match, but the byte count is lower. I have revision D of the ROMs, and
I've been wondering if HP came up with a different way to store objects
that is less space consuming. Now I certainly won't pass up more
efficient data compactions!

Thanks to anyone who can shed some light on these issues.
Mark Ferris                         smart:    ferris@tcville.edsg.hac.com
Image and Signal Processing Lab     dumb:     ferris%tcville@hac2arpa.hac.com
Hughes Aircraft Co., EDSG           uucp:     hacgate!tcville!ferris

bill@videovax.tv.tek.com (William K. McFadden) (06/14/90)

In article <8815@hacgate.UUCP> ferris@tcville.HAC.COM () writes:
>I have the distinct impression, and I have a sinking feeling that it is
>because it is correct, that for an object to be globally accessable,
>it must reside in the HOME directory.  If this is indeed true, it is
>unfortunate there isn't a path variable the user can create.

Some time ago, jc@atcmp.nl (Jan Christiaan van Winkel) posted a method of
getting around this.  What you do is create a { HOME LIB } directory and use a
program called 'SVC' (service call) to call it.  The SVC program resides in
your home directory.  It is true that the LIB directory gets full of lots of
programs, but I think it is better than having them cluttering the HOME
directory.  Anyway, here is the program (with some improvements I've made):

SVC  (Bytes #1C7Fh 49)

<< PATH			;get current path
   SWAP			;get program name in level 1
   { HOME LIB } EVAL	;go to LIB directory (HOME LIB by itself also works,
			;but bombs in debug mode, i.e., single stepping)
   RCL			;recall library routine to stack
   SWAP EVAL		;go back to original directory
   EVAL			;execute library routine
>>

To use this routine from a program, you put the library routine's arguments on
the stack, followed by the name of the routine in single quotes.  Then call
SVC.  For example:

6.133990
'DOW'
SVC

Which returns "Wednesday" to the stack.  Notice also that SVC returns to the
original directory before executing the library routine.  Hence it will use
that directory's environment.

>The situation
>in which this creates the most trouble is having a program in a lower
>directory assigned to a key.  When in another directory and in USER mode,
>pressing that key places on the stack the name of the program, which EVALs
>to only itself.

Instead of assigning 'DOW' to a key, you would assign << 'DOW' SVC >> to the
key, making it globally accessible.  However, this forces you to put DOW in the
LIB directory.  If this is not desirable you could instead assign to the key
<< PATH HOME DIR1 DIR2 .. DIRn DOW EVAL >>, where HOME .. DIRn is the path to
the program (DOW in this example).  If you wanted the program to reside in the
other directory but execute in the current one, you could use << PATH HOME
DIR1 DIR2 .. DIRn 'DOW' RCL SWAP EVAL EVAL >>.  In effect, you would assign a
custom version of the SVC program to the key.  These ideas could also be
extended to control alarms that execute a program in another directory but
leave the calculator in the original directory when finished.

>Is there a _system provided_ way to make a key assignment
>inactive when not in the directory that the object assigned to that key
>resides?  What this boils down to is having different key assignments for
>each directory. Is this possible?

Other than using menu keys, I don't know of a way to unassign a key when you
leave the directory.  I suppose you could use TYPE or IFERR to detect the
existance of a program and evaluate it if it's there or execute the default
function if it isn't.  For example, << IFERR 'DOW' RCL EVAL THEN DROP SIN
END >> would execute DOW if it exists, otherwise would execute SIN (or whatever
the default function is for that key).

>I have noticed when using the BYTES command, that 100% of the time, the
>number of bytes returned is _lower_ than the amount specified either in
>the manual or by other people when keying their programs.  The checksums
>match, but the byte count is lower. I have revision D of the ROMs, and
>I've been wondering if HP came up with a different way to store objects
>that is less space consuming. Now I certainly won't pass up more
>efficient data compactions!

This, too, puzzled me at first.  I discovered you can get two different answers
depending on what you supply to the BYTES command.  For example, 'SVC' BYTES
returns #1C7Fh 49, but 'SVC' RCL BYTES returns #1C7Fh 41.5.  The difference is
the first call to BYTES included the program name in its count, and the second
didn't.  I have seen programs posted to the net both ways, but I believe the
HP48 I/O firmware uses the first version.

Happy programming!
-- 
Bill McFadden    Tektronix, Inc.  P.O. Box 500  MS 58-639  Beaverton, OR  97077
bill@videovax.tv.tek.com,     {hplabs,uw-beaver,decvax}!tektronix!videovax!bill
Phone: (503) 627-6920       "The biggest difference between developing a missle
component and a toy is the 'cost constraint.'" -- John Anderson, Engineer, TI

billw@hpcvra.CV.HP.COM (William C Wickes) (06/14/90)

* There is only one key assignment list maintained by the 48, so there
is no automated way to make directory-sensitive key assignments.  Note
however, that the custom menu IS directory-dependent--you can have
a different custom menu in every subdirectory.

* The BYTES command works in two ways: 1) if its argument is a global
name, BYTES computes the total memory size of the associated global
variable, and the checksum of the stored object; 2) for any other object,
the memory size and checksum of the object itself are returned.  Thus
you will get a smaller size (since it doesn't include the variable
overhead) for an object on the stack than for the same object stored
in a variable (the checksums will be the same).  I might guess that
you are using BYTES on stack objects, whereas the programs you
are checking against are using BYTES on the names of stored objects.

steveh@hpcvra.CV.HP.COM (Steve Harper) (06/16/90)

It does seem an obvious enough requirement to be able
to access an object "downstream" in the directory
structure (or "upstream" and then back down some other
branch), doesn't it?  How could we be so foolish as to
leave something like that out of the 48?  Well, we
weren't and we didn't.  I was going to say that all
you have to do is look on page such-and-so of the
manual... but if it's in there, I can't find it (:-(!
This must be something reserved for the reference
manual...

1. In the 28, if you EVAL a list, nothing happens.
It just returns the list, which is data.  On the
48, this was changed.  If you EVAL a list, the
individual objects in the list are EVAL'd in
order...essentially the same as a program.  So...
If you do something like {dir1 dir2 dir3 prog} EVAL,
the machine will search for dir1 in your current path,
and if it finds it, will make that your current
directory.  From there, it looks for dir2, which
can of course be a sub-directory in dir1, and makes
it the current directory.  Then the search continues
for dir3, etc, and then prog, which is a program, will
get executed... er, EVAL'd (sorry, Bill!).  This is
all well and good except that your current directory
is now dir3, which is likely not what you wanted.
The purpose of the SVC program in the previous
response was to accomplish what EVALing the list
does, but in addition to return the current directory
to what it was before.  Well, it turns out there is
some special code in the RCL function... If I do
this, for example: {dir1 dir2 dir3 prog} RCL, the
same searching takes place as before, but the current
directory does not change, and the object (prog, in this
case) is returned to the stack (RCL'd, not EVAL'd).
If it was a piece of data I wanted, I'm done; if it was
a program, I just do an EVAL after the RCL to execute
it (ooh, there's that word "execute" again...).  So you
can access objects anywhere in the directory structure
from anywhere else.  You just have to know the "path"
and put it in a list preceeding the object and then
RCL that list.  This is similar to a DOS or UNIX
path, except that in the 48, you have direct access to
anything upstream of your current directory without
having to specify it.

2. This same syntax can be used to EVAL or RCL objects
in the directory structure of a backup object.  Let's
say your favorite application consists of several
data variables and several programs and subroutines all
stored in a directory called 'app'.  You can save the
whole kit and kaboodle in the independent ram card in
port 2 by doing: 'app' RCL 2:app STO.  Now you can pull
the card (turn the machine off first...) and give it to
a friend or put it on the shelf for safe keeping.  Now
one day you or somebody else puts the card back in a
48 and wants to restore, not the whole application, but
only one little subroutine down in a sub-directory of
'app'.  2:{app subdir prog} RCL brings it back.  If the
object is a program to be EVAL'd, you could use EVAL
directly and skip the RCL step.  The machine will not
let your current directory reside in a backup object, so
the RCL isn't necessary here.  Forget which port your
card is in?  The wildcard character "&" instead of a
port number in the tagged backup object will cause the
machine to search port 2, port 1, port 0, and then
even search main ram to find the object.  &:obj RCL
will RCL obj from port 2 if it's there.  If not, then
it will RCL it from port 1.  If no luck there either,
it will try port 0, and if it still hasn't found obj,
then it will look in the current path in main ram.

Remember, to keep the parser happy, the tagged object
in the command line has two colons, like this: :2:obj.
The first one goes away when you press enter and put it
on the stack: 2:obj.  This is why, when you enter the
colon to the command line, you automatically get two of
them... except in alpha mode...

Neat, huh???  Hope this helps....

Steve

adamsd@crash.cts.com (Adams Douglas) (06/16/90)

I gather then that the { <dirpath> <obj> } RCL method you describe is
also the best way to do what _I_ was wondering, namely how do you
efficiently _move_ an object from one directory to another?