AMS-81 is a satellite pass scheduling and real-time tracking utility designed for amateur radio operators, computing orbital positions from Keplerian elements. The program propagates orbits by iteratively solving Kepler’s equation using an eccentric anomaly refinement loop (lines 5100–5150), then transforms results through a rotation matrix built from inclination, RAAN, and argument of perigee (lines 3740–3790). Ground station coordinates are converted to Earth-centered Cartesian coordinates accounting for the oblate Earth flattening factor (lines 3020–3110). A rich set of symbolic constant aliases—including U, G, TEN, HEX, INF, and others—compresses frequently used numeric literals throughout the code. SLOW/FAST mode switching and a configurable step-size variable PHI allow the tracking loop to balance computational accuracy against display refresh speed.
Program Analysis
Program Structure
The program is organized around a main menu at lines 10–120 that dispatches to four functional areas based on a single keypress. The four activities are scheduling (option 1, lines 130–960), real-time tracking (option 2, lines 970–2290), Keplerian file editing (option 3, lines 2300–2810), and QTH (ground station) configuration (option 4, lines 2820–3120). A save/resave path exists at lines 3130–3230. The remaining lines (roughly 3240–5650) form a library of subroutines shared across all four activities.
Symbolic Constant Aliases
To save memory and reduce token overhead, frequently used numeric values are pre-assigned to short variable names at program start or within initialization routines. Key aliases encountered throughout the listing include:
| Variable | Approximate Value / Meaning |
|---|---|
U | 1 |
G | 0 |
U2 | 2 |
U3 | 3 |
U4 | 4 |
TEN | 10 |
HEX | 16 |
INF | A large sentinel value (used for orbit counter initialization) |
P0 | π/180 (degrees-to-radians factor) |
P2 | 2π |
HA | 0.5 |
HUN | 100 |
THO | 1000 (also used as PAUSE duration) |
DYR | Days per year (365.25 or similar) |
R0 | Earth’s equatorial radius |
G0 | Gravitational parameter (GM) |
G1 | Earth’s rotation rate (radians per day) |
CL | Speed of light (used for Doppler calculation) |
AF | Step-size scaling factor |
IN | Step increment base |
Orbital Mechanics Engine
Orbit propagation begins in subroutine KSC (line 3460), which sets up mean motion N, semi-major axis A, and the J2 perturbation corrections for RAAN drift (O) and argument-of-perigee precession (W) using a K2 coefficient at line 3650. The rotation matrix C() (lines 3740–3790) transforms perifocal coordinates to Earth-centered inertial (ECI) coordinates.
Kepler’s equation is solved iteratively in lines 5100–5150:
- An initial estimate of eccentric anomaly
Eis formed from the mean anomalyMplus first- and second-order series terms (line 5100). - The residual
M5 = E - e·sin(E) - Mis computed (line 5110). - Newton–Raphson correction
E = E - M5 / (1 - e·cos(E))is applied (lines 5130–5140) until convergence to within 1×10⁻⁶.
ECI position is then rotated into Earth-fixed coordinates using the Greenwich sidereal angle G7 (lines 5220–5250), and the ground-station vector (computed at lines 3020–3110 with oblate-Earth correction) is subtracted to yield the topocentric range vector.
Ground Station Geometry
Lines 3020–3110 convert the observer’s geodetic latitude L9, west longitude W9, and altitude H9 into Earth-centered Cartesian coordinates X9, Y9, Z9. The geodetic-to-geocentric latitude conversion at line 3080 uses the standard flattening formula tan(φ_c) = (1-f)² · tan(φ_g), where F is the flattening constant. Elevation E9 and azimuth A9 are derived in the CO4 / AZ subroutine block (lines 5270–5390).
Scheduling Logic
The scheduler (lines 130–960) uses subroutine SCH (line 5550) to bracket AOS (Acquisition of Signal) and LOS (Loss of Signal) by bisecting the sign of the dot product QS between the satellite position and the ground station vector. The step size PHI is halved whenever a sign change is detected, converging on the horizon crossing. The array A() stores AOS time, AOS range, LOS time, and LOS range for each pass, and the display loop (lines 470–960) formats these into a columnar schedule with day dividers injected by subroutine DD (line 1670).
Real-Time Tracking Display
The tracking activity (lines 970–2290) calls subroutine LP2 in a tight loop, displaying UTC, azimuth, elevation, range, phase angle (for eccentric orbits), and Doppler shift. The Doppler estimate at lines 1580–1600 approximates the radial velocity from consecutive range measurements R5 divided by the elapsed time, scaled by the carrier frequency F(I) and speed of light CL. SLOW/FAST mode is managed by the FS flag: pressing F sets FS=U (fast), pressing D sets FS=G (slow). Page-full pauses at line 2040 prompt the operator to continue or exit.
Date/Time Handling
Two date formats are accepted by the DAY subroutine (lines 4050–4390): a compact decimal epoch like 83 105.46677538 (two-digit year, day-of-year with fractional day) and a calendar format like 15APR83 111209 (DDMMMYY HHMMSS). A 13-element month table M$() stores three-letter abbreviations alongside cumulative day-of-year offsets. Leap-year detection is handled by testing divisibility by 4 and checking whether the day number is at or past day 59 (lines 4350, 4450). The inverse DAO routine (lines 4400–4630) converts an internal day number back to both display formats simultaneously.
Keplerian File Editor
Option 3 (lines 2300–2810) presents each Keplerian element in turn for in-place editing. Elements are stored in parallel arrays: I(I) inclination, O(I) RAAN, E(I) eccentricity, W(I) argument of perigee, M(I) mean anomaly at epoch, N(U,I) mean motion (or semi-major axis if >100), and N(U2,I) mean motion derivative. The satellite name S$(I), catalog ID I$(I), and downlink frequency F(I) are also editable. Any modification sets the dirty flag SV=U, enabling the “NEED TO RESAVE” option 5 on the main menu.
Keypress and Flow-Control Idioms
The program makes heavy use of a polling keypress subroutine KSC (line 3270) that checks INKEY$ without blocking. A PAUSE 0 / INKEY$ construct is used at other points for true blocking waits. The GO variable serves as a global flow-control token: GO=G (0) signals an abort-to-main-menu condition tested after nearly every subroutine call with the pattern IF GO=G THEN GOTO G (branching to line 0, which does not exist—a standard technique to fall through to the top of the program). GO=U9 (9) signals a page-pause condition handled within KSC.
Notable Techniques
- The orbital visibility pre-check at line 3920 uses the maximum elevation formula to quickly reject satellite/QTH combinations where passes are geometrically impossible, printing “PASSES CANNOT OCCUR” and aborting.
- The adaptive step size in
PHI(lines 1360–1390 and 5560–5650) scales the propagation interval by the ratio of the current angular change to a target change angleCA, allowing large steps far from events and fine steps near AOS/LOS and maximum elevation. - Line 3800 indexes a Greenwich sidereal time table
G()by year to initializeG2, avoiding recomputation of the epoch sidereal angle from scratch each call. - The
VAL E$(J, U5 TO TEN)idiom at line 2620 extracts element values from a string array used as a formatted data file, acting as a simple flat-file database. - SLOW is unconditionally re-entered at line 3940 before error messages to ensure readable display timing regardless of the current
FSstate.
Potential Anomalies
- At line 3480, if
N(U,I)is zero it is set toHUN(100) to prevent division by zero, then interpreted as a semi-major axis rather than mean motion—this dual-mode interpretation (lines 3490–3540) may produce unexpected results if an element set is partially initialized. - The Doppler computation (line 1580) divides by
(D-T6), which is the elapsed time since the last update in fractional days. When the tracking loop runs very fast,D-T6can be extremely small, potentially producing noisy Doppler readings; theIF T6<>Dguard prevents a divide-by-zero but does not smooth the result. - The azimuth subroutine at line 5320 special-cases
X8=0(satellite exactly north or south) by assigning 90° or 270°, but theIF X8<>Gtest means any non-zeroX8, however small, goes to theATNbranch—correct behavior, but the zero case is intentionally narrowly defined.
Content
Source Code
10 LET GO=U
20 LET FS=G
30 CLS
40 SLOW
50 PRINT H$
60 PRINT " VERSION N5BF 1.4 01APR83"
70 PRINT AT U8,U7;"%<%<%<% %A%C%T%I%V%I%T%I%E%S% %>%>%>";AT TEN,U7;;"1 = SCHEDULE";TAB U7;"2 = TRACK";TAB U7;"3 = KEPLERIAN FILE";TAB U7;"4 = QTH INFO";AT HEX,TEN;"@@SELECT 1-4@@"
80 IF SV=1 THEN PRINT AT U14,U7;"5 = NEED TO RESAVE";AT HEX,U20;"5"
90 LET A$=INKEY$
100 IF A$="" THEN GOTO 90
110 PRINT AT HEX,U22;A$
120 IF A$<>"1" THEN GOTO 970
130 GOSUB 4890
140 IF GO=G THEN GOTO G
150 GOSUB HD1
160 GOSUB INK
170 GOSUB CO3
180 LET LOS=U
190 GOSUB SCH
200 IF GO=G THEN GOTO G
210 LET A(U)=D
220 LET A(U2)=R5
230 LET LOS=-U
240 LET QS=U
250 GOSUB SCH
260 IF GO=G THEN GOTO G
270 LET A(U3)=D
280 LET A(U4)=R5
290 LET PHI=G
300 IF E(I)<U01 AND N>TEN THEN GOTO 430
310 LET D=D+(INT Q-Q+HA)/N
320 LET T=G
330 GOSUB CO1
340 IF A(U)>D OR A(U3)<D OR E(I)<U01 THEN GOTO 370
350 LET E9=R0*(COS (E9*P0)*ASN (R5/R)+ACS (R0/R))
360 GOTO LP1
370 LET D=A(U)
380 IF A(U4)>A(U2) THEN LET D=A(U3)
390 LET T=U
400 GOSUB CO1
410 LET E9=U2*R0*ACS (R0/R)
420 GOTO LP1
430 LET D=(A(U)+A(U3))/U2
440 GOSUB CO1
450 LET T=U2
460 GOTO LP1
470 CLS
480 GOSUB DAO
490 PRINT AT G,G;H$;"ACCESS SKED FROM: ";D$;" >>";C$;" VIA ";S$(I);"<<","% %D%A%Y% % % %A%O%S% % %L%O%S% % % %M%A%X% %D%X%/%E%L% % % %A%Z"
500 LET LP=U4
510 RETURN
520 IF GO=G THEN GOTO G
530 LET A(U5)=D
540 LET D=A(U)
550 GOSUB DAO
560 LET D$=D$( TO U5)+D$(U8 TO U12)+N$
570 LET J=U12
580 LET D=A(U3)
590 GOSUB TIM
600 LET D$(HEX TO 17)=" "
610 LET D=A(U5)
620 LET J=U18
630 GOSUB TIM
640 LET D$=D$( TO U21)+" "
650 IF T=U2 THEN GOTO 720
660 LET D$=D$+STR$ INT E9+" "
670 IF LEN D$>=29 THEN GOTO 700
680 LET D$=D$( TO U22)+D$(U22 TO )
690 GOTO 670
700 IF T=U THEN LET D$(U28)="*"
710 GOTO 740
720 GOSUB LZ2
730 LET D$=D$( TO 24)+" %E%L "
740 GOSUB LZ3
750 PRINT AT LP,G;D$( TO U32)
760 LET LP=LP+U
770 IF A(U3)-A(U)<U THEN GOTO 840
780 LET D=A(U3)
790 LET D$=N$+" "
800 LET J=U9
810 GOSUB DAO
820 PRINT AT LP,U4;"(LOS DATE = ";D$( TO U7);")"
830 LET LP=LP+U1
840 IF LP<U20 THEN GOTO 930
850 LET GO=U9
860 PRINT "## RETURN = 0, CONT = 1 ##"
870 GOSUB KSC
880 IF F$="Z" AND PRIN=U THEN COPY
890 IF GO=U9 THEN GOTO 870
900 GOSUB CLB
910 IF GO=G THEN GOTO G
920 GOSUB HD1
930 LET D=A(U3)
940 GOSUB INK
950 LET QS=-U
960 GOTO 180
970 IF A$<>"2" THEN GOTO 2300
980 LET CT=1.2*CA
990 LET CB=.8*CA
1000 GOSUB 4890
1010 LET LOS=U
1020 IF GO=G THEN GOTO G
1030 GOSUB HD2
1040 GOSUB INK
1050 GOSUB CO1
1060 IF GO=G THEN GOTO G
1070 IF E9>G THEN GOTO 1140
1080 LET QS=-U
1090 LET LOS=U
1100 GOSUB SCH
1110 LET PHI=G
1120 GOSUB CO1
1130 IF GO=G THEN GOTO G
1140 LET FS=G
1150 LET F8=G
1160 LET T6=D
1170 LET R6=R5
1180 LET PHI=CA*R*AF
1190 GOSUB LP2
1200 IF GO=G THEN GOTO G
1210 IF LP=U4 THEN GOSUB LP2
1220 IF LOS=-U THEN GOTO 1080
1230 GOSUB INK
1240 LET D2=D
1250 LET E8=E9
1260 LET A8=A9
1270 LET PH2=PHI
1280 FOR L=U TO U5
1290 GOSUB CO1
1300 IF GO=G THEN GOTO G
1310 GOSUB DD
1320 IF DAZ>CT OR DEL>CT THEN GOTO 1340
1330 IF (DAZ>CB OR DEL>CB) AND INT Q=INT Q1 THEN GOTO 1540
1340 LET D1=DAZ
1350 IF DEL>DAZ THEN LET D1=DEL
1360 LET PHI=CA*PHI/D1
1370 LET D=D2
1380 IF INT Q=INT Q1 AND PHI>1E-5 THEN NEXT L
1390 LET PHI=PH2
1400 LET ER=G
1410 GOSUB CO1
1420 IF GO=G THEN GOTO G
1430 GOSUB DD
1440 IF DAZ>CT OR DEL>CT THEN GOTO 1470
1450 IF DAZ>CB OR DEL>CB THEN GOTO 1530
1460 IF ER=G THEN GOTO LSC
1470 LET ER=U
1480 LET D1=DAZ
1490 IF DEL>DAZ THEN LET D1=DEL
1500 LET D1=SGN (D1-CA)
1510 LET PHI=-HA*ABS PHI*D1
1520 GOTO LSC
1530 LET PHI=PH2
1540 IF E9>HA THEN GOTO 1580
1550 LET LOS=-U
1560 GOSUB SCH
1570 IF GO=G THEN GOTO G
1580 IF T6<>D THEN LET F8=F(I)*(R6-R5)/(D-T6)/CL
1590 LET R6=R5
1600 LET T6=D
1610 GOTO 1190
1620 LET DAZ=ABS (A9-A8)
1630 IF DAZ>180 THEN LET DAZ=360-DAZ
1640 LET DAZ=ABS (DAZ*(COS (E9*P0)))
1650 LET DEL=ABS (E9-E8)
1660 RETURN
1670 IF INT D=D0 THEN GOTO 1760
1680 LET D$=N$
1690 LET J=U9
1700 GOSUB DAO
1710 IF GO=U2 OR GO=U7 THEN GOSUB SS
1720 PRINT AT LP,G;" ----";D$( TO U7);"---- "
1730 LET D0=INT D
1740 LET LP=LP+U
1750 IF LP>U20 AND GO<>U2 AND GO<>U7 THEN GOTO HD2
1760 LET D$=" "
1770 LET J=U
1780 GOSUB TIM
1790 IF GO=G THEN RETURN
1800 GOSUB LZ3
1810 GOSUB LZ2
1820 LET D$=D$( TO U4)+":"+D$(U5 TO )+STR$ INT R5+" "
1830 IF LEN D$>=U21 THEN GOTO 1860
1840 LET D$=D$( TO U15)+D$(U15 TO )
1850 GOTO 1830
1860 IF E(I)>=U01 THEN LET D$=D$+STR$ INT (M/P2*256)+" "
1870 IF E(I)<U01 THEN LET D$=D$+"--- "
1880 IF LEN D$>=U25 THEN GOTO 1910
1890 LET D$=D$( TO U21)+D$(U21 TO )
1900 GOTO 1880
1910 LET A$=STR$ (INT (F8/HUN+HA)/TEN)
1920 IF INT VAL A$=VAL A$ THEN LET A$=A$+".0"
1930 IF F8=G THEN LET A$=STR$ F(I)
1940 LET D$=D$+A$+" "
1950 IF LEN D$>=U32 THEN GOTO 1980
1960 LET D$=D$( TO U25)+D$(U25 TO )
1970 GOTO 1950
1980 IF GO=U2 OR GO=U7 THEN GOSUB SS
1990 IF GO=G THEN RETURN
2000 PRINT AT LP,G;D$( TO U32)
2010 LET LP=LP+U
2020 IF LP<U21 OR GO=U2 OR GO=U7 THEN RETURN
2030 IF GO=U3 THEN GOTO HD2
2040 LET GO=U9
2050 PRINT J$
2060 GOSUB KSC
2070 IF GO=U9 THEN GOTO 2060
2080 GOSUB CLB
2090 IF GO=G OR GO=U2 OR GO=U7 THEN RETURN
2100 CLS
2110 LET D0=INT D
2120 GOSUB DAO
2130 PRINT AT G,G;H$;" TRACKING FROM ";D$," >>";C$;" VIA ";S$(I);"<<","% % %U%T%C% % % % %A%Z% %E%L% %R%A%N%G%E% %P%H%S% %D%O%P%P%L%E%R"
2140 LET LP=U4
2150 LET GO=U
2160 RETURN
2170 IF GO=U2 AND ST=U9 THEN GOTO 2240
2180 PRINT AT U21,G;J$
2190 LET GO=U9
2200 GOSUB KSC
2210 IF GO=U9 THEN GOTO 2200
2220 GOSUB CLB
2230 IF GO<>U2 AND GO<>U7 AND GO<>G THEN LET GO=U3
2240 SCROLL
2250 LET LP=U20
2260 PRINT AT U21,U31;
2270 RETURN
2280 PRINT AT U21,G;N$;N$;" "
2290 RETURN
2300 IF A$<>"3" THEN GOTO 2820
2310 GOSUB SAT
2320 IF GO=G THEN GOTO G
2330 CLS
2340 PRINT H$;AT U2,G;"%N%A%M%E% ";AT U2,U7;S$(I)
2350 PRINT AT U18,G;L$;K$
2360 INPUT A$
2370 IF A$="" THEN GOTO 2410
2380 LET SV=U
2390 LET S$(I)=A$
2400 PRINT AT U2,U7;S$(I);N$
2410 PRINT AT U3,G;"%I%D% % % ";AT U3,U7;I$(I)
2420 INPUT A$
2430 IF A$="" THEN GOTO 2470
2440 LET SV=U
2450 LET I$(I)=A$
2460 PRINT AT U3,U7;I$(I);N$
2470 LET D=T(I)
2480 GOSUB DAO
2485 IF GO=G THEN GOTO G
2490 PRINT AT U4,G;"%E%P%O%C%H";AT U4,U7;D$
2500 INPUT D$
2510 IF D$="" THEN GOTO 2610
2520 PRINT AT U4,U7;D$;X$
2530 GOSUB DAY
2540 IF ER=G THEN GOTO 2570
2550 GOSUB 3250
2560 GOTO 2500
2570 LET T(I)=D
2580 LET SV=U
2590 GOSUB DAO
2600 PRINT AT U4,U7;D$;N$
2610 FOR J=U TO U8
2620 LET A(J)=VAL E$(J,U5 TO TEN)
2630 PRINT AT J+U4,G;E$(J, TO U4);"% ";A(J);X$
2640 INPUT A$
2650 IF A$="" THEN GOTO 2690
2660 LET A(J)=VAL A$
2670 PRINT AT J+U4,U7;A(J);X$
2680 LET SV=U
2690 NEXT J
2700 LET N(U2,I)=A(U7)
2710 LET I(I)=A(U)
2720 LET O(I)=A(U2)
2730 LET E(I)=A(U3)
2740 LET W(I)=A(U4)
2750 LET M(I)=A(U5)
2760 LET N(U,I)=A(U6)
2770 LET F(I)=A(U8)
2780 IF A$="" THEN GOTO G
2790 PRINT AT U18,G;"##";K$;N$
2800 INPUT A$
2810 GOTO G
2820 IF A$<>"4" THEN GOTO 3130
2830 CLS
2840 PRINT H$,,"%C%A%L%L% ";C$;AT U18,G;L$;K$
2850 INPUT A$
2860 IF A$="" THEN GOTO 2900
2870 LET C$=A$
2880 PRINT AT U2,U7;C$;N$
2890 LET SV=U
2900 FOR J=U9 TO 11
2910 LET A(J-U8)=VAL E$(J,U6 TO U9)
2920 PRINT AT J-U6,G;E$(J, TO U5);TAB U7;A(J-U8)
2930 INPUT A$
2940 IF A$="" THEN GOTO 2980
2950 LET A(J-U8)=VAL A$
2960 PRINT AT J-U6,U7;A(J-U8);N$
2970 LET SV=U
2980 NEXT J
2990 LET L9=A(U)
3000 LET W9=A(U2)
3010 LET H9=A(U3)
3020 LET L8=L9*P0
3030 LET S9=SIN L8
3040 LET C9=COS L8
3050 LET S8=SIN (-W9*P0)
3060 LET C8=COS (W9*P0)
3070 LET R9=R0*(U-F/U2+F/U2*COS (U2*L8))+H9/THO
3080 LET L8=ATN ((U-F)**U2*S9/C9)
3090 LET Z9=R9*SIN L8
3100 LET X9=R9*COS L8*C8
3110 LET Y9=R9*COS L8*S8
3120 GOTO 2780
3130 IF A$<>"5" OR SV=G THEN GOTO G
3140 CLS
3150 PRINT H$,TAB U2;"@@START RECORDER.....";K$
3160 LET A$=INKEY$
3170 IF A$="" THEN GOTO 3160
3180 IF A$="0" THEN GOTO G
3190 PRINT ,,TAB U3;" SAVE BEGINS IN 20 SECONDS"
3200 PAUSE THO
3210 LET SV=G
3220 SAVE "AMS8%1"
3230 GOTO G
3240 CLS
3250 PRINT AT U6,G;D$;AT U7,G;"EPOCH INPUT ERROR. USE FORMAT:","83 105.46677538",," > OR <",,"15APR83 111209"
3260 RETURN
3270 IF GO=U9 AND ST=U9 OR FS=G THEN SLOW
3280 LET F$=INKEY$
3290 IF F$="" THEN GOTO 3410
3300 PRINT AT U21,U31;F$
3310 IF F$<>"0" THEN GOTO 3350
3320 LET GO=G
3330 LET ST=U9
3340 RETURN
3350 IF CODE F$<38 AND CODE F$>27 THEN GOTO 3400
3360 IF F$="F" THEN LET FS=U
3370 IF F$="D" THEN LET FS=G
3380 IF F$="T" THEN LET D0=INF
3390 GOTO KSE
3400 LET ST=VAL F$
3410 IF GO<>U9 THEN GOTO KSE
3420 LET GO=ST
3430 LET ST=U9
3440 IF FS=U AND GO<>U9 THEN FAST
3450 RETURN
3460 GOSUB KSC
3470 IF GO=G OR K=K9 THEN RETURN
3480 IF N(U,I)=G THEN LET N(U,I)=HUN
3490 IF N(U,I)>HUN THEN GOTO 3530
3500 LET N0=N(U,I)
3510 LET A0=(G0/N0/N0)**(U/U3)
3520 GOTO 3550
3530 LET A0=N(U,I)
3540 LET N0=SQR (G0/N(U,I)**U3)
3550 LET N=N0+U2*(D-T(I))*N(U2,I)
3560 LET A=(G0/N/N)**(U/U3)
3570 IF N<G OR A<R0 THEN GOTO 3930
3580 IF E(I)>=0 AND E(I)<1 THEN GOTO 3610
3590 PRINT "BAD ECCENTRICITY"
3600 GOTO 3940
3610 LET E2=U-E(I)**U2
3620 LET E1=SQR E2
3630 LET Q0=M(I)/360
3640 LET AF=U/ABS (U-SQR ABS (COS (I(I)*P0)*COS (L9*P0))/N)/A/N/360
3650 LET K2=9.95*(R0/A)**3.5/E2**U2
3660 LET S1=SIN (I(I)*P0)
3670 LET C1=COS (I(I)*P0)
3680 LET O=O(I)-(D-T(I))*K2*C1
3690 LET S0=SIN (O*P0)
3700 LET C0=COS (O*P0)
3710 LET W=W(I)+(D-T(I))*K2*(2.5*C1*C1-HA)
3720 LET S2=SIN (W*P0)
3730 LET C2=COS (W*P0)
3740 LET C(U,U)=C2*C0-S2*S0*C1
3750 LET C(U2,U)=C2*S0+S2*C0*C1
3760 LET C(U3,U)=S2*S1
3770 LET C(U,U2)=-S2*C0-C2*S0*C1
3780 LET C(U2,U2)=-S2*S0+C2*C0*C1
3790 LET C(U3,U2)=C2*S1
3800 LET G2=G(INT (T(I)/DYR)+U3)
3810 LET D1=D
3820 LET D=INT (T(I)/DYR)+U81
3830 LET D$=STR$ D+" 000."
3840 GOSUB DAY
3850 LET Y0=D
3860 LET K9=K
3870 LET D=D1
3880 LET D1=P2/U4
3890 IF L9<G THEN LET D1=D1*U3
3900 LET J=I(I)*P0
3910 IF J>PI/U2 THEN LET J=PI-J
3920 IF ACS (R0*(U+E(I)*COS (D1-W*P0))/A/(U-E(I)**U2))+J>ABS L9*P0 THEN RETURN
3930 PRINT "##PASSES CANNOT OCCUR ";K$
3940 SLOW
3950 LET GO=G
3960 IF INKEY$="" THEN GOTO 3960
3970 RETURN
3980 LET D2=D
3990 LET D=D+PHI
4000 LET Q1=Q
4010 LET Q=Q0+(D-T(I))*(N0+N(U2,I)*(D-T(I)))
4020 LET K=INT Q
4030 LET M=(Q-K)*P2
4040 RETURN
4050 GOSUB KSC
4060 IF GO=G THEN RETURN
4070 LET ER=U
4080 IF LEN D$<U7 THEN RETURN
4090 IF CODE D$(U3)>37 THEN GOTO 4220
4100 FOR L=U TO LEN D$
4110 IF L=U3 OR L=U7 THEN GOTO 4130
4120 IF CODE D$(L)>U37 OR CODE D$(L)<U28 THEN RETURN
4130 NEXT L
4140 IF D$(U7)<>"." AND D$(U7)<>" " THEN RETURN
4150 LET D=INT (VAL D$(U4 TO U6)+DYR*(VAL D$(U TO U2)-U81))
4160 IF D$(U7)="." THEN LET D=D+VAL D$(U7 TO LEN D$)
4170 IF LEN D$>=U13 THEN GOTO 4190
4180 LET D$=D$+"000000"
4190 IF D$(U7)<>"." THEN LET D=D+((VAL D$(U12 TO U13)/U60+VAL D$(TEN TO 11))/U60+VAL D$(U8 TO U9))/U24
4200 LET ER=G
4210 RETURN
4220 IF LEN D$<U8 THEN RETURN
4230 FOR L=U TO U12
4240 IF D$(U3 TO U5)=M$(L,U TO U3) THEN GOTO 4270
4250 NEXT L
4260 RETURN
4270 LET D$(U3 TO U5)=M$(L,U4 TO U6)
4280 FOR L=U TO LEN D$
4290 IF L=U8 THEN GOTO 4310
4300 IF CODE D$(L)>U37 OR CODE D$(L)<U28 THEN RETURN
4310 NEXT L
4320 LET Y3=VAL D$(U6 TO U7)
4330 IF Y3<TEN THEN RETURN
4340 LET F9=G
4350 IF Y3/U4=INT (Y3/U4) AND VAL D$(U3 TO U5)>58 THEN LET F9=U
4360 LET D=INT ((Y3-U81)*DYR)
4370 LET D=D+VAL D$(U3 TO U5)+VAL D$(U TO U2)+F9
4380 LET D$=D$(U2 TO LEN D$)
4390 GOTO 4160
4400 LET ER=G
4410 LET Y3=U81+(INT D-U01)/DYR
4420 LET D1=INT (DYR*(Y3-INT Y3))
4430 LET Y3=INT Y3
4440 LET F9=G
4450 IF Y3/U4=INT (Y3/U4) AND D1>=59 THEN LET F9=U
4460 LET D1=D1-F9
4470 FOR L=U TO U12
4480 IF D1>=VAL M$(L,U4 TO U6) THEN NEXT L
4490 LET D$=M$(L-U,U TO U3)
4500 IF F9=U AND D1=58 THEN LET D1=59
4510 LET D1=D1+U-VAL M$(L-U,U4 TO U6)
4520 LET D$=STR$ INT D1+D$+STR$ Y3
4530 IF D1<TEN THEN LET D$="0"+D$
4540 LET J=U9
4550 LET D$=D$+" "
4560 LET D1=(D-INT D+5E-6)*24
4570 GOSUB KSC
4580 FOR L=J TO J+U4 STEP U2
4590 LET D$(L TO L+U)=STR$ INT D1
4600 IF D1<TEN THEN LET D$(L TO L+U)="0"+STR$ INT D1
4610 LET D1=(D1-INT D1)*U60
4620 NEXT L
4630 RETURN
4640 CLS
4650 PRINT H$,
4660 IF A$="1" THEN PRINT TAB U2;"%<%<%<% %S%C%H%E%D%U%L%I%N%G% % %A%C%T%I%V%I%T%Y% %>%>%>"
4670 IF A$="2" THEN PRINT TAB U3;"%<%<%<% %T%R%A%C%K%I%N%G% % %A%C%T%I%V%I%T%Y% %>%>%>"
4680 IF A$="3" THEN PRINT TAB U2;"%<%<% %K%E%P%L%E%R%I%A%N% %F%I%L%E% %U%P%D%A%T%E% %>%>%>"
4690 PRINT
4700 FOR I=U TO U14
4710 PRINT CHR$ (I+U37);" = ";S$(I)
4720 LET A$=INKEY$
4730 IF A$<>"" THEN GOTO 4780
4740 NEXT I
4750 PRINT ,,"##SELECT A-N (RETURN=0)##";
4760 LET A$=INKEY$
4770 IF A$="" THEN GOTO 4760
4780 PRINT AT U19,U24;A$
4790 LET I=CODE A$-U37
4800 IF I>U14 OR I<U THEN LET GO=G
4810 RETURN
4820 IF E9<U9H THEN LET D$=D$+"0"
4830 LET D$=D$+STR$ INT (E9+HA)+" "
4840 RETURN
4850 IF A9<99.5 THEN LET D$=D$+"0"
4860 IF A9<U9H THEN LET D$=D$+"0"
4870 LET D$=D$+STR$ INT (A9+HA)+" "
4880 RETURN
4890 LET K9=INF
4900 LET PHI=G
4910 GOSUB SAT
4920 IF GO=G THEN RETURN
4930 PRINT ,,S$(I, TO U9);" EPOCH: ";AT U19,G;"@@ENTER EPOCH DATE+TIME ";K$
4940 INPUT D$
4950 LET FS=U
4960 PRINT AT U21,17;D$
4970 IF D$<>"S" THEN GOTO 5000
4980 LET D=D3
4990 RETURN
5000 IF D$<>"0" THEN GOTO 5030
5010 LET GO=G
5020 RETURN
5030 GOSUB DAY
5040 IF ER<>G THEN GOTO 5070
5050 LET D3=D
5060 RETURN
5070 GOSUB 3240
5080 SLOW
5090 GOTO 4940
5100 LET E=M+E(I)*SIN M+HA*E(I)**U2*SIN (U2*M)
5110 LET M5=E-E(I)*SIN E-M
5120 LET R3=U-E(I)*COS E
5130 IF ABS M5<1E-6 THEN GOTO 5160
5140 LET E=E-M5/R3
5150 GOTO 5110
5160 LET X=A*(COS E-E(I))
5170 LET Y=A*E1*SIN E
5180 LET R=A*R3
5190 LET Z=X*C(U3,U)+Y*C(U3,U2)
5200 LET X0=X*C(U,U)+Y*C(U,U2)
5210 LET Y=X*C(U2,U)+Y*C(U2,U2)
5220 LET G7=(D-Y0)*G1+G2
5230 LET G7=(G7-INT G7)*P2
5240 LET X=X0*COS G7+Y*SIN G7
5250 LET Y=-X0*SIN G7+Y*COS G7
5260 RETURN
5270 GOSUB CO4
5280 IF GO=G THEN RETURN
5290 LET X8=-X5*C8*S9-Y5*S8*S9+Z5*C9
5300 LET Y8=Y5*C8-X5*S8
5310 GOSUB KSC
5320 IF X8<>G THEN GOTO 5360
5330 LET A9=90
5340 IF Y8<G THEN LET A9=270
5350 RETURN
5360 LET A9=ATN (Y8/X8)/P0
5370 IF X8<G THEN LET A9=A9+180
5380 IF A9<G THEN LET A9=A9+360
5390 RETURN
5400 GOSUB 3980
5410 GOSUB KSC
5420 IF GO=G THEN RETURN
5430 GOSUB 5100
5440 LET X5=X-X9
5450 LET Y5=Y-Y9
5460 LET Z5=Z-Z9
5470 LET QS=X5*X9+Y5*Y9+Z5*Z9
5480 GOSUB KSC
5490 RETURN
5500 GOSUB CO3
5510 IF GO=G THEN RETURN
5520 LET R5=SQR (X5*X5+Y5*Y5+Z5*Z5)
5530 LET E9=ASN ((X5*C8*C9+Y5*S8*C9+Z5*S9)/R5)/P0
5540 RETURN
5550 LET E8=SGN QS
5560 LET PHI=-SGN QS*IN*R*AF*LOS
5570 GOSUB INK
5580 GOSUB CO3
5590 IF GO=G THEN RETURN
5600 IF SGN QS=E8 THEN GOTO 5560
5610 LET PHI=-HA*ABS PHI*SGN QS*LOS
5620 GOSUB CO4
5630 IF GO=G THEN RETURN
5640 IF ABS E9<HA THEN RETURN
5650 GOTO 5610
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


