Flight Planner

Developer(s): Chuck Dawson
Date: 1985
Type: Program
Platform(s): TS 2068
Tags: Hobby

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:

  1. Initialization (lines 30–75): Dimensions arrays, sets defaults, and calls the aircraft setup subroutine.
  2. Aircraft/winds setup (lines 80–130, 1030–1170): Prompts for aircraft type, max altitude, TAS and fuel flow per altitude band, and wind data.
  3. Route planning loop (lines 140–990): Collects departure and successive fixes, computes leg data, and prints a tabular log.
  4. Fix lookup/entry (lines 510–670): Searches the stored fix database; if not found, prompts for lat/lon/variation and stores it.
  5. RNAV fix computation (lines 1670–1860): Converts a VOR radial/distance to a lat/lon fix stored in slot 500.
  6. 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.
  7. Navigation computation (lines 350–500, 860–985): Calculates true course, distance, wind correction angle, ground speed, fuel, and time.
  8. Totals and map display (lines 1000–2090): Prints totals, draws the US outline, and plots the route graphically.
  9. US map drawing subroutine (lines 5000–5300): A long sequence of PLOT and DRAW calls 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:

RegimeConditionBandsStep
Low (VFR/IFR)MAXALT < 180003000 to MAXALT/1000, step 33000 ft
High (RVSM/jet)MAXALT >= 1800018 to MAXALT/1000, step 66000 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 an IF statement.
  • PRINT CHR$ 8 in a loop (line 734) moves the cursor left to overwrite the just-printed wind data with “N/A” when winds are unavailable (W(P)=PASS where PASS=-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 the GO SUB falls 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 TIME calculation 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

Appears On

One of the largest single-tape collections anywhere, with over 40 programs spanning flight planning, satellite tracking, hydrology, Forth programming, a 17-game mega-pack, and a complete calligraphic font renderer. A snapshot of a thriving Texas user group at its peak.

Related Products

Related Articles

Related Content

Image Gallery

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.

Scroll to Top