]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/KLN89/kln89_page_nav.cxx
Add --fg-aircraft option, and aircraft dir path list. Partial support in places that...
[flightgear.git] / src / Instrumentation / KLN89 / kln89_page_nav.cxx
1 // kln89_page_*.[ch]xx - this file is one of the "pages" that
2 //                       are used in the KLN89 GPS unit simulation. 
3 //
4 // Written by David Luff, started 2005.
5 //
6 // Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 // $Id$
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "kln89_page_nav.hxx"
29 #include <Main/fg_props.hxx>
30
31 KLN89NavPage::KLN89NavPage(KLN89* parent) 
32 : KLN89Page(parent) {
33         _nSubPages = 4;
34         _subPage = 0;
35         _name = "NAV";
36         _posFormat = 0;         // Check - should this default to ref from waypoint?
37         _vnv = 0;
38         _nav4DataSnippet = 0;
39         _cdiFormat = 0;
40         _menuActive = false;
41         _menuPos = 0;
42         _suspendAVS = false;
43         _scanWpSet = false;
44         _scanWpIndex = -1;
45 }
46
47 KLN89NavPage::~KLN89NavPage() {
48 }
49
50 void KLN89NavPage::Update(double dt) {
51         GPSFlightPlan* fp = _kln89->_activeFP;
52         GPSWaypoint* awp = _kln89->GetActiveWaypoint();
53         // Scan-pull out on nav4 page switches off the cursor
54         if(3 == _subPage && fgGetBool("/instrumentation/kln89/scan-pull")) { _kln89->_mode = KLN89_MODE_DISP; }
55         bool crsr = (_kln89->_mode == KLN89_MODE_CRSR);
56         bool blink = _kln89->_blink;
57         double lat = _kln89->_gpsLat * SG_RADIANS_TO_DEGREES;
58         double lon = _kln89->_gpsLon * SG_RADIANS_TO_DEGREES;
59         
60         if(_subPage != 3) { _scanWpSet = false; }
61         
62         if(0 == _subPage) {
63                 if(_kln89->_navFlagged) {
64                         _kln89->DrawText(">    F L A G", 2, 0, 2);
65                         _kln89->DrawText("DTK ---  TK ---", 2, 0, 1);
66                         _kln89->DrawText(">--- To    --:--", 2, 0, 0);
67                         _kln89->DrawSpecialChar(0, 2, 7, 1);
68                         _kln89->DrawSpecialChar(0, 2, 15, 1);
69                         _kln89->DrawSpecialChar(0, 2, 4, 0);
70                         _kln89->DrawSpecialChar(1, 2, 3, 2);
71                         _kln89->DrawSpecialChar(1, 2, 4, 2);
72                         _kln89->DrawSpecialChar(1, 2, 6, 2);
73                         _kln89->DrawSpecialChar(1, 2, 10, 2);
74                         _kln89->DrawSpecialChar(1, 2, 12, 2);
75                         _kln89->DrawSpecialChar(1, 2, 13, 2);
76                 } else {
77                         if(_kln89->_dto) {
78                                 _kln89->DrawDTO(2, 7, 3);
79                         } else {
80                                 if(!(_kln89->_waypointAlert && _kln89->_blink)) {
81                                         _kln89->DrawSpecialChar(3, 2, 8, 3);
82                                 }
83                         }
84                         _kln89->DrawText(awp->id, 2, 10, 3);
85                         if(!_kln89->_dto && !_kln89->_obsMode && !_kln89->_fromWaypoint.id.empty()) {
86                                 _kln89->DrawText(_kln89->_fromWaypoint.id, 2, 1, 3);
87                         }
88                         if(!(crsr && blink && _uLinePos == 1)) {
89                                 if(_cdiFormat == 0) {
90                                         _kln89->DrawCDI();
91                                 } else if(_cdiFormat == 1) {
92                                         _kln89->DrawText("Fly", 2, 2, 2);
93                                         double x = _kln89->CalcCrossTrackDeviation();
94                                         // TODO - check the R/L from sign of x below - I *think* it holds but not sure!
95                                         // Note also that we're setting Fly R or L based on the aircraft
96                                         // position only, not the heading.  Not sure if this is correct or not.
97                                         _kln89->DrawText(x < 0.0 ? "R" : "L", 2, 6, 2);
98                                         char buf[6];
99                                         int n;
100                                         x = fabs(x * (_kln89->_distUnits == GPS_DIST_UNITS_NM ? 1.0 : SG_NM_TO_METER * 0.001));
101                                         if(x < 1.0) {
102                                                 n = snprintf(buf, 6, "%0.2f", x);
103                                         } else if(x < 100.0) {
104                                                 n = snprintf(buf, 6, "%0.1f", x);
105                                         } else {
106                                                 n = snprintf(buf, 6, "%i", (int)(x+0.5));
107                                         }
108                                         _kln89->DrawText((string)buf, 2, 13-n, 2);
109                                         _kln89->DrawText(_kln89->_distUnits == GPS_DIST_UNITS_NM ? "nm" : "km", 2, 13, 2);
110                                 } else {
111                                         _kln89->DrawText("CDI Scale:", 2, 1, 2);
112                                         double d = _kln89->_cdiScales[_kln89->_currentCdiScaleIndex] * (_kln89->_distUnits == GPS_DIST_UNITS_NM ? 1.0 : SG_NM_TO_METER * 0.001);
113                                         char buf[5];
114                                         string s;
115                                         if(d >= 1.0) {
116                                                 snprintf(buf, 4, "%2.1f", d);
117                                                 s = buf;
118                                         } else {
119                                                 snprintf(buf, 5, "%2.2f", d);
120                                                 // trim the leading zero
121                                                 s = buf;
122                                                 s = s.substr(1, s.size() - 1);
123                                         }
124                                         _kln89->DrawText(s, 2, 11, 2);
125                                         _kln89->DrawText(_kln89->_distUnits == GPS_DIST_UNITS_NM ? "nm" : "km", 2, 14, 2);
126                                 }
127                         }
128                         _kln89->DrawChar('>', 2, 0, 2);
129                         _kln89->DrawChar('>', 2, 0, 0);
130                         if(crsr) {
131                                 if(_uLinePos == 1) _kln89->Underline(2, 1, 2, 15);
132                                 else if(_uLinePos == 2) _kln89->Underline(2, 1, 0, 9);
133                         }
134                         // Desired and actual magnetic track
135                         if(!_kln89->_obsMode) {
136                                 _kln89->DrawText("DTK", 2, 0, 1);
137                                 _kln89->DrawHeading((int)_kln89->_dtkMag, 2, 7, 1);
138                         }
139                         _kln89->DrawText("TK", 2, 9, 1);
140                         if(_kln89->_groundSpeed_ms > 3) {       // about 6 knots, don't know exactly what value to disable track
141                                 // The trouble with relying on FG gps's track value is we don't know when it's valid.
142                                 _kln89->DrawHeading((int)_kln89->_magTrackDeg, 2, 15, 1);
143                         } else {
144                                 _kln89->DrawText("---", 2, 12, 1);
145                                 _kln89->DrawSpecialChar(0, 2, 15, 1);
146                         }
147                         
148                         // Radial to/from active waypoint.
149                         // TODO - Not sure if this either is or should be true or mag!!!!!!!
150                         if(!(crsr && blink && _uLinePos == 2)) {
151                                 if(0 == _vnv) {
152                                         _kln89->DrawHeading((int)_kln89->GetHeadingToActiveWaypoint(), 2, 4, 0);
153                                         _kln89->DrawText("To", 2, 5, 0);
154                                 } else if(1 == _vnv) {
155                                         _kln89->DrawHeading((int)_kln89->GetHeadingFromActiveWaypoint(), 2, 4, 0);
156                                         _kln89->DrawText("Fr", 2, 5, 0);
157                                 } else {
158                                         _kln89->DrawText("Vnv Off", 2, 1, 0);
159                                 }
160                         }
161                         // It seems that the floating point groundspeed must be at least 30kt
162                         // for an ETA to be calculated.  Note that this means that (integer) 30kt
163                         // can appear in the frame 1 display both with and without an ETA displayed.
164                         // TODO - need to switch off track (and heading bug change) based on instantaneous speed as well
165                         // since the long gps lag filter means we can still be displaying when stopped on ground.
166                         if(_kln89->_groundSpeed_kts > 30.0) {
167                                 // Assuming eta display is always hh:mm
168                                 // Does it ever switch to seconds when close?
169                                 if(_kln89->_eta / 3600.0 > 100.0) {
170                                         // More that 100 hours ! - Doesn't fit.
171                                         _kln89->DrawText("--:--", 2, 11, 0);
172                                 } else {
173                                         _kln89->DrawTime(_kln89->_eta, 2, 15, 0);
174                                 }
175                         } else {
176                                 _kln89->DrawText("--:--", 2, 11, 0);
177                         }
178                 }
179         } else if(1 == _subPage) {
180                 // Present position
181                 _kln89->DrawChar('>', 2, 1, 3);
182                 if(!(crsr && blink && _uLinePos == 1)) _kln89->DrawText("PRESENT POSN", 2, 2, 3);
183                 if(crsr && _uLinePos == 1) _kln89->Underline(2, 2, 3, 12);
184                 if(0 == _posFormat) {
185                         // Lat/lon
186                         _kln89->DrawLatitude(lat, 2, 3, 1);
187                         _kln89->DrawLongitude(lon, 2, 3, 0);
188                 } else {
189                         // Ref from wp - defaults to nearest vor (and resets to default when page left and re-entered).
190                 }
191         } else if(2 == _subPage) {
192                 _kln89->DrawText("Time", 2, 0, 3);
193                 // TODO - hardwired to UTC at the moment
194                 _kln89->DrawText("UTC", 2, 6, 3);
195                 string th = fgGetString("/instrumentation/clock/indicated-hour");
196                 string tm = fgGetString("/instrumentation/clock/indicated-min");
197                 if(th.size() == 1) th = "0" + th;
198                 if(tm.size() == 1) tm = "0" + tm;
199                 _kln89->DrawText(th + tm, 2, 11, 3);
200                 _kln89->DrawText("Depart", 2, 0, 2);
201                 _kln89->DrawText(_kln89->_departureTimeString, 2, 11, 2);
202                 _kln89->DrawText("ETA", 2, 0, 1);
203                 if(_kln89->_departed) {
204                         /* Rules of ETA waypoint are:
205                          If the active waypoint is part of the active flightplan, then display
206                          the ETA to the final (destination) waypoint of the active flightplan.
207                          If the active waypoint is not part of the active flightplan, then
208                          display the ETA to the active waypoint. */
209                         // TODO - implement the above properly - we haven't below!
210                         string wid = "";
211                         if(fp->waypoints.size()) {
212                                 wid = fp->waypoints[fp->waypoints.size() - 1]->id;
213                         } else if(awp) {
214                                 wid = awp->id;
215                         }
216                         if(!wid.empty()) {
217                                 _kln89->DrawText(wid, 2, 4, 1);
218                                 double tsec = _kln89->GetTimeToWaypoint(wid);
219                                 if(tsec < 0.0) {
220                                         _kln89->DrawText("----", 2, 11, 1);
221                                 } else {
222                                         int etah = (int)tsec / 3600;
223                                         int etam = ((int)tsec - etah * 3600) / 60;
224                                         etah += atoi(fgGetString("/instrumentation/clock/indicated-hour"));
225                                         etam += atoi(fgGetString("/instrumentation/clock/indicated-min"));
226                                         while(etam > 59) {
227                                                 etam -= 60;
228                                                 etah += 1;
229                                         }
230                                         while(etah > 23) {
231                                                 etah -= 24;
232                                         }
233                                         char buf[6];
234                                         int n = snprintf(buf, 6, "%02i%02i", etah, etam);
235                                         _kln89->DrawText((string)buf, 2, 15-n, 1);
236                                 }
237                         } else {
238                                 _kln89->DrawText("----", 2, 11, 1);
239                         }
240                 } else {
241                         _kln89->DrawText("----", 2, 11, 1);
242                 }
243                 _kln89->DrawText("Flight", 2, 0, 0);
244                 if(_kln89->_departed) {
245                         int eh = (int)_kln89->_elapsedTime / 3600;
246                         int em = ((int)_kln89->_elapsedTime - eh * 3600) / 60;
247                         char buf[6];
248                         int n = snprintf(buf, 6, "%i:%02i", eh, em);
249                         _kln89->DrawText((string)buf, 2, 15-n, 0);
250                 } else {
251                         _kln89->DrawText("-:--", 2, 11, 0);
252                 }
253         } else {        // if(3 == _subPage)
254                 // Switch the cursor off if scan-pull is out on this page.
255                 if(fgGetBool("/instrumentation/kln89/scan-pull")) { _kln89->_mode = KLN89_MODE_DISP; } 
256                 // The moving map page the core KLN89 class draws this.
257                 if(_kln89->_mapOrientation == 2 && _kln89->_groundSpeed_kts < 2) {
258                         // Don't draw it if in track up mode and groundspeed < 2kts, as per real-life unit.
259                 } else {
260                         _kln89->DrawMap(!_suspendAVS);
261                 }
262                 // Now draw any annotation over it.
263                 int scale = KLN89MapScales[_kln89->_mapScaleUnits][_kln89->_mapScaleIndex];
264                 string scle_str = GPSitoa(scale);
265                 if(crsr) {
266                         if(_menuActive) {
267                                 // Draw a background quad to encompass on/off for the first three at 'off' length
268                                 _kln89->DrawMapQuad(28, 9, 48, 36, true);
269                                 _kln89->DrawMapText("SUA:", 1, 27, true);
270                                 if(!(_menuPos == 0 && _kln89->_blink)) _kln89->DrawMapText((_kln89->_drawSUA ? "on" : "off"), 29, 27, true);
271                                 if(_menuPos == 0) _kln89->DrawLine(28, 27, 48, 27);
272                                 _kln89->DrawMapText("VOR:", 1, 18, true);
273                                 if(!(_menuPos == 1 && _kln89->_blink)) _kln89->DrawMapText((_kln89->_drawVOR ? "on" : "off"), 29, 18, true);
274                                 if(_menuPos == 1) _kln89->DrawLine(28, 18, 48, 18);
275                                 _kln89->DrawMapText("APT:", 1, 9, true);
276                                 if(!(_menuPos == 2 && _kln89->_blink)) _kln89->DrawMapText((_kln89->_drawApt ? "on" : "off"), 29, 9, true);
277                                 if(_menuPos == 2) _kln89->DrawLine(28, 9, 48, 9);
278                                 _kln89->DrawMapQuad(0, 0, 27, 8, true);
279                                 if(!(_menuPos == 3 && _kln89->_blink)) {
280                                         if(_kln89->_mapOrientation == 0) {
281                                                 _kln89->DrawMapText("N", 1, 0, true);
282                                                 _kln89->DrawMapUpArrow(7, 1);
283                                         } else if(_kln89->_mapOrientation == 1) {
284                                                 _kln89->DrawMapText("DTK", 1, 0, true);
285                                                 _kln89->DrawMapUpArrow(21, 1);
286                                         } else {
287                                                 // Don't bother with heading up for now!
288                                                 _kln89->DrawMapText("TK", 1, 0, true);
289                                                 _kln89->DrawMapUpArrow(14, 1);
290                                         }
291                                 }
292                                 if(_menuPos == 3) _kln89->DrawLine(0, 0, 27, 0);
293                         } else {
294                                 if(_uLinePos == 2) {
295                                         if(!_kln89->_blink) {
296                                                 _kln89->DrawMapText("Menu?", 1, 9, true);
297                                                 _kln89->DrawEnt();
298                                                 _kln89->DrawLine(0, 9, 34, 9);
299                                         } else {
300                                                 _kln89->DrawMapQuad(0, 9, 34, 17, true);
301                                         }
302                                 } else {
303                                         _kln89->DrawMapText("Menu?", 1, 9, true);
304                                 }
305                                 // right-justify the scale when _uLinePos == 3
306                                 if(!(_uLinePos == 3 && _kln89->_blink)) _kln89->DrawMapText(scle_str, (_uLinePos == 3 ? 29 - (scle_str.size() * 7) : 1), 0, true);
307                                 if(_uLinePos == 3) _kln89->DrawLine(0, 0, 27, 0);
308                         }
309                 } else {
310                         // Just draw the scale
311                         _kln89->DrawMapText(scle_str, 1, 0, true);
312                 }
313                 // If the scan-pull knob is out, draw one of the waypoints (if applicable).
314                 if(fgGetBool("/instrumentation/kln89/scan-pull")) {
315                         if(_kln89->_activeFP->waypoints.size()) {
316                                 //cout << "Need to draw a waypoint!\n";
317                                 _kln89->DrawLine(70, 0, 111, 0);
318                                 if(!_kln89->_blink) {
319                                         //_kln89->DrawMapQuad(45, 0, 97, 8, true);
320                                         if(!_scanWpSet) {
321                                                 _scanWpIndex = _kln89->GetActiveWaypointIndex();
322                                                 _scanWpSet = true;
323                                         }
324                                         _kln89->DrawMapText(_kln89->_activeFP->waypoints[_scanWpIndex]->id, 71, 0, true);
325                                 }               
326                         }
327                 }
328                 // And do part of the field 1 update, since NAV 4 is a special case for the last line.
329                 _kln89->DrawChar('>', 1, 0, 0);
330                 if(crsr && _uLinePos == 1) _kln89->Underline(1, 1, 0, 5);
331                 if(!(crsr && _uLinePos == 1 && _kln89->_blink)) {
332                         if(_kln89->_obsMode && _nav4DataSnippet == 0) _nav4DataSnippet = 1;
333                         double tsec;
334                         switch(_nav4DataSnippet) {
335                         case 0:
336                                 // DTK
337                                 _kln89->DrawLabel("DTK", -39, 6); 
338                                 // TODO - check we have an active FP / dtk and draw dashes if not.
339                                 char buf0[4];
340                                 snprintf(buf0, 4, "%03i", (int)(_kln89->_dtkMag));
341                                 _kln89->DrawText((string)buf0, 1, 3, 0);
342                                 break;
343                         case 1:
344                                 // groundspeed
345                                 _kln89->DrawSpeed(_kln89->_groundSpeed_kts, 1, 5, 0);
346                                 break;
347                         case 2:
348                                 // ETE
349                                 tsec = _kln89->GetETE();
350                                 if(tsec < 0.0) {
351                                         _kln89->DrawText("--:--", 1, 1, 0);
352                                 } else {
353                                         int eteh = (int)tsec / 3600;
354                                         int etem = ((int)tsec - eteh * 3600) / 60;
355                                         char buf[6];
356                                         int n = snprintf(buf, 6, "%02i:%02i", eteh, etem);
357                                         _kln89->DrawText((string)buf, 1, 6-n, 0);
358                                 }
359                                 break;
360                         case 3:
361                                 // Cross-track correction
362                                 double x = _kln89->CalcCrossTrackDeviation();
363                                 if(x < 0.0) {
364                                         _kln89->DrawSpecialChar(3, 1, 5, 0);
365                                 } else {
366                                         _kln89->DrawSpecialChar(7, 1, 5, 0);
367                                 }
368                                 char buf3[6];
369                                 int n;
370                                 x = fabs(x * (_kln89->_distUnits == GPS_DIST_UNITS_NM ? 1.0 : SG_NM_TO_METER * 0.001));
371                                 if(x < 1.0) {
372                                         n = snprintf(buf3, 6, "%0.2f", x);
373                                 } else if(x < 100.0) {
374                                         n = snprintf(buf3, 6, "%0.1f", x);
375                                 } else {
376                                         n = snprintf(buf3, 6, "%i", (int)(x+0.5));
377                                 }
378                                 _kln89->DrawText((string)buf3, 1, 5-n, 0);
379                                 break;
380                         }
381                 }
382         }
383         
384         KLN89Page::Update(dt);
385 }
386
387 // Returns the id string of the selected waypoint on NAV4 if valid, else returns an empty string.
388 string KLN89NavPage::GetNav4WpId() {
389         if(3 == _subPage) {
390                 if(fgGetBool("/instrumentation/kln89/scan-pull")) {
391                         if(_kln89->_activeFP->waypoints.size()) {
392                                 if(!_scanWpSet) {
393                                         return(_kln89->_activeWaypoint.id);
394                                 } else {
395                                         return(_kln89->_activeFP->waypoints[_scanWpIndex]->id);
396                                 }               
397                         }
398                 }
399         }
400         return("");
401 }
402
403 void KLN89NavPage::LooseFocus() {
404         _suspendAVS = false;
405         _scanWpSet = false;
406 }
407
408 void KLN89NavPage::CrsrPressed() {
409         if(_kln89->_mode == KLN89_MODE_DISP) {
410                 // Crsr just switched off
411                 _menuActive = false;
412         } else {
413                 // Crsr just switched on
414                 if(_subPage < 3) {
415                         _uLinePos = 1;
416                 } else {
417                         _uLinePos = 3;
418                 }
419         }
420 }
421
422 void KLN89NavPage::EntPressed() {
423         if(_kln89->_mode == KLN89_MODE_CRSR) {
424                 if(_subPage == 3 && _uLinePos == 2 && !_menuActive) {
425                         _menuActive = true;
426                         _menuPos = 0;
427                         _suspendAVS = false;
428                 }
429         }
430 }
431
432 void KLN89NavPage::ClrPressed() {
433         if(_kln89->_mode == KLN89_MODE_CRSR) {
434                 if(_subPage == 0) {
435                         if(_uLinePos == 1) {
436                                 _cdiFormat++;
437                                 if(_cdiFormat > 2) _cdiFormat = 0;
438                         } else if(_uLinePos == 2) {
439                                 _vnv++;
440                                 if(_vnv > 2) _vnv = 0;
441                         }
442                 }
443                 if(_subPage == 3) {
444                         if(_uLinePos > 1) {
445                                 _suspendAVS = !_suspendAVS;
446                                 _menuActive = false;
447                         } else if(_uLinePos == 1) {
448                                 _nav4DataSnippet++;
449                                 if(_nav4DataSnippet > 3) _nav4DataSnippet = 0;
450                         }
451                 }
452         } else {
453                 if(_subPage == 3) {
454                         _suspendAVS = !_suspendAVS;
455                 }
456         }
457 }
458
459 void KLN89NavPage::Knob1Left1() {
460         if(_kln89->_mode == KLN89_MODE_CRSR) {
461                 if(!(_subPage == 3 && _menuActive)) {
462                         if(_uLinePos > 0) _uLinePos--;
463                 } else {
464                         if(_menuPos > 0) _menuPos--;
465                 }
466         }
467 }
468
469 void KLN89NavPage::Knob1Right1() {
470         if(_kln89->_mode == KLN89_MODE_CRSR) {
471                 if(_subPage < 2) {
472                         if(_uLinePos < 2) _uLinePos++;
473                 } else if(_subPage == 2) {
474                         _uLinePos = 1;
475                 } else {
476                         // NAV 4 - this is complicated by whether the menu is displayed or not.
477                         if(_menuActive) {
478                                 if(_menuPos < 3) _menuPos++;
479                         } else {
480                                 if(_uLinePos < 3) _uLinePos++;
481                         }
482                 }
483         }
484 }
485
486 void KLN89NavPage::Knob2Left1() {
487         // If the inner-knob is out on the nav4 page, the only effect is to cycle the displayed waypoint.
488         if(3 == _subPage && fgGetBool("/instrumentation/kln89/scan-pull")) {
489                 if(_kln89->_activeFP->waypoints.size()) {       // TODO - find out what happens when scan-pull is on on nav4 without an active FP.
490                         // It's unlikely that we could get here without _scanWpSet, but theoretically possible, so we need to cover it.
491                         if(!_scanWpSet) {
492                                 _scanWpIndex = _kln89->GetActiveWaypointIndex();
493                                 _scanWpSet = true;
494                         } else {
495                                 if(0 == _scanWpIndex) {
496                                         _scanWpIndex = _kln89->_activeFP->waypoints.size() - 1;
497                                 } else {
498                                         _scanWpIndex--;
499                                 }
500                         }
501                 }
502                 return;
503         }
504         if(_kln89->_mode != KLN89_MODE_CRSR || _uLinePos == 0) {
505                 KLN89Page::Knob2Left1();
506                 return;
507         }
508         if(_subPage == 0) {
509                 if(_uLinePos == 1 && _cdiFormat == 2) {
510                         _kln89->CDIFSDIncrease();
511                 }
512         } else if(_subPage == 3) {
513                 if(_menuActive) {
514                         if(_menuPos == 0) {
515                                 _kln89->_drawSUA = !_kln89->_drawSUA;
516                         } else if(_menuPos == 1) {
517                                 _kln89->_drawVOR = !_kln89->_drawVOR;
518                         } else if(_menuPos == 2) {
519                                 _kln89->_drawApt = !_kln89->_drawApt;
520                         } else {
521                                 if(_kln89->_mapOrientation == 0) {
522                                         // Don't allow heading up for now
523                                         _kln89->_mapOrientation = 2;
524                                 } else {
525                                         _kln89->_mapOrientation--;
526                                 }
527                                 _kln89->UpdateMapHeading();
528                         }
529                 } else if(_uLinePos == 3) {
530                         // TODO - add AUTO
531                         if(_kln89->_mapScaleIndex == 0) {
532                                 _kln89->_mapScaleIndex = 20;
533                         } else {
534                                 _kln89->_mapScaleIndex--;
535                         }
536                 }
537         }
538 }
539
540 void KLN89NavPage::Knob2Right1() {
541         // If the inner-knob is out on the nav4 page, the only effect is to cycle the displayed waypoint.
542         if(3 == _subPage && fgGetBool("/instrumentation/kln89/scan-pull")) {
543                 if(_kln89->_activeFP->waypoints.size()) {       // TODO - find out what happens when scan-pull is on on nav4 without an active FP.
544                         // It's unlikely that we could get here without _scanWpSet, but theoretically possible, so we need to cover it.
545                         if(!_scanWpSet) {
546                                 _scanWpIndex = _kln89->GetActiveWaypointIndex();
547                                 _scanWpSet = true;
548                         } else {
549                                 _scanWpIndex++;
550                                 if(_scanWpIndex > static_cast<int>(_kln89->_activeFP->waypoints.size()) - 1) {
551                                         _scanWpIndex = 0;
552                                 }
553                         }
554                 }
555                 return;
556         }
557         if(_kln89->_mode != KLN89_MODE_CRSR || _uLinePos == 0) {
558                 KLN89Page::Knob2Right1();
559                 return;
560         }
561         if(_subPage == 0) {
562                 if(_uLinePos == 1 && _cdiFormat == 2) {
563                         _kln89->CDIFSDDecrease();
564                 }
565         } else if(_subPage == 3) {
566                 if(_menuActive) {
567                         if(_menuPos == 0) {
568                                 _kln89->_drawSUA = !_kln89->_drawSUA;
569                         } else if(_menuPos == 1) {
570                                 _kln89->_drawVOR = !_kln89->_drawVOR;
571                         } else if(_menuPos == 2) {
572                                 _kln89->_drawApt = !_kln89->_drawApt;
573                         } else {
574                                 if(_kln89->_mapOrientation >= 2) {
575                                         // Don't allow heading up for now
576                                         _kln89->_mapOrientation = 0;
577                                 } else {
578                                         _kln89->_mapOrientation++;
579                                 }
580                                 _kln89->UpdateMapHeading();
581                         }
582                 } else if(_uLinePos == 3) {
583                         // TODO - add AUTO
584                         if(_kln89->_mapScaleIndex == 20) {
585                                 _kln89->_mapScaleIndex = 0;
586                         } else {
587                                 _kln89->_mapScaleIndex++;
588                         }
589                 }
590         }
591 }