HP Forums

Full Version: [41CL] Another question for users
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

I'm thinking about doing a different version of the 41CL Extra Functions. But the FAT is full, so I have been thinking of ways to modify the set of functions available. One thing I thought of was to eliminate the UPLUG functions entirely - and instead using the PLUG functions with something like an "EMPT" identifier to signal to unplug the current image. I also thought that it might be handy to be able to use something like "?" in the Alpha register with the PLUG functions to return the current image plugged into the port. Any comments?


Certainly Angel would love to assist you in creating a sub function fat in a second bank switched page! :-)

Seriously: I think it's a good idea to omit redundant uplug - functions and to offer information about the page currently plugged in by exactly those modifications that you proposed:

- "FREE" or "0" (zero) in Alpha for unplugging;
just zero would save some bytes when used in a focal program.
( and in the mcode test routine as well, of course ).

- "?" for retrieving information.

Monte; Sounds as good ideas (EMPT/? for UPLUG/PLUG?)

Functions like the BAUDs and TURBOs could take the argument (speed) from X to make the sets single functions.

Functions like the BAUDs and TURBOs could take the argument (speed) from X to make the sets single functions.

Yes in PROGRAM mode, but please, please make them prompting in RUN mode !!!!

my first thought is "great idea"; my second is "OMG!! - there goes the PowerCL down to the gutter!"

I hope you keep the same FAT entries for those functions that remain, and only the removed ones are replaced with new?

Yes, I'll keep the same FAT numbering for the untouched functions. I'll also do my best to keep any other entry points (common subroutines) the same. That's why I was asking the question here, to let everyone point out any constraints that I should keep in mind.

I was hoping that I could utilize the subroutines that I have included in the new X-functions image, but probably not enough people have that version loaded in their machines. So I'll probably make a new version stand-alone in that regard. I do plan to use dynamic paging though (basically loading common routines into Page 4 as required, and then restoring Page 4 to its previous condition.)

Thanks everyone for the feedback. Monte

Here´s a few inputs for your consideration for the new version:

1. Protect YFNS/YFNP against accidental UNPLUG - checking for "OK" in ALPHA is a good method, also used in several other functions.

2. Restrict MMUCLR to operate only when the MMU is disabled.

3. Making UPLUGxx as an alternate of PLUGxx is a good idea to save 14 entries in the FAT. The EMPT mnemonic will work, although I´m sure I´ll miss the simplicity of today´s approach.

4. Making them prompting could save another 10+ entries. This is the approach used in the PowerCL, where SHIFT is also used to toggle between the PLUG and UNPLUG actions. I prefer this method for usability and maximum FAT entries saving, but the drawback is that in a program it will take an additional program line for the parameter.

5. Do a complete unplugging when using UPLUGxx on modules that straddle two ports - currently only the MMU settings for the first one are changed, and the "left-over" is behind.

6. Last and definitely *most*: pls. re-set the current page-4 mapping when doing the dynamic swapping you're planning - it's a fantastic idea but I'd not want the Library#4 to get lost during the action!


Edited: 29 May 2013, 3:42 a.m.

Agreed :-)

1. Not sure how this will work in conjunction with the new "EMPT" identifier and PLUG. Perhaps a dedicated identifier that means "no matter what"?

2. Good idea. Shouldn't be too hard.

3. I know. Engineering is all about compromise.

4. I'll think about it, but I shied away from prompting in the beginning just because it seemed more natural to me to specify the Port in the command itself.

5. This one can be a little messy. Searching the IMDB for the size, given the address extracted from the MMU programming, takes some time (witness the IMDB? execution time with an address specified). But there are unused bits in the MMU registers that could conceivably be used to mark the type of image loaded, that would make the process much easier. But that means even more changes to the PLUG function coding. May be worth it though.

6. Definitely will utilize the new MMU stack functionality, to restore the previous MMU contents.


It's not really important, but I can't see the point why "EMPT", a 4 character mnemonic, should be used to designate UPLUG. "0" would be sufficient, the PLUG routine could check for that special value first.
Or a special character can be defined for that task, which doesn't occur in IMDB mnemonics, like "-". And for unplugging YFNZ / YFNP, "00" or "--" should be required. Looks better than "EMPTOK". :-)

1a. It´s possible that the EMTP string is in alpha from a previous UNPLUG action (perhaps one big module that straddles two ports), and thus it´s still important to protect the YFNS page from accidental unplugging.

1b. Conversely, it´ll be important to protect it from accidental plugging over it, i.e. using PLUG for another module on the page currently used by YFNS.

5. The MMU bit idea sounds like the way to go - much more efficient than working it all out each time.


Edited: 30 May 2013, 3:00 a.m.

Good point - I like the 4-chr mnemonic for consistency. If the YFNS is protected from plug accidents using EMTP then there´s a need for a master-unplug code that would work on YFNS:- this is where I´d suggest using "OK" in alpha would do.

I went for a run this morning to fight the coach-potato syndrome (too much programming does that to you) and let my mind wander freely...

It occurred to me that the better approach to protect YFNS is not using special mnemonics, but to implement a true protection scheme that can be applied to any page. What a better use for those MMU bits still available than to be used to flag ports as plug-protected, so they cannot be unplugged or plugged-over while the protection status is ON.

YFNS would then inherit the protected status by default when plugged the first time (or after a MMUCLR event), remaining as such until the user decides to change it. Two functions needed (say YLOCK and YFREE as example) or just one if using the Toggle approach (say MMUTOG).

Other protection type could be write-protect for RAM pages, as the HEPAX does with function RAMTOG.

Your toughts?


I think that a "protect" bit in the MMU register itself makes sense. That works fine for the PLUG commands but I'm not sure that I want to mess with the YPOKE command. But if you're YPOKEing in the system area you need to know what you're doing anyway...

A page write-protect bit would also be easy to do, but again, it won't protect against a YPOKE with a physical address. I was originally going to implement a hardware write-protect bit in the MMU register, until I realized that an access with a physical address would bypass the feature. It will protect writes using the WROM instruction though.

I'll have to think some more about this. The error message cases are kind of complicated with dynamic paging. You can't just branch to an error message, but have to clean up the MMU for page 4 before exiting out with an error message. Another puzzle to solve.


Tentative updates to 41CL Extra Functions:

1. Eliminate all UPLUG functions, fold functionality into PLUG functions as described below.

2. Merge YFNZ and YFNP back into single image, restoring YBPNT, YBPNT?, YBUILD,

3. Add new MAPCLR function, to go with MAPEN and MAPDIS. Only works while mapping
is disabled.

4. MMUCLR function only works while MMU is disabled.

5. Add new PLUGL (plug into library, page 4) function.

6. Add new PLUG12 and PLUG34 functions, specifically for images that span two ports.

7. PLUG functions implement the 4-deep stack for MMU entries. Since this is not backwards-
compatible, I may want to implement some kind of enable for the functionality. I'm still
thinking about this. The MMU stack creates a 4-deep stack for each MMU entry, so
plugging in an image pushes the previous contents, which are restored when the image
is unplugged.

8. PLUG functions with "?" in Alpha return MMU contents for that page. Only works with
single page PLUG versions.

9.PLUG functions with ",," in Alpha pop the MMU stack, unplugging the current contents.
Works with all PLUG versions.

10. PLUG with "L:" in Alpha locks MMU contents - cannot be overwritten or unplugged.
(But writing directly to the MMU registers with YPOKE will override.)

11: PLUG with "U:" in Alpha unlocks MMU contents to allow overwriting or unplugging.

12: PLUG with "L:" or "U:" preceeding image identifier plugs in image with that attribute.
No prefix always inserts unlocked status, EXCEPT for YFNZ(S,P), which are always
inserted with locked status when plugged in.


here are some comments from me, fell free to ignore them as you see fit.

1. ok, still digesting the news...

2. sounds logical now that there are FAT entries available

3. not sure I see the need for it (desn´t MAPDIS suffice?) but ok

4. Great!

5. Excellent. Will it also work for the FORTH module, which takes ports 4 and 7?

6. Good idea, but what about PLUGging images straddling ports, i.e. using ports 9/A, or B/C...?

7. I think I get the concept of the MMU stack for each page, I guess this is how you´ll implement the dynamic page swapping. Yet it has some uncertainty regarding its work. Will the stack be pushed each time PLUG is used on that page? If so, I can foresee trouble when unplugging the image, which could (would) result not in an empty page but with another module replacing the previous one. Considering that the user may (most certainly will) have forgotten all about which ones were the previous tenants of that page, I envision trouble.

8. What about a PLUG? function instead?

9. See #7 above. Somehow I like "EMTP" better, not sure which characters have you chosen, two commas? Wouldn't it be needed to also have another function to really unplug the page, popping the four levels of the MMU stack at once?

10. What about a YLOCK function instead?

11. What about a YUNLOCK function instead?

13. Nice but the mnemonics are getting kinda long. It could also be accomplished using PLUG followed by YLOCK / YUNLOCK.

Great to see all this thinking going into the CL software, hope this gives you some more food for thought.


3. Currently the only way to initialize the MMU entries for Pages 0-3 is to use individual YPOKEs to the MMU registers. MMUCLR doesn't touch these entries at present, although I could just change that instead.

5. I suppose I could build the special case of the FORTH module into the PLUGL code. That would let me eliminate the special section in the CL manual...

6. Argh... that's more possibilities than I wanted to think about. My original goal, back at the beginning, was to have the functions be an analog of what users were used to when dealing with physical modules. Hence the PLUG mnemonics. I suppose I could remove the restriction of a single-page image for the L and U versions, to allow straddling a port, but I am concerned that might lead to more accidental "plugging over something" cases.

7. I am still thinking about this. I envisioned that it might be useful when I temporarily needed access to a particular function and would just transiently plug something in over my standard setup and then quickly return to normal. But the feature may only be really useful with Page 4.

8. But a PLUG? function will need a page parameter. I was trying to keep the user interface the same. It's probably the same number of keystrokes either way.

9. I was trying to reduce keystrokes. And thinking of the "cd .." from my UNIX days.

10 & 11. Same thing as #8. My expectation is that the lock/unlock status will almost always be set during the initial PLUG of an image, and even then only rarely.

12. But it's optional, and has the advantage of being backwards-compatible. But I'll think about it some more.

I appreciate the feedback. As far as the continued development, it gives me something to keep my brain active, even if we're the only two people in the world who care...


Edited: 2 June 2013, 11:31 a.m.

even if we're the only two people in the world who care...

You're not, but some of us are mostly "lurkers".

Where there's a choice between a bigger improvement or compatibility, I'd vote for the bigger improvement.

Here´s some follow up:

8.,10. & 11. - I always forget that PLUG is not just ONE function, but really are 14 functions instead; so you´re right new functions like YLOCK, etc. would also mean a set of them... not a good approach, unless of course they're replaced by a single prompting function; YLOCK _, plus pg#

The port metaphor is ok in that it mimics the real physical machine, but it´s also constrained by using the whole port as the "unit". That's why you implemented the PLUGL and PLUGU variants to begin with. With this we ended up with the 14 functions we have today:

PLUG1/2/3/4 for whole ports,

PLUG1L/2L/3L/4L, and PLUG1U/2U/3U/4U for half ports, plus

PLUGP and PLUGH for the HPIL-port.

Using the PAGE as a unit instead gets rid of this issue, but of course that'd need to be a prompting implementation or otherwise you´d need 11 of them: PLUGG4/6/7/8/9/A/B/C/D/E/F. This is how the PLUGG function launcher in the PowerCL works, dispatching behind the scenes to the half-port YFNS functions according to the input entered in its prompt.

This digression is just contextual, it's probably not reasonable to modify the PORT paradigm at this point, therefore the PLUG12 and PLUG34 could have their place - although there are just a few 16-k modules, so it's a very corner case. I counted 10 images in this category, as follows: ADV1, ADV2, P3BC, SIMM, ASTT, FUNS, SANA, XXXF, K135, DEMO.

They'll be good to avoid the accidental plugging-over, as it'd happen today using PLUG1/2/3/4 with those images - yet I guess nobody's complained about this. So if there are available FAT entries it'll be good to include them, forgetting about the port straddling as a practical design criteria.

My two cents again, I too need to keep this aging brain active.


As a lurker & user, I am very much enjoying this line of exploration of new CL functions. Just sayin'

My first reason for wanting to add PLUG12 and PLUG34 is that it will allow me to quickly check for the LOCK status before actually looking up the image information in the IMDB.

I realized last night that the LOCK feature can also be used when the MMU isn't enabled... protecting a physical module plugged into a port from an accidental conflict.


That enough is worth the admission price; PLUG12 and PLUG34 are definitely in! :-)

Speaking of physical modules conflicting with MMU settings - this is awfully similar to the "ROM Shadowing" we hear from other systems (like Clonix/NoVo and the W&W-41CY?). Would that be feasible on the CL as well?

From what I understand of "ROM shadowing" it would just require something to run at the power-on polling point. Basically fetch the MMU status for a page, temporarily disable translation, fetch a byte from the page to see if there is something in the physical Port, go to the next page if yes, restore the MMU settings if no. If you think that this is a useful feature it would not be hard to add. Of course it would require that the 41CL Extra Functions be plugged in, and I'd probably want to not check the page containing these functions...


I may be out of my depth here, why not do something like the following ...

a) interactive assign a module:

-> PLUG, non programmable, working like the ASN


-> ALPHA module-name ALPHA -> PLUG XXXX _

-> enter page number 0..9 A..F -> PLUG XXXX E

b) interactive remove a module:

-> PLUG, non programmable, working like the ASN



-> enter page number 0..9 A..F -> PLUG E

c) programmable assign a module:

-> PPLUG, programmable, working like the PSIZE

-> alpha contains the module name

-> X contains the module page

d) programmable remove a module:

-> PPLUG, programmable, working like the PSIZE

-> alpha is empty

-> X contains the module page

e) module query by page:

-> PLUGX?, working like the SIZE?

-> IN: X contains the module page

-> OUT: alpha contains the module name

f) module query by alpha:

-> PLUGA?, working like the SIZE?

-> IN: alpha contains the module name

-> OUT: X contains the module page

with error management:

1) message "DOUBLE XROM" in case of duplicate rom id

2) message "PAGE USED" if page is already used

3) message "NOT FOUND" if module name is not found

with flag 25 managed correctly

my grain of salt ...

Best regards,


edit: added e & f entry

Edited: 3 June 2013, 9:52 p.m.

Unfortunately, the interactive versions are probably beyond my programming capabilities.

Edited: 3 June 2013, 11:38 p.m.

From the ease of use this is great, and it follows the standards set by HP with their extension modules, like the X-Functions. It needs the X register and the Alpha registers to hold the data input parameters, perhaps the only drawback.

It´s also more RPN-like that the prompting - I remember some arguments against prompting functions used when the 48SX first came out; like using SF 00 vs. 0, XEQ "SF".

Prompting functions however are more intuitive and friendlier, you don´t need to remember the input sequence - which it´s suggested by the function itself.

Alpha prompting for ROM-based functions is a bit of a tricky issue. In RUN mode it all works dandy, but in a program things get hairy. Consider that HP never implemented this in plug-in ROMS, like the X-Functions; but rather they used the ALPHA register to hold the arguments of the functions instead. Think of PASN for instance, very different from ASN.

There are a few ways around this, as follows - in order of complexity and smoothness of the integration with the OS:

1. Get two functions to do the task, one in RUN mode (prompting, non-programmable) and another in program mode (takes inputs from X/Alpha). This is the ASN vs. PASN approach. The prompting function follows the standard conventions using the prompting bits in the function name, very well documented and trivial to implement. No extra coding is required at all for numeric prompts; little code snippets are needed to handle HEX inputs (like using A,B,C...F for the pages as opposed to 10, 12, ..15)

2. Use just one function, but behaving differently depending on which mode it´s being used in. This is checked using the CPU flags 4 and 13, so a couple of tests at the very beginning of the function code will fork to either mode. This can be done in a subroutine, common to many functions in the ROM. Drawback is the blank prompt in PRGM mode that must be input but is not taken in. The parameters are still taken from the stack (X) and/or ALPHA.

3. Implement the non-merged scheme whereby in a program the arguments are taken from the next program line. Examples of this abound in the 41Z and the SandMath (for instance RCL+ 12, or ZRCL 05). The simple version of this requires adding the argument line manually by the user. Same drawback as before with the blank input.

4. A refinement of the above - whereby the argument line is automatically placed in the program by the function itself. This is the HEPAX model, also used in the PowerCL and the SandMath. No drawbacks to speak of (except a corner case when doing SST execution in-between both lines) but it requires quite a lot of code, so it´s probably out of the question.

So in summary:

- if there are enough FAT entries available then #1 above is a safe and sound approach, by far the simplest.

- #2 is also easy and halves the number of FAT entries required.

- #3 is nicer and a very good compromise, as the extra code required is small and independent.

- #4 is tough. Extensive use of the [NEXTxx] routines is required (partial key sequence), and lots of trickery to bypass the OS design limitations.

A long rant but hopefully it helps.


Edited: 4 June 2013, 2:08 a.m.

yes that Rom Shadowing surrogate is a very nice approach! - it'll avoid conflicts mapping MMU entries to already taken ports. A logical extension of this is to implement these checks when doing MMUEN - making sure all the destinations are safe.

That will take care of half of the problem. The other half occurs when the user plugs a physical module into an MMU-occupied page. Addressing this requires a hardware re-design, or maybe not?

Edited: 4 June 2013, 1:56 a.m.

Here´s a real-life example of option #2 above applied to the four PLUG functions for whole ports. I modified the code in YFNP, adding a few lines at the beginning of the function to handle the input value in the prompt if used in RUN mode, or to take it from X if in program mode.

The new function PLUGX (following Sylvain's suggestion) replaces PLUG1, PLUG2, PLUG3, and PLUG4.

PAGERR	A6AC	20D	?NC XQ  	Build Msg - UF25 clear
A6AE 014 "T"
A6AF 019 "Y"
A6B0 010 "P"
A6B1 005 "E" "TYPE ERR"
A6B2 020 " "
A6B3 005 "E"
A6B4 012 "R"
A6B5 212 "R"
A6B6 1F1 ?NC GO display & halt execution
A6B7 0FE ->3F7C [APEREX]
Header A6B8 053 "X"
Header A6B9 007 "G" Plug Port
Header A6BA 015 "U" Prompting (1 char)
Header A6BB 30C "L"
Header A6BC 110 "P"
A6BE 01F JC +03 SST'ing a program
A6C0 02B JNC +05 NOT RUN'ing a program
A6C1 0F8 READ 3(X)
A6C2 38D ?NC XQ Convert it to hex - uses F8
A6C3 008 ->02E3 [BCDBIN]
A6C4 10E A=C ALL leaves it in C and A
A6C5 04E C=0 ALL
A6C6 0A6 A<>C S&X put x in C[S&X]
A6C7 25C PT= 9 acceptable values: 1,2,3,4
A6C8 226 C=C-1 S&X x-1
A6C9 226 C=C-1 S&X x-2
A6CA 01B JNC +03
A6CB 210 LD@PT- 8 PORT1
A6CC 06B JNC +13d [JOIN]
A6CD 226 C=C-1 S&X x-3
A6CE 01B JNC +03
A6CF 290 LD@PT- A PORT 2
A6D0 04B JNC +09 [JOIN]
A6D1 226 C=C-1 S&X x-4
A6D2 01B JNC +03
A6D3 310 LD@PT- C PORT 3
A6D4 02B JNC +05 [JOIN]
A6D5 226 C=C-1 S&X x-5
A6D6 0B5 ?NC GO
A6D7 0A2 ->282D [ERRDE]
A6D8 390 LD@PT- E PORT 4
JOIN A6D9 070 N=C ALL save for later use
A6DA 379 PORT DEP: Check module information
A6DD 06E A<>B ALL safeguard A in B
A6DE 0F0 C<>N ALL recall case
A6DF 0AE A<>C ALL put case in A
A6E0 0B0 C=N ALL restore C
A6E1 0A2 A<>C @PT plug case in C
A6E2 06E A<>B ALL restore original A
A6E3 01C PT= 3
A6E4 0A2 A<>C @PT
A6E5 0D0 LD@PT- 3
A6E6 3DC PT=PT+1
A6E7 362 ?A#C @PT is it type 3?
A6E8 223 JNC -60d [PAGERR]; if it's type 3 then error
A6E9 0A2 A<>C @PT otherwise restore tag
DPAGEX A6EA 09C PT= 5 check for type 0 or 8 first

the rest is all as-is, I'm sure you'll recognize the whereabouts - it starts at the same address as PLUG1 in the YFNP module, just moved the " TYPE ERR" message above the header.

lines A6BD to A6D4 are the RUN/PRGM initial routine. This can be put in an independent subroutine and called upon initialization. In fact such a routine is in the Library#4 already.

Lines A6DD to A6E2 make the changes compatible with the [MODN] routine output (I assumed register B was free to use and that A and C were needed).


Edited: 4 June 2013, 3:28 a.m.

If the user only plugs in a module while the calculator is off the power-on polling point will always catch a newly-inserted module. The only problem with this approach is due to the polling sequence, which goes 5-6-7---F-3. So the result will depend on where the 41CL Extra functions reside in the sequence, relative to the module. A newly-inserted module that is polled prior to the Extra Functions poll will catch the MMU-enabled image rather than an inserted module for the polling point. The module will still be detected, but if there is power-on code in the module that is supposed to be run, that won't happen.