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/props/tiedpropertylist.hxx>
33 #include <simgear/sound/sample_openal.hxx>
34 #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 : public simgear::TiedPropertyList
106 inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value)
112 inline void tie (SGPropertyNode *node,
113 const char *relative_path,
114 const SGRawValue<T> &raw_value)
116 Tie(node->getNode(relative_path, true),raw_value);
119 PropertiesHandler() {};
121 void unbind () {Untie();}
124 ///////////////////////////////////////////////////////////////////////////
125 // FGVoicePlayer::Voice ////////////////////////////////////////////
126 ///////////////////////////////////////////////////////////////////////////
132 /////////////////////////////////////////////////////////////////////////
133 // FGVoicePlayer::Voice::Element ////////////////////////////////////////
134 /////////////////////////////////////////////////////////////////////////
141 virtual inline void play (float volume) {}
142 virtual inline void stop () {}
143 virtual bool is_playing () = 0;
144 virtual inline void set_volume (float volume) {}
147 /////////////////////////////////////////////////////////////////////////
148 // FGVoicePlayer::Voice::SampleElement ///////////////////////////
149 /////////////////////////////////////////////////////////////////////////
151 class SampleElement : public Element
153 SGSharedPtr<SGSoundSample> _sample;
157 inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
158 : _sample(sample), _volume(volume) { silence = false; }
160 virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
161 virtual inline void stop () { if (_sample) _sample->stop(); }
162 virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
163 virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
166 /////////////////////////////////////////////////////////////////////////
167 // FGVoicePlayer::Voice::SilenceElement //////////////////////////
168 /////////////////////////////////////////////////////////////////////////
170 class SilenceElement : public Element
176 inline SilenceElement (double duration)
177 : _duration(duration) { silence = true; }
179 virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
180 virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
183 /////////////////////////////////////////////////////////////////////////
184 // FGVoicePlayer::Voice (continued) //////////////////////////////
185 /////////////////////////////////////////////////////////////////////////
189 inline Voice (FGVoicePlayer *_player)
190 : element(NULL), player(_player), volume(1.0) {}
194 inline void append (Element *_element) { elements.push_back(_element); }
197 void stop (bool now);
198 void set_volume (float _volume);
199 void volume_changed ();
203 FGVoicePlayer *player;
207 vector<Element *> elements;
208 vector<Element *>::iterator iter;
210 inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
213 ///////////////////////////////////////////////////////////////////////////
214 // FGVoicePlayer (continued) ///////////////////////////////////////
215 ///////////////////////////////////////////////////////////////////////////
230 inline FGVoicePlayer (PropertiesHandler* properties_handler, string _dev_name)
231 : volume(1.0), voice(NULL), next_voice(NULL), paused(false),
232 dev_name(_dev_name), dir_prefix(""),
233 speaker(this,properties_handler) {}
240 bool is_playing() { return (voice!=NULL);}
247 void play (Voice *_voice, unsigned int flags = 0);
253 void stop (unsigned int flags = 0);
255 void set_volume (float _volume);
258 void bind (SGPropertyNode *node, const char* default_dir_prefix);
262 ///////////////////////////////////////////////////////////////////////////
263 // FGVoicePlayer::Speaker //////////////////////////////////////////
264 ///////////////////////////////////////////////////////////////////////////
268 FGVoicePlayer *player;
269 PropertiesHandler* properties_handler;
274 inline void tie (SGPropertyNode *node, const char *name, T *ptr)
276 properties_handler->tie
277 (node, (string("speaker/") + name).c_str(),
278 RawValueMethodsData<FGVoicePlayer::Speaker,T,T*>
280 &FGVoicePlayer::Speaker::get_property,
281 &FGVoicePlayer::Speaker::set_property));
286 inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); }
289 inline T get_property (T *ptr) const { return *ptr; }
293 inline Speaker (FGVoicePlayer *_player,PropertiesHandler* _properties_handler)
295 properties_handler(_properties_handler),
301 void bind (SGPropertyNode *node);
302 void update_configuration ();
306 ///////////////////////////////////////////////////////////////////////////
307 // FGVoicePlayer (continued) ///////////////////////////////////////
308 ///////////////////////////////////////////////////////////////////////////
310 SGSharedPtr<SGSampleGroup> _sgr;
313 map< string, SGSharedPtr<SGSoundSample> > samples;
314 vector<Voice *> _voices;
319 SGSoundSample *get_sample (const char *name);
321 inline void append (Voice *voice, Voice::Element *element) { voice->append(element); }
322 inline void append (Voice *voice, const char *sample_name) { voice->append(new Voice::SampleElement(get_sample(sample_name))); }
323 inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); }
325 inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); }
328 inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); }
329 template <class T1, class T2>
330 inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); }
331 template <class T1, class T2, class T3>
332 inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); }
333 template <class T1, class T2, class T3, class T4>
334 inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); }
337 ///////////////////////////////////////////////////////////////////////////////
338 // MK_VIII ////////////////////////////////////////////////////////////////////
339 ///////////////////////////////////////////////////////////////////////////////
341 class MK_VIII : public SGSubsystem
343 // keep in sync with Mode6Handler::altitude_callout_definitions[]
344 static const unsigned n_altitude_callouts = 11;
346 /////////////////////////////////////////////////////////////////////////////
347 // MK_VIII::Parameter ///////////////////////////////////////////////////////
348 /////////////////////////////////////////////////////////////////////////////
359 : _value(0), ncd(true) {}
361 inline T get () const { assert(! ncd); return _value; }
362 inline T *get_pointer () { return &_value; }
363 inline void set (T value) { ncd = false; _value = value; }
364 inline void unset () { ncd = true; }
366 inline void set (const Parameter<T> *parameter)
371 set(parameter->get());
374 inline void set (const Parameter<double> *parameter, double factor)
379 set(parameter->get() * factor);
383 /////////////////////////////////////////////////////////////////////////////
384 // MK_VIII::Sample //////////////////////////////////////////////////////////
385 /////////////////////////////////////////////////////////////////////////////
394 inline Sample (T _value)
395 : timestamp(globals->get_sim_time_sec()), value(_value) {}
398 /////////////////////////////////////////////////////////////////////////////
399 // MK_VIII::Timer ///////////////////////////////////////////////////////////
400 /////////////////////////////////////////////////////////////////////////////
412 inline void start () { running = true; start_time = globals->get_sim_time_sec(); }
413 inline void stop () { running = false; }
414 inline double elapsed () const { assert(running); return globals->get_sim_time_sec() - start_time; }
415 inline double start_or_elapsed ()
427 /////////////////////////////////////////////////////////////////////////////
428 // MK_VIII::PropertiesHandler ///////////////////////////////////////////////
429 /////////////////////////////////////////////////////////////////////////////
431 class PropertiesHandler : public FGVoicePlayer::PropertiesHandler
438 SGPropertyNode_ptr ai_caged;
439 SGPropertyNode_ptr ai_roll;
440 SGPropertyNode_ptr ai_serviceable;
441 SGPropertyNode_ptr altimeter_altitude;
442 SGPropertyNode_ptr altimeter_serviceable;
443 SGPropertyNode_ptr altitude;
444 SGPropertyNode_ptr altitude_agl;
445 SGPropertyNode_ptr altitude_gear_agl;
446 SGPropertyNode_ptr altitude_radar_agl;
447 SGPropertyNode_ptr orientation_roll;
448 SGPropertyNode_ptr asi_serviceable;
449 SGPropertyNode_ptr asi_speed;
450 SGPropertyNode_ptr autopilot_heading_lock;
451 SGPropertyNode_ptr flaps;
452 SGPropertyNode_ptr gear_down;
453 SGPropertyNode_ptr latitude;
454 SGPropertyNode_ptr longitude;
455 SGPropertyNode_ptr nav0_cdi_serviceable;
456 SGPropertyNode_ptr nav0_gs_distance;
457 SGPropertyNode_ptr nav0_gs_needle_deflection;
458 SGPropertyNode_ptr nav0_gs_serviceable;
459 SGPropertyNode_ptr nav0_has_gs;
460 SGPropertyNode_ptr nav0_heading_needle_deflection;
461 SGPropertyNode_ptr nav0_in_range;
462 SGPropertyNode_ptr nav0_nav_loc;
463 SGPropertyNode_ptr nav0_serviceable;
464 SGPropertyNode_ptr power;
465 SGPropertyNode_ptr replay_state;
466 SGPropertyNode_ptr vs;
467 } external_properties;
469 inline PropertiesHandler (MK_VIII *device)
470 : FGVoicePlayer::PropertiesHandler(), mk(device) {}
472 PropertiesHandler() : FGVoicePlayer::PropertiesHandler() {}
478 PropertiesHandler properties_handler;
481 /////////////////////////////////////////////////////////////////////////////
482 // MK_VIII::PowerHandler ////////////////////////////////////////////////////
483 /////////////////////////////////////////////////////////////////////////////
492 Timer power_loss_timer;
493 Timer abnormal_timer;
494 Timer low_surge_timer;
495 Timer high_surge_timer;
496 Timer very_high_surge_timer;
498 bool handle_abnormal_voltage (bool abnormal,
500 double max_duration);
506 inline PowerHandler (MK_VIII *device)
507 : mk(device), serviceable(false), powered(false) {}
509 void bind (SGPropertyNode *node);
513 /////////////////////////////////////////////////////////////////////////////
514 // MK_VIII::SystemHandler ///////////////////////////////////////////////////
515 /////////////////////////////////////////////////////////////////////////////
524 int last_replay_state;
525 Timer reposition_timer;
538 inline SystemHandler (MK_VIII *device)
539 : mk(device), state(STATE_OFF) {}
546 /////////////////////////////////////////////////////////////////////////////
547 // MK_VIII::ConfigurationModule /////////////////////////////////////////////
548 /////////////////////////////////////////////////////////////////////////////
550 class ConfigurationModule
553 // keep in sync with IOHandler::present_status()
556 CATEGORY_AIRCRAFT_MODE_TYPE_SELECT,
557 CATEGORY_AIR_DATA_INPUT_SELECT,
558 CATEGORY_POSITION_INPUT_SELECT,
559 CATEGORY_ALTITUDE_CALLOUTS,
560 CATEGORY_AUDIO_MENU_SELECT,
561 CATEGORY_TERRAIN_DISPLAY_SELECT,
562 CATEGORY_OPTIONS_SELECT_GROUP_1,
563 CATEGORY_RADIO_ALTITUDE_INPUT_SELECT,
564 CATEGORY_NAVIGATION_INPUT_SELECT,
565 CATEGORY_ATTITUDE_INPUT_SELECT,
566 CATEGORY_HEADING_INPUT_SELECT,
567 CATEGORY_WINDSHEAR_INPUT_SELECT,
568 CATEGORY_INPUT_OUTPUT_DISCRETE_TYPE_SELECT,
569 CATEGORY_AUDIO_OUTPUT_LEVEL,
570 CATEGORY_UNDEFINED_INPUT_SELECT_1,
571 CATEGORY_UNDEFINED_INPUT_SELECT_2,
572 CATEGORY_UNDEFINED_INPUT_SELECT_3,
579 STATE_INVALID_DATABASE,
580 STATE_INVALID_AIRCRAFT_TYPE
584 int effective_categories[N_CATEGORIES];
586 ConfigurationModule (MK_VIII *device);
589 void bind (SGPropertyNode *node);
594 int categories[N_CATEGORIES];
596 bool read_aircraft_mode_type_select (int value);
597 bool read_air_data_input_select (int value);
598 bool read_position_input_select (int value);
599 bool read_altitude_callouts (int value);
600 bool read_audio_menu_select (int value);
601 bool read_terrain_display_select (int value);
602 bool read_options_select_group_1 (int value);
603 bool read_radio_altitude_input_select (int value);
604 bool read_navigation_input_select (int value);
605 bool read_attitude_input_select (int value);
606 bool read_heading_input_select (int value);
607 bool read_windshear_input_select (int value);
608 bool read_input_output_discrete_type_select (int value);
609 bool read_audio_output_level (int value);
610 bool read_undefined_input_select (int value);
612 static bool m6_t2_is_bank_angle (Parameter<double> *agl,
615 static bool m6_t4_is_bank_angle (Parameter<double> *agl,
620 /////////////////////////////////////////////////////////////////////////////
621 // MK_VIII::FaultHandler ////////////////////////////////////////////////////
622 /////////////////////////////////////////////////////////////////////////////
634 static const unsigned int fault_inops[];
636 bool has_faults (unsigned int inop);
639 // keep in sync with IOHandler::present_status()
642 FAULT_ALL_MODES_INHIBIT,
645 FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID,
646 FAULT_SELF_TEST_INVALID,
647 FAULT_GLIDESLOPE_CANCEL_INVALID,
648 FAULT_STEEP_APPROACH_INVALID,
650 FAULT_TA_TCF_INHIBIT,
651 FAULT_MODES14_INPUTS_INVALID,
652 FAULT_MODE5_INPUTS_INVALID,
653 FAULT_MODE6_INPUTS_INVALID,
654 FAULT_BANK_ANGLE_INPUTS_INVALID,
655 FAULT_TCF_INPUTS_INVALID,
659 bool faults[N_FAULTS];
661 inline FaultHandler (MK_VIII *device)
666 void set_fault (Fault fault);
667 void unset_fault (Fault fault);
669 bool has_faults () const;
672 /////////////////////////////////////////////////////////////////////////////
673 // MK_VIII::IOHandler ///////////////////////////////////////////////////////
674 /////////////////////////////////////////////////////////////////////////////
688 struct LampConfiguration
694 struct FaultsConfiguration
696 double max_flaps_down_airspeed;
697 double max_gear_down_airspeed;
702 const LampConfiguration *lamp;
703 const FaultsConfiguration *faults;
705 bool steep_approach_enabled;
706 bool gpws_inhibit_enabled;
707 bool momentary_flap_override_enabled;
708 bool alternate_steep_approach;
709 bool use_internal_gps;
710 bool localizer_enabled;
712 bool use_attitude_indicator;
715 struct _s_input_feeders
721 bool glideslope_inhibit;
722 bool decision_height;
723 bool autopilot_engaged;
728 bool uncorrected_barometric_altitude;
729 bool barometric_altitude_rate;
731 bool glideslope_deviation;
733 bool localizer_deviation;
734 bool computed_airspeed;
735 bool decision_height;
743 bool landing_gear; // appendix E 6.6.2, 3.15.1.4
744 bool landing_flaps; // appendix E 6.6.4, 3.15.1.2
745 bool momentary_flap_override; // appendix E 6.6.6, 3.15.1.6
746 bool self_test; // appendix E 6.6.7, 3.15.1.10
747 bool glideslope_inhibit; // appendix E 6.6.11, 3.15.1.1
748 bool glideslope_cancel; // appendix E 6.6.13, 3.15.1.5
749 bool decision_height; // appendix E 6.6.14, 3.10.2
750 bool mode6_low_volume; // appendix E 6.6.15, 3.15.1.7
751 bool audio_inhibit; // appendix E 6.6.16, 3.15.1.3
752 bool ta_tcf_inhibit; // appendix E 6.6.20, 3.15.1.9
753 bool autopilot_engaged; // appendix E 6.6.21, 3.15.1.8
754 bool steep_approach; // appendix E 6.6.25, 3.15.1.11
755 bool gpws_inhibit; // appendix E 6.6.27, 3.15.1.12
760 Parameter<double> uncorrected_barometric_altitude; // appendix E 6.2.1
761 Parameter<double> barometric_altitude_rate; // appendix E 6.2.2
762 Parameter<double> gps_altitude; // appendix E 6.2.4
763 Parameter<double> gps_latitude; // appendix E 6.2.7
764 Parameter<double> gps_longitude; // appendix E 6.2.8
765 Parameter<double> gps_vertical_figure_of_merit; // appendix E 6.2.13
766 Parameter<double> radio_altitude; // appendix E 6.2.29
767 Parameter<double> glideslope_deviation; // appendix E 6.2.30
768 Parameter<double> roll_angle; // appendix E 6.2.31
769 Parameter<double> localizer_deviation; // appendix E 6.2.33
770 Parameter<double> computed_airspeed; // appendix E 6.2.39
771 Parameter<double> decision_height; // appendix E 6.2.41
779 bool gpws_warning; // appendix E 7.4.1, 3.15.2.5
780 bool gpws_alert; // appendix E 7.4.1, 3.15.2.6
781 bool audio_on; // appendix E 7.4.2, 3.15.2.10
782 bool gpws_inop; // appendix E 7.4.3, 3.15.2.3
783 bool tad_inop; // appendix E 7.4.3, 3.15.2.4
784 bool flap_override; // appendix E 7.4.5, 3.15.2.8
785 bool glideslope_cancel; // appendix E 7.4.6, 3.15.2.7
786 bool steep_approach; // appendix E 7.4.12, 3.15.2.9
791 int egpws_alert_discrete_1; // appendix E 7.1.1.1
792 int egpwc_logic_discretes; // appendix E 7.1.1.2
793 int mode6_callouts_discrete_1; // appendix E 7.1.1.3
794 int mode6_callouts_discrete_2; // appendix E 7.1.1.4
795 int egpws_alert_discrete_2; // appendix E 7.1.1.5
796 int egpwc_alert_discrete_3; // appendix E 7.1.1.6
804 Parameter<double> barometric_altitude_rate;
805 Parameter<double> decision_height;
806 Parameter<double> geometric_altitude;
807 Parameter<double> glideslope_deviation_dots;
808 Parameter<double> gps_altitude;
809 Parameter<double> gps_latitude;
810 Parameter<double> gps_longitude;
811 Parameter<double> gps_vertical_figure_of_merit;
812 Parameter<double> localizer_deviation_dots;
813 Parameter<double> radio_altitude;
814 Parameter<double> roll_angle;
815 Parameter<double> terrain_clearance;
818 IOHandler (MK_VIII *device);
824 void enter_ground ();
825 void enter_takeoff ();
827 void update_inputs ();
828 void update_input_faults ();
829 void update_alternate_discrete_input (bool *ptr);
830 void update_internal_latches ();
832 void update_egpws_alert_discrete_1 ();
833 void update_egpwc_logic_discretes ();
834 void update_mode6_callouts_discrete_1 ();
835 void update_mode6_callouts_discrete_2 ();
836 void update_egpws_alert_discrete_2 ();
837 void update_egpwc_alert_discrete_3 ();
838 void update_outputs ();
841 void update_lamps ();
842 void set_lamp (Lamp lamp);
844 bool gpws_inhibit () const;
845 bool real_flaps_down () const;
846 bool flaps_down () const;
847 bool flap_override () const;
848 bool steep_approach () const;
849 bool momentary_steep_approach_enabled () const;
851 void bind (SGPropertyNode *node);
857 ///////////////////////////////////////////////////////////////////////////
858 // MK_VIII::IOHandler::TerrainClearanceFilter /////////////////////////////
859 ///////////////////////////////////////////////////////////////////////////
861 class TerrainClearanceFilter
863 typedef deque< Sample<double> > samples_type;
864 samples_type samples;
869 inline TerrainClearanceFilter ()
870 : value(0.0), last_update(-1.0) {}
872 double update (double agl);
876 ///////////////////////////////////////////////////////////////////////////
877 // MK_VIII::IOHandler (continued) /////////////////////////////////////////
878 ///////////////////////////////////////////////////////////////////////////
880 TerrainClearanceFilter terrain_clearance_filter;
885 Timer audio_inhibit_fault_timer;
886 Timer landing_gear_fault_timer;
887 Timer flaps_down_fault_timer;
888 Timer momentary_flap_override_fault_timer;
889 Timer self_test_fault_timer;
890 Timer glideslope_cancel_fault_timer;
891 Timer steep_approach_fault_timer;
892 Timer gpws_inhibit_fault_timer;
893 Timer ta_tcf_inhibit_fault_timer;
895 bool last_landing_gear;
896 bool last_real_flaps_down;
898 typedef deque< Sample< Parameter<double> > > altitude_samples_type;
899 altitude_samples_type altitude_samples;
903 bool glideslope_cancel;
906 void update_terrain_clearance ();
907 void reset_terrain_clearance ();
909 void handle_input_fault (bool test, FaultHandler::Fault fault);
910 void handle_input_fault (bool test,
913 FaultHandler::Fault fault);
915 void tie_input (SGPropertyNode *node,
919 void tie_input (SGPropertyNode *node,
921 Parameter<double> *input,
923 void tie_output (SGPropertyNode *node,
926 void tie_output (SGPropertyNode *node,
932 bool get_discrete_input (bool *ptr) const;
933 void set_discrete_input (bool *ptr, bool value);
935 void present_status ();
936 void present_status_section (const char *name);
937 void present_status_item (const char *name, const char *value = NULL);
938 void present_status_subitem (const char *name);
940 bool get_present_status () const;
941 void set_present_status (bool value);
943 bool *get_lamp_output (Lamp lamp);
946 class VoicePlayer : public FGVoicePlayer
949 VoicePlayer (MK_VIII *device) :
950 FGVoicePlayer(&device->properties_handler, "mk-viii")
958 Voice *application_data_base_failed;
960 Voice *bank_angle_bank_angle;
961 Voice *bank_angle_bank_angle_3;
962 Voice *bank_angle_inop;
963 Voice *bank_angle_pause_bank_angle;
964 Voice *bank_angle_pause_bank_angle_3;
965 Voice *callouts_inop;
966 Voice *configuration_type_invalid;
968 Voice *dont_sink_pause_dont_sink;
969 Voice *five_hundred_above;
971 Voice *glideslope_inop;
973 Voice *hard_glideslope;
975 Voice *minimums_minimums;
978 Voice *sink_rate_pause_sink_rate;
979 Voice *soft_glideslope;
981 Voice *terrain_pause_terrain;
982 Voice *too_low_flaps;
984 Voice *too_low_terrain;
985 Voice *altitude_callouts[n_altitude_callouts];
991 /////////////////////////////////////////////////////////////////////////////
992 // MK_VIII::SelfTestHandler /////////////////////////////////////////////////
993 /////////////////////////////////////////////////////////////////////////////
995 class SelfTestHandler
1008 ACTION_SLEEP = 1 << 0,
1009 ACTION_VOICE = 1 << 1,
1010 ACTION_DISCRETE_ON_OFF = 1 << 2,
1011 ACTION_DONE = 1 << 3
1017 double sleep_duration;
1024 bool button_pressed;
1025 double button_press_timestamp;
1026 IOHandler::Outputs saved_outputs;
1029 bool _was_here (int position);
1031 Action sleep (double duration);
1032 Action play (VoicePlayer::Voice *voice);
1033 Action discrete_on (bool *discrete, double duration);
1034 Action discrete_on_off (bool *discrete, double duration);
1035 Action discrete_on_off (bool *discrete, VoicePlayer::Voice *voice);
1054 inline SelfTestHandler (MK_VIII *device)
1055 : mk(device), button_pressed(false), state(STATE_NONE) {}
1057 inline void power_off () { stop(); }
1058 inline void set_inop () { stop(); }
1059 void handle_button_event (bool value);
1063 /////////////////////////////////////////////////////////////////////////////
1064 // MK_VIII::AlertHandler ////////////////////////////////////////////////////
1065 /////////////////////////////////////////////////////////////////////////////
1071 unsigned int old_alerts;
1072 unsigned int voice_alerts;
1073 unsigned int repeated_alerts;
1074 VoicePlayer::Voice *altitude_callout_voice;
1077 inline bool has_alerts (unsigned int test) const { return (alerts & test) != 0; }
1078 inline bool has_old_alerts (unsigned int test) const { return (old_alerts & test) != 0; }
1079 inline bool must_play_voice (unsigned int test) const { return ! has_old_alerts(test) || (repeated_alerts & test) != 0; }
1080 bool select_voice_alerts (unsigned int test);
1085 ALERT_MODE1_PULL_UP = 1 << 0,
1086 ALERT_MODE1_SINK_RATE = 1 << 1,
1088 ALERT_MODE2A_PREFACE = 1 << 2,
1089 ALERT_MODE2B_PREFACE = 1 << 3,
1090 ALERT_MODE2A = 1 << 4,
1091 ALERT_MODE2B = 1 << 5,
1092 ALERT_MODE2B_LANDING_MODE = 1 << 6,
1093 ALERT_MODE2A_ALTITUDE_GAIN = 1 << 7,
1094 ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING = 1 << 8,
1096 ALERT_MODE3 = 1 << 9,
1098 ALERT_MODE4_TOO_LOW_FLAPS = 1 << 10,
1099 ALERT_MODE4_TOO_LOW_GEAR = 1 << 11,
1100 ALERT_MODE4AB_TOO_LOW_TERRAIN = 1 << 12,
1101 ALERT_MODE4C_TOO_LOW_TERRAIN = 1 << 13,
1103 ALERT_MODE5_SOFT = 1 << 14,
1104 ALERT_MODE5_HARD = 1 << 15,
1106 ALERT_MODE6_MINIMUMS = 1 << 16,
1107 ALERT_MODE6_ALTITUDE_CALLOUT = 1 << 17,
1108 ALERT_MODE6_LOW_BANK_ANGLE_1 = 1 << 18,
1109 ALERT_MODE6_HIGH_BANK_ANGLE_1 = 1 << 19,
1110 ALERT_MODE6_LOW_BANK_ANGLE_2 = 1 << 20,
1111 ALERT_MODE6_HIGH_BANK_ANGLE_2 = 1 << 21,
1112 ALERT_MODE6_LOW_BANK_ANGLE_3 = 1 << 22,
1113 ALERT_MODE6_HIGH_BANK_ANGLE_3 = 1 << 23,
1115 ALERT_TCF_TOO_LOW_TERRAIN = 1 << 24
1120 ALERT_FLAG_REPEAT = 1 << 0
1123 unsigned int alerts;
1125 inline AlertHandler (MK_VIII *device)
1132 void set_alerts (unsigned int _alerts,
1133 unsigned int flags = 0,
1134 VoicePlayer::Voice *_altitude_callout_voice = NULL);
1135 void unset_alerts (unsigned int _alerts);
1137 inline void repeat_alert (unsigned int alert) { set_alerts(alert, ALERT_FLAG_REPEAT); }
1138 inline void set_altitude_callout_alert (VoicePlayer::Voice *voice) { set_alerts(ALERT_MODE6_ALTITUDE_CALLOUT, 0, voice); }
1141 /////////////////////////////////////////////////////////////////////////////
1142 // MK_VIII::StateHandler ////////////////////////////////////////////////////
1143 /////////////////////////////////////////////////////////////////////////////
1149 Timer potentially_airborne_timer;
1151 void update_ground ();
1152 void enter_ground ();
1153 void leave_ground ();
1155 void update_takeoff ();
1156 void enter_takeoff ();
1157 void leave_takeoff ();
1163 inline StateHandler (MK_VIII *device)
1164 : mk(device), ground(true), takeoff(true) {}
1166 void post_reposition ();
1170 /////////////////////////////////////////////////////////////////////////////
1171 // MK_VIII::Mode1Handler ////////////////////////////////////////////////////
1172 /////////////////////////////////////////////////////////////////////////////
1178 Timer pull_up_timer;
1179 Timer sink_rate_timer;
1181 double sink_rate_tti; // time-to-impact in minutes
1183 double get_pull_up_bias ();
1186 double get_sink_rate_bias ();
1187 bool is_sink_rate ();
1188 double get_sink_rate_tti ();
1190 void update_pull_up ();
1191 void update_sink_rate ();
1196 bool flap_override_bias;
1198 double (*pull_up_min_agl1) (double vs);
1199 int pull_up_max_agl1;
1200 double (*pull_up_min_agl2) (double vs);
1201 int pull_up_max_agl2;
1202 } EnvelopesConfiguration;
1206 const EnvelopesConfiguration *envelopes;
1209 inline Mode1Handler (MK_VIII *device)
1215 /////////////////////////////////////////////////////////////////////////////
1216 // MK_VIII::Mode2Handler ////////////////////////////////////////////////////
1217 /////////////////////////////////////////////////////////////////////////////
1222 ///////////////////////////////////////////////////////////////////////////
1223 // MK_VIII::Mode2Handler::ClosureRateFilter ///////////////////////////////
1224 ///////////////////////////////////////////////////////////////////////////
1226 class ClosureRateFilter
1228 /////////////////////////////////////////////////////////////////////////
1229 // MK_VIII::Mode2Handler::ClosureRateFilter::PassFilter /////////////////
1230 /////////////////////////////////////////////////////////////////////////
1242 inline PassFilter (double _a0, double _a1, double _b1)
1243 : a0(_a0), a1(_a1), b1(_b1) {}
1245 inline double filter (double input)
1247 last_output = a0 * input + a1 * last_input + b1 * last_output;
1253 inline void reset ()
1260 /////////////////////////////////////////////////////////////////////////
1261 // MK_VIII::Mode2Handler::ClosureRateFilter (continued) /////////////////
1262 /////////////////////////////////////////////////////////////////////////
1267 Parameter<double> last_ra; // last radio altitude
1268 Parameter<double> last_ba; // last barometric altitude
1269 PassFilter ra_filter; // radio altitude rate filter
1270 PassFilter ba_filter; // barometric altitude rate filter
1272 double limit_radio_altitude_rate (double r);
1275 Parameter<double> output;
1277 inline ClosureRateFilter (MK_VIII *device)
1279 ra_filter(0.05, 0, 0.95), // low-pass filter
1280 ba_filter(0.93, -0.93, 0.86) {} // high-pass-filter
1286 ///////////////////////////////////////////////////////////////////////////
1287 // MK_VIII::Mode2Handler (continued) //////////////////////////////////////
1288 ///////////////////////////////////////////////////////////////////////////
1292 ClosureRateFilter closure_rate_filter;
1294 Timer takeoff_timer;
1295 Timer pull_up_timer;
1297 double a_start_time;
1298 Timer a_altitude_gain_timer;
1299 double a_altitude_gain_alt;
1301 void check_pull_up (unsigned int preface_alert, unsigned int alert);
1303 bool b_conditions ();
1318 const Configuration *conf;
1320 inline Mode2Handler (MK_VIII *device)
1321 : mk(device), closure_rate_filter(device) {}
1325 void leave_ground ();
1326 void enter_takeoff ();
1330 /////////////////////////////////////////////////////////////////////////////
1331 // MK_VIII::Mode3Handler ////////////////////////////////////////////////////
1332 /////////////////////////////////////////////////////////////////////////////
1339 bool has_descent_alt;
1343 double max_alt_loss (double _bias);
1344 double get_bias (double initial_bias, double alt_loss);
1345 bool is (double *alt_loss);
1351 int (*max_agl) (bool flap_override);
1352 double (*max_alt_loss) (bool flap_override, double agl);
1355 const Configuration *conf;
1357 inline Mode3Handler (MK_VIII *device)
1358 : mk(device), armed(false), has_descent_alt(false) {}
1360 void enter_takeoff ();
1364 /////////////////////////////////////////////////////////////////////////////
1365 // MK_VIII::Mode4Handler ////////////////////////////////////////////////////
1366 /////////////////////////////////////////////////////////////////////////////
1376 double (*min_agl2) (double airspeed);
1378 } EnvelopesConfiguration;
1382 const EnvelopesConfiguration *ac;
1383 const EnvelopesConfiguration *b;
1384 } ModesConfiguration;
1388 VoicePlayer::Voice *voice_too_low_gear;
1389 const ModesConfiguration *modes;
1392 inline Mode4Handler (MK_VIII *device)
1393 : mk(device),ab_bias(0.0),ab_expanded_bias(0.0),c_bias(0.0) {}
1395 double get_upper_agl (const EnvelopesConfiguration *c);
1402 double ab_expanded_bias;
1405 const EnvelopesConfiguration *get_ab_envelope ();
1406 double get_bias (double initial_bias, double min_agl);
1407 void handle_alert (unsigned int alert, double min_agl, double *bias);
1410 void update_ab_expanded ();
1414 /////////////////////////////////////////////////////////////////////////////
1415 // MK_VIII::Mode5Handler ////////////////////////////////////////////////////
1416 /////////////////////////////////////////////////////////////////////////////
1428 bool is_soft (double bias);
1430 double get_soft_bias (double initial_bias);
1432 void update_hard (bool is);
1433 void update_soft (bool is);
1436 inline Mode5Handler (MK_VIII *device)
1437 : mk(device), soft_bias(0.0) {}
1442 /////////////////////////////////////////////////////////////////////////////
1443 // MK_VIII::Mode6Handler ////////////////////////////////////////////////////
1444 /////////////////////////////////////////////////////////////////////////////
1449 // keep in sync with altitude_callout_definitions[]
1452 ALTITUDE_CALLOUT_1000,
1453 ALTITUDE_CALLOUT_500,
1454 ALTITUDE_CALLOUT_400,
1455 ALTITUDE_CALLOUT_300,
1456 ALTITUDE_CALLOUT_200,
1457 ALTITUDE_CALLOUT_100,
1458 ALTITUDE_CALLOUT_50,
1459 ALTITUDE_CALLOUT_40,
1460 ALTITUDE_CALLOUT_30,
1461 ALTITUDE_CALLOUT_20,
1465 typedef bool (*BankAnglePredicate) (Parameter<double> *agl,
1466 double abs_roll_deg,
1471 bool minimums_enabled;
1472 bool smart_500_enabled;
1473 VoicePlayer::Voice *above_field_voice;
1475 bool altitude_callouts_enabled[n_altitude_callouts];
1476 bool bank_angle_enabled;
1477 BankAnglePredicate is_bank_angle;
1480 static const int altitude_callout_definitions[];
1482 inline Mode6Handler (MK_VIII *device)
1487 void enter_takeoff ();
1488 void leave_takeoff ();
1489 void set_volume (float volume);
1490 bool altitude_callouts_enabled ();
1496 bool last_decision_height;
1497 Parameter<double> last_radio_altitude;
1498 Parameter<double> last_altitude_above_field;
1500 bool altitude_callouts_issued[n_altitude_callouts];
1501 bool minimums_issued;
1502 bool above_field_issued;
1505 Parameter<bool> has_runway;
1509 double elevation; // elevation in feet
1512 void reset_minimums ();
1513 void reset_altitude_callouts ();
1514 bool is_playing_altitude_callout ();
1515 bool is_near_minimums (double callout);
1516 bool is_outside_band (double elevation, double callout);
1517 bool inhibit_smart_500 ();
1519 void update_minimums ();
1520 void update_altitude_callouts ();
1522 bool test_runway (const FGRunway *_runway);
1523 bool test_airport (const FGAirport *airport);
1524 void update_runway ();
1526 void get_altitude_above_field (Parameter<double> *parameter);
1527 void update_above_field_callout ();
1529 bool is_bank_angle (double abs_roll_angle, double bias);
1530 bool is_high_bank_angle ();
1531 unsigned int get_bank_angle_alerts ();
1532 void update_bank_angle ();
1534 class AirportFilter : public FGAirport::AirportFilter
1537 AirportFilter(Mode6Handler *s)
1540 virtual bool passAirport(FGAirport *a) const;
1542 virtual FGPositioned::Type maxType() const {
1543 return FGPositioned::AIRPORT;
1551 /////////////////////////////////////////////////////////////////////////////
1552 // MK_VIII::TCFHandler //////////////////////////////////////////////////////
1553 /////////////////////////////////////////////////////////////////////////////
1559 double latitude; // latitude in degrees
1560 double longitude; // longitude in degrees
1565 Position position; // position of threshold
1566 double heading; // runway heading
1571 static const double k;
1578 Position center; // center point
1579 double elevation; // elevation in feet
1580 double half_length; // runway half length, in nautical miles
1581 RunwayEdge edges[2]; // runway threshold and end
1582 Position bias_area[4]; // vertices of the bias area
1587 double initial_value;
1589 double get_azimuth_difference (double from_lat,
1594 double get_azimuth_difference (const FGRunway *_runway);
1596 FGRunway* select_runway (const FGAirport *airport);
1597 void update_runway ();
1599 void get_bias_area_edges (Position *edge,
1601 double half_width_m,
1602 Position *bias_edge1,
1603 Position *bias_edge2);
1605 bool is_inside_edge_triangle (RunwayEdge *edge);
1606 bool is_inside_bias_area ();
1611 class AirportFilter : public FGAirport::AirportFilter
1614 AirportFilter(MK_VIII *device)
1617 virtual bool passAirport(FGAirport *a) const;
1627 inline TCFHandler (MK_VIII *device)
1633 /////////////////////////////////////////////////////////////////////////////
1634 // MK_VIII (continued) //////////////////////////////////////////////////////
1635 /////////////////////////////////////////////////////////////////////////////
1640 PowerHandler power_handler;
1641 SystemHandler system_handler;
1642 ConfigurationModule configuration_module;
1643 FaultHandler fault_handler;
1644 IOHandler io_handler;
1645 VoicePlayer voice_player;
1646 SelfTestHandler self_test_handler;
1647 AlertHandler alert_handler;
1648 StateHandler state_handler;
1649 Mode1Handler mode1_handler;
1650 Mode2Handler mode2_handler;
1651 Mode3Handler mode3_handler;
1652 Mode4Handler mode4_handler;
1653 Mode5Handler mode5_handler;
1654 Mode6Handler mode6_handler;
1655 TCFHandler tcf_handler;
1659 int runway_database;
1663 MK_VIII (SGPropertyNode *node);
1665 virtual void init ();
1666 virtual void bind ();
1667 virtual void unbind ();
1668 virtual void update (double dt);
1672 # pragma warning( pop )
1675 #endif // __INSTRUMENTS_MK_VIII_HXX