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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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/structure/subsystem_mgr.hxx>
40 #include <Airports/runways.hxx>
41 #include <Airports/simple.hxx>
42 #include <Main/globals.hxx>
43 #include <Sound/voiceplayer.hxx>
46 # pragma warning( push )
47 # pragma warning( disable: 4355 )
51 ///////////////////////////////////////////////////////////////////////////////
52 // MK_VIII ////////////////////////////////////////////////////////////////////
53 ///////////////////////////////////////////////////////////////////////////////
55 class MK_VIII : public SGSubsystem
57 // keep in sync with Mode6Handler::altitude_callout_definitions[]
58 static const unsigned n_altitude_callouts = 11;
60 /////////////////////////////////////////////////////////////////////////////
61 // MK_VIII::Parameter ///////////////////////////////////////////////////////
62 /////////////////////////////////////////////////////////////////////////////
73 : _value(0), ncd(true) {}
75 inline T get () const { assert(! ncd); return _value; }
76 inline T *get_pointer () { return &_value; }
77 inline void set (T value) { ncd = false; _value = value; }
78 inline void unset () { ncd = true; }
80 inline void set (const Parameter<T> *parameter)
85 set(parameter->get());
88 inline void set (const Parameter<double> *parameter, double factor)
93 set(parameter->get() * factor);
97 /////////////////////////////////////////////////////////////////////////////
98 // MK_VIII::Sample //////////////////////////////////////////////////////////
99 /////////////////////////////////////////////////////////////////////////////
108 inline Sample (T _value)
109 : timestamp(globals->get_sim_time_sec()), value(_value) {}
112 /////////////////////////////////////////////////////////////////////////////
113 // MK_VIII::Timer ///////////////////////////////////////////////////////////
114 /////////////////////////////////////////////////////////////////////////////
126 inline void start () { running = true; start_time = globals->get_sim_time_sec(); }
127 inline void stop () { running = false; }
128 inline double elapsed () const { assert(running); return globals->get_sim_time_sec() - start_time; }
129 inline double start_or_elapsed ()
141 /////////////////////////////////////////////////////////////////////////////
142 // MK_VIII::PropertiesHandler ///////////////////////////////////////////////
143 /////////////////////////////////////////////////////////////////////////////
145 class PropertiesHandler : public FGVoicePlayer::PropertiesHandler
152 SGPropertyNode_ptr ai_caged;
153 SGPropertyNode_ptr ai_roll;
154 SGPropertyNode_ptr ai_serviceable;
155 SGPropertyNode_ptr altimeter_altitude;
156 SGPropertyNode_ptr altimeter_serviceable;
157 SGPropertyNode_ptr altitude;
158 SGPropertyNode_ptr altitude_agl;
159 SGPropertyNode_ptr altitude_gear_agl;
160 SGPropertyNode_ptr altitude_radar_agl;
161 SGPropertyNode_ptr orientation_roll;
162 SGPropertyNode_ptr asi_serviceable;
163 SGPropertyNode_ptr asi_speed;
164 SGPropertyNode_ptr autopilot_heading_lock;
165 SGPropertyNode_ptr flaps;
166 SGPropertyNode_ptr gear_down;
167 SGPropertyNode_ptr latitude;
168 SGPropertyNode_ptr longitude;
169 SGPropertyNode_ptr nav0_cdi_serviceable;
170 SGPropertyNode_ptr nav0_gs_distance;
171 SGPropertyNode_ptr nav0_gs_needle_deflection;
172 SGPropertyNode_ptr nav0_gs_serviceable;
173 SGPropertyNode_ptr nav0_has_gs;
174 SGPropertyNode_ptr nav0_heading_needle_deflection;
175 SGPropertyNode_ptr nav0_in_range;
176 SGPropertyNode_ptr nav0_nav_loc;
177 SGPropertyNode_ptr nav0_serviceable;
178 SGPropertyNode_ptr power;
179 SGPropertyNode_ptr replay_state;
180 SGPropertyNode_ptr vs;
181 } external_properties;
183 inline PropertiesHandler (MK_VIII *device)
184 : FGVoicePlayer::PropertiesHandler(), mk(device) {}
186 PropertiesHandler() : FGVoicePlayer::PropertiesHandler() {}
192 PropertiesHandler properties_handler;
195 /////////////////////////////////////////////////////////////////////////////
196 // MK_VIII::PowerHandler ////////////////////////////////////////////////////
197 /////////////////////////////////////////////////////////////////////////////
206 Timer power_loss_timer;
207 Timer abnormal_timer;
208 Timer low_surge_timer;
209 Timer high_surge_timer;
210 Timer very_high_surge_timer;
212 bool handle_abnormal_voltage (bool abnormal,
214 double max_duration);
220 inline PowerHandler (MK_VIII *device)
221 : mk(device), serviceable(false), powered(false) {}
223 void bind (SGPropertyNode *node);
227 /////////////////////////////////////////////////////////////////////////////
228 // MK_VIII::SystemHandler ///////////////////////////////////////////////////
229 /////////////////////////////////////////////////////////////////////////////
238 int last_replay_state;
239 Timer reposition_timer;
252 inline SystemHandler (MK_VIII *device)
253 : mk(device), state(STATE_OFF) {}
260 /////////////////////////////////////////////////////////////////////////////
261 // MK_VIII::ConfigurationModule /////////////////////////////////////////////
262 /////////////////////////////////////////////////////////////////////////////
264 class ConfigurationModule
267 // keep in sync with IOHandler::present_status()
270 CATEGORY_AIRCRAFT_MODE_TYPE_SELECT,
271 CATEGORY_AIR_DATA_INPUT_SELECT,
272 CATEGORY_POSITION_INPUT_SELECT,
273 CATEGORY_ALTITUDE_CALLOUTS,
274 CATEGORY_AUDIO_MENU_SELECT,
275 CATEGORY_TERRAIN_DISPLAY_SELECT,
276 CATEGORY_OPTIONS_SELECT_GROUP_1,
277 CATEGORY_RADIO_ALTITUDE_INPUT_SELECT,
278 CATEGORY_NAVIGATION_INPUT_SELECT,
279 CATEGORY_ATTITUDE_INPUT_SELECT,
280 CATEGORY_HEADING_INPUT_SELECT,
281 CATEGORY_WINDSHEAR_INPUT_SELECT,
282 CATEGORY_INPUT_OUTPUT_DISCRETE_TYPE_SELECT,
283 CATEGORY_AUDIO_OUTPUT_LEVEL,
284 CATEGORY_UNDEFINED_INPUT_SELECT_1,
285 CATEGORY_UNDEFINED_INPUT_SELECT_2,
286 CATEGORY_UNDEFINED_INPUT_SELECT_3,
293 STATE_INVALID_DATABASE,
294 STATE_INVALID_AIRCRAFT_TYPE
298 int effective_categories[N_CATEGORIES];
300 ConfigurationModule (MK_VIII *device);
303 void bind (SGPropertyNode *node);
308 int categories[N_CATEGORIES];
310 bool read_aircraft_mode_type_select (int value);
311 bool read_air_data_input_select (int value);
312 bool read_position_input_select (int value);
313 bool read_altitude_callouts (int value);
314 bool read_audio_menu_select (int value);
315 bool read_terrain_display_select (int value);
316 bool read_options_select_group_1 (int value);
317 bool read_radio_altitude_input_select (int value);
318 bool read_navigation_input_select (int value);
319 bool read_attitude_input_select (int value);
320 bool read_heading_input_select (int value);
321 bool read_windshear_input_select (int value);
322 bool read_input_output_discrete_type_select (int value);
323 bool read_audio_output_level (int value);
324 bool read_undefined_input_select (int value);
326 static bool m6_t2_is_bank_angle (Parameter<double> *agl,
329 static bool m6_t4_is_bank_angle (Parameter<double> *agl,
334 /////////////////////////////////////////////////////////////////////////////
335 // MK_VIII::FaultHandler ////////////////////////////////////////////////////
336 /////////////////////////////////////////////////////////////////////////////
348 static const unsigned int fault_inops[];
350 bool has_faults (unsigned int inop);
353 // keep in sync with IOHandler::present_status()
356 FAULT_ALL_MODES_INHIBIT,
359 FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID,
360 FAULT_SELF_TEST_INVALID,
361 FAULT_GLIDESLOPE_CANCEL_INVALID,
362 FAULT_STEEP_APPROACH_INVALID,
364 FAULT_TA_TCF_INHIBIT,
365 FAULT_MODES14_INPUTS_INVALID,
366 FAULT_MODE5_INPUTS_INVALID,
367 FAULT_MODE6_INPUTS_INVALID,
368 FAULT_BANK_ANGLE_INPUTS_INVALID,
369 FAULT_TCF_INPUTS_INVALID,
373 bool faults[N_FAULTS];
375 inline FaultHandler (MK_VIII *device)
380 void set_fault (Fault fault);
381 void unset_fault (Fault fault);
383 bool has_faults () const;
386 /////////////////////////////////////////////////////////////////////////////
387 // MK_VIII::IOHandler ///////////////////////////////////////////////////////
388 /////////////////////////////////////////////////////////////////////////////
402 struct LampConfiguration
408 struct FaultsConfiguration
410 double max_flaps_down_airspeed;
411 double max_gear_down_airspeed;
416 const LampConfiguration *lamp;
417 const FaultsConfiguration *faults;
419 bool steep_approach_enabled;
420 bool gpws_inhibit_enabled;
421 bool momentary_flap_override_enabled;
422 bool alternate_steep_approach;
423 bool use_internal_gps;
424 bool localizer_enabled;
426 bool use_attitude_indicator;
429 struct _s_input_feeders
435 bool glideslope_inhibit;
436 bool decision_height;
437 bool autopilot_engaged;
442 bool uncorrected_barometric_altitude;
443 bool barometric_altitude_rate;
445 bool glideslope_deviation;
447 bool localizer_deviation;
448 bool computed_airspeed;
449 bool decision_height;
457 bool landing_gear; // appendix E 6.6.2, 3.15.1.4
458 bool landing_flaps; // appendix E 6.6.4, 3.15.1.2
459 bool momentary_flap_override; // appendix E 6.6.6, 3.15.1.6
460 bool self_test; // appendix E 6.6.7, 3.15.1.10
461 bool glideslope_inhibit; // appendix E 6.6.11, 3.15.1.1
462 bool glideslope_cancel; // appendix E 6.6.13, 3.15.1.5
463 bool decision_height; // appendix E 6.6.14, 3.10.2
464 bool mode6_low_volume; // appendix E 6.6.15, 3.15.1.7
465 bool audio_inhibit; // appendix E 6.6.16, 3.15.1.3
466 bool ta_tcf_inhibit; // appendix E 6.6.20, 3.15.1.9
467 bool autopilot_engaged; // appendix E 6.6.21, 3.15.1.8
468 bool steep_approach; // appendix E 6.6.25, 3.15.1.11
469 bool gpws_inhibit; // appendix E 6.6.27, 3.15.1.12
474 Parameter<double> uncorrected_barometric_altitude; // appendix E 6.2.1
475 Parameter<double> barometric_altitude_rate; // appendix E 6.2.2
476 Parameter<double> gps_altitude; // appendix E 6.2.4
477 Parameter<double> gps_latitude; // appendix E 6.2.7
478 Parameter<double> gps_longitude; // appendix E 6.2.8
479 Parameter<double> gps_vertical_figure_of_merit; // appendix E 6.2.13
480 Parameter<double> radio_altitude; // appendix E 6.2.29
481 Parameter<double> glideslope_deviation; // appendix E 6.2.30
482 Parameter<double> roll_angle; // appendix E 6.2.31
483 Parameter<double> localizer_deviation; // appendix E 6.2.33
484 Parameter<double> computed_airspeed; // appendix E 6.2.39
485 Parameter<double> decision_height; // appendix E 6.2.41
493 bool gpws_warning; // appendix E 7.4.1, 3.15.2.5
494 bool gpws_alert; // appendix E 7.4.1, 3.15.2.6
495 bool audio_on; // appendix E 7.4.2, 3.15.2.10
496 bool gpws_inop; // appendix E 7.4.3, 3.15.2.3
497 bool tad_inop; // appendix E 7.4.3, 3.15.2.4
498 bool flap_override; // appendix E 7.4.5, 3.15.2.8
499 bool glideslope_cancel; // appendix E 7.4.6, 3.15.2.7
500 bool steep_approach; // appendix E 7.4.12, 3.15.2.9
505 int egpws_alert_discrete_1; // appendix E 7.1.1.1
506 int egpwc_logic_discretes; // appendix E 7.1.1.2
507 int mode6_callouts_discrete_1; // appendix E 7.1.1.3
508 int mode6_callouts_discrete_2; // appendix E 7.1.1.4
509 int egpws_alert_discrete_2; // appendix E 7.1.1.5
510 int egpwc_alert_discrete_3; // appendix E 7.1.1.6
518 Parameter<double> barometric_altitude_rate;
519 Parameter<double> decision_height;
520 Parameter<double> geometric_altitude;
521 Parameter<double> glideslope_deviation_dots;
522 Parameter<double> gps_altitude;
523 Parameter<double> gps_latitude;
524 Parameter<double> gps_longitude;
525 Parameter<double> gps_vertical_figure_of_merit;
526 Parameter<double> localizer_deviation_dots;
527 Parameter<double> radio_altitude;
528 Parameter<double> roll_angle;
529 Parameter<double> terrain_clearance;
532 IOHandler (MK_VIII *device);
538 void enter_ground ();
539 void enter_takeoff ();
541 void update_inputs ();
542 void update_input_faults ();
543 void update_alternate_discrete_input (bool *ptr);
544 void update_internal_latches ();
546 void update_egpws_alert_discrete_1 ();
547 void update_egpwc_logic_discretes ();
548 void update_mode6_callouts_discrete_1 ();
549 void update_mode6_callouts_discrete_2 ();
550 void update_egpws_alert_discrete_2 ();
551 void update_egpwc_alert_discrete_3 ();
552 void update_outputs ();
555 void update_lamps ();
556 void set_lamp (Lamp lamp);
558 bool gpws_inhibit () const;
559 bool real_flaps_down () const;
560 bool flaps_down () const;
561 bool flap_override () const;
562 bool steep_approach () const;
563 bool momentary_steep_approach_enabled () const;
565 void bind (SGPropertyNode *node);
571 ///////////////////////////////////////////////////////////////////////////
572 // MK_VIII::IOHandler::TerrainClearanceFilter /////////////////////////////
573 ///////////////////////////////////////////////////////////////////////////
575 class TerrainClearanceFilter
577 typedef deque< Sample<double> > samples_type;
578 samples_type samples;
583 inline TerrainClearanceFilter ()
584 : value(0.0), last_update(-1.0) {}
586 double update (double agl);
590 ///////////////////////////////////////////////////////////////////////////
591 // MK_VIII::IOHandler (continued) /////////////////////////////////////////
592 ///////////////////////////////////////////////////////////////////////////
594 TerrainClearanceFilter terrain_clearance_filter;
599 Timer audio_inhibit_fault_timer;
600 Timer landing_gear_fault_timer;
601 Timer flaps_down_fault_timer;
602 Timer momentary_flap_override_fault_timer;
603 Timer self_test_fault_timer;
604 Timer glideslope_cancel_fault_timer;
605 Timer steep_approach_fault_timer;
606 Timer gpws_inhibit_fault_timer;
607 Timer ta_tcf_inhibit_fault_timer;
609 bool last_landing_gear;
610 bool last_real_flaps_down;
612 typedef deque< Sample< Parameter<double> > > altitude_samples_type;
613 altitude_samples_type altitude_samples;
617 bool glideslope_cancel;
620 void update_terrain_clearance ();
621 void reset_terrain_clearance ();
623 void handle_input_fault (bool test, FaultHandler::Fault fault);
624 void handle_input_fault (bool test,
627 FaultHandler::Fault fault);
629 void tie_input (SGPropertyNode *node,
633 void tie_input (SGPropertyNode *node,
635 Parameter<double> *input,
637 void tie_output (SGPropertyNode *node,
640 void tie_output (SGPropertyNode *node,
646 bool get_discrete_input (bool *ptr) const;
647 void set_discrete_input (bool *ptr, bool value);
649 void present_status ();
650 void present_status_section (const char *name);
651 void present_status_item (const char *name, const char *value = NULL);
652 void present_status_subitem (const char *name);
654 bool get_present_status () const;
655 void set_present_status (bool value);
657 bool *get_lamp_output (Lamp lamp);
660 class VoicePlayer : public FGVoicePlayer
663 VoicePlayer (MK_VIII *device) :
664 FGVoicePlayer(&device->properties_handler, "mk-viii")
672 Voice *application_data_base_failed;
674 Voice *bank_angle_bank_angle;
675 Voice *bank_angle_bank_angle_3;
676 Voice *bank_angle_inop;
677 Voice *bank_angle_pause_bank_angle;
678 Voice *bank_angle_pause_bank_angle_3;
679 Voice *callouts_inop;
680 Voice *configuration_type_invalid;
682 Voice *dont_sink_pause_dont_sink;
683 Voice *five_hundred_above;
685 Voice *glideslope_inop;
687 Voice *hard_glideslope;
689 Voice *minimums_minimums;
692 Voice *sink_rate_pause_sink_rate;
693 Voice *soft_glideslope;
695 Voice *terrain_pause_terrain;
696 Voice *too_low_flaps;
698 Voice *too_low_terrain;
699 Voice *altitude_callouts[n_altitude_callouts];
705 /////////////////////////////////////////////////////////////////////////////
706 // MK_VIII::SelfTestHandler /////////////////////////////////////////////////
707 /////////////////////////////////////////////////////////////////////////////
709 class SelfTestHandler
722 ACTION_SLEEP = 1 << 0,
723 ACTION_VOICE = 1 << 1,
724 ACTION_DISCRETE_ON_OFF = 1 << 2,
731 double sleep_duration;
739 double button_press_timestamp;
740 IOHandler::Outputs saved_outputs;
743 bool _was_here (int position);
745 Action sleep (double duration);
746 Action play (VoicePlayer::Voice *voice);
747 Action discrete_on (bool *discrete, double duration);
748 Action discrete_on_off (bool *discrete, double duration);
749 Action discrete_on_off (bool *discrete, VoicePlayer::Voice *voice);
768 inline SelfTestHandler (MK_VIII *device)
769 : mk(device), button_pressed(false), state(STATE_NONE) {}
771 inline void power_off () { stop(); }
772 inline void set_inop () { stop(); }
773 void handle_button_event (bool value);
777 /////////////////////////////////////////////////////////////////////////////
778 // MK_VIII::AlertHandler ////////////////////////////////////////////////////
779 /////////////////////////////////////////////////////////////////////////////
785 unsigned int old_alerts;
786 unsigned int voice_alerts;
787 unsigned int repeated_alerts;
788 VoicePlayer::Voice *altitude_callout_voice;
791 inline bool has_alerts (unsigned int test) const { return (alerts & test) != 0; }
792 inline bool has_old_alerts (unsigned int test) const { return (old_alerts & test) != 0; }
793 inline bool must_play_voice (unsigned int test) const { return ! has_old_alerts(test) || (repeated_alerts & test) != 0; }
794 bool select_voice_alerts (unsigned int test);
799 ALERT_MODE1_PULL_UP = 1 << 0,
800 ALERT_MODE1_SINK_RATE = 1 << 1,
802 ALERT_MODE2A_PREFACE = 1 << 2,
803 ALERT_MODE2B_PREFACE = 1 << 3,
804 ALERT_MODE2A = 1 << 4,
805 ALERT_MODE2B = 1 << 5,
806 ALERT_MODE2B_LANDING_MODE = 1 << 6,
807 ALERT_MODE2A_ALTITUDE_GAIN = 1 << 7,
808 ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING = 1 << 8,
810 ALERT_MODE3 = 1 << 9,
812 ALERT_MODE4_TOO_LOW_FLAPS = 1 << 10,
813 ALERT_MODE4_TOO_LOW_GEAR = 1 << 11,
814 ALERT_MODE4AB_TOO_LOW_TERRAIN = 1 << 12,
815 ALERT_MODE4C_TOO_LOW_TERRAIN = 1 << 13,
817 ALERT_MODE5_SOFT = 1 << 14,
818 ALERT_MODE5_HARD = 1 << 15,
820 ALERT_MODE6_MINIMUMS = 1 << 16,
821 ALERT_MODE6_ALTITUDE_CALLOUT = 1 << 17,
822 ALERT_MODE6_LOW_BANK_ANGLE_1 = 1 << 18,
823 ALERT_MODE6_HIGH_BANK_ANGLE_1 = 1 << 19,
824 ALERT_MODE6_LOW_BANK_ANGLE_2 = 1 << 20,
825 ALERT_MODE6_HIGH_BANK_ANGLE_2 = 1 << 21,
826 ALERT_MODE6_LOW_BANK_ANGLE_3 = 1 << 22,
827 ALERT_MODE6_HIGH_BANK_ANGLE_3 = 1 << 23,
829 ALERT_TCF_TOO_LOW_TERRAIN = 1 << 24
834 ALERT_FLAG_REPEAT = 1 << 0
839 inline AlertHandler (MK_VIII *device)
846 void set_alerts (unsigned int _alerts,
847 unsigned int flags = 0,
848 VoicePlayer::Voice *_altitude_callout_voice = NULL);
849 void unset_alerts (unsigned int _alerts);
851 inline void repeat_alert (unsigned int alert) { set_alerts(alert, ALERT_FLAG_REPEAT); }
852 inline void set_altitude_callout_alert (VoicePlayer::Voice *voice) { set_alerts(ALERT_MODE6_ALTITUDE_CALLOUT, 0, voice); }
855 /////////////////////////////////////////////////////////////////////////////
856 // MK_VIII::StateHandler ////////////////////////////////////////////////////
857 /////////////////////////////////////////////////////////////////////////////
863 Timer potentially_airborne_timer;
865 void update_ground ();
866 void enter_ground ();
867 void leave_ground ();
869 void update_takeoff ();
870 void enter_takeoff ();
871 void leave_takeoff ();
877 inline StateHandler (MK_VIII *device)
878 : mk(device), ground(true), takeoff(true) {}
880 void post_reposition ();
884 /////////////////////////////////////////////////////////////////////////////
885 // MK_VIII::Mode1Handler ////////////////////////////////////////////////////
886 /////////////////////////////////////////////////////////////////////////////
893 Timer sink_rate_timer;
895 double sink_rate_tti; // time-to-impact in minutes
897 double get_pull_up_bias ();
900 double get_sink_rate_bias ();
901 bool is_sink_rate ();
902 double get_sink_rate_tti ();
904 void update_pull_up ();
905 void update_sink_rate ();
910 bool flap_override_bias;
912 double (*pull_up_min_agl1) (double vs);
913 int pull_up_max_agl1;
914 double (*pull_up_min_agl2) (double vs);
915 int pull_up_max_agl2;
916 } EnvelopesConfiguration;
920 const EnvelopesConfiguration *envelopes;
923 inline Mode1Handler (MK_VIII *device)
929 /////////////////////////////////////////////////////////////////////////////
930 // MK_VIII::Mode2Handler ////////////////////////////////////////////////////
931 /////////////////////////////////////////////////////////////////////////////
936 ///////////////////////////////////////////////////////////////////////////
937 // MK_VIII::Mode2Handler::ClosureRateFilter ///////////////////////////////
938 ///////////////////////////////////////////////////////////////////////////
940 class ClosureRateFilter
942 /////////////////////////////////////////////////////////////////////////
943 // MK_VIII::Mode2Handler::ClosureRateFilter::PassFilter /////////////////
944 /////////////////////////////////////////////////////////////////////////
956 inline PassFilter (double _a0, double _a1, double _b1)
957 : a0(_a0), a1(_a1), b1(_b1) {}
959 inline double filter (double input)
961 last_output = a0 * input + a1 * last_input + b1 * last_output;
974 /////////////////////////////////////////////////////////////////////////
975 // MK_VIII::Mode2Handler::ClosureRateFilter (continued) /////////////////
976 /////////////////////////////////////////////////////////////////////////
981 Parameter<double> last_ra; // last radio altitude
982 Parameter<double> last_ba; // last barometric altitude
983 PassFilter ra_filter; // radio altitude rate filter
984 PassFilter ba_filter; // barometric altitude rate filter
986 double limit_radio_altitude_rate (double r);
989 Parameter<double> output;
991 inline ClosureRateFilter (MK_VIII *device)
993 ra_filter(0.05, 0, 0.95), // low-pass filter
994 ba_filter(0.93, -0.93, 0.86) {} // high-pass-filter
1000 ///////////////////////////////////////////////////////////////////////////
1001 // MK_VIII::Mode2Handler (continued) //////////////////////////////////////
1002 ///////////////////////////////////////////////////////////////////////////
1006 ClosureRateFilter closure_rate_filter;
1008 Timer takeoff_timer;
1009 Timer pull_up_timer;
1011 double a_start_time;
1012 Timer a_altitude_gain_timer;
1013 double a_altitude_gain_alt;
1015 void check_pull_up (unsigned int preface_alert, unsigned int alert);
1017 bool b_conditions ();
1032 const Configuration *conf;
1034 inline Mode2Handler (MK_VIII *device)
1035 : mk(device), closure_rate_filter(device) {}
1039 void leave_ground ();
1040 void enter_takeoff ();
1044 /////////////////////////////////////////////////////////////////////////////
1045 // MK_VIII::Mode3Handler ////////////////////////////////////////////////////
1046 /////////////////////////////////////////////////////////////////////////////
1053 bool has_descent_alt;
1057 double max_alt_loss (double _bias);
1058 double get_bias (double initial_bias, double alt_loss);
1059 bool is (double *alt_loss);
1065 int (*max_agl) (bool flap_override);
1066 double (*max_alt_loss) (bool flap_override, double agl);
1069 const Configuration *conf;
1071 inline Mode3Handler (MK_VIII *device)
1072 : mk(device), armed(false), has_descent_alt(false) {}
1074 void enter_takeoff ();
1078 /////////////////////////////////////////////////////////////////////////////
1079 // MK_VIII::Mode4Handler ////////////////////////////////////////////////////
1080 /////////////////////////////////////////////////////////////////////////////
1090 double (*min_agl2) (double airspeed);
1092 } EnvelopesConfiguration;
1096 const EnvelopesConfiguration *ac;
1097 const EnvelopesConfiguration *b;
1098 } ModesConfiguration;
1102 VoicePlayer::Voice *voice_too_low_gear;
1103 const ModesConfiguration *modes;
1106 inline Mode4Handler (MK_VIII *device)
1107 : mk(device),ab_bias(0.0),ab_expanded_bias(0.0),c_bias(0.0) {}
1109 double get_upper_agl (const EnvelopesConfiguration *c);
1116 double ab_expanded_bias;
1119 const EnvelopesConfiguration *get_ab_envelope ();
1120 double get_bias (double initial_bias, double min_agl);
1121 void handle_alert (unsigned int alert, double min_agl, double *bias);
1124 void update_ab_expanded ();
1128 /////////////////////////////////////////////////////////////////////////////
1129 // MK_VIII::Mode5Handler ////////////////////////////////////////////////////
1130 /////////////////////////////////////////////////////////////////////////////
1142 bool is_soft (double bias);
1144 double get_soft_bias (double initial_bias);
1146 void update_hard (bool is);
1147 void update_soft (bool is);
1150 inline Mode5Handler (MK_VIII *device)
1151 : mk(device), soft_bias(0.0) {}
1156 /////////////////////////////////////////////////////////////////////////////
1157 // MK_VIII::Mode6Handler ////////////////////////////////////////////////////
1158 /////////////////////////////////////////////////////////////////////////////
1163 // keep in sync with altitude_callout_definitions[]
1166 ALTITUDE_CALLOUT_1000,
1167 ALTITUDE_CALLOUT_500,
1168 ALTITUDE_CALLOUT_400,
1169 ALTITUDE_CALLOUT_300,
1170 ALTITUDE_CALLOUT_200,
1171 ALTITUDE_CALLOUT_100,
1172 ALTITUDE_CALLOUT_50,
1173 ALTITUDE_CALLOUT_40,
1174 ALTITUDE_CALLOUT_30,
1175 ALTITUDE_CALLOUT_20,
1179 typedef bool (*BankAnglePredicate) (Parameter<double> *agl,
1180 double abs_roll_deg,
1185 bool minimums_enabled;
1186 bool smart_500_enabled;
1187 VoicePlayer::Voice *above_field_voice;
1189 bool altitude_callouts_enabled[n_altitude_callouts];
1190 bool bank_angle_enabled;
1191 BankAnglePredicate is_bank_angle;
1194 static const int altitude_callout_definitions[];
1196 inline Mode6Handler (MK_VIII *device)
1201 void enter_takeoff ();
1202 void leave_takeoff ();
1203 void set_volume (float volume);
1204 bool altitude_callouts_enabled ();
1210 bool last_decision_height;
1211 Parameter<double> last_radio_altitude;
1212 Parameter<double> last_altitude_above_field;
1214 bool altitude_callouts_issued[n_altitude_callouts];
1215 bool minimums_issued;
1216 bool above_field_issued;
1219 Parameter<bool> has_runway;
1223 double elevation; // elevation in feet
1226 void reset_minimums ();
1227 void reset_altitude_callouts ();
1228 bool is_playing_altitude_callout ();
1229 bool is_near_minimums (double callout);
1230 bool is_outside_band (double elevation, double callout);
1231 bool inhibit_smart_500 ();
1233 void update_minimums ();
1234 void update_altitude_callouts ();
1236 bool test_runway (const FGRunway *_runway);
1237 bool test_airport (const FGAirport *airport);
1238 void update_runway ();
1240 void get_altitude_above_field (Parameter<double> *parameter);
1241 void update_above_field_callout ();
1243 bool is_bank_angle (double abs_roll_angle, double bias);
1244 bool is_high_bank_angle ();
1245 unsigned int get_bank_angle_alerts ();
1246 void update_bank_angle ();
1248 class AirportFilter : public FGAirport::AirportFilter
1251 AirportFilter(Mode6Handler *s)
1254 virtual bool passAirport(FGAirport *a) const;
1256 virtual FGPositioned::Type maxType() const {
1257 return FGPositioned::AIRPORT;
1265 /////////////////////////////////////////////////////////////////////////////
1266 // MK_VIII::TCFHandler //////////////////////////////////////////////////////
1267 /////////////////////////////////////////////////////////////////////////////
1273 double latitude; // latitude in degrees
1274 double longitude; // longitude in degrees
1279 Position position; // position of threshold
1280 double heading; // runway heading
1285 static const double k;
1292 Position center; // center point
1293 double elevation; // elevation in feet
1294 double half_length; // runway half length, in nautical miles
1295 RunwayEdge edges[2]; // runway threshold and end
1296 Position bias_area[4]; // vertices of the bias area
1301 double initial_value;
1303 double get_azimuth_difference (double from_lat,
1308 double get_azimuth_difference (const FGRunway *_runway);
1310 FGRunway* select_runway (const FGAirport *airport);
1311 void update_runway ();
1313 void get_bias_area_edges (Position *edge,
1315 double half_width_m,
1316 Position *bias_edge1,
1317 Position *bias_edge2);
1319 bool is_inside_edge_triangle (RunwayEdge *edge);
1320 bool is_inside_bias_area ();
1325 class AirportFilter : public FGAirport::AirportFilter
1328 AirportFilter(MK_VIII *device)
1331 virtual bool passAirport(FGAirport *a) const;
1341 inline TCFHandler (MK_VIII *device)
1347 /////////////////////////////////////////////////////////////////////////////
1348 // MK_VIII (continued) //////////////////////////////////////////////////////
1349 /////////////////////////////////////////////////////////////////////////////
1354 PowerHandler power_handler;
1355 SystemHandler system_handler;
1356 ConfigurationModule configuration_module;
1357 FaultHandler fault_handler;
1358 IOHandler io_handler;
1359 VoicePlayer voice_player;
1360 SelfTestHandler self_test_handler;
1361 AlertHandler alert_handler;
1362 StateHandler state_handler;
1363 Mode1Handler mode1_handler;
1364 Mode2Handler mode2_handler;
1365 Mode3Handler mode3_handler;
1366 Mode4Handler mode4_handler;
1367 Mode5Handler mode5_handler;
1368 Mode6Handler mode6_handler;
1369 TCFHandler tcf_handler;
1373 int runway_database;
1377 MK_VIII (SGPropertyNode *node);
1379 virtual void init ();
1380 virtual void bind ();
1381 virtual void unbind ();
1382 virtual void update (double dt);
1386 # pragma warning( pop )
1389 #endif // __INSTRUMENTS_MK_VIII_HXX