]> git.mxchange.org Git - flightgear.git/commitdiff
Enable correct DTO waypoint selection
authordaveluff <daveluff>
Sat, 7 Nov 2009 00:18:08 +0000 (00:18 +0000)
committerTim Moore <timoore@redhat.com>
Sat, 7 Nov 2009 07:56:55 +0000 (08:56 +0100)
12 files changed:
src/Instrumentation/KLN89/kln89.cxx
src/Instrumentation/KLN89/kln89.hxx
src/Instrumentation/KLN89/kln89_page.cxx
src/Instrumentation/KLN89/kln89_page.hxx
src/Instrumentation/KLN89/kln89_page_apt.cxx
src/Instrumentation/KLN89/kln89_page_dir.cxx
src/Instrumentation/KLN89/kln89_page_dir.hxx
src/Instrumentation/KLN89/kln89_page_int.cxx
src/Instrumentation/KLN89/kln89_page_ndb.cxx
src/Instrumentation/KLN89/kln89_page_vor.cxx
src/Instrumentation/dclgps.cxx
src/Instrumentation/dclgps.hxx

index eebf46e168d4e959e7f06337a6de0e0f1b2928f8..c028e17aeee061f7fa61e69cbec76182d5e9acaf 100644 (file)
@@ -206,6 +206,8 @@ KLN89::KLN89(RenderArea2D* instrument)
        _entRestoreCrsr = false;
        
        _dispMsg = false;
+       
+       _dtoReview = false;
 
        // Moving map stuff
        _mapOrientation = 0;
@@ -597,6 +599,17 @@ void KLN89::ToggleOBSMode() {
        DCLGPS::ToggleOBSMode();
 }
 
+void KLN89::DtoInitiate(const string& id) {
+       _dtoReview = false;
+       // Set the current page to NAV1
+       _curPage = 6;
+       _activePage = _pages[_curPage];
+       _activePage->SetSubPage(0);
+       // TODO - need to output a scratchpad message with the new course, but we don't know it yet!
+       // Call the base class to actually initiate the DTO.
+       DCLGPS::DtoInitiate(id);
+}
+
 void KLN89::DrawBar(int page) {
        int px = 1 + (page * 15);
        int py = 1;
index 26dcccd3d106b141cf9f43941b8648691c4dfb69..2206fb1b0139dff69a710bfd50864d35f5a937b1 100644 (file)
@@ -107,6 +107,9 @@ public:
 
 private:
        void ToggleOBSMode();
+       
+       // Initiate Direct To operation to the supplied ID.
+       void DtoInitiate(const string& id);
 
        //----------------------- Drawing functions which take CHARACTER units -------------------------
        // Render string s in display field field at position x, y
@@ -282,6 +285,10 @@ private:
        // since button events get directed to the page that was active before the
        // message was displayed, not the message page itself.
        bool _dispMsg;  // Set true while the message page is being displayed
+       
+       // Sometimes the datapages can be used to review a waypoint whilst the user makes a decision,
+       // and we need to remember why.
+       bool _dtoReview;        // Set true when we a reviewing a waypoint for DTO operation.
 };
 
 #endif  // _KLN89_HXX
index d3e5b8d4bba7dea0ac4fd0d100e25ba3afa628b1..43c78550be7d08396b5131eb997333e3ad520a03 100644 (file)
@@ -204,6 +204,12 @@ void KLN89Page::SetId(const string& s) {
        _id = s;
 }
 
+void KLN89Page::SetSubPage(int n) {
+       if(n < 0) n = 0;
+       if(n >= _nSubPages) n = _nSubPages-1;
+       _subPage = n;
+}
+
 const string& KLN89Page::GetId() {
        return(_id);
 }
index a4e686ab8762407c2f2eda5688b13175be0513bb..89ea5a7e7a0ca38c8af344823d21b34afd1fa017 100644 (file)
@@ -69,6 +69,7 @@ public:
        virtual const string& GetId();
        
        inline int GetSubPage() { return(_subPage); }
+       void SetSubPage(int n);
        
        inline int GetNSubPages() { return(_nSubPages); }
        
index 1f4ffcb8aa9e51f1d88bfad4b90ae6567020c127..96cceea0d0c6c21e48b6295010bdba6f5aa22dd6 100644 (file)
@@ -643,8 +643,12 @@ void KLN89AptPage::ClrPressed() {
 void KLN89AptPage::EntPressed() {
        if(_entInvert) {
                _entInvert = false;
-               _last_apt_id = _apt_id;
-               _apt_id = _save_apt_id;
+               if(_kln89->_dtoReview) {
+                       _kln89->DtoInitiate(_apt_id);
+               } else {
+                       _last_apt_id = _apt_id;
+                       _apt_id = _save_apt_id;
+               }
        } else if(_subPage == 7 && _kln89->_mode == KLN89_MODE_CRSR && _uLinePos > 0) {
                // We are selecting an approach
                if(_iafDialog) {
index c80bd2397041983be0b329ca606e4e8de758c61c..a8382b06f9be22298acca1d92e709b1bde2fe5de 100644 (file)
 #endif
 
 #include "kln89_page_dir.hxx"
+#include <Main/fg_props.hxx>
 
 KLN89DirPage::KLN89DirPage(KLN89* parent)
 : KLN89Page(parent) {
        _nSubPages = 1;
        _subPage = 0;
        _name = "DIR";
+       _maxULinePos = 4;
        _DToWpDispMode = 2;
 }
 
@@ -43,16 +45,16 @@ void KLN89DirPage::Update(double dt) {
        _kln89->DrawText("DIRECT TO:", 2, 2, 3);
        
        if(_kln89->_mode == KLN89_MODE_CRSR) {
+               string s = _id;
+               while(s.size() < 5) s += ' ';
                if(_DToWpDispMode == 0) {
-                       string s = _id;
-                       while(s.size() < 5) s += ' ';
                        if(!_kln89->_blink) {
                                _kln89->DrawText(s, 2, 4, 1, false, 99);
                                _kln89->DrawEnt(1, 0, 1);
                        }
                } else if(_DToWpDispMode == 1) {
                        if(!_kln89->_blink) {
-                               // TODO
+                               _kln89->DrawText(s, 2, 4, 1, false, _uLinePos);
                                _kln89->DrawEnt(1, 0, 1);
                        }
                        _kln89->Underline(2, 4, 1, 5);
@@ -67,13 +69,16 @@ void KLN89DirPage::Update(double dt) {
        KLN89Page::Update(dt);
 }
 
+// This can only be called from the KLN89 when DTO is pressed from outside of the DIR page.
+// DO NOT USE IT to set _id internally from the DIR page, since it initialises various state 
+// based on the assumption that the DIR page is being first entered.
 void KLN89DirPage::SetId(const string& s) {
        if(s.size()) {
                _id = s;
-               // TODO - fill in lat, lon, type
-               // or just pass in waypoints (probably better!)
                _DToWpDispMode = 0;
-               // TODO - this (above) should probably be dependent on whether s is a *valid* waypoint!
+               if(!_kln89->_activeFP->IsEmpty()) {
+                       _DToWpDispIndex = (int)_kln89->_activeFP->waypoints.size() - 1;
+               }
        } else {
                _DToWpDispMode = 2;
        }
@@ -81,6 +86,11 @@ void KLN89DirPage::SetId(const string& s) {
        _uLinePos = 1;  // Needed to stop Leg flashing
 }
 
+void KLN89DirPage::CrsrPressed() {
+       // Pressing CRSR clears the ID field (from sim).
+       _DToWpDispMode = 2;
+}
+
 void KLN89DirPage::ClrPressed() {
        if(_kln89->_mode == KLN89_MODE_CRSR) {
                if(_DToWpDispMode <= 1) {
@@ -98,22 +108,115 @@ void KLN89DirPage::ClrPressed() {
 }
 
 void KLN89DirPage::EntPressed() {
-       //cout << "DTO ENT Pressed()\n";
-       if(_id.empty()) {
+       // Trim any RH whitespace from _id
+       while(!_id.empty()) {
+               if(_id[_id.size()-1] == ' ') {
+                       _id = _id.substr(0, _id.size()-1);
+               } else {
+                       // Important to break, since usr waypoint names may contain space.
+                       break;
+               }
+       }
+       if(_DToWpDispMode == 2 || _id.empty()) {
                _kln89->DtoCancel();
        } else {
-               _kln89->DtoInitiate(_id);
+               if(_DToWpDispMode == 0) {
+                       // It's a waypoint from the active flightplan - these get processed without data page review.
+                       _kln89->DtoInitiate(_id);
+               } else {
+                       // Display the appropriate data page for review (USR page if the ident is not currently valid)
+                       _kln89->_dtoReview = true;
+                       GPSWaypoint* wp = _kln89->FindFirstByExactId(_id);
+                       if(wp) {
+                               // Set the current page to be the appropriate data page
+                               _kln89->_curPage = wp->type;
+                               delete wp;
+                       } else {
+                               // Set the current page to be the user page
+                               _kln89->_curPage = 4;
+                       }
+                       // set the page ID and entInvert, and activate the current page.
+                       _kln89->_activePage = _kln89->_pages[_kln89->_curPage];
+                       _kln89->_activePage->SetId(_id);
+                       _kln89->_activePage->SetEntInvert(true);
+               }
        }
 }
 
 void KLN89DirPage::Knob2Left1() {
        if(_kln89->_mode == KLN89_MODE_CRSR) {
-               if(_DToWpDispMode == 0) {
-                       _DToWpDispMode = 1;
-               } else if(_DToWpDispMode == 1) {
-                       // TODO
+               if(fgGetBool("/instrumentation/kln89/scan-pull")) {
+                       if(_DToWpDispMode == 2) {
+                               if(!_kln89->_activeFP->IsEmpty()) {
+                                       // Switch to mode 0, set the position to the end of the active flightplan *and* run the mode 0 case.
+                                       _DToWpDispMode = 0;
+                                       _DToWpDispIndex = (int)_kln89->_activeFP->waypoints.size() - 1;
+                               }
+                       }
+                       if(_DToWpDispMode == 0) {
+                               // If the knob is pulled out, then the unit cycles through the waypoints of the active flight plan
+                               // (This is deduced from the Bendix-King sim, I haven't found it documented in the pilot guide).
+                               // If the active flight plan is empty it clears the field (this is possible, e.g. if a data page was
+                               // active when DTO was pressed).
+                               if(!_kln89->_activeFP->IsEmpty()) {
+                                       if(_DToWpDispIndex == 0) {
+                                               _DToWpDispIndex = (int)_kln89->_activeFP->waypoints.size() - 1;
+                                       } else {
+                                               _DToWpDispIndex--;
+                                       }
+                                       _id = _kln89->_activeFP->waypoints[_DToWpDispIndex]->id;
+                               } else {
+                                       _DToWpDispMode = 2;
+                               }
+                       }
+                       // _DToWpDispMode == 1 is a NO-OP when the knob is out.
                } else {
-                       // TODO
+                       if(_DToWpDispMode == 0) {
+                               // If the knob is not pulled out, then turning it transitions the DIR page to the waypoint selection mode
+                               // and sets the waypoint to the first beginning with '9'
+                               _id = "9";
+                               GPSWaypoint* wp = _kln89->FindFirstById(_id);
+                               if(wp) {
+                                       _id = wp->id;
+                                       delete wp;
+                               }
+                               _uLinePos = 0;
+                               _DToWpDispMode = 1;
+                       } else if(_DToWpDispMode == 1) {
+                               while(_id.size() < (_uLinePos + 1)) {
+                                       _id += ' ';
+                               }
+                               char ch = _id[_uLinePos];
+                               if(ch == ' ') {
+                                       ch = '9';
+                               } else if(ch == '0') {
+                                       ch = 'Z';
+                               } else if(ch == 'A') {
+                                       // It seems that blanks are allowed within the name, but not for the first character
+                                       if(_uLinePos == 0) {
+                                               ch = '9';
+                                       } else {
+                                               ch = ' ';
+                                       }
+                               } else {
+                                       ch--;
+                               }
+                               _id[_uLinePos] = ch;
+                               GPSWaypoint* wp = _kln89->FindFirstById(_id.substr(0, _uLinePos+1));
+                               if(wp) {
+                                       _id = wp->id;
+                                       delete wp;
+                               }
+                       } else {
+                               _id = "9";
+                               GPSWaypoint* wp = _kln89->FindFirstById(_id);
+                               if(wp) {
+                                       _id = wp->id;
+                                       delete wp;
+                               }
+                               _uLinePos = 0;
+                               _DToWpDispMode = 1;
+                       }
                }
        } else {
                // If the cursor is not displayed, then we return to the page that was displayed prior to DTO being pressed,
@@ -125,12 +228,78 @@ void KLN89DirPage::Knob2Left1() {
 
 void KLN89DirPage::Knob2Right1() {
        if(_kln89->_mode == KLN89_MODE_CRSR) {
-               if(_DToWpDispMode == 0) {
-                       _DToWpDispMode = 1;
-               } else if(_DToWpDispMode == 1) {
-                       // TODO
+               if(fgGetBool("/instrumentation/kln89/scan-pull")) {
+                       if(_DToWpDispMode == 2) {
+                               if(!_kln89->_activeFP->IsEmpty()) {
+                                       // Switch to mode 0, set the position to the end of the active flightplan *and* run the mode 0 case.
+                                       _DToWpDispMode = 0;
+                                       _DToWpDispIndex = (int)_kln89->_activeFP->waypoints.size() - 1;
+                               }
+                       }
+                       if(_DToWpDispMode == 0) {
+                               // If the knob is pulled out, then the unit cycles through the waypoints of the active flight plan
+                               // (This is deduced from the Bendix-King sim, I haven't found it documented in the pilot guide).
+                               // If the active flight plan is empty it clears the field (this is possible, e.g. if a data page was
+                               // active when DTO was pressed).
+                               if(!_kln89->_activeFP->IsEmpty()) {
+                                       if(_DToWpDispIndex == (int)_kln89->_activeFP->waypoints.size() - 1) {
+                                               _DToWpDispIndex = 0;
+                                       } else {
+                                               _DToWpDispIndex++;
+                                       }
+                                       _id = _kln89->_activeFP->waypoints[_DToWpDispIndex]->id;
+                               } else {
+                                       _DToWpDispMode = 2;
+                               }
+                       }
+                       // _DToWpDispMode == 1 is a NO-OP when the knob is out.
                } else {
-                       // TODO
+                       if(_DToWpDispMode == 0) {
+                               // If the knob is not pulled out, then turning it transitions the DIR page to the waypoint selection mode
+                               // and sets the waypoint to the first beginning with 'A'
+                               _id = "A";
+                               GPSWaypoint* wp = _kln89->FindFirstById(_id);
+                               if(wp) {
+                                       _id = wp->id;
+                                       delete wp;
+                               }
+                               _uLinePos = 0;
+                               _DToWpDispMode = 1;
+                       } else if(_DToWpDispMode == 1) {
+                               while(_id.size() < (_uLinePos + 1)) {
+                                       _id += ' ';
+                               }
+                               char ch = _id[_uLinePos];
+                               if(ch == ' ') {
+                                       ch = 'A';
+                               } else if(ch == 'Z') {
+                                       ch = '0';
+                               } else if(ch == '9') {
+                                       // It seems that blanks are allowed within the name, but not for the first character
+                                       if(_uLinePos == 0) {
+                                               ch = 'A';
+                                       } else {
+                                               ch = ' ';
+                                       }
+                               } else {
+                                       ch++;
+                               }
+                               _id[_uLinePos] = ch;
+                               GPSWaypoint* wp = _kln89->FindFirstById(_id.substr(0, _uLinePos+1));
+                               if(wp) {
+                                       _id = wp->id;
+                                       delete wp;
+                               }
+                       } else {
+                               _id = "A";
+                               GPSWaypoint* wp = _kln89->FindFirstById(_id);
+                               if(wp) {
+                                       _id = wp->id;
+                                       delete wp;
+                               }
+                               _uLinePos = 0;
+                               _DToWpDispMode = 1;
+                       }
                }
        } else {
                // If the cursor is not displayed, then we return to the page that was displayed prior to DTO being pressed,
index fe8f18261cb4e5b0ec4f85e5bc081db0f5c653b3..ac5899327bcb0511b903e3ebb4968e82c938d011 100644 (file)
@@ -36,6 +36,7 @@ public:
        
        void SetId(const string& s);
        
+       void CrsrPressed();
        void ClrPressed();
        void EntPressed();
        void Knob2Left1();
@@ -49,6 +50,10 @@ private:
        // 2 => Blanks.  These can be displayed flashing when the cursor is active (eg. when CLR is pressed) and are always displayed if the cursor is turned off.
        int _DToWpDispMode;
        
+       // Position of the list in the mode that scans through the active flight plan.
+       // This should be initialised to point at the final waypoint of the active flight plan when we enter mode zero above.
+       int _DToWpDispIndex;
+       
        // We need to save the mode when DTO gets pressed, since potentially this class handles page exit via. the CLR event handler
        KLN89Mode _saveMasterMode;
 };
index 694e06ce6cccd8f7630429e35f63490939493f7b..1edb2428d943b998a0d2a7b650e849c57cb8fec0 100644 (file)
@@ -195,8 +195,13 @@ void KLN89IntPage::ClrPressed() {
 void KLN89IntPage::EntPressed() {
        if(_entInvert) {
                _entInvert = false;
-               _last_int_id = _int_id;
-               _int_id = _save_int_id;
+               _entInvert = false;
+               if(_kln89->_dtoReview) {
+                       _kln89->DtoInitiate(_int_id);
+               } else {
+                       _last_int_id = _int_id;
+                       _int_id = _save_int_id;
+               }
        }
 }
 
index 0a70f1d633d7260dd2f67777085a22ee1a2f9181..b6b90bebdafc7673e3a26aa02442b6c1f616945e 100644 (file)
@@ -158,8 +158,12 @@ void KLN89NDBPage::ClrPressed() {
 void KLN89NDBPage::EntPressed() {
        if(_entInvert) {
                _entInvert = false;
-               _last_ndb_id = _ndb_id;
-               _ndb_id = _save_ndb_id;
+               if(_kln89->_dtoReview) {
+                       _kln89->DtoInitiate(_ndb_id);
+               } else {
+                       _last_ndb_id = _ndb_id;
+                       _ndb_id = _save_ndb_id;
+               }
        }
 }
 
index a7719f495ebacc5629ab5ccc374628b5abff3d1c..414a8c487d208ff3c3b01efab105a4a7bc5c46a4 100644 (file)
@@ -170,8 +170,13 @@ void KLN89VorPage::ClrPressed() {
 void KLN89VorPage::EntPressed() {
        if(_entInvert) {
                _entInvert = false;
-               _last_vor_id = _vor_id;
-               _vor_id = _save_vor_id;
+               _entInvert = false;
+               if(_kln89->_dtoReview) {
+                       _kln89->DtoInitiate(_vor_id);
+               } else {
+                       _last_vor_id = _vor_id;
+                       _vor_id = _save_vor_id;
+               }
        }
 }
 
index 6feb0a286b92394a6c7739560a30150ca22bc2d2..d3da8e828e5902107f6400b70898a05bd31ad366 100644 (file)
@@ -717,21 +717,25 @@ double DCLGPS::GetCDIDeflection() const {
 }
 
 void DCLGPS::DtoInitiate(const string& s) {
-       //cout << "DtoInitiate, s = " << s << '\n';
        const GPSWaypoint* wp = FindFirstByExactId(s);
        if(wp) {
-               //cout << "Waypoint found, starting dto operation!\n";
+               // TODO - Currently we start DTO operation unconditionally, regardless of which mode we are in.
+               // In fact, the following rules apply:
+               // In LEG mode, start DTO as we currently do.
+               // In OBS mode, set the active waypoint to the requested waypoint, and then:
+               // If the KLN89 is not connected to an external HSI or CDI, set the OBS course to go direct to the waypoint.
+               // If the KLN89 *is* connected to an external HSI or CDI, it cannot set the course itself, and will display
+               // a scratchpad message with the course to set manually on the HSI/CDI.
+               // In both OBS cases, leave _dto false, since we don't need the virtual waypoint created.
                _dto = true;
                _activeWaypoint = *wp;
                _fromWaypoint.lat = _gpsLat;
                _fromWaypoint.lon = _gpsLon;
                _fromWaypoint.type = GPS_WP_VIRT;
                _fromWaypoint.id = "DTOWP";
-    delete wp;
+               delete wp;
        } else {
-               //cout << "Waypoint not found, ignoring dto request\n";
-               // Should bring up the user waypoint page, but we're not implementing that yet.
-               _dto = false;   // TODO - implement this some day.
+               _dto = false;
        }
 }
 
index 76dd764ddea020bdc6d3cd82c614202d78fa0828..295a7ad6436d8402db30461a5e09592e9b430b52 100644 (file)
@@ -287,7 +287,7 @@ public:
        inline bool GetToFlag() const { return(_headingBugTo); }
        
        // Initiate Direct To operation to the supplied ID.
-       void DtoInitiate(const string& id);
+       virtual void DtoInitiate(const string& id);
        // Cancel Direct To operation
        void DtoCancel();
        
@@ -343,8 +343,8 @@ protected:
 
 protected:
        // Find first of any type of waypoint by id.  (TODO - Possibly we should return multiple waypoints here).
-  GPSWaypoint* FindFirstById(const string& id) const;
-  GPSWaypoint* FindFirstByExactId(const string& id) const;
+       GPSWaypoint* FindFirstById(const string& id) const;
+       GPSWaypoint* FindFirstByExactId(const string& id) const;
    
        FGNavRecord* FindFirstVorById(const string& id, bool &multi, bool exact = false);
        FGNavRecord* FindFirstNDBById(const string& id, bool &multi, bool exact = false);
@@ -353,8 +353,8 @@ protected:
        // Find the closest VOR to a position in RADIANS.
        FGNavRecord* FindClosestVor(double lat_rad, double lon_rad);
 
-  // helper to implement the above FindFirstXXX methods
-  FGPositioned* FindTypedFirstById(const std::string& id, FGPositioned::Type ty, bool &multi, bool exact);
+       // helper to implement the above FindFirstXXX methods
+       FGPositioned* FindTypedFirstById(const std::string& id, FGPositioned::Type ty, bool &multi, bool exact);
 
        // Position, orientation and velocity.
        // These should be read from FG's built-in GPS logic if possible.