Quote:
I am trying to create a "one touch" routine that will, as much as possible,
back up the entire state of my calculator to the SD card.
I expect that it's possible.
Quote:
The commands are simple enough to backup the home directory (ARCHIVE) and flag
settings (RCLF then STO to a variable of form :3:FLAGS, for example).
Or just store the list in a global variable, which will be included in the
archive.
Quote:
However, I would like my little program to be as thorough as possible, and I
was wondering if there is any easy way write the entire contents of IRAM,
ERAM, and FLASH (ports 0, 1, 2) to backup objects on the SD card, as
effortlessly as ARCHIVE does for the HOME directory.
Well, first off, on the 49 series (except perhaps the 48gII, which I'm not
very familiar with), I'd recommend not using port 0 for anything, unless
perhaps some library requires that it be in port 0. So why is it there? Well,
because it is useful on the 48 series, because a port is required for using
libraries, but not everyone owns an SRAM card for his 48SX or 48GX, and of
course the other models can't use a card. You might think as port 0 as being
somewhat like a RAM disk on a DOS system; if you don't have the hardware, then
simulate it with software. A major disadvantage of using port 0 is that it
shares the same pool of memory with "System RAM", so using it reduces the
amount of free memory. Another disadvantage is that a memory clear clears port
0 as well. But with the 49 series, you have other ports built-in, so why use
port 0?
Quote:
At this point this is largely an academic point--I don't store program objects
or variables in ports 0 thru 3, and since I install libraries from the SD card
I have the originals to reinstall manually if I ever have to. But it is a
curiosity and it would be neat to know if anyone else has ever considered it.
Sure. Wolfgang's Filer6 program includes includes an ->SD-> card operation, capable of
moving selected or all port objects to an flash card. See
http://page.mi.fu-berlin.de/raut/WR49/index.htm#General. It also has
other advantages; I prefer it to the built-in filer.
Quote:
As for backing up user key assignments, I must admit this interests me not at
all. The HP49+ keyboard is busy enough without me make a dogs breakfast of it
with my own assignments, so I don't use them. But if these assignments can be
recalled and saved to a backup object, like flags can, that would be good to
know.
That's not an issue anyway, because the user key assignments and alarm
information are stored in the hidden subdirectory, and are included within an
archive. Of course, when you RESTORE the archive, some of the alarms may be
past due, so I suppose that it would be a good idea to check them.
But you wanted all objects in a port to be backed up to the card, not just the
libraries. A very simple and easy (but not "one-touch") way is to tag all of
them in the filer, and then use it to copy them to the card. But writing a
UserRPL program to do it seems pretty straight-forward.
Traditionally, existing objects in ports can't be overwritten; if you want to
replace one, you have to purge it first. This first program behaves like that;
it errors out the first time that it can't store a file on the card.
%%HP: T(3)F(.);
@ For 49g+ or 50g.
@ Program to copy all objects from port 0, 1, or 2 to a flash card.
@ Will error out ("Object In Use") if the file already exists in the directory
@ on the flash card.
@ There must be enough free system memory available to hold the largest object
@ in the port, plus a little more.
@ There must be enough available capacity on the memory card to hold all of
@ the objects from the port.
@ Arguments:
@ Level 2: Real or zint, port number to copy objects from.
@ Level 1: String, directory on the card to store the files in, in the form
@ "DIR1/DIR2/DIR3". Use just an empty string, "", to store them in
@ the root directory. To key in the / character, press ALPHA (if
@ needed), then press RightShift, and then press the divide key.
@ Results from the BYTES command:
@ Checksum: #7B4Eh
@ Size: 149.
\<< @ Begin program.
"/" + @ Append to path.
SWAP PVARS DROP @ List of port variable names.
1. @ Loop index initial value.
OVER SIZE @ Loop index final value.
FOR n @
DUP n GET @ Tagged port variable name.
DUP RCL @ Port variable object.
SWAP DTAG @ Untagged port variable name.
IF @
DUP TYPE 28. == @ Library number?
THEN @
"L" SWAP + @ Prepend "L".
ELSE @
\->STR @ Quoted name within string.
2. OVER SIZE 1. - SUB @ Remove "'" name delimiters.
END @
4. PICK SWAP + @ Prepend path string.
3. \->TAG @ Tag with port number for memory card.
STO @ Store object as file on memory card.
NEXT @
DROP2 @ Discard path and list.
\>> @ End program.
But suppose that you want to store the files on the card, even if they already
exist there? That's an easy modification. This next program will replace
existing files
without warning.
%%HP: T(3)F(.);
@ For 49g+ or 50g.
@ Program to copy all objects from port 0, 1, or 2 to a flash card.
@ Will replace same-named files without warning.
@ There must be enough free system memory available to hold the largest object
@ in the port, plus a little more.
@ There must be enough available capacity on the flash card to hold all of the
@ objects from the port.
@ Arguments:
@ Level 2: Real or zint, port number to copy objects from.
@ Level 1: String, directory on the card to store the files in, in the form
@ "DIR1/DIR2/DIR3". Use just an empty string, "", to store them in
@ the root directory. To key in the / character, press ALPHA (if
@ needed), then press RightShift, and then press the divide key.
@ Results from the BYTES command:
@ Checksum: # C9EEh
@ Size: 154.
\<< @ Begin program.
"/" + @ Append to path.
SWAP PVARS DROP @ List of port variable names.
1. @ Loop index initial value.
OVER SIZE @ Loop index final value.
FOR n @
DUP n GET @ Tagged port variable name.
DUP RCL @ Port variable object.
SWAP DTAG @ Untagged port variable name.
IF @
DUP TYPE 28. == @ Library number?
THEN @
"L" SWAP + @ Prepend "L".
ELSE @
\->STR @ Quoted name within string.
2. OVER SIZE 1. - SUB @ Remove "'" name delimiters.
END @
4. PICK SWAP + @ Prepend path string.
3. \->TAG @ Tag with port number for memory card.
DUP PURGE @ Purge file if it exists.
STO @ Store object as file on memory card.
NEXT @
DROP2 @ Discard path and list.
\>> @ End program.
How about one that asks what to do if the file already exists? That doesn't
seem as if it ought to be too difficult, but I was surprised at how much time
I spent chasing down typos, as well as some things that I meant to type in,
but apparently didn't; maybe I needed a little food to power my brain? I
really should remember to eat when I need to. Anyway, this one seems to work
now.
%%HP: T(3)F(.);
@ For 49g+ or 50g.
@ Program to copy all objects from port 0, 1, or 2 to a memory card.
@ Will ask whether to replace a file.
@ There must be enough free system memory available to hold the largest object
@ in the port, plus a little more.
@ There must be enough available capacity on the memory card to hold all of
@ the objects from the port.
@ Arguments:
@ Level 2: Real or zint, port number to copy objects from.
@ Level 1: String, directory on the card to store the files in, in the form
@ "DIR1/DIR2/DIR3". Use just an empty string, "", to store them in
@ the root directory. To key in the / character, press ALPHA (if
@ needed), then press RightShift, and then press the divide key.
@ Results from the BYTES command:
@ Checksum: # D168h
@ Size: 491.5
\<< @ Begin program.
\<< @ Beginning of recursive subprogram for file exists.
PICK3 @ Untagged port variable name string.
"\010already on card.\010Press R to replace.\010Press S to skip.\010Press Q to quit." @
+ @ Concatenate strings.
CLLCD @ Clear display.
3. DISP @ Prompt for keystroke.
0. WAIT @ Wait for keystroke.
CLLCD @ Clear display.
IP @ Ignore keyplane.
CASE @
DUP 52. == @ R pressed?
THEN @
DROP @ Discard key value.
DUP PURGE @ Purge file from card.
STO @ Store object as file on memory card.
END @
DUP 53. == @ S pressed?
THEN @
3. DROPN @ Discard key value, name, and object.
END @
51. == @ Q pressed?
THEN @
5. DROPN @ Clean up stack.
0. DOERR @ Error out.
END @
\<-s EVAL @ Recurse.
END @
\>> @ End of subprogram for file exists.
\-> \<-s @ Bind.
\<< @ Begin local defining procedure.
"/" + @ Append to path.
SWAP PVARS DROP @ List of port variable names.
1. @ Loop index initial value.
OVER SIZE @ Loop index final value.
FOR n @
DUP n GET @ Tagged port variable name.
DUP RCL @ Port variable object.
SWAP DTAG @ Untagged port variable name.
IF @
DUP TYPE 28. == @ Library number?
THEN @
"L" SWAP + @ Prepend "L".
ELSE @
\->STR @ Quoted name within string.
2. OVER SIZE 1. - SUB @ Remove "'" name delimiters.
END @
DUP UNROT @ Copy to level 3.
5. PICK SWAP + @ Prepend path string.
3. \->TAG @ Tag with port number for memory card.
DUP2 @ Copy for error condition.
IFERR @ Trap error.
STO @ Try storing object as file on memory card.
THEN @
IF @
ERRN #9h == @ "Object in Use" error?
THEN @
IF @
-55. FC? @ Last argument saved?
THEN @
DROP2 @ Discard extra object and name.
END @
\<-s EVAL @ Execute subprogram.
ELSE @
ERRN DOERR @ Execute any other error.
END @
ELSE @
DROP2 @ Discard extra object and name.
END @
DROP @ Discard the string.
NEXT @
DROP2 @ Discard path and list.
\>> @ End local defining procedure.
\>> @ End program.
I really admire the input form in Jorge's BCKP21, but I'm too lazy to attempt
that.
A bigger problem would be automatically restoring the files to a port, as
there doesn't seem to be any built-in RPL (or assembly language) method of
getting a list of the files on the card (or in one of it's directories). Using
the filer is easy enough, but
SDFiler may well
include that capability (I haven't tried it yet).
Quote:
many thanks,
many welcomes, and,
Regards,
James