This program is a flight planning tool that calculates courses, distances, wind corrections, ground speeds, fuel burns, and flight times for a series of waypoints entered by the pilot. It stores up to 500 navigation fixes with their latitude/longitude (encoded as a combined decimal value) and magnetic variation, and supports RNAV fixes defined by a VOR radial and distance. After computing the route, it draws a map of the continental United States using a series of DRAW commands with arc parameters, then plots the route using CIRCLE, PLOT, and DRAW. The wind-correction-angle and ground-speed calculations use ASN and COS trigonometry on the wind triangle. Altitude bands are handled differently for aircraft with a maximum cruise altitude below or above 18,000 feet, accommodating both VFR and high-altitude IFR profiles.
Program Analysis
Program Structure
The program is organized into several functional blocks accessed via GO SUB or GO TO:
- Initialization (lines 30–75): Dimensions arrays, sets defaults, and calls the aircraft setup subroutine.
- Aircraft/winds setup (lines 80–130, 1030–1170): Prompts for aircraft type, max altitude, TAS and fuel flow per altitude band, and wind data.
- Route planning loop (lines 140–990): Collects departure and successive fixes, computes leg data, and prints a tabular log.
- Fix lookup/entry (lines 510–670): Searches the stored fix database; if not found, prompts for lat/lon/variation and stores it.
- RNAV fix computation (lines 1670–1860): Converts a VOR radial/distance to a lat/lon fix stored in slot 500.
- Altitude selection (lines 1180–1440): On the first leg, evaluates all altitude bands and then asks the pilot to choose one before rerunning the route.
- Navigation computation (lines 350–500, 860–985): Calculates true course, distance, wind correction angle, ground speed, fuel, and time.
- Totals and map display (lines 1000–2090): Prints totals, draws the US outline, and plots the route graphically.
- US map drawing subroutine (lines 5000–5300): A long sequence of
PLOTandDRAWcalls with arc parameters that trace the continental US coastline and borders.
Coordinate Encoding
Latitude and longitude are packed into a single floating-point value stored in array A(). The formula at line 620 is:
A(N) = INT(LA)*60 + (LA - INT(LA))*100 + (INT(LO)*60 + (LO - INT(LO))*100) / 1E4
This converts degrees.minutes input into total minutes, storing latitude minutes in the integer part and longitude minutes in the four decimal places (scaled by 1E4). Unpacking occurs at lines 350–380 and 1700–1710 using INT and multiplication by 1E4.
Navigation Mathematics
The great-circle approximation at line 450 uses a flat-Earth distance formula corrected for latitude via COS(AVE), where AVE is the mean latitude in radians. True course is computed using ATN at line 480 with quadrant correction at line 490. The wind triangle is solved at lines 870–880:
- Crab angle (CA):
R * ASN(SIN((WD-TC)/R) * WS / TAS)— standard wind triangle using arcsine. - Ground speed (GS):
COS(CA/R)*TAS - COS((WD-TC)/R)*WS— component subtraction along track.
The constant R=57.29578 (180/π) is used as a degrees-to-radians conversion factor; angles are kept in degrees and divided by R before trig calls.
Altitude Band Indexing
The program supports two altitude regimes controlled by MAXALT:
| Regime | Condition | Bands | Step |
|---|---|---|---|
| Low (VFR/IFR) | MAXALT < 18000 | 3000 to MAXALT/1000, step 3 | 3000 ft |
| High (RVSM/jet) | MAXALT >= 18000 | 18 to MAXALT/1000, step 6 | 6000 ft |
The index expression I/(3+3*(MAXALT>=18000))-(MAXALT>=18000)*2 maps the loop variable I (in thousands of feet) to a 1-based array index into T(), G(), W(), and V(). The special cases I=36 and I=40 are adjusted at lines 732/755 to skip non-standard flight levels (FL360→FL340, FL400→FL390 style corrections).
Fix Database
Up to 500 fixes are stored across three parallel arrays: A$() (5-character name), A() (packed lat/lon), and V$() (variation as a string). The lookup subroutine at lines 510–670 performs a linear scan of A$() using a single-element string array Z$(1) as a comparand — a common TS2068 BASIC technique to compare strings of fixed length. Slot 500 is reserved as a scratch location for RNAV fixes.
RNAV Fix Computation
Lines 1670–1860 compute a position from a VOR radial and distance. The radial is corrected for variation (line 1760), then flat-Earth offsets in latitude minutes (DLAT) and longitude minutes (DLONG) are calculated using sine/cosine, with the longitude offset corrected for latitude via COS(PI/10800 * mean_lat). The result is packed into A(500) and the fix name has “r” appended to distinguish it.
Map Drawing Subroutine
The subroutine at lines 5000–5300 draws the continental US outline using 30+ DRAW statements, many with a third arc parameter for curved segments (coastlines, the Gulf Coast, etc.). After the map is drawn, the route is overlaid at lines 1990–2070: each fix is converted from packed lat/lon to pixel coordinates using linear scale factors (*.064 for longitude, *.061 for latitude), then CIRCLE, PLOT, and DRAW mark each waypoint and connect legs. Fix labels are positioned using a slope-based offset (M) to avoid overwriting the line.
Error Handling and ON ERR
Line 1925 uses ON ERR GO TO 2085 to catch any graphics errors (e.g., coordinates outside screen bounds) during map plotting. Line 2085 resets the error trap with ON ERR RESET and plays a musical fanfare using BEEP. This is the TS2068-specific ON ERR / RESET mechanism.
Notable BASIC Idioms
- Boolean arithmetic for conditional printing:
"0" AND (MC<10)prints a leading zero without anIFstatement. PRINT CHR$ 8in a loop (line 734) moves the cursor left to overwrite the just-printed wind data with “N/A” when winds are unavailable (W(P)=PASSwherePASS=-10).GO TO 480+380*(B=D)at line 470 is a computed jump: if longitudes are equal (B=D), jumps to line 860, skipping the ATN computation to avoid division by zero.- Line 990 uses
GO TO 240+760*(B$=S$): if the entered fix matches the destination, jumps to line 1000 (totals), otherwise loops back to line 240. - The variable name
PRINT(line 80) is used as a flag for printer output — legal in Sinclair BASIC since keywords are only recognized as such at the start of a statement.
Potential Anomalies
- Line 1030 is called at line 75 (
GO SUB 1030) but the listing shows line 1040 as the first line of that subroutine — line 1030 is absent, so theGO SUBfalls through to line 1040, which is standard behavior for a missing target line. - The commented-out variation formula at lines 410 and 1720 suggests the program once auto-computed magnetic variation from position; it was replaced by manual entry via
V$(). - The
TIMEcalculation at line 930 adds a climb-time correction(FIX=1 OR J=FIX)*ALT/(MAXALT*10)only on the first or last leg, which is a simplified approximation. - Array
F(10)(line 57) is used to cache fix coordinates for the graphical plot (lines 340, 1250, 2000–2010), but is limited to 10 entries — routes with more than 9 intermediate fixes would overflow it.
Content
Source Code
1 REM SAVE "PLANNER" LINE 1: REM © by Chuck Dawson, 1985; ALL RIGHTS RESERVED
10 REM GOTO 1870 TO LIST FIXES
12 BORDER 1: PAPER 1: INK 9
14 POKE 23658,8
16 CLS
18 OVER 0
20 GO TO 80
30 LET PASS=-10
31 LET WD=0
32 LET WS=0
35 DIM V(5)
40 DIM A(500)
42 DIM D$(10,5)
45 DIM T(5)
47 DIM V$(500,3)
50 DIM A$(500,5)
55 DIM G(5)
57 DIM F(10)
60 DIM Z$(1,5)
65 DIM W(5)
70 LET N=1
75 GO SUB 1030
80 LET PRINT=0: INPUT "DO YOU WANT THESE RESULTS SENT TO THE PRINTER? ";W$: IF CODE W$=89 THEN LET PRINT=1
85 PRINT AT 20,0;"CURRENT AIRCRAFT IS ";F$,"IS THIS CORRECT?"
90 INPUT Y$
100 IF CODE Y$=78 THEN GO SUB 1030
130 OVER 0: PAPER 1: BORDER 1: GO SUB 730
140 LET FIX=0
145 LET ALT=0
150 LET TOTQ=0
155 LET TOTG=0
160 LET TOTT=0
165 OVER 0: PAPER 1: BORDER 1
170 CLS
180 INPUT "INPUT DEPARTURE POINT ";B$
190 GO SUB 510
200 PRINT AT 0,0;"0" AND WD<10;"0" AND WD<100;WD;"/";WS;TAB 9;"DIS MC GAS CA GS TIME";ALT;" FT"
210 LET A1=INT A(I)
220 LET B1=(A(I)-INT (A(I)))*1E4
230 LET E$=B$
240 LET C$=B$
245 LET V=VAL (V$(I))
250 LET HERE=A(I)
255 IF ALT=0 THEN GO TO 1180
260 INPUT "INPUT NEXT FIX ";B$
290 IF B$=" STOP " THEN GO TO 1000
300 LET FIX=FIX+1
310 GO SUB 510
320 LET D$(FIX)=B$
330 LET THERE=A(I)
340 LET F(FIX+1)=A(I)
342 GO SUB 350
345 GO TO 990
350 LET A=INT HERE
360 LET B=INT (.5+(HERE-A)*1E4)
370 LET C=INT THERE
380 LET D=INT (.5+(THERE-C)*1E4)
390 LET E=(A+C)/120
400 LET G=(B+D)/120
410 REM LET V=-1*INT (((G-96)*13/(62-E))+7.2)
420 LET LAT=ABS (A-C)
430 LET LONG=ABS (B-D)
440 LET AVE=PI*(A+C)/21600
450 LET Q=INT (SQR ((LAT^2)+(COS AVE*LONG)^2)+.5)
460 LET TC=180*(C<A)+360*(A<C)
470 GO TO 480+380*(B=D)
480 LET TC=.5+(180/PI)*ATN ((A-C)/((B-D)*COS AVE))
490 LET TC=INT TC+90*(B>D)+270*(B<D)
500 GO TO 860
510 IF B$="RNAV" THEN GO TO 1670
520 LET Z$(1)=B$
530 FOR I=1 TO 500
540 IF A$(I)=Z$(1) THEN RETURN
550 NEXT I
560 PRINT AT 20,0;B$;" NOT STORED "
570 INPUT "LATITUDE? (DEG.MIN) ";LA
590 INPUT "LONGITUDE? (DEG.MIN) ";LO
600 INPUT "VARIATION? (+W -E) "; LINE V$(N)
610 LET A$(N)=B$
620 LET A(N)=INT LA*60+(LA-INT LA)*100+(INT LO*60+(LO-INT LO)*100)/1E4
630 LET I=N
640 LET N=N+1
650 IF N=500 THEN LET N=400
660 PRINT AT 20,0;" "
670 RETURN
730 CLS
732 FOR I=3+15*(MAXALT>=18000) TO MAXALT/1000 STEP 3+3*(MAXALT>=18000): LET I=I-2*(I=36)-(I=40)
733 LET P=I/(3+3*(MAXALT>=18000))-(MAXALT>=18000)*2
734 PRINT : PRINT I*1000,W(P);"/";V(P): IF W(P)=PASS THEN FOR B=1 TO 16: PRINT CHR$ 8;: NEXT B: PRINT " N/A "
735 NEXT I
740 INPUT "DO YOU WANT TO CHANGE THE WINDS?";K$: IF CODE K$<>89 THEN GO TO 840
745 CLS
750 FOR I=3+15*(MAXALT>=18000) TO MAXALT/1000 STEP 3+3*(MAXALT>=18000)
755 LET I=I-2*(I=36)-(I=40)
760 PRINT AT 0,0;"FOR ";I;"000 FEET, INPUT WIND DIRECTION "
770 INPUT W(I/(3+3*(MAXALT>=18000))-(MAXALT>=18000)*2)
775 IF W(I/(3+3*(MAXALT>=18000))-(MAXALT>=18000)*2)=PASS THEN GO TO 800
780 PRINT AT 0,0;"FOR ";I;"000 FEET, INPUT WIND VELOCITY "
790 INPUT V(I/(3+3*(MAXALT>=18000))-(MAXALT>=18000)*2)
800 NEXT I
840 CLS
850 RETURN
860 LET R=57.29578
865 LET TAS=T((ALT/(3000+500*(ALT>=16500)))*(MAXALT<=18000)+((ALT-12000)/6000)*(MAXALT>18000))
870 LET CA=INT (.5+(R*ASN (SIN ((WD-TC)/R)*WS/TAS)))
880 LET GS=INT (.5+(COS (CA/R)*TAS-(COS ((WD-TC)/R))*WS))
890 PRINT AT 2*FIX,0;C$;"-";B$;TAB 0;"▀▀▀▀▀▀▀";"▀" AND (LEN (B$+C$)>6);"▀" AND (LEN (B$+C$)>7)
900 PRINT AT 2*FIX,9+(Q<10)+(Q<100);Q;
910 LET TOTQ=TOTQ+Q
915 LET MC=TC+V: IF MC<=0 THEN LET MC=360+MC
920 PRINT TAB 13;"0" AND MC<10;"0" AND MC<100;MC;
930 LET TIME=Q/GS+(FIX=1 OR J=FIX)*ALT/(MAXALT*10)
935 LET GS=INT (.5+Q/TIME)
940 LET GAS=G((ALT/(3000+500*(ALT>=16500)))*(MAXALT<=18000)+((ALT-12000)/6000)*(MAXALT>18000))*TIME
945 LET TOTG=TOTG+GAS
950 PRINT TAB 17;" " AND (INT (GAS+.5))<10;STR$ (INT (.5+GAS)) AND WD>=0;"-----N/A-----" AND WD<0;
955 IF WD<0 THEN GO TO 985
960 PRINT TAB (20+(ABS CA<10));ABS CA;"R" AND CA>0;"L" AND CA<0;TAB 24;GS;
970 LET TOTT=TOTT+TIME
980 PRINT TAB 28;INT TIME;"+";"0" AND (INT (.5+((TIME-INT TIME)*60))<10);INT (.5+((TIME-INT TIME)*60))
985 RETURN
990 GO TO 240+760*(B$=S$)
1000 LET TOTT=(INT (TOTT*60+.5))/60
1010 PRINT AT 2*FIX+2,0;"TOTALs";TAB (9+(TOTQ<10)+(TOTQ<100));TOTQ;TAB 17;INT (.5+TOTG);TAB 24;INT (.5+TOTQ/TOTT);TAB 28;INT TOTT;"+";"0" AND (INT (.5+((TOTT-INT TOTT)*60))<10);INT (.5+((TOTT-INT TOTT)*60))
1020 GO TO 1900
1040 PRINT "INPUT TYPE AIRCRAFT "
1050 INPUT F$
1060 PRINT
1070 PRINT "INPUT MAX CRUISE ALTITUDE"
1080 INPUT MAXALT
1085 CLS
1110 FOR I=3+15*(MAXALT>=18000) TO MAXALT/1000 STEP 3+3*(MAXALT>=18000)
1115 LET I=I-2*(I=36)-(I=40)
1120 PRINT AT 0,0;" FOR ";I;"000 FEET, INPUT NORMAL CRUISE TAS (KTS) "
1130 INPUT T(I/(3+3*(MAXALT>=18000))-(MAXALT>=18000)*2)
1140 PRINT AT 0,0;" FOR ";I;"000 FEET, INPUT NORMAL FUEL FLOW (GAL/HR)"
1150 INPUT G(I/(3+3*(MAXALT>=18000))-(MAXALT>=18000)*2)
1160 NEXT I
1170 RETURN
1180 PRINT AT 0,0;" "'" "
1190 INPUT "INPUT DESTINATION ";B$
1195 LET S$=B$
1200 LET ALT=3000+15000*(MAXALT>=18000)
1210 LET FIX=FIX+1
1220 GO SUB 510
1230 LET D$(FIX)=B$
1240 LET THERE=A(I)
1250 LET F(FIX+1)=A(I)
1260 FOR J=1 TO 4+(MAXALT>=15000 AND MAXALT<18000)+(MAXALT>=39000)
1270 LET WS=V(J)
1280 LET WD=W(J)
1290 LET ALT=J*3000*(MAXALT<=18000)+(12000+J*6000-2000*(J=4)-3000*(J=5))*(MAXALT>18000)
1300 GO SUB 350
1310 PRINT AT 2*FIX,0;" " AND ALT<10000;ALT;" FT "
1320 LET FIX=FIX+1
1330 NEXT J
1335 LET J=50
1340 PRINT ''"INPUT DESIRED ALTITUDE."'"(NOTE: ABOVE FIGURES DO NOT CONSIDER M.E.A.'s ALONG ROUTE)"
1350 INPUT ALT
1355 IF ALT<1000 THEN LET ALT=ALT*100
1360 LET WS=V((ALT/(3000+500*(ALT>=16500)))*(MAXALT<=18000)+((ALT-12000)/6000)*(MAXALT>18000))
1370 LET WD=W((ALT/(3000+500*(ALT>=16500)))*(MAXALT<=18000)+((ALT-12000)/6000)*(MAXALT>18000))
1380 LET FIX=0
1390 CLS
1400 LET B$=C$
1410 LET TOTQ=0
1420 LET TOTT=0
1430 LET TOTG=0
1440 GO TO 190
1670 INPUT "INPUT VORTAC ";B$
1690 GO SUB 520
1700 LET LAT=INT A(I)
1710 LET LONG=1E4*(A(I)-INT A(I))
1720 REM LET V=-1*INT ((LONG/60-96)*13/(62-LAT/60))+7.2
1721 LET V$(500)=V$(I)
1730 LET B$=B$+"r"
1740 INPUT "INPUT RADIAL ";C
1760 LET C=C-V
1780 INPUT "INPUT DISTANCE ";D
1800 LET DLAT=INT ((D*SIN ((C-90)*PI/180))+.5)
1810 LET NEWLAT=LAT-DLAT
1820 LET DLONG=INT ((D*COS ((C-90)*PI/180)/COS (PI/10800*((LAT+NEWLAT)/2)))+.5): LET NEWLONG=LONG-DLONG
1840 LET A(500)=NEWLAT+NEWLONG/1E4
1850 LET I=500
1860 RETURN
1870 FOR J=1 TO 500
1890 PRINT J;"▖" AND (J=N);TAB 4;A$(J);TAB 11;A(J);TAB 22;V$(J)
1895 NEXT J
1900 IF PRINT=1 THEN COPY
1910 PAUSE 0
1920 BORDER 5: PAPER 5: CLS
1925 ON ERR GO TO 2085
1930 GO SUB 5000
1940 LET B=(A1-1540)*.064
1950 LET A=(6500-B1)*.061
1960 LET LIN=(42.5-B)/2
1970 LET COL=(A-.5)/2
1980 PRINT AT LIN,COL+1-(4.5+(LEN E$>=4))*(TC<170);E$ AND (A>=0 AND A<64 AND B>=0 AND B<44)
1990 FOR I=1 TO FIX
2000 LET D=(INT (F(I+1))-1540)*.064
2010 LET C=.061*(6500-((F(I+1)-INT (F(I+1)))*1E4))
2015 LET AA=A*4: LET BB=B*4: LET CC=C*4: LET DD=D*4
2020 CIRCLE AA,BB,2: PLOT AA,BB: DRAW CC-AA,DD-BB
2032 IF A=C THEN LET M=200: GO TO 2035
2033 LET M=(B-D)/(A-C)
2035 LET A=C: LET B=D
2040 LET LIN=(42.5-B)/2
2050 LET COL=(A-.5)/2
2060 PRINT AT LIN+(M<=1 AND M>-.1)-(M<=-.1 AND M>-.2),1-(M<=1 AND M>-.1)+COL;D$(I) AND (A>=0 AND A<64 AND B>=0 AND B<44)
2070 NEXT I
2080 CIRCLE CC,DD,2
2085 ON ERR RESET : BEEP .2,9: BEEP .2,12: BEEP 1,12: BEEP .1,10: BEEP .1,9: BEEP .1,7: BEEP .4,9: BEEP .4,10: BEEP .4,11: BEEP 1,12
2090 IF PRINT=1 THEN COPY
2100 INPUT "ANOTHER ROUTE? ";Y$
2110 IF CODE Y$=89 THEN GO TO 130
2120 GO TO 5310
5000 OVER 0
5010 PLOT 22,98
5020 DRAW 54,0
5030 DRAW 0,69
5040 DRAW 42,0
5050 DRAW 0,-30
5060 DRAW 45,-10,.2
5070 DRAW 44,-1,-.5
5080 DRAW 0,-23
5090 DRAW 3,-36,-.8
5100 DRAW -37,-29
5110 DRAW -8,-33,1.5
5115 DRAW 1,-5
5117 DRAW -1,5
5120 DRAW -22,2,-1
5130 DRAW -15,20,-1
5140 DRAW -25,28,-.5
5150 DRAW -33,-6,2
5160 DRAW -23,20,-1.2
5170 DRAW -25,29,-.1
5180 PLOT 24,93
5190 DRAW -22,0
5200 PLOT 77,167
5210 DRAW 0,8
5215 DRAW -76,0
5220 DRAW 199,0
5230 DRAW 0,-4
5231 DRAW 3,-43,-.2
5240 DRAW -3,43,.2
5250 DRAW 55,0
5260 PLOT 208,120
5270 DRAW 47,0
5280 PLOT 210,68
5290 DRAW 44,-4,-.5
5300 RETURN
5310 PRINT #0; FLASH 1;" HAVE A GOOD FLIGHT! © CWD ": IF PRINT=1 THEN LPRINT "HAVE A GOOD FLIGHT!"
5320 PAUSE 0: STOP
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
