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