HP Forums

Full Version: HP-85 Lineart Program
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

The following is a graphics demo from the early 80s. I found the C version of it[1] and converted it to the HP-85.

Initially it precomputes a bunch of values (taking for ever, of course) and then starts creating graphics displays. After each display it beeps and waits 5 seconds, then starts on the next one.

The initial wait is long enough that I added a progress bar to let you know that its working, it prints "*" characters over a horizontal bar. When the bar is covered with (about 12 ) "*" the program is ready to start drawing.

Enjoy!

**vp

--------------------------------------------------------

1000 N0=12
1010 N1=343
1020 DIM F0(12,343)
1030 RAD
1040 GCLEAR @ SCALE 0,N0,0,10 @ XAXIS 0,1 @ MOVE 0,2 @ LABEL "Please Wait"
1050 FOR M=0 TO N0-1
1055 MOVE M+.4,1 @ LABEL "*"
1060 FOR X=0 TO N1-1
1070 ON M+1 GOTO 1110,1120,1130,1140,1150,1160,1170,1180,1190,1200,1210,1220
1110 F0(M,X)=SIN (2*PI *X/N1) @ GOTO 1300
1120 F0(M,X)=-SIN (2*PI *X/N1) @ GOTO 1300
1130 F0(M,X)=COS (2*PI *X/N1) @ GOTO 1300
1140 F0(M,X)=-COS (2*PI *X/N1) @ GOTO 1300
1150 F0(M,X)=SIN (4*PI *X/N1) @ GOTO 1300
1160 F0(M,X)=-SIN (4*PI *X/N1) @ GOTO 1300
1170 F0(M,X)=COS (4*PI *X/N1) @ GOTO 1300
1180 F0(M,X)=-COS (4*PI *X/N1) @ GOTO 1300
1190 F0(M,X)=SIN (6*PI *X/N1) @ GOTO 1300
1200 F0(M,X)=-SIN (6*PI *X/N1) @ GOTO 1300
1210 F0(M,X)=COS (6*PI *X/N1) @ GOTO 1300
1220 F0(M,X)=-COS (6*PI *X/N1) @ GOTO 1300
1300 NEXT X
1310 NEXT M
1400 ! ---------------
1410 DEF FNR(N) = INT (RND *(N-1))+1
2000 ! ---------------
2010 FOR C0=0 TO 100
2020 GCLEAR @ SCALE -1,1,-1,1
2030 I=FNR(N0)
2040 J=FNR(N0)
2050 IF I=J THEN 2040
2060 K=FNR(N0)
2070 L=FNR(N0)
2080 IF K=L THEN 2070
2090 FOR M=0 TO N1-1
2100 MOVE F0(I,M),F0(K,M)
2110 DRAW F0(J,M),F0(L,M)
2120 NEXT M
2130 BEEP @ WAIT 5000
2140 NEXT C0
2150 END

------------------------------------------------------------

[1] The original version was for the Sunview environment (a GUI for early SUN Microsystems workstations). SUN gave the source as an example of the graphics library supplied with these machines (Sun2 and Sun3 if you really want to know), and I have ported this to a number of systems over the years (BBC micro, TurboC for DOS, Pascal, etc.)

Vasili,
Awsome job. Didn't someone have a similar program for the HP-41C at some point where it would print on the portable printer? If so, maybe they can post it here again. (Hopefully !?@*)
Andreas

Vassilis,

can you explain, in a few words, what the SCALE statement does and what the screen resolution of the HP-85 is? We'll probably see a Sharp or Casio version in the future.

Marcus

I *really* should stop posting after midnight! :-)

Anyway there were a couple of problems with the program (namely it won't run on an HP-85 because of the huge array for the precomputed data). So here is a version that actually runs on an HP-85 and some screendumps to show what you should expect to see.

Some explanation about the program. Normally there are 12 functions, with functions 2,4,6,8 and 12 being the same as 1,3,5,9, and 11 but multiplied by -1. (i.e. if f1 is sin(x), f2 would be -sin(x)).

To avoid storing all twelve functions we calculate only the odd ones and then compute the even ones (by multiplying the corresponding odd value by -1) during the drawing (lines 2100 and 2110).

In the following listing lines starting with # are comments. BASIC lines always start with a line number.

#        Number of functions
1000 N0=12
# Number of lines
1010 N1=343
1020 DIM F0(6,343)
1030 RAD
1040 GCLEAR @ SCALE 0,N0/2,0,10 @ XAXIS 0,1 @ MOVE 0,2 @ LABEL "Please Wait"
1050 FOR M=0 TO N0/2-1
# Draw progress bar (series of 6 "*" characters
1055 MOVE M+.4,1 @ LABEL "*"
1060 FOR X=0 TO N1-1
1070 ON M+1 GOTO 1110,1130,1150,1170,1190,1210
1110 F0(M,X)=SIN (2*PI *X/N1) @ GOTO 1300
1130 F0(M,X)=COS (2*PI *X/N1) @ GOTO 1300
1150 F0(M,X)=SIN (4*PI *X/N1) @ GOTO 1300
1170 F0(M,X)=COS (4*PI *X/N1) @ GOTO 1300
1190 F0(M,X)=SIN (6*PI *X/N1) @ GOTO 1300
1210 F0(M,X)=COS (6*PI *X/N1) @ GOTO 1300
1300 NEXT X
1310 NEXT M
1400 ! ---------------
# Return random number between 0 and N (here 11)
1410 DEF FNR(N) = INT (RND *N)
1500 ! ---------------
# Return -1 is M odd and 1 if M even
1510 DEF FNS(M)
1520 FNS=-1
1530 IF M MOD 2=0 THEN FNS=1
1540 FN END
2000 ! ---------------
2010 FOR C0=0 TO 100
2020 GCLEAR @ SCALE -1,1,-1,1
2030 I=FNR(N0)
2040 J=FNR(N0)
# if I=J, get a new number for J
2050 IF I=J THEN 2040
2060 K=FNR(N0)
2070 L=FNR(N0)
# if K=L get a new number for L
2080 IF K=L THEN 2070
2090 FOR M=0 TO N1-1
2100 MOVE F0(INT (I/2),M)*FNS(I),F0(INT (K/2),M)*FNS(K)
2110 DRAW F0(INT (J/2),M)*FNS(J),F0(INT (L/2),M)*FNS(L)
2120 NEXT M
# You can put a COPY instruction here to get a screendump
2130 BEEP @ WAIT 5000
2140 NEXT C0
2150 END

The smaller array means that less data can be stored initially, so some computation needs to be carried out while drawing (lines 2100, 2110). This slows the drawing phase, but shortens the precompute phase, so you only have to wait for 6 stars (*):


Here are some actual screendumps from the HP-85 thermal printer. The images look a bit better on the screen.

**vp

Marcus von Cube wrote:

> can you explain, in a few words, what the SCALE statement does

The scale defines the mininum and maximum values of the X and Y axes.

The format is:
SCALE Xmin, Xmax, Ymin, Ymax

In this case, since we are using SIN and COS, we define SCALE to be -1,1,-1,1

> what the screen resolution of the HP-85 is? 
The HP-85 screen is rather small (5in diagonal) and supports a text screen (16 lines x 32 characters) and a graphics screen (192 x 256 pixels). Information can exist on both the text and graphics buffers and you can switch between them with the A/C key (alpha/graphics).


> We'll probably see a Sharp or Casio version in the future.

Shouldn't be too difficult. Its a very easy program to port. If you want I can send you the TurboC version (for MSDOS).

**vp

Andreas Terzis wrote:

> Didn't someone have a similar program for the HP-41C at some point
> where it would print on the portable printer?

If you want to produce such graphs on the HP-41 you'd need the HP-7470A HP-IL plotter and the HP-82184A Plotter Module. I am not sure whether the portable printer can really be used for such graphs (or rather let me rephrase, the 82162A probably can print the actual bitmap, but with the 41C driving it, it will take forever).

**vp

Hi, Vassilis:

Vassilis posted:

"The HP-85 screen is rather small (5in diagonal) and supports a text screen (16 lines x 32 characters) [...]"

    Actually, the physical text screen is indeed 16 lines x 32 characters, but the logical (buffered) text screen in 4 times larger, i.e., 64 lines x 32 characters, and you can page up and down in a continuous way, and enter, edit, or re-execute lines in any of the 4 pages.
Best regards from V.

Hi again, Vassilis:

    Very nice for you to post this piece of vintage software. I remember seeing and running this in absolute awe
    when I was young, and made several simple improvements to optimize for much needed running speed, among them:

    • at lines 1060-1300, the values 2*PI/N1, 4*PI/N1, 6*PI/N1 are
      invariant within the FOR X loop, so you can save time by
      simply assigning them first outside of the loop, say:
          Q1=2*PI/N1 @ Q2=2*Q1 @ Q3=3*Q1
      then using these variables within the loop, say:
          1110 F0(M,X)=SIN (Q1*X) @ GOTO 1300
      ...
      and the same for the other two. This can be done in 6 places
      and saves significant time.

    • User-defined function calling is very convenient *but* notoriously slow in HP-85 BASIC
      (and some other HP BASICs as well, HP-71B BASIC comes to mind) so you can save a lot of time by deleting:
            1510 DEF FNS(M)
      1520 FNS=-1
      1530 IF M MOD 2=0 THEN FNS=1
      1540 FN END
      and replace the lines where it's called by this:
      2100     MOVE F0(INT (I/2),M)*(1-2*(I MOD 2)),F0(INT (K/2),M)*(1-2*(K MOD 2))
      2110 DRAW F0(INT (J/2),M)*(1-2*(J MOD 2)),F0(INT (L/2),M)*(1-2*(L MOD 2))
      now, since I,J,K, and L are invariant within the FOR M loop at lines 2090-2120,
      you can precompute outside the FOR M loop their several appearances and assign them to variables, like this:
            I2=INT(I/2) @ I3=1-2*(I MOD 2) @  J2=INT(J/2) @ J3=1-2*(J MOD 2) 
      K2=INT(K/2) @ K3=1-2*(K MOD 2) @ L2=INT(L/2) @ L3=1-2*(L MOD 2)
      so that within the FOR M loop you only have:
      2100     MOVE F0(I2,M)*I3,F0(K2,M)*K3
      2110 DRAW F0(J2,M)*J3,F0(L2,M)*L3
      which is much simpler and thus will run much faster.

    • Likewise with FNR, simply delete:
            1410 DEF FNR(N) = INT (RND *N)
      and replace the lines where it's called:
            2030   I=INT(RND*N0)
      2040 J=INT(RND*N0)

      2060 K=INT(RND*N0)
      2070 L=INT(RND*N0)

      this will also run faster.

    • Finally, you can concatenate as many statements as will fit in a line, using the @ concatenator, which will degrade readability but will shorten the program listing, decrease its size in RAM, and make it somewhat faster as well.

    The resulting program will be shorter and appreciably faster, as you may see.

Best regards from V.

Hello Vassilis,

There was a similar, but simpler program from HP in one demo or game disc for the HP85. I remember I wrote a HP41 version using a Tandy 4 color mini plotter printer (was quite commun at the time). I will post it if I can recover it from my archives.

J-F

Here are the HP41 and Basic versions:

Edited: 17 Mar 2006, 2:07 p.m.

Thanks Valentin for the enhancements.

I didn't want to mess too much with the code, but I should have observed the loop invariants. First write a slow program and then complain about the speed of the processor? Maybe I was an applied physics researcher in a previous life :-)

**vp

PS I was also thinking that rather than filling the array before I start drawing, I should use it to cache computed values. I.e. fill it with an invalid number (say 2). Then every time you come across an entry that is less than 2 you use it, otherwise, you calculate the correct value and store it in the array and then use it. Eventually the array will be populated and the program will run at full speed. However, it may complicate the inner loop so much that it will make the program slow even when the array is fully populated.

You can even calculate these values once and store them in a file.
If the file exists, you load it, otherwise you calculate the values and create the file.

BTW has anybody really noticed how SLOW the HP-85B is compared to the HP-87XM (these are the machines I am currently using, but I would expect this to be true for the A versions of these models as well).

Each drawing in the lineart program takes 3+ minutes on the HP-85B, but less than half (1.10 minutes) on the 87. I thought that the memory management hardware on the 87 where supposed to make it a bit slower.

BTW both machines are running exactly the same program. The earlier version (the one on the top of this pafe) that precomputes all values (and runs only on the 87), is slightly faster even though it does not include any of Vallentine's enhancements.


Edited: 17 Mar 2006, 3:08 p.m.