HP-71B BASIC Question - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html) +--- Forum: General Forum (/forum-4.html) +--- Thread: HP-71B BASIC Question (/thread-16481.html) |
HP-71B BASIC Question - Sylvain Cote - 03-16-2021 12:53 AM I have created a program that have multiple sub-routines and I have a user defined function (UDF) that need to be called from the main body and from the sub-routines. The manual and my tests told me that is not possible to call a UDF defined in the main body from a sub-routine. I am currently obliged to define it multiple times, in the main body and in all sub-routines creating code duplication. Do any of you have a work around ? (while still using UDF) Code: ! main body edit: I am searching for something equivalent to the C++ scoping "::" operator that would allow me to call the UDF defined in main space from a sub-routine space RE: HP-71B BASIC Question - toml_12953 - 03-16-2021 01:42 AM (03-16-2021 12:53 AM)Sylvain Cote Wrote: I have created a program that have multiple sub-routines and I have a user defined function (UDF) that need to be called from the main body and from the sub-routines. You might have to use GOSUB instead of CALL in order to avoid having to define the function multiple times. It doesn't look like there's any way around the separation of environments. RE: HP-71B BASIC Question - Valentin Albillo - 03-16-2021 02:38 AM . Hi, Sylvain: (03-16-2021 12:53 AM)Sylvain Cote Wrote: I have created a program that have multiple sub-routines and I have a user defined function (UDF) that need to be called from the main body and from the sub-routines. Not a criticism or nitpicking but you need to use the proper terminology: what you are trying to do is to call an UDF from a subprogram (CALL), not from a subroutine (GOSUB) Calling a main-program UDF from a subprogram is not possible, they use separate environments. Your options are:
Neither option is ideal, each have their disadvantages but at least you won't have to repeat the UDF in the main program and all subprograms that do use it. Regards. V. RE: HP-71B BASIC Question - J-F Garnier - 03-16-2021 09:34 AM (03-16-2021 12:53 AM)Sylvain Cote Wrote: edit: I am searching for something equivalent to the C++ scoping "::" operator that would allow me to call the UDF defined in main space from a sub-routine space Something equivalent exists for the CALL keyword, you can write: CALL MYSUB IN MYFILE to call the subprogram MYSUB in the file MYFILE. But not for UDFs. They are local to the current environment (where they are defined) in the Series 70/80 "Technical BASIC". The UDF implementation is a major difference relative to the HP BASIC in Series 200/300 ("RMB"), where the UDF are similar to subprograms, with their own environment, and can be called from any subprogram. Drawback of this approach is that they can't access the global variables of the environment that uses them, as is possible in the Series 70/80. J-F RE: HP-71B BASIC Question - Sylvain Cote - 03-17-2021 02:28 PM Valentin, criticize or nitpick at will, you are welcome. Valentin, Tom & Jean-François, you made me realize that I was asking too much from the BASIC language. I have been spoiled from all the languages/paradigms that I have used since the 1980's and I have difficulty going back to a world that does not even have functional decomposition. I am currently writing a HP-71B BASIC program that does low level HP-IL control and while the code grows I was trying to bring order to chaos. I will refactor the code to remove all the CALL/SUB and replace them with GOSUB/LABEL. I will also need to seriously manage variables names/usage because they becomes global. Thank you! Sylvain RE: HP-71B BASIC Question - Valentin Albillo - 03-17-2021 05:49 PM . Hi again, Sylvain: (03-17-2021 02:28 PM)Sylvain Cote Wrote: Valentin, criticize or nitpick at will, you are welcome. No, no, not at alll, I only tried to point out that you were actually using subprograms, not subroutines as you called them. Quote:Valentin, Tom & Jean-François, you made me realize that I was asking too much from the BASIC language. That's patronizing in the extreme. The HP-71B BASIC dialect is not "the BASIC language" but a 40-year old dialect which was very advanced for a handheld device in its time but 40 years later is nothing but a relic. "The BASIC language" nowadays would be something like MS Visual BASIC in its latest team-oriented incarnations, and you can ask very very much from it and it will deliver, in spades. I've participated in very large commercial projects using it and it worked flawlessly, minimizing the development time and being a pleasure to use. Quote:I have been spoiled from all the languages/paradigms that I have used since the 1980's and I have difficulty going back to a world that does not even have functional decomposition. May I remind you that all those "functional decompositions" and other such niceties in the end are converted behind the scenes to a bunch of low-level assembly language operations full of goto's and whatnot. Also, the HP-71B BASIC implementation takes much less than 64 Kb, and I wonder about the size of those advanced languages that even have "functional decomposition". Megabytes ? Gigabytes ? Last but not least, the possibility of sharing variables and other objects among the main program and subprograms already existed in HP's BASIC in the Series 80 and other models using so-called RMB BASIC, by using the COMMON statement to define a list of elements (don't remember right now if that included UDFs) to share among them. The 71B BASIC dialect does not implement that statement but that doesn't imply that "BASIC" in general doesn't. Quote:I will refactor the code to remove all the CALL/SUB and replace them with GOSUB/LABEL. Your decision, but it seems to me that this is the hardest way of the three I suggested. If your user-defined functions are single-line (as opposed to multi-line) no matter how long, it would be most convenient to use the S$ approach. Which is more, even if the definition takes 1,000 characters, you can dimension a 1,000-char string and VAL will evaluate it without complaining, which a single-line UDF can't do, being limited to ~90 chars or less. On the other hand, replacing your subprograms with subroutines will force you to redesign your variable names so there's no conflicts among them and might also incur in unforeseen side effects (OPTION BASE, for instance) as you're merging a number of different local environments into a single one. I think this goes against maintanability and dismisses the many good points inherent in using subprograms in the first place. Best regards. V. RE: HP-71B BASIC Question - Sylvain Cote - 03-17-2021 07:30 PM (03-17-2021 05:49 PM)Valentin Albillo Wrote:ROTFL, I did ask for it!(03-17-2021 02:28 PM)Sylvain Cote Wrote: Valentin, criticize or nitpick at will, you are welcome.No, no, not at alll, I only tried to point out that you were actually using subprograms, not subroutines as you called them. You are right, I should have wrote: "Valentin, Tom & Jean-François, you made me realize that I was asking too much from the HP-71B BASIC language implementation" Since this thread was about the HP-71B BASIC question, I wrongly assumed that my statement would be taken in that context, sorry about that. I also agree that other BASIC implementations has more advanced concepts build into them. Sure, all higher level languages with higher level abstractions are at the end converted to assembly language that are full of goto and gosub. IMHO the 64KB limit is a moot point because there have been other interpreters created that has support for more advance concept and runs within that space constraint. The HP-71B machine was part of the BASIC rage that span the 1970's & 1980's and that's ok. Now I have to decide how I will refactor my program. Thank you Valentin for your invaluable input, I mean it. Best regards, Sylvain RE: HP-71B BASIC Question - toml_12953 - 03-18-2021 07:56 AM (03-17-2021 07:30 PM)Sylvain Cote Wrote:(03-17-2021 05:49 PM)Valentin Albillo Wrote: No, no, not at alll, I only tried to point out that you were actually using subprograms, not subroutines as you called them.ROTFL, I did ask for it! I understood what you meant. RE: HP-71B BASIC Question - Sylvain Cote - 03-18-2021 11:02 AM I have decided to use the GOSUB/LABEL route, here is a snippet of code to show what it look like ... Code: 400 DEF FNB(S1)=IP(FP(S1/2^6)*2) ! IsDriveBusy(StatusByte) : returns 0=normal or 1=busy : mask 00100000 Code: 440 'ISMSTYPE': ! IN: A / UPD: D / OUT: - ! sub is device at address a mass storage type ? Code: 450 'BUSYWAIT': ! IN: A / UPD: S / OUT: - ! sub wait until drive is ready Code: 460 'READSTAT': ! IN: A / UPD: - / OUT: S,B,E,C,L ! sub read and decode drive status Code: 470 'BUILDMSG': ! IN: B,E,C,L / UPD: - / OUT: M$ ! sub build drive status message Code: 490 'REWIND': ! IN: A / UPD: S,B,E,C,L,M$ / OUT: - ! sub rewind tape RE: HP-71B BASIC Question - J-F Garnier - 03-19-2021 09:01 AM (03-18-2021 11:02 AM)Sylvain Cote Wrote: I have decided to use the GOSUB/LABEL route, here is a snippet of code to show what it look like ... Sylvain, may I suggest some improvements? You may implement or even replace these UDFs using the more efficient binary functions of the HP-IL ROM, for instance: replace IP(FP(S1/2^6)*2) with BIT(S1,5) replace FP(S1/2^4)*2^4 with BINAND(S1,15) There is no bit binary shift operation in the HP-71 BASIC but the integer division can be used, and you can rewrite IP(D1/2^4) as just (D1 DIV 16). J-F RE: HP-71B BASIC Question - Sylvain Cote - 03-19-2021 07:07 PM (03-19-2021 09:01 AM)J-F Garnier Wrote:Bonjour Jean-François,(03-18-2021 11:02 AM)Sylvain Cote Wrote: I have decided to use the GOSUB/LABEL route, here is a snippet of code to show what it look like ... The last time I have done serious programming on the HP-71B was in the 1980's. After spending a lot more hours than intended on that project, it is starting to come back, but man I am seriously rusted on that platform. Nice optimizations, tank you very much. Sylvain RE: HP-71B BASIC Question - Valentin Albillo - 03-20-2021 12:51 AM (03-19-2021 07:07 PM)Sylvain Cote Wrote: The last time I have done serious programming on the HP-71B was in the 1980's. A few simple additional ones, many of them avoid unnecessary GOTO's (slow and unsightly): 1) Your original (sans comments): 440 'ISMSTYPE': 441 D=DEVAID(A) @ IF FND(D)=1 THEN GOTO 443 442 DISP "Err: Inv Device Type" @ STOP 443 RETURN Somewhat optimized: 440 'ISMSTYPE': 441 D=DEVAID(A) @ IF FND(D)=1 THEN RETURN 442 DISP "Err: Inv Device Type" @ STOP 443 RETURN 2) Your original (sans comments): 450 'BUSYWAIT': 451 S=SPOLL(A) @ IF FNB(S)=1 THEN GOTO 451 452 RETURN Somewhat optimized: 450 'BUSYWAIT': 451 S=SPOLL(A) @ IF FNB(S) THEN 451 452 RETURN If you can use the JPC ROM: 450 'BUSYWAIT': 451 REPEAT @ S=SPOLL(A) @ UNTIL NOT FNB(S) 452 RETURN 3) Your original (sans comments): 460 'READSTAT': 461 S=SPOLL(A) @ B=FNB(S) @ E=FNE(S) @ C=FNC(S) 462 IF E=0 AND B=0 THEN L=0 @ GOTO 465 463 IF E=0 AND B=1 THEN L=1 @ GOTO 465 464 IF C=7 OR C=9 OR C=10 THEN L=1 ELSE L=2 465 RETURN Somewhat optimized: 460 'READSTAT': 461 S=SPOLL(A) @ B=FNB(S) @ E=FNE(S) @ C=FNC(S) 462 IF NOT E AND NOT B THEN L=0 @ RETURN 463 IF NOT E AND B THEN L=1 @ RETURN 464 IF C=7 OR C=9 OR C=10 THEN L=1 ELSE L=2 465 RETURN 4) Your original (sans comments): 470 'BUILDMSG' 471 IF E=0 AND B=0 THEN M$="" @ GOTO 486 472 IF E=0 AND B=1 THEN M$="Drive Busy" @ GOTO 484 473 IF C= 7 THEN M$="New Tape" @ GOTO 484 474 IF C= 9 THEN M$="Rec Number" @ GOTO 484 475 IF C=10 THEN M$="Rec Checksum" @ GOTO 484 476 IF C= 4 THEN M$="No Tape" @ GOTO 484 477 IF C= 8 THEN M$="Time Out" @ GOTO 484 478 IF C= 3 THEN M$="Tape:EOT+TS" @ GOTO 484 479 IF C= 1 THEN M$="End of Tape" @ GOTO 484 480 IF C= 2 THEN M$="Tape Stalled" @ GOTO 484 481 IF C= 5 OR C=6 THEN M$="Device" @ GOTO 484 482 IF C=12 THEN M$="Tape Size" @ GOTO 484 483 M$="Unknown" 484 IF L=1 THEN M$="Wrn:"&STR$(C)&":"&M$ 485 IF L=2 THEN M$="Err:"&STR$(C)&":"&M$ 486 RETURN Somewhat optimized and if you can use the JPC ROM: 470 'BUILDMSG' 471 IF NOT E AND NOT B THEN M$="" @ RETURN 472 IF NOT E AND B THEN M$="Drive Busy" @ GOTO 484 473 SELECT C @ CASE 7 @ M$="New Tape" 474 CASE 9 @ M$="Rec Number" 475 CASE 10 @ M$="Rec Checksum" 476 CASE 4 @ M$="No Tape" 477 CASE 8 @ M$="Time Out" 478 CASE 3 @ M$="Tape:EOT+TS" 479 CASE 1 @ M$="End of Tape" 480 CASE 2 @ M$="Tape Stalled" 481 CASE 5,6 @ M$="Device" 482 CASE 12 @ M$="Tape Size" 483 CASE ELSE @ M$="Unknown" @ END SELECT 484 IF L=1 THEN M$="Wrn:"&STR$(C)&":"&M$ 485 IF L=2 THEN M$="Err:"&STR$(C)&":"&M$ 486 RETURN 5) Your original (sans comments): 490 'REWIND': 491 GOSUB 'BUSYWAIT' @ GOSUB 'READSTAT' 492 IF L=2 THEN GOSUB 'BUILDMSG' @ DISP M$ @ STOP 493 DISP "Rewinding Tape ..." 494 SEND UNT UNL LISTEN A DDL 7 @ GOSUB 'BUSYWAIT'y 495 RETURN Somewhat optimized: 490 'REWIND': 491 GOSUB 'BUSYWAIT' @ GOSUB 'READSTAT' 492 IF L=2 THEN GOSUB 'BUILDMSG' @ DISP M$ @ STOP 493 DISP "Rewinding Tape ..." 494 SEND UNT UNL LISTEN A DDL 7 @ GOTO 'BUSYWAIT' (line 495 is now unnecessary and can be deleted) Hope that helps, make sure and check that they work Ok. Have a nice weekend and best regards. V. RE: HP-71B BASIC Question - J-F Garnier - 03-20-2021 09:23 AM (03-20-2021 12:51 AM)Valentin Albillo Wrote: A few simple additional ones, many of them avoid unnecessary GOTO's (slow and unsightly): Probably a matter of programming style, but I would rewrite it as: 440 'ISMSTYPE': 441 D=DEVAID(A) 442 IF FND(D)=0 THEN DISP "Err: Inv Device Type" @ STOP 443 RETURN There are as many programming styles as programmers ! Quote:Somewhat optimized and if you can use the JPC ROM: Yes! If you want to write better structured code, the JPC ROM is a must, with it's structured programming constructions modelled from the Series 200/300 HP BASIC. J-F RE: HP-71B BASIC Question - Sylvain Cote - 03-20-2021 01:03 PM Thank you Valentin and Jean-François for your comments, greatly appreciated. I am not the final consumer of this program, so I have the following hardware constraint: HP-71B, HP-IL and ~140KB of main memory, so no JPC for now . For the development phase, I have purposely made the choice to only have one exit point per sub-routine and to have the code logic reversed in some parts to have more freedom for error handling in case I need it. The final optimized code will include your suggestions when possible. Best regards, Sylvain RE: HP-71B BASIC Question - Sylvain Cote - 03-22-2021 10:31 PM I just published the final program in the General Software Library section (HERE). Any comments, suggestions, bugs report, etc are welcome. Sylvain RE: HP-71B BASIC Question - J-F Garnier - 03-24-2021 10:05 AM (03-22-2021 10:31 PM)Sylvain Cote Wrote: I just published the final program in the General Software Library section (HERE). Now that we know the final purpose of your program, I'm curious. What kind of system is using the same cassette type? Did you check yourself that these cassettes are readable in a 82161 drive? Some months ago, I have been contacted by a person who wanted to buy a PIL-Box to read cassettes used in a non-HP system. He too wanted to use a 82161 drive to read them. I provided the PIL-Box, explicitly saying I can't guarantee it will work, but didn't have feedback then. It was to read cassettes used in an old Data East DECO system. BTW, I advised this person to try my ILvLIF utility (together with the PIL-Box and the 82161) to make an image of the cassettes. J-F RE: HP-71B BASIC Question - Massimo Gnerucci - 03-24-2021 10:49 AM (03-24-2021 10:05 AM)J-F Garnier Wrote: It was to read cassettes used in an old Data East DECO system. Something like this? RE: HP-71B BASIC Question - rprosperi - 03-24-2021 12:40 PM (03-24-2021 10:05 AM)J-F Garnier Wrote: BTW, I advised this person to try my ILvLIF utility (together with the PIL-Box and the 82161) to make an image of the cassettes. I recommended ILvLIF at the very start of the exploration of these tapes, as dumping the tape to a PC disk file is its very purpose. Since the tapes contained non-HP data, using ILvLIF was deemed unlikely to succeed, and with an old tape, not in great shape (e.g. the pressure pad needed to be replaced) they did not want to possibly wear or damage the tape. I would have tried it anyhow, but in the end, it appears it likely would not have succeeded any better. But it's not too late to try, I plan to suggest doing so now when we meet on Saturday. RE: HP-71B BASIC Question - J-F Garnier - 03-24-2021 04:51 PM (03-24-2021 12:40 PM)rprosperi Wrote:(03-24-2021 10:05 AM)J-F Garnier Wrote: BTW, I advised this person to try my ILvLIF utility (together with the PIL-Box and the 82161) to make an image of the cassettes. The ILvLIF code would have to be tweaked a bit, to bypass the check for a LIF type volume and set the right tape parameters (# of sectors). Should not be too difficult. Quote:But it's not too late to try, I plan to suggest doing so now when we meet on Saturday. ? Are you/were you involved in these tape recovery? The tapes from Mark mentioned by Sylvain, or the tapes from Mike (the guy who bought me a PIL-Box in Aug.2020)? J-F RE: HP-71B BASIC Question - rprosperi - 03-24-2021 07:36 PM (03-24-2021 04:51 PM)J-F Garnier Wrote: The ILvLIF code would have to be tweaked a bit, to bypass the check for a LIF type volume and set the right tape parameters (# of sectors). Should not be too difficult. If it's simple and you have the time, please do issue a test version. It can't hurt... (03-24-2021 04:51 PM)J-F Garnier Wrote: ? Are you/were you involved in these tape recovery? The tapes from Mark mentioned by Sylvain, or the tapes from Mike (the guy who bought me a PIL-Box in Aug.2020)? This is a project (attempting to extract non-HP data from some compatible tapes) being done by a crew at HPCC (so with Mark), and is discussed bi-weekly during the virtual HPCC meetings (you see, we can't enough zoom sessions during the week with our jobs and family virtual meetings...). This is where I suggested ILvLIF, and where an initially very simple program to get the raw data began, and ultimately morphed into the more professional solution crafted by Sylvain. |