1 // mk_viii.hxx -- Honeywell MK VIII EGPWS emulation
3 // Written by Jean-Yves Lefort, started September 2005.
5 // Copyright (C) 2005, 2006 Jean-Yves Lefort - jylefort@FreeBSD.org
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #ifndef __INSTRUMENTS_MK_VIII_HXX
23 #define __INSTRUMENTS_MK_VIII_HXX
31 #include <simgear/props/props.hxx>
32 #include <simgear/sound/sample_openal.hxx>
33 #include <simgear/structure/subsystem_mgr.hxx>
41 #include <Airports/runways.hxx>
42 #include <Airports/simple.hxx>
43 #include <Main/globals.hxx>
46 # pragma warning( push )
47 # pragma warning( disable: 4355 )
50 /////////////////////////////////////////////////////////////////////////////
51 // FGVoicePlayer /////////////////////////////////////////////////////
52 /////////////////////////////////////////////////////////////////////////////
58 /////////////////////////////////////////////////////////////////////////////
59 // MK::RawValueMethodsData /////////////////////////////////////////////
60 /////////////////////////////////////////////////////////////////////////////
62 template <class C, class VT, class DT>
63 class RawValueMethodsData : public SGRawValue<VT>
66 typedef VT (C::*getter_t) (DT) const;
67 typedef void (C::*setter_t) (DT, VT);
69 RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0)
70 : _obj(obj), _data(data), _getter(getter), _setter(setter) {}
72 virtual VT getValue () const
75 return (_obj.*_getter)(_data);
77 return SGRawValue<VT>::DefaultValue();
79 virtual bool setValue (VT value)
83 (_obj.*_setter)(_data, value);
89 virtual SGRawValue<VT> *clone () const
91 return new RawValueMethodsData<C,VT,DT>(_obj, _data, _getter, _setter);
101 class PropertiesHandler
104 vector<SGPropertyNode_ptr> tied_properties;
107 inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value)
109 node->tie(raw_value);
110 tied_properties.push_back(node);
114 inline void tie (SGPropertyNode *node,
115 const char *relative_path,
116 const SGRawValue<T> &raw_value)
118 tie(node->getNode(relative_path, true), raw_value);
121 PropertiesHandler() {};
126 ///////////////////////////////////////////////////////////////////////////
127 // FGVoicePlayer::Voice ////////////////////////////////////////////
128 ///////////////////////////////////////////////////////////////////////////
134 /////////////////////////////////////////////////////////////////////////
135 // FGVoicePlayer::Voice::Element ////////////////////////////////////////
136 /////////////////////////////////////////////////////////////////////////
143 virtual inline void play (float volume) {}
144 virtual inline void stop () {}
145 virtual bool is_playing () = 0;
146 virtual inline void set_volume (float volume) {}
149 /////////////////////////////////////////////////////////////////////////
150 // FGVoicePlayer::Voice::SampleElement ///////////////////////////
151 /////////////////////////////////////////////////////////////////////////
153 class SampleElement : public Element
155 SGSharedPtr<SGSoundSample> _sample;
159 inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
160 : _sample(sample), _volume(volume) { silence = false; }
162 virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
163 virtual inline void stop () { if (_sample) _sample->stop(); }
164 virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
165 virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
168 /////////////////////////////////////////////////////////////////////////
169 // FGVoicePlayer::Voice::SilenceElement //////////////////////////
170 /////////////////////////////////////////////////////////////////////////
172 class SilenceElement : public Element
178 inline SilenceElement (double duration)
179 : _duration(duration) { silence = true; }
181 virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
182 virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
185 /////////////////////////////////////////////////////////////////////////
186 // FGVoicePlayer::Voice (continued) //////////////////////////////
187 /////////////////////////////////////////////////////////////////////////
191 inline Voice (FGVoicePlayer *_player)
192 : element(NULL), player(_player), volume(1.0) {}
196 inline void append (Element *_element) { elements.push_back(_element); }
199 void stop (bool now);
200 void set_volume (float _volume);
201 void volume_changed ();
205 FGVoicePlayer *player;
209 vector<Element *> elements;
210 vector<Element *>::iterator iter;
212 inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
215 ///////////////////////////////////////////////////////////////////////////
216 // FGVoicePlayer (continued) ///////////////////////////////////////
217 ///////////////////////////////////////////////////////////////////////////
232 inline FGVoicePlayer (PropertiesHandler* properties_handler, string _dev_name)
233 : volume(1.0), voice(NULL), next_voice(NULL), paused(false),
234 dev_name(_dev_name), dir_prefix(""),
235 speaker(this,properties_handler) {}
242 bool is_playing() { return (voice!=NULL);}
249 void play (Voice *_voice, unsigned int flags = 0);
255 void stop (unsigned int flags = 0);
257 void set_volume (float _volume);
260 void bind (SGPropertyNode *node, const char* default_dir_prefix);
264 ///////////////////////////////////////////////////////////////////////////
265 // FGVoicePlayer::Speaker //////////////////////////////////////////
266 ///////////////////////////////////////////////////////////////////////////
270 FGVoicePlayer *player;
271 PropertiesHandler* properties_handler;
276 inline void tie (SGPropertyNode *node, const char *name, T *ptr)
278 properties_handler->tie
279 (node, (string("speaker/") + name).c_str(),
280 RawValueMethodsData<FGVoicePlayer::Speaker,T,T*>
282 &FGVoicePlayer::Speaker::get_property,
283 &FGVoicePlayer::Speaker::set_property));
288 inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); }
291 inline T get_property (T *ptr) const { return *ptr; }
295 inline Speaker (FGVoicePlayer *_player,PropertiesHandler* _properties_handler)
297 properties_handler(_properties_handler),
303 void bind (SGPropertyNode *node);
304 void update_configuration ();
308 ///////////////////////////////////////////////////////////////////////////
309 // FGVoicePlayer (continued) ///////////////////////////////////////
310 ///////////////////////////////////////////////////////////////////////////
312 SGSharedPtr<SGSampleGroup> _sgr;
315 map< string, SGSharedPtr<SGSoundSample> > samples;
316 vector<Voice *> _voices;
321 SGSoundSample *get_sample (const char *name);
323 inline void append (Voice *voice, Voice::Element *element) { voice->append(element); }
324 inline void append (Voice *voice, const char *sample_name) { voice->append(new Voice::SampleElement(get_sample(sample_name))); }
325 inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); }
327 inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); }
330 inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); }
331 template <class T1, class T2>
332 inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); }
333 template <class T1, class T2, class T3>
334 inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); }
335 template <class T1, class T2, class T3, class T4>
336 inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); }
339 ///////////////////////////////////////////////////////////////////////////////
340 // MK_VIII ////////////////////////////////////////////////////////////////////
341 ///////////////////////////////////////////////////////////////////////////////
343 class MK_VIII : public SGSubsystem
345 // keep in sync with Mode6Handler::altitude_callout_definitions[]
346 static const unsigned n_altitude_callouts = 11;
348 /////////////////////////////////////////////////////////////////////////////
349 // MK_VIII::Parameter ///////////////////////////////////////////////////////
350 /////////////////////////////////////////////////////////////////////////////
361 : _value(0), ncd(true) {}
363 inline T get () const { assert(! ncd); return _value; }
364 inline T *get_pointer () { return &_value; }
365 inline void set (T value) { ncd = false; _value = value; }
366 inline void unset () { ncd = true; }
368 inline void set (const Parameter<T> *parameter)
373 set(parameter->get());
376 inline void set (const Parameter<double> *parameter, double factor)
381 set(parameter->get() * factor);
385 /////////////////////////////////////////////////////////////////////////////
386 // MK_VIII::Sample //////////////////////////////////////////////////////////
387 /////////////////////////////////////////////////////////////////////////////
396 inline Sample (T _value)
397 : timestamp(globals->get_sim_time_sec()), value(_value) {}
400 /////////////////////////////////////////////////////////////////////////////
401 // MK_VIII::Timer ///////////////////////////////////////////////////////////
402 /////////////////////////////////////////////////////////////////////////////
414 inline void start () { running = true; start_time = globals->get_sim_time_sec(); }
415 inline void stop () { running = false; }
416 inline double elapsed () const { assert(running); return globals->get_sim_time_sec() - start_time; }
417 inline double start_or_elapsed ()
429 /////////////////////////////////////////////////////////////////////////////
430 // MK_VIII::PropertiesHandler ///////////////////////////////////////////////
431 /////////////////////////////////////////////////////////////////////////////
433 class PropertiesHandler : public FGVoicePlayer::PropertiesHandler
440 SGPropertyNode_ptr ai_caged;
441 SGPropertyNode_ptr ai_roll;
442 SGPropertyNode_ptr ai_serviceable;
443 SGPropertyNode_ptr altimeter_altitude;
444 SGPropertyNode_ptr altimeter_serviceable;
445 SGPropertyNode_ptr altitude;
446 SGPropertyNode_ptr altitude_agl;
447 SGPropertyNode_ptr altitude_gear_agl;
448 SGPropertyNode_ptr altitude_radar_agl;
449 SGPropertyNode_ptr orientation_roll;
450 SGPropertyNode_ptr asi_serviceable;
451 SGPropertyNode_ptr asi_speed;
452 SGPropertyNode_ptr autopilot_heading_lock;
453 SGPropertyNode_ptr flaps;
454 SGPropertyNode_ptr gear_down;
455 SGPropertyNode_ptr latitude;
456 SGPropertyNode_ptr longitude;
457 SGPropertyNode_ptr nav0_cdi_serviceable;
458 SGPropertyNode_ptr nav0_gs_distance;
459 SGPropertyNode_ptr nav0_gs_needle_deflection;
460 SGPropertyNode_ptr nav0_gs_serviceable;
461 SGPropertyNode_ptr nav0_has_gs;
462 SGPropertyNode_ptr nav0_heading_needle_deflection;
463 SGPropertyNode_ptr nav0_in_range;
464 SGPropertyNode_ptr nav0_nav_loc;
465 SGPropertyNode_ptr nav0_serviceable;
466 SGPropertyNode_ptr power;
467 SGPropertyNode_ptr replay_state;
468 SGPropertyNode_ptr vs;
469 } external_properties;
471 inline PropertiesHandler (MK_VIII *device)
472 : FGVoicePlayer::PropertiesHandler(), mk(device) {}
474 PropertiesHandler() : FGVoicePlayer::PropertiesHandler() {}
480 PropertiesHandler properties_handler;
483 /////////////////////////////////////////////////////////////////////////////
484 // MK_VIII::PowerHandler ////////////////////////////////////////////////////
485 /////////////////////////////////////////////////////////////////////////////
494 Timer power_loss_timer;
495 Timer abnormal_timer;
496 Timer low_surge_timer;
497 Timer high_surge_timer;
498 Timer very_high_surge_timer;
500 bool handle_abnormal_voltage (bool abnormal,
502 double max_duration);
508 inline PowerHandler (MK_VIII *device)
509 : mk(device), serviceable(false), powered(false) {}
511 void bind (SGPropertyNode *node);
515 /////////////////////////////////////////////////////////////////////////////
516 // MK_VIII::SystemHandler ///////////////////////////////////////////////////
517 /////////////////////////////////////////////////////////////////////////////
526 int last_replay_state;
527 Timer reposition_timer;
540 inline SystemHandler (MK_VIII *device)
541 : mk(device), state(STATE_OFF) {}
548 /////////////////////////////////////////////////////////////////////////////
549 // MK_VIII::ConfigurationModule /////////////////////////////////////////////
550 /////////////////////////////////////////////////////////////////////////////
552 class ConfigurationModule
555 // keep in sync with IOHandler::present_status()
558 CATEGORY_AIRCRAFT_MODE_TYPE_SELECT,
559 CATEGORY_AIR_DATA_INPUT_SELECT,
560 CATEGORY_POSITION_INPUT_SELECT,
561 CATEGORY_ALTITUDE_CALLOUTS,
562 CATEGORY_AUDIO_MENU_SELECT,
563 CATEGORY_TERRAIN_DISPLAY_SELECT,
564 CATEGORY_OPTIONS_SELECT_GROUP_1,
565 CATEGORY_RADIO_ALTITUDE_INPUT_SELECT,
566 CATEGORY_NAVIGATION_INPUT_SELECT,
567 CATEGORY_ATTITUDE_INPUT_SELECT,
568 CATEGORY_HEADING_INPUT_SELECT,
569 CATEGORY_WINDSHEAR_INPUT_SELECT,
570 CATEGORY_INPUT_OUTPUT_DISCRETE_TYPE_SELECT,
571 CATEGORY_AUDIO_OUTPUT_LEVEL,
572 CATEGORY_UNDEFINED_INPUT_SELECT_1,
573 CATEGORY_UNDEFINED_INPUT_SELECT_2,
574 CATEGORY_UNDEFINED_INPUT_SELECT_3,
581 STATE_INVALID_DATABASE,
582 STATE_INVALID_AIRCRAFT_TYPE
586 int effective_categories[N_CATEGORIES];
588 ConfigurationModule (MK_VIII *device);
591 void bind (SGPropertyNode *node);
596 int categories[N_CATEGORIES];
598 bool read_aircraft_mode_type_select (int value);
599 bool read_air_data_input_select (int value);
600 bool read_position_input_select (int value);
601 bool read_altitude_callouts (int value);
602 bool read_audio_menu_select (int value);
603 bool read_terrain_display_select (int value);
604 bool read_options_select_group_1 (int value);
605 bool read_radio_altitude_input_select (int value);
606 bool read_navigation_input_select (int value);
607 bool read_attitude_input_select (int value);
608 bool read_heading_input_select (int value);
609 bool read_windshear_input_select (int value);
610 bool read_input_output_discrete_type_select (int value);
611 bool read_audio_output_level (int value);
612 bool read_undefined_input_select (int value);
614 static bool m6_t2_is_bank_angle (Parameter<double> *agl,
617 static bool m6_t4_is_bank_angle (Parameter<double> *agl,
622 /////////////////////////////////////////////////////////////////////////////
623 // MK_VIII::FaultHandler ////////////////////////////////////////////////////
624 /////////////////////////////////////////////////////////////////////////////
636 static const unsigned int fault_inops[];
638 bool has_faults (unsigned int inop);
641 // keep in sync with IOHandler::present_status()
644 FAULT_ALL_MODES_INHIBIT,
647 FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID,
648 FAULT_SELF_TEST_INVALID,
649 FAULT_GLIDESLOPE_CANCEL_INVALID,
650 FAULT_STEEP_APPROACH_INVALID,
652 FAULT_TA_TCF_INHIBIT,
653 FAULT_MODES14_INPUTS_INVALID,
654 FAULT_MODE5_INPUTS_INVALID,
655 FAULT_MODE6_INPUTS_INVALID,
656 FAULT_BANK_ANGLE_INPUTS_INVALID,
657 FAULT_TCF_INPUTS_INVALID,
661 bool faults[N_FAULTS];
663 inline FaultHandler (MK_VIII *device)
668 void set_fault (Fault fault);
669 void unset_fault (Fault fault);
671 bool has_faults () const;
674 /////////////////////////////////////////////////////////////////////////////
675 // MK_VIII::IOHandler ///////////////////////////////////////////////////////
676 /////////////////////////////////////////////////////////////////////////////
690 struct LampConfiguration
696 struct FaultsConfiguration
698 double max_flaps_down_airspeed;
699 double max_gear_down_airspeed;
704 const LampConfiguration *lamp;
705 const FaultsConfiguration *faults;
707 bool steep_approach_enabled;
708 bool gpws_inhibit_enabled;
709 bool momentary_flap_override_enabled;
710 bool alternate_steep_approach;
711 bool use_internal_gps;
712 bool localizer_enabled;
714 bool use_attitude_indicator;
717 struct _s_input_feeders
723 bool glideslope_inhibit;
724 bool decision_height;
725 bool autopilot_engaged;
730 bool uncorrected_barometric_altitude;
731 bool barometric_altitude_rate;
733 bool glideslope_deviation;
735 bool localizer_deviation;
736 bool computed_airspeed;
737 bool decision_height;
745 bool landing_gear; // appendix E 6.6.2, 3.15.1.4
746 bool landing_flaps; // appendix E 6.6.4, 3.15.1.2
747 bool momentary_flap_override; // appendix E 6.6.6, 3.15.1.6
748 bool self_test; // appendix E 6.6.7, 3.15.1.10
749 bool glideslope_inhibit; // appendix E 6.6.11, 3.15.1.1
750 bool glideslope_cancel; // appendix E 6.6.13, 3.15.1.5
751 bool decision_height; // appendix E 6.6.14, 3.10.2
752 bool mode6_low_volume; // appendix E 6.6.15, 3.15.1.7
753 bool audio_inhibit; // appendix E 6.6.16, 3.15.1.3
754 bool ta_tcf_inhibit; // appendix E 6.6.20, 3.15.1.9
755 bool autopilot_engaged; // appendix E 6.6.21, 3.15.1.8
756 bool steep_approach; // appendix E 6.6.25, 3.15.1.11
757 bool gpws_inhibit; // appendix E 6.6.27, 3.15.1.12
762 Parameter<double> uncorrected_barometric_altitude; // appendix E 6.2.1
763 Parameter<double> barometric_altitude_rate; // appendix E 6.2.2
764 Parameter<double> gps_altitude; // appendix E 6.2.4
765 Parameter<double> gps_latitude; // appendix E 6.2.7
766 Parameter<double> gps_longitude; // appendix E 6.2.8
767 Parameter<double> gps_vertical_figure_of_merit; // appendix E 6.2.13
768 Parameter<double> radio_altitude; // appendix E 6.2.29
769 Parameter<double> glideslope_deviation; // appendix E 6.2.30
770 Parameter<double> roll_angle; // appendix E 6.2.31
771 Parameter<double> localizer_deviation; // appendix E 6.2.33
772 Parameter<double> computed_airspeed; // appendix E 6.2.39
773 Parameter<double> decision_height; // appendix E 6.2.41
781 bool gpws_warning; // appendix E 7.4.1, 3.15.2.5
782 bool gpws_alert; // appendix E 7.4.1, 3.15.2.6
783 bool audio_on; // appendix E 7.4.2, 3.15.2.10
784 bool gpws_inop; // appendix E 7.4.3, 3.15.2.3
785 bool tad_inop; // appendix E 7.4.3, 3.15.2.4
786 bool flap_override; // appendix E 7.4.5, 3.15.2.8
787 bool glideslope_cancel; // appendix E 7.4.6, 3.15.2.7
788 bool steep_approach; // appendix E 7.4.12, 3.15.2.9
793 int egpws_alert_discrete_1; // appendix E 7.1.1.1
794 int egpwc_logic_discretes; // appendix E 7.1.1.2
795 int mode6_callouts_discrete_1; // appendix E 7.1.1.3
796 int mode6_callouts_discrete_2; // appendix E 7.1.1.4
797 int egpws_alert_discrete_2; // appendix E 7.1.1.5
798 int egpwc_alert_discrete_3; // appendix E 7.1.1.6
806 Parameter<double> barometric_altitude_rate;
807 Parameter<double> decision_height;
808 Parameter<double> geometric_altitude;
809 Parameter<double> glideslope_deviation_dots;
810 Parameter<double> gps_altitude;
811 Parameter<double> gps_latitude;
812 Parameter<double> gps_longitude;
813 Parameter<double> gps_vertical_figure_of_merit;
814 Parameter<double> localizer_deviation_dots;
815 Parameter<double> radio_altitude;
816 Parameter<double> roll_angle;
817 Parameter<double> terrain_clearance;
820 IOHandler (MK_VIII *device);
826 void enter_ground ();
827 void enter_takeoff ();
829 void update_inputs ();
830 void update_input_faults ();
831 void update_alternate_discrete_input (bool *ptr);
832 void update_internal_latches ();
834 void update_egpws_alert_discrete_1 ();
835 void update_egpwc_logic_discretes ();
836 void update_mode6_callouts_discrete_1 ();
837 void update_mode6_callouts_discrete_2 ();
838 void update_egpws_alert_discrete_2 ();
839 void update_egpwc_alert_discrete_3 ();
840 void update_outputs ();
843 void update_lamps ();
844 void set_lamp (Lamp lamp);
846 bool gpws_inhibit () const;
847 bool real_flaps_down () const;
848 bool flaps_down () const;
849 bool flap_override () const;
850 bool steep_approach () const;
851 bool momentary_steep_approach_enabled () const;
853 void bind (SGPropertyNode *node);
859 ///////////////////////////////////////////////////////////////////////////
860 // MK_VIII::IOHandler::TerrainClearanceFilter /////////////////////////////
861 ///////////////////////////////////////////////////////////////////////////
863 class TerrainClearanceFilter
865 typedef deque< Sample<double> > samples_type;
866 samples_type samples;
871 inline TerrainClearanceFilter ()
872 : value(0.0), last_update(-1.0) {}
874 double update (double agl);
878 ///////////////////////////////////////////////////////////////////////////
879 // MK_VIII::IOHandler (continued) /////////////////////////////////////////
880 ///////////////////////////////////////////////////////////////////////////
882 TerrainClearanceFilter terrain_clearance_filter;
887 Timer audio_inhibit_fault_timer;
888 Timer landing_gear_fault_timer;
889 Timer flaps_down_fault_timer;
890 Timer momentary_flap_override_fault_timer;
891 Timer self_test_fault_timer;
892 Timer glideslope_cancel_fault_timer;
893 Timer steep_approach_fault_timer;
894 Timer gpws_inhibit_fault_timer;
895 Timer ta_tcf_inhibit_fault_timer;
897 bool last_landing_gear;
898 bool last_real_flaps_down;
900 typedef deque< Sample< Parameter<double> > > altitude_samples_type;
901 altitude_samples_type altitude_samples;
905 bool glideslope_cancel;
908 void update_terrain_clearance ();
909 void reset_terrain_clearance ();
911 void handle_input_fault (bool test, FaultHandler::Fault fault);
912 void handle_input_fault (bool test,
915 FaultHandler::Fault fault);
917 void tie_input (SGPropertyNode *node,
921 void tie_input (SGPropertyNode *node,
923 Parameter<double> *input,
925 void tie_output (SGPropertyNode *node,
928 void tie_output (SGPropertyNode *node,
934 bool get_discrete_input (bool *ptr) const;
935 void set_discrete_input (bool *ptr, bool value);
937 void present_status ();
938 void present_status_section (const char *name);
939 void present_status_item (const char *name, const char *value = NULL);
940 void present_status_subitem (const char *name);
942 bool get_present_status () const;
943 void set_present_status (bool value);
945 bool *get_lamp_output (Lamp lamp);
948 class VoicePlayer : public FGVoicePlayer
951 VoicePlayer (MK_VIII *device) :
952 FGVoicePlayer(&device->properties_handler, "mk-viii")
960 Voice *application_data_base_failed;
962 Voice *bank_angle_bank_angle;
963 Voice *bank_angle_bank_angle_3;
964 Voice *bank_angle_inop;
965 Voice *bank_angle_pause_bank_angle;
966 Voice *bank_angle_pause_bank_angle_3;
967 Voice *callouts_inop;
968 Voice *configuration_type_invalid;
970 Voice *dont_sink_pause_dont_sink;
971 Voice *five_hundred_above;
973 Voice *glideslope_inop;
975 Voice *hard_glideslope;
977 Voice *minimums_minimums;
980 Voice *sink_rate_pause_sink_rate;
981 Voice *soft_glideslope;
983 Voice *terrain_pause_terrain;
984 Voice *too_low_flaps;
986 Voice *too_low_terrain;
987 Voice *altitude_callouts[n_altitude_callouts];
993 /////////////////////////////////////////////////////////////////////////////
994 // MK_VIII::SelfTestHandler /////////////////////////////////////////////////
995 /////////////////////////////////////////////////////////////////////////////
997 class SelfTestHandler
1010 ACTION_SLEEP = 1 << 0,
1011 ACTION_VOICE = 1 << 1,
1012 ACTION_DISCRETE_ON_OFF = 1 << 2,
1013 ACTION_DONE = 1 << 3
1019 double sleep_duration;
1026 bool button_pressed;
1027 double button_press_timestamp;
1028 IOHandler::Outputs saved_outputs;
1031 bool _was_here (int position);
1033 Action sleep (double duration);
1034 Action play (VoicePlayer::Voice *voice);
1035 Action discrete_on (bool *discrete, double duration);
1036 Action discrete_on_off (bool *discrete, double duration);
1037 Action discrete_on_off (bool *discrete, VoicePlayer::Voice *voice);
1056 inline SelfTestHandler (MK_VIII *device)
1057 : mk(device), button_pressed(false), state(STATE_NONE) {}
1059 inline void power_off () { stop(); }
1060 inline void set_inop () { stop(); }
1061 void handle_button_event (bool value);
1065 /////////////////////////////////////////////////////////////////////////////
1066 // MK_VIII::AlertHandler ////////////////////////////////////////////////////
1067 /////////////////////////////////////////////////////////////////////////////
1073 unsigned int old_alerts;
1074 unsigned int voice_alerts;
1075 unsigned int repeated_alerts;
1076 VoicePlayer::Voice *altitude_callout_voice;
1079 inline bool has_alerts (unsigned int test) const { return (alerts & test) != 0; }
1080 inline bool has_old_alerts (unsigned int test) const { return (old_alerts & test) != 0; }
1081 inline bool must_play_voice (unsigned int test) const { return ! has_old_alerts(test) || (repeated_alerts & test) != 0; }
1082 bool select_voice_alerts (unsigned int test);
1087 ALERT_MODE1_PULL_UP = 1 << 0,
1088 ALERT_MODE1_SINK_RATE = 1 << 1,
1090 ALERT_MODE2A_PREFACE = 1 << 2,
1091 ALERT_MODE2B_PREFACE = 1 << 3,
1092 ALERT_MODE2A = 1 << 4,
1093 ALERT_MODE2B = 1 << 5,
1094 ALERT_MODE2B_LANDING_MODE = 1 << 6,
1095 ALERT_MODE2A_ALTITUDE_GAIN = 1 << 7,
1096 ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING = 1 << 8,
1098 ALERT_MODE3 = 1 << 9,
1100 ALERT_MODE4_TOO_LOW_FLAPS = 1 << 10,
1101 ALERT_MODE4_TOO_LOW_GEAR = 1 << 11,
1102 ALERT_MODE4AB_TOO_LOW_TERRAIN = 1 << 12,
1103 ALERT_MODE4C_TOO_LOW_TERRAIN = 1 << 13,
1105 ALERT_MODE5_SOFT = 1 << 14,
1106 ALERT_MODE5_HARD = 1 << 15,
1108 ALERT_MODE6_MINIMUMS = 1 << 16,
1109 ALERT_MODE6_ALTITUDE_CALLOUT = 1 << 17,
1110 ALERT_MODE6_LOW_BANK_ANGLE_1 = 1 << 18,
1111 ALERT_MODE6_HIGH_BANK_ANGLE_1 = 1 << 19,
1112 ALERT_MODE6_LOW_BANK_ANGLE_2 = 1 << 20,
1113 ALERT_MODE6_HIGH_BANK_ANGLE_2 = 1 << 21,
1114 ALERT_MODE6_LOW_BANK_ANGLE_3 = 1 << 22,
1115 ALERT_MODE6_HIGH_BANK_ANGLE_3 = 1 << 23,
1117 ALERT_TCF_TOO_LOW_TERRAIN = 1 << 24
1122 ALERT_FLAG_REPEAT = 1 << 0
1125 unsigned int alerts;
1127 inline AlertHandler (MK_VIII *device)
1134 void set_alerts (unsigned int _alerts,
1135 unsigned int flags = 0,
1136 VoicePlayer::Voice *_altitude_callout_voice = NULL);
1137 void unset_alerts (unsigned int _alerts);
1139 inline void repeat_alert (unsigned int alert) { set_alerts(alert, ALERT_FLAG_REPEAT); }
1140 inline void set_altitude_callout_alert (VoicePlayer::Voice *voice) { set_alerts(ALERT_MODE6_ALTITUDE_CALLOUT, 0, voice); }
1143 /////////////////////////////////////////////////////////////////////////////
1144 // MK_VIII::StateHandler ////////////////////////////////////////////////////
1145 /////////////////////////////////////////////////////////////////////////////
1151 Timer potentially_airborne_timer;
1153 void update_ground ();
1154 void enter_ground ();
1155 void leave_ground ();
1157 void update_takeoff ();
1158 void enter_takeoff ();
1159 void leave_takeoff ();
1165 inline StateHandler (MK_VIII *device)
1166 : mk(device), ground(true), takeoff(true) {}
1168 void post_reposition ();
1172 /////////////////////////////////////////////////////////////////////////////
1173 // MK_VIII::Mode1Handler ////////////////////////////////////////////////////
1174 /////////////////////////////////////////////////////////////////////////////
1180 Timer pull_up_timer;
1181 Timer sink_rate_timer;
1183 double sink_rate_tti; // time-to-impact in minutes
1185 double get_pull_up_bias ();
1188 double get_sink_rate_bias ();
1189 bool is_sink_rate ();
1190 double get_sink_rate_tti ();
1192 void update_pull_up ();
1193 void update_sink_rate ();
1198 bool flap_override_bias;
1200 double (*pull_up_min_agl1) (double vs);
1201 int pull_up_max_agl1;
1202 double (*pull_up_min_agl2) (double vs);
1203 int pull_up_max_agl2;
1204 } EnvelopesConfiguration;
1208 const EnvelopesConfiguration *envelopes;
1211 inline Mode1Handler (MK_VIII *device)
1217 /////////////////////////////////////////////////////////////////////////////
1218 // MK_VIII::Mode2Handler ////////////////////////////////////////////////////
1219 /////////////////////////////////////////////////////////////////////////////
1224 ///////////////////////////////////////////////////////////////////////////
1225 // MK_VIII::Mode2Handler::ClosureRateFilter ///////////////////////////////
1226 ///////////////////////////////////////////////////////////////////////////
1228 class ClosureRateFilter
1230 /////////////////////////////////////////////////////////////////////////
1231 // MK_VIII::Mode2Handler::ClosureRateFilter::PassFilter /////////////////
1232 /////////////////////////////////////////////////////////////////////////
1244 inline PassFilter (double _a0, double _a1, double _b1)
1245 : a0(_a0), a1(_a1), b1(_b1) {}
1247 inline double filter (double input)
1249 last_output = a0 * input + a1 * last_input + b1 * last_output;
1255 inline void reset ()
1262 /////////////////////////////////////////////////////////////////////////
1263 // MK_VIII::Mode2Handler::ClosureRateFilter (continued) /////////////////
1264 /////////////////////////////////////////////////////////////////////////
1269 Parameter<double> last_ra; // last radio altitude
1270 Parameter<double> last_ba; // last barometric altitude
1271 PassFilter ra_filter; // radio altitude rate filter
1272 PassFilter ba_filter; // barometric altitude rate filter
1274 double limit_radio_altitude_rate (double r);
1277 Parameter<double> output;
1279 inline ClosureRateFilter (MK_VIII *device)
1281 ra_filter(0.05, 0, 0.95), // low-pass filter
1282 ba_filter(0.93, -0.93, 0.86) {} // high-pass-filter
1288 ///////////////////////////////////////////////////////////////////////////
1289 // MK_VIII::Mode2Handler (continued) //////////////////////////////////////
1290 ///////////////////////////////////////////////////////////////////////////
1294 ClosureRateFilter closure_rate_filter;
1296 Timer takeoff_timer;
1297 Timer pull_up_timer;
1299 double a_start_time;
1300 Timer a_altitude_gain_timer;
1301 double a_altitude_gain_alt;
1303 void check_pull_up (unsigned int preface_alert, unsigned int alert);
1305 bool b_conditions ();
1320 const Configuration *conf;
1322 inline Mode2Handler (MK_VIII *device)
1323 : mk(device), closure_rate_filter(device) {}
1327 void leave_ground ();
1328 void enter_takeoff ();
1332 /////////////////////////////////////////////////////////////////////////////
1333 // MK_VIII::Mode3Handler ////////////////////////////////////////////////////
1334 /////////////////////////////////////////////////////////////////////////////
1341 bool has_descent_alt;
1345 double max_alt_loss (double _bias);
1346 double get_bias (double initial_bias, double alt_loss);
1347 bool is (double *alt_loss);
1353 int (*max_agl) (bool flap_override);
1354 double (*max_alt_loss) (bool flap_override, double agl);
1357 const Configuration *conf;
1359 inline Mode3Handler (MK_VIII *device)
1360 : mk(device), armed(false), has_descent_alt(false) {}
1362 void enter_takeoff ();
1366 /////////////////////////////////////////////////////////////////////////////
1367 // MK_VIII::Mode4Handler ////////////////////////////////////////////////////
1368 /////////////////////////////////////////////////////////////////////////////
1378 double (*min_agl2) (double airspeed);
1380 } EnvelopesConfiguration;
1384 const EnvelopesConfiguration *ac;
1385 const EnvelopesConfiguration *b;
1386 } ModesConfiguration;
1390 VoicePlayer::Voice *voice_too_low_gear;
1391 const ModesConfiguration *modes;
1394 inline Mode4Handler (MK_VIII *device)
1395 : mk(device),ab_bias(0.0),ab_expanded_bias(0.0),c_bias(0.0) {}
1397 double get_upper_agl (const EnvelopesConfiguration *c);
1404 double ab_expanded_bias;
1407 const EnvelopesConfiguration *get_ab_envelope ();
1408 double get_bias (double initial_bias, double min_agl);
1409 void handle_alert (unsigned int alert, double min_agl, double *bias);
1412 void update_ab_expanded ();
1416 /////////////////////////////////////////////////////////////////////////////
1417 // MK_VIII::Mode5Handler ////////////////////////////////////////////////////
1418 /////////////////////////////////////////////////////////////////////////////
1430 bool is_soft (double bias);
1432 double get_soft_bias (double initial_bias);
1434 void update_hard (bool is);
1435 void update_soft (bool is);
1438 inline Mode5Handler (MK_VIII *device)
1439 : mk(device), soft_bias(0.0) {}
1444 /////////////////////////////////////////////////////////////////////////////
1445 // MK_VIII::Mode6Handler ////////////////////////////////////////////////////
1446 /////////////////////////////////////////////////////////////////////////////
1451 // keep in sync with altitude_callout_definitions[]
1454 ALTITUDE_CALLOUT_1000,
1455 ALTITUDE_CALLOUT_500,
1456 ALTITUDE_CALLOUT_400,
1457 ALTITUDE_CALLOUT_300,
1458 ALTITUDE_CALLOUT_200,
1459 ALTITUDE_CALLOUT_100,
1460 ALTITUDE_CALLOUT_50,
1461 ALTITUDE_CALLOUT_40,
1462 ALTITUDE_CALLOUT_30,
1463 ALTITUDE_CALLOUT_20,
1467 typedef bool (*BankAnglePredicate) (Parameter<double> *agl,
1468 double abs_roll_deg,
1473 bool minimums_enabled;
1474 bool smart_500_enabled;
1475 VoicePlayer::Voice *above_field_voice;
1477 bool altitude_callouts_enabled[n_altitude_callouts];
1478 bool bank_angle_enabled;
1479 BankAnglePredicate is_bank_angle;
1482 static const int altitude_callout_definitions[];
1484 inline Mode6Handler (MK_VIII *device)
1489 void enter_takeoff ();
1490 void leave_takeoff ();
1491 void set_volume (float volume);
1492 bool altitude_callouts_enabled ();
1498 bool last_decision_height;
1499 Parameter<double> last_radio_altitude;
1500 Parameter<double> last_altitude_above_field;
1502 bool altitude_callouts_issued[n_altitude_callouts];
1503 bool minimums_issued;
1504 bool above_field_issued;
1507 Parameter<bool> has_runway;
1511 double elevation; // elevation in feet
1514 void reset_minimums ();
1515 void reset_altitude_callouts ();
1516 bool is_playing_altitude_callout ();
1517 bool is_near_minimums (double callout);
1518 bool is_outside_band (double elevation, double callout);
1519 bool inhibit_smart_500 ();
1521 void update_minimums ();
1522 void update_altitude_callouts ();
1524 bool test_runway (const FGRunway *_runway);
1525 bool test_airport (const FGAirport *airport);
1526 void update_runway ();
1528 void get_altitude_above_field (Parameter<double> *parameter);
1529 void update_above_field_callout ();
1531 bool is_bank_angle (double abs_roll_angle, double bias);
1532 bool is_high_bank_angle ();
1533 unsigned int get_bank_angle_alerts ();
1534 void update_bank_angle ();
1536 class AirportFilter : public FGAirport::AirportFilter
1539 AirportFilter(Mode6Handler *s)
1542 virtual bool passAirport(FGAirport *a) const;
1544 virtual FGPositioned::Type maxType() const {
1545 return FGPositioned::AIRPORT;
1553 /////////////////////////////////////////////////////////////////////////////
1554 // MK_VIII::TCFHandler //////////////////////////////////////////////////////
1555 /////////////////////////////////////////////////////////////////////////////
1561 double latitude; // latitude in degrees
1562 double longitude; // longitude in degrees
1567 Position position; // position of threshold
1568 double heading; // runway heading
1573 static const double k;
1580 Position center; // center point
1581 double elevation; // elevation in feet
1582 double half_length; // runway half length, in nautical miles
1583 RunwayEdge edges[2]; // runway threshold and end
1584 Position bias_area[4]; // vertices of the bias area
1589 double initial_value;
1591 double get_azimuth_difference (double from_lat,
1596 double get_azimuth_difference (const FGRunway *_runway);
1598 FGRunway* select_runway (const FGAirport *airport);
1599 void update_runway ();
1601 void get_bias_area_edges (Position *edge,
1603 double half_width_m,
1604 Position *bias_edge1,
1605 Position *bias_edge2);
1607 bool is_inside_edge_triangle (RunwayEdge *edge);
1608 bool is_inside_bias_area ();
1613 class AirportFilter : public FGAirport::AirportFilter
1616 AirportFilter(MK_VIII *device)
1619 virtual bool passAirport(FGAirport *a) const;
1629 inline TCFHandler (MK_VIII *device)
1635 /////////////////////////////////////////////////////////////////////////////
1636 // MK_VIII (continued) //////////////////////////////////////////////////////
1637 /////////////////////////////////////////////////////////////////////////////
1642 PowerHandler power_handler;
1643 SystemHandler system_handler;
1644 ConfigurationModule configuration_module;
1645 FaultHandler fault_handler;
1646 IOHandler io_handler;
1647 VoicePlayer voice_player;
1648 SelfTestHandler self_test_handler;
1649 AlertHandler alert_handler;
1650 StateHandler state_handler;
1651 Mode1Handler mode1_handler;
1652 Mode2Handler mode2_handler;
1653 Mode3Handler mode3_handler;
1654 Mode4Handler mode4_handler;
1655 Mode5Handler mode5_handler;
1656 Mode6Handler mode6_handler;
1657 TCFHandler tcf_handler;
1661 int runway_database;
1665 MK_VIII (SGPropertyNode *node);
1667 virtual void init ();
1668 virtual void bind ();
1669 virtual void unbind ();
1670 virtual void update (double dt);
1674 # pragma warning( pop )
1677 #endif // __INSTRUMENTS_MK_VIII_HXX