100 REMark =========================
101 REMark "QLissajous" Figures
102 REMark by J.R. Waterman
102 REMark 20 May 2021
104 REMark =========================
105 REMark Based on a Spectrum
106 REMark listing by Stephen Keevil
107 REMark in Sinclair Programs
108 REMark July 1983 - page 19
109 REMark =========================
200 screen_setup
210 values
220 print_values
230 lissajous
240 CURSOR #0,129,20: PRINT #0,"PRESS ANY KEY FOR ANOTHER LISSAJOUS FIGURE"
250 REPeat loop
260   IF INKEY$(0)<>"" THEN EXIT loop
270 END REPeat loop
280 CLS #1: CLS #0
290 GO TO 210
1000 REMark ========================
1001 DEFine FuNction hcf(a,b)
1002 REMark ========================
1005 LOCal n,smaller,f
1010 IF a=b THEN RETurn b
1020 smaller=b: IF a<b THEN smaller=a
1030 FOR n=1 TO smaller+1
1040   IF a MOD n=0 AND b MOD n=0 THEN f=n
1050 NEXT n
1060 RETurn f
1070 END DEFine hcf
2000 REMark ========================
2001 DEFine PROCedure values
2002 REMark ========================
2005 LOCal smaller,n,h
2010 CURSOR #0,57,10: PRINT #0,"Input ratio of frequencies for Y and X axes - integer values only:"
2020 get_yfreq: get_xfreq: PAUSE 50: CLS #0
2040 get_yamp: get_xamp: REMark [PAUSE 50: CLS #0] - add this later if the amplitude facility is ever needed
2060 get_phaseangle
2071 REMark *** Y and X amplitudes are kept at 1 for now
2072 REMark *** need to cancel Y:X ratio to lowest terms - find HCF
2080 smaller=xfreq: IF xfreq>yfreq THEN smaller=yfreq
2090 h=hcf(yfreq,xfreq): yfreq=yfreq/h: xfreq=xfreq/h
2095 END DEFine values
2100 REMark ========================
2101 DEFine PROCedure get_yfreq
2102 REMark ========================
2110 CURSOR #0,57,20: PRINT #0,"Y-axis frequency:": CURSOR #0,171,20: INPUT #0,yfreq
2120 IF yfreq<>INT(yfreq) THEN int_vals_only: AT #0,2,28: PRINT #0,FILL$(" ",56): get_yfreq
2130 END DEFine get_yfreq
2150 REMark ========================
2151 DEFine PROCedure get_xfreq
2152 REMark ========================
2160 CURSOR #0,333,20: PRINT #0,"X-axis frequency:": CURSOR #0,447,20: INPUT #0,xfreq
2170 IF xfreq<>INT(xfreq) THEN int_vals_only: AT #0,2,74: PRINT #0,FILL$(" ",11): get_xfreq
2180 END DEFine get_xfreq
2200 REMark ========================
2201 DEFine PROCedure get_phaseangle
2202 REMark ========================
2210 AT #0,1,28: PRINT #0,"Input phase angle (0-360";CHR$(186);"):": AT #0,1,57: INPUT #0,phase
2220 IF phase<0 OR phase>360 THEN outside_range: AT #0,1,57: PRINT #0,FILL$(" ",28): get_phaseangle
2260 pa=RAD(phase)
2290 END DEFine get_phaseangle
2300 REMark ========================
2301 DEFine PROCedure get_yamp
2302 REMark ========================
2310 yamp=1
2320 END DEFine get_yamp
2350 REMark ========================
2351 DEFine PROCedure get_xamp
2352 REMark ========================
2360 xamp=1
2370 END DEFine get_xamp
2400 REMark ========================
2401 DEFine PROCedure int_vals_only
2402 REMark ========================
2405 LOCal n
2410 CURSOR #0,333,10: INK #0,2: PRINT #0,"integer values only!"
2420 BEEP 32767,88: FOR n=1 TO 150: NEXT n: BEEP
2430 CURSOR #0,333,10: INK #0,4: PRINT #0,"integer values only:"
2440 END DEFine int_vals_only
2450 REMark ========================
2451 DEFine PROCedure outside_range
2452 REMark ========================
2455 LOCal n
2460 AT #0,1,47: INK #0,2: PRINT #0,"0-360";CHR$(186)
2470 BEEP 32767,88: FOR n=1 TO 150: NEXT n: BEEP
2480 AT #0,1,47: INK #0,4: PRINT #0,"0-360";CHR$(186)
2490 END DEFine outside_range
2500 REMark ========================
2501 DEFine PROCedure print_values
2502 REMark ========================
2510 CLS #0
2520 AT #0,1,14: PRINT #0,"Frequency ratio, Y:X = ";yfreq;":";xfreq
2530 AT #0,1,55-(phase>9)-(phase>99): PRINT #0,"Phase angle = ";phase;CHR$(186)
2590 END DEFine print_values
3000 REMark ========================
3001 DEFine PROCedure lissajous
3002 REMark ========================
3010 LOCal n,scl
3020 scl=191.5
3030 POINT scl,scl+yamp*scl*SIN(pa)
3040 FOR n=1 TO 256
3050   LINE TO scl+xamp*scl*SIN(xfreq*n/128*PI),scl+yamp*scl*SIN(yfreq*n/128*PI+pa)
3060 NEXT n
3090 END DEFine lissajous
9000 REMark ========================
9001 DEFine PROCedure screen_setup
9002 REMark ========================
9010 MODE 4
9020 WINDOW #2,512,216,0,0
9030 BORDER #2,1,255: PAPER #2,0: INK #2,7
9040 WINDOW #1,260,192,126,12
9050 PAPER #1,0: INK #1,2: SCALE #1,383,0,0
9060 WINDOW #0,512,40,0,216
9070 PAPER #0,0: INK #0,4
9080 CLS #0: CLS #2: CLS #1
9090 END DEFine screen_setup
10000 REMark ========================
10001 DEFine PROCedure mon
10002 REMark ========================
10003 REMark Standard monitor screen
10010 MODE 4
10020 WINDOW #2,256,202,0,0
10030 BORDER #2,1,255: PAPER #2,7: INK #2,2
10040 WINDOW #1,256,202,256,0
10050 BORDER #1,1,255: PAPER #1,2: INK #1,7
10060 WINDOW #0,512,54,0,202
10070 PAPER #0,0: INK #0,4
10080 CLS #0: CLS #1: CLS #2
10090 END DEFine mon
11000 REMark ========================
11001 DEFine PROCedure tv
11002 REMark ========================
11003 REMark Standard TV screen
11005 MODE 8
11010 WINDOW #0,512,256,0,0
11015 PAPER #0,0: CLS #0
11020 WINDOW #2,448,200,32,16
11030 PAPER #2,1: INK #2,7
11040 WINDOW #1,448,200,32,16
11050 PAPER #1,2: INK #1,7
11060 WINDOW #0,448,40,32,216
11070 PAPER #0,0: INK #0,7
11080 CLS #0: CLS #1: CLS #2
11090 END DEFine tv
