FlightGear next
mk_viii.hxx
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: GPL-2.0+
3 * SPDX-FileCopyrightText: 2005,2006 (C) Jean-Yves Lefort - jylefort@FreeBSD.org
4 *
5 * mk_viii.hxx -- Honeywell MK VIII EGPWS emulation
6 * Written by Jean-Yves Lefort, started September 2005.
7 *
8 * Copyright (C) 2005, 2006 Jean-Yves Lefort - jylefort@FreeBSD.org
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23*/
24
25#pragma once
26
27#include <assert.h>
28
29#include <vector>
30#include <deque>
31#include <map>
32
33#include <simgear/props/props.hxx>
34#include <simgear/props/tiedpropertylist.hxx>
35#include <simgear/structure/subsystem_mgr.hxx>
36
37class SGSampleGroup;
38
39#include <Airports/runways.hxx>
40#include <Airports/airport.hxx>
41#include <Main/globals.hxx>
42#include <Sound/voiceplayer.hxx>
43
44#ifdef _MSC_VER
45# pragma warning( push )
46# pragma warning( disable: 4355 )
47#endif
48
49
51// MK_VIII ////////////////////////////////////////////////////////////////////
53
54class MK_VIII : public SGSubsystem
55{
56 // keep in sync with Mode6Handler::altitude_callout_definitions[]
57 static const unsigned n_altitude_callouts = 12;
58
60 // MK_VIII::Parameter ///////////////////////////////////////////////////////
62
63 template <class T>
64 class Parameter
65 {
66 T _value;
67
68 public:
69 bool ncd;
70
71 inline Parameter ()
72 : _value(0), ncd(true) {}
73
74 inline T get () const { assert(! ncd); return _value; }
75 inline T *get_pointer () { return &_value; }
76 inline void set (T value) { ncd = false; _value = value; }
77 inline void unset () { ncd = true; }
78
79 inline void set (const Parameter<T> *parameter)
80 {
81 if (parameter->ncd)
82 unset();
83 else
84 set(parameter->get());
85 }
86
87 inline void set (const Parameter<double> *parameter, double factor)
88 {
89 if (parameter->ncd)
90 unset();
91 else
92 set(parameter->get() * factor);
93 }
94 };
95
97 // MK_VIII::Sample //////////////////////////////////////////////////////////
99
100 template <class T>
101 class Sample
102 {
103 public:
104 double timestamp;
105 T value;
106
107 inline Sample (T _value)
108 : timestamp(globals->get_sim_time_sec()), value(_value) {}
109 };
110
112 // MK_VIII::Timer ///////////////////////////////////////////////////////////
114
115 class Timer
116 {
117 double start_time;
118
119 public:
120 bool running;
121
122 inline Timer ()
123 : start_time(0.0), running(false) {}
124
125 inline void start () { running = true; start_time = globals->get_sim_time_sec(); }
126 inline void stop () { running = false; }
127 inline double elapsed () const { assert(running); return globals->get_sim_time_sec() - start_time; }
128 inline double start_or_elapsed ()
129 {
130 if (running)
131 return elapsed();
132 else
133 {
134 start();
135 return 0;
136 }
137 }
138 };
139
141 // MK_VIII::PropertiesHandler ///////////////////////////////////////////////
143
144 class PropertiesHandler : public FGVoicePlayer::PropertiesHandler
145 {
146 MK_VIII *mk;
147
148 public:
149 struct
150 {
151 SGPropertyNode_ptr ai_caged;
152 SGPropertyNode_ptr ai_roll;
153 SGPropertyNode_ptr ai_serviceable;
154 SGPropertyNode_ptr altimeter_altitude;
155 SGPropertyNode_ptr altimeter_serviceable;
156 SGPropertyNode_ptr altitude;
157 SGPropertyNode_ptr altitude_agl;
158 SGPropertyNode_ptr altitude_gear_agl;
159 SGPropertyNode_ptr altitude_radar_agl;
160 SGPropertyNode_ptr orientation_roll;
161 SGPropertyNode_ptr asi_serviceable;
162 SGPropertyNode_ptr asi_speed;
163 SGPropertyNode_ptr autopilot_heading_lock;
164 SGPropertyNode_ptr flaps;
165 SGPropertyNode_ptr gear_down;
166 SGPropertyNode_ptr throttle;
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;
182
183 inline PropertiesHandler (MK_VIII *device)
184 : FGVoicePlayer::PropertiesHandler(), mk(device) {}
185
186 PropertiesHandler() : FGVoicePlayer::PropertiesHandler(), mk(NULL) {}
187
188 void init ();
189 };
190
191 public:
192 PropertiesHandler properties_handler;
193
194 private:
196 // MK_VIII::PowerHandler ////////////////////////////////////////////////////
198
199 class PowerHandler
200 {
201 MK_VIII *mk;
202
203 bool serviceable;
204 bool powered;
205
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;
211
212 bool handle_abnormal_voltage (bool abnormal,
213 Timer *timer,
214 double max_duration);
215
216 void power_on ();
217 void power_off ();
218
219 public:
220 inline PowerHandler (MK_VIII *device)
221 : mk(device), serviceable(false), powered(false) {}
222
223 void bind (SGPropertyNode *node);
224 void update ();
225 };
226
228 // MK_VIII::SystemHandler ///////////////////////////////////////////////////
230
231 class SystemHandler
232 {
233 MK_VIII *mk;
234
235 double boot_delay;
236 Timer boot_timer;
237
238 int last_replay_state;
239 Timer reposition_timer;
240
241 public:
242 typedef enum
243 {
244 STATE_OFF,
245 STATE_BOOTING,
246 STATE_ON,
247 STATE_REPOSITION
248 } State;
249
250 State state;
251
252 inline SystemHandler (MK_VIII *device)
253 : mk(device), boot_delay(0.0), last_replay_state(0), state(STATE_OFF) {}
254
255 void power_on ();
256 void power_off ();
257 void update ();
258 };
259
261 // MK_VIII::ConfigurationModule /////////////////////////////////////////////
263
264 class ConfigurationModule
265 {
266 public:
267 // keep in sync with IOHandler::present_status()
268 typedef enum
269 {
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,
287 N_CATEGORIES
288 } Category;
289
290 typedef enum
291 {
292 STATE_OK,
293 STATE_INVALID_DATABASE,
294 STATE_INVALID_AIRCRAFT_TYPE
295 } State;
296
297 State state;
298
299 int effective_categories[N_CATEGORIES];
300
301 ConfigurationModule (MK_VIII *device);
302
303 void boot ();
304 void bind (SGPropertyNode *node);
305
306 private:
307 MK_VIII *mk;
308
309 int categories[N_CATEGORIES];
310
311 bool read_aircraft_mode_type_select (int value);
312 bool read_air_data_input_select (int value);
313 bool read_position_input_select (int value);
314 bool read_altitude_callouts (int value);
315 bool read_audio_menu_select (int value);
316 bool read_terrain_display_select (int value);
317 bool read_options_select_group_1 (int value);
318 bool read_radio_altitude_input_select (int value);
319 bool read_navigation_input_select (int value);
320 bool read_attitude_input_select (int value);
321 bool read_heading_input_select (int value);
322 bool read_windshear_input_select (int value);
323 bool read_input_output_discrete_type_select (int value);
324 bool read_audio_output_level (int value);
325 bool read_undefined_input_select (int value);
326
327 static bool m6_t2_is_bank_angle (Parameter<double> *agl,
328 double abs_roll_deg,
329 bool ap_engaged);
330 static bool m6_t4_is_bank_angle (Parameter<double> *agl,
331 double abs_roll_deg,
332 bool ap_engaged);
333 };
334
336 // MK_VIII::FaultHandler ////////////////////////////////////////////////////
338
339 class FaultHandler
340 {
341 enum
342 {
343 INOP_GPWS = 1 << 0,
344 INOP_TAD = 1 << 1
345 };
346
347 MK_VIII *mk;
348
349 static const unsigned int fault_inops[];
350
351 bool has_faults (unsigned int inop);
352
353 public:
354 // keep in sync with IOHandler::present_status()
355
356 typedef enum
357 {
358 FAULT_ALL_MODES_INHIBIT,
359 FAULT_GEAR_SWITCH,
360 FAULT_FLAPS_SWITCH,
361 FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID,
362 FAULT_SELF_TEST_INVALID,
363 FAULT_GLIDESLOPE_CANCEL_INVALID,
364 FAULT_STEEP_APPROACH_INVALID,
365 FAULT_GPWS_INHIBIT,
366 FAULT_TA_TCF_INHIBIT,
367 FAULT_MODES14_INPUTS_INVALID,
368 FAULT_MODE5_INPUTS_INVALID,
369 FAULT_MODE6_INPUTS_INVALID,
370 FAULT_BANK_ANGLE_INPUTS_INVALID,
371 FAULT_TCF_INPUTS_INVALID,
372 N_FAULTS
373 } Fault;
374
375 unsigned int faults;
376
377 inline FaultHandler(MK_VIII *device) :
378 mk(device), faults(0) {
379 }
380
381 void boot();
382
383 void set_fault(Fault fault);
384 void unset_fault(Fault fault);
385
386 bool has_faults() const;
387 };
388
389 public:
390
392 // MK_VIII::IOHandler ///////////////////////////////////////////////////////
395 {
396 public:
404
406 {
409 };
410
416
431
455
457 {
459 {
460 bool landing_gear; // appendix E 6.6.2, 3.15.1.4
461 bool landing_flaps; // appendix E 6.6.4, 3.15.1.2
462 bool momentary_flap_override; // appendix E 6.6.6, 3.15.1.6
463 bool self_test; // appendix E 6.6.7, 3.15.1.10
464 bool glideslope_inhibit; // appendix E 6.6.11, 3.15.1.1
465 bool glideslope_cancel; // appendix E 6.6.13, 3.15.1.5
467 bool decision_height; // appendix E 6.6.14, 3.10.2
468 bool mode6_low_volume; // appendix E 6.6.15, 3.15.1.7
469 bool audio_inhibit; // appendix E 6.6.16, 3.15.1.3
470 bool ta_tcf_inhibit; // appendix E 6.6.20, 3.15.1.9
471 bool autopilot_engaged; // appendix E 6.6.21, 3.15.1.8
472 bool steep_approach; // appendix E 6.6.25, 3.15.1.11
473 bool gpws_inhibit; // appendix E 6.6.27, 3.15.1.12
475
477 {
478 Parameter<double> uncorrected_barometric_altitude; // appendix E 6.2.1
479 Parameter<double> barometric_altitude_rate; // appendix E 6.2.2
480 Parameter<double> gps_altitude; // appendix E 6.2.4
481 Parameter<double> gps_latitude; // appendix E 6.2.7
482 Parameter<double> gps_longitude; // appendix E 6.2.8
483 Parameter<double> gps_vertical_figure_of_merit; // appendix E 6.2.13
484 Parameter<double> radio_altitude; // appendix E 6.2.29
485 Parameter<double> glideslope_deviation; // appendix E 6.2.30
486 Parameter<double> roll_angle; // appendix E 6.2.31
487 Parameter<double> localizer_deviation; // appendix E 6.2.33
488 Parameter<double> computed_airspeed; // appendix E 6.2.39
489 Parameter<double> decision_height; // appendix E 6.2.41
492
493 struct Outputs
494 {
496 {
497 bool gpws_warning; // appendix E 7.4.1, 3.15.2.5
498 bool gpws_alert; // appendix E 7.4.1, 3.15.2.6
499 bool audio_on; // appendix E 7.4.2, 3.15.2.10
500 bool gpws_inop; // appendix E 7.4.3, 3.15.2.3
501 bool tad_inop; // appendix E 7.4.3, 3.15.2.4
502 bool flap_override; // appendix E 7.4.5, 3.15.2.8
503 bool glideslope_cancel; // appendix E 7.4.6, 3.15.2.7
504 bool steep_approach; // appendix E 7.4.12, 3.15.2.9
506
508 {
509 int egpws_alert_discrete_1; // appendix E 7.1.1.1
510 int egpwc_logic_discretes; // appendix E 7.1.1.2
511 int mode6_callouts_discrete_1; // appendix E 7.1.1.3
512 int mode6_callouts_discrete_2; // appendix E 7.1.1.4
513 int egpws_alert_discrete_2; // appendix E 7.1.1.5
514 int egpwc_alert_discrete_3; // appendix E 7.1.1.6
516 };
517
519
520 struct _s_data
521 {
522 Parameter<double> barometric_altitude_rate;
523 Parameter<double> decision_height;
524 Parameter<double> geometric_altitude;
525 Parameter<double> glideslope_deviation_dots;
526 Parameter<double> gps_altitude;
527 Parameter<double> gps_latitude;
528 Parameter<double> gps_longitude;
530 Parameter<double> localizer_deviation_dots;
531 Parameter<double> radio_altitude;
532 Parameter<double> roll_angle;
533 Parameter<double> terrain_clearance;
535
536 IOHandler (MK_VIII *device);
537
538 void boot ();
539 void post_boot ();
540 void power_off ();
541
542 void enter_ground ();
543 void enter_takeoff ();
544
545 void update_inputs ();
546 void update_input_faults ();
547 void update_alternate_discrete_input (bool *ptr);
549
556 void update_outputs ();
557 void reposition ();
558
559 void update_lamps ();
560 void set_lamp (Lamp lamp);
561
562 bool gpws_inhibit () const;
563 bool real_flaps_down () const;
564 bool flaps_down () const;
565 bool flap_override () const;
566 bool steep_approach () const;
568
569 void bind (SGPropertyNode *node);
570
572
573 private:
574
576 // MK_VIII::IOHandler::TerrainClearanceFilter /////////////////////////////
578
579 class TerrainClearanceFilter
580 {
581 typedef std::deque< Sample<double> > samples_type;
582 samples_type samples;
583 double value;
584 double last_update;
585
586 public:
587 inline TerrainClearanceFilter ()
588 : value(0.0), last_update(-1.0) {}
589
590 double update (double agl);
591 void reset ();
592 };
593
595 // MK_VIII::IOHandler (continued) /////////////////////////////////////////
597
598 TerrainClearanceFilter terrain_clearance_filter;
599
600 Lamp _lamp;
601 Timer lamp_timer;
602
603 Timer audio_inhibit_fault_timer;
604 Timer landing_gear_fault_timer;
605 Timer flaps_down_fault_timer;
606 Timer momentary_flap_override_fault_timer;
607 Timer self_test_fault_timer;
608 Timer glideslope_cancel_fault_timer;
609 Timer steep_approach_fault_timer;
610 Timer gpws_inhibit_fault_timer;
611 Timer ta_tcf_inhibit_fault_timer;
612
613 bool last_landing_gear;
614 bool last_real_flaps_down;
615
616 typedef std::deque< Sample< Parameter<double> > > altitude_samples_type;
617 altitude_samples_type altitude_samples;
618
619 struct
620 {
622 } power_saved;
623
624 void update_terrain_clearance ();
625 void reset_terrain_clearance ();
626
627 void handle_input_fault (bool test, FaultHandler::Fault fault);
628 void handle_input_fault (bool test,
629 Timer *timer,
630 double max_duration,
631 FaultHandler::Fault fault);
632
633 void tie_input (SGPropertyNode *node,
634 const char *name,
635 bool *input,
636 bool *feed = NULL);
637 void tie_input (SGPropertyNode *node,
638 const char *name,
639 Parameter<double> *input,
640 bool *feed = NULL);
641 void tie_output (SGPropertyNode *node,
642 const char *name,
643 bool *output);
644 void tie_output (SGPropertyNode *node,
645 const char *name,
646 int *output);
647
648 public:
649
650 bool get_discrete_input (bool *ptr) const;
651 void set_discrete_input (bool *ptr, bool value);
652
653 void present_status ();
654 void present_status_section (const char *name);
655 void present_status_item (const char *name, const char *value = NULL);
656 void present_status_subitem (const char *name);
657
658 bool get_present_status () const;
659 void set_present_status (bool value);
660
661 bool *get_lamp_output (Lamp lamp);
662 };
663
709
710 private:
712 // MK_VIII::SelfTestHandler /////////////////////////////////////////////////
714
715 class SelfTestHandler
716 {
717 MK_VIII *mk;
718
719 typedef enum
720 {
721 CANCEL_NONE,
722 CANCEL_SHORT,
723 CANCEL_LONG
724 } Cancel;
725
726 enum
727 {
728 ACTION_SLEEP = 1 << 0,
729 ACTION_VOICE = 1 << 1,
730 ACTION_DISCRETE_ON_OFF = 1 << 2,
731 ACTION_DONE = 1 << 3
732 };
733
734 typedef struct
735 {
736 unsigned int flags;
737 double sleep_duration;
738 bool *discrete;
739 } Action;
740
741 Cancel cancel;
742 Action action;
743 int current;
744 bool button_pressed;
745 double button_press_timestamp;
746 IOHandler::Outputs saved_outputs;
747 double sleep_start;
748
749 bool _was_here (int position);
750
751 Action sleep (double duration);
752 Action play (VoicePlayer::Voice *voice);
753 Action discrete_on (bool *discrete, double duration);
754 Action discrete_on_off (bool *discrete, double duration);
755 Action discrete_on_off (bool *discrete, VoicePlayer::Voice *voice);
756 Action done ();
757
758 Action run ();
759
760 void start ();
761 void stop ();
762 void shutdown ();
763
764 public:
765 typedef enum
766 {
767 STATE_NONE,
768 STATE_START,
769 STATE_RUNNING
770 } State;
771
772 State state;
773
774 inline SelfTestHandler (MK_VIII *device)
775 : mk(device), button_pressed(false), state(STATE_NONE) {}
776
777 inline void power_off () { stop(); }
778 inline void set_inop () { stop(); }
779 void handle_button_event (bool value);
780 bool update ();
781 };
782
784 // MK_VIII::AlertHandler ////////////////////////////////////////////////////
786
787 class AlertHandler
788 {
789 MK_VIII *mk;
790
791 unsigned int old_alerts;
792 unsigned int voice_alerts;
793 unsigned int repeated_alerts;
794 VoicePlayer::Voice *altitude_callout_voice;
795
796 void reset ();
797 inline bool has_alerts (unsigned int test) const { return (alerts & test) != 0; }
798 inline bool has_old_alerts (unsigned int test) const { return (old_alerts & test) != 0; }
799 inline bool must_play_voice (unsigned int test) const { return ! has_old_alerts(test) || (repeated_alerts & test) != 0; }
800 bool select_voice_alerts (unsigned int test);
801
802 public:
803 enum
804 {
805 ALERT_MODE1_PULL_UP = 1 << 0,
806 ALERT_MODE1_SINK_RATE = 1 << 1,
807
808 ALERT_MODE2A_PREFACE = 1 << 2,
809 ALERT_MODE2B_PREFACE = 1 << 3,
810 ALERT_MODE2A = 1 << 4,
811 ALERT_MODE2B = 1 << 5,
812 ALERT_MODE2B_LANDING_MODE = 1 << 6,
813 ALERT_MODE2A_ALTITUDE_GAIN = 1 << 7,
814 ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING = 1 << 8,
815
816 ALERT_MODE3 = 1 << 9,
817
818 ALERT_MODE4_TOO_LOW_FLAPS = 1 << 10,
819 ALERT_MODE4_TOO_LOW_GEAR = 1 << 11,
820 ALERT_MODE4AB_TOO_LOW_TERRAIN = 1 << 12,
821 ALERT_MODE4C_TOO_LOW_TERRAIN = 1 << 13,
822
823 ALERT_MODE5_SOFT = 1 << 14,
824 ALERT_MODE5_HARD = 1 << 15,
825
826 ALERT_MODE6_MINIMUMS = 1 << 16,
827
828 ALERT_MODE6_ALTITUDE_CALLOUT = 1 << 17,
829 ALERT_MODE6_LOW_BANK_ANGLE_1 = 1 << 18,
830 ALERT_MODE6_HIGH_BANK_ANGLE_1 = 1 << 19,
831 ALERT_MODE6_LOW_BANK_ANGLE_2 = 1 << 20,
832 ALERT_MODE6_HIGH_BANK_ANGLE_2 = 1 << 21,
833 ALERT_MODE6_LOW_BANK_ANGLE_3 = 1 << 22,
834 ALERT_MODE6_HIGH_BANK_ANGLE_3 = 1 << 23,
835
836 ALERT_TCF_TOO_LOW_TERRAIN = 1 << 24,
837
838 ALERT_MODE6_MINIMUMS_100 = 1 << 28,
839 ALERT_MODE6_RETARD = 1 << 29,
840 };
841
842 enum
843 {
844 ALERT_FLAG_REPEAT = 1 << 0
845 };
846
847 unsigned int alerts;
848
849 inline AlertHandler (MK_VIII *device)
850 : mk(device) {}
851
852 void boot ();
853 void reposition ();
854 void update ();
855
856 void set_alerts (unsigned int _alerts,
857 unsigned int flags = 0,
858 VoicePlayer::Voice *_altitude_callout_voice = NULL);
859 void unset_alerts (unsigned int _alerts);
860
861 inline void repeat_alert (unsigned int alert) { set_alerts(alert, ALERT_FLAG_REPEAT); }
862 inline void set_altitude_callout_alert (VoicePlayer::Voice *voice) { set_alerts(ALERT_MODE6_ALTITUDE_CALLOUT, 0, voice); }
863 };
864
866 // MK_VIII::StateHandler ////////////////////////////////////////////////////
868
869 class StateHandler
870 {
871 MK_VIII *mk;
872
873 Timer potentially_airborne_timer;
874
875 void update_ground ();
876 void enter_ground ();
877 void leave_ground ();
878
879 void update_takeoff ();
880 void enter_takeoff ();
881 void leave_takeoff ();
882
883 public:
884 bool ground;
885 bool takeoff;
886
887 inline StateHandler (MK_VIII *device)
888 : mk(device), ground(true), takeoff(true) {}
889
890 void post_reposition ();
891 void update ();
892 };
893
895 // MK_VIII::Mode1Handler ////////////////////////////////////////////////////
897
898 class Mode1Handler
899 {
900 MK_VIII *mk;
901
902 Timer pull_up_timer;
903 Timer sink_rate_timer;
904
905 double sink_rate_tti; // time-to-impact in minutes
906
907 double get_pull_up_bias ();
908 bool is_pull_up ();
909
910 double get_sink_rate_bias ();
911 bool is_sink_rate ();
912 double get_sink_rate_tti ();
913
914 void update_pull_up ();
915 void update_sink_rate ();
916
917 public:
918 typedef struct
919 {
922 double (*pull_up_min_agl1) (double vs);
924 double (*pull_up_min_agl2) (double vs);
927
928 struct
929 {
930 const EnvelopesConfiguration *envelopes;
931 } conf;
932
933 inline Mode1Handler (MK_VIII *device)
934 : mk(device), sink_rate_tti(0.0) {}
935
936 void update ();
937 };
938
940 // MK_VIII::Mode2Handler ////////////////////////////////////////////////////
942
943 class Mode2Handler
944 {
945
947 // MK_VIII::Mode2Handler::ClosureRateFilter ///////////////////////////////
949
950 class ClosureRateFilter
951 {
953 // MK_VIII::Mode2Handler::ClosureRateFilter::PassFilter /////////////////
955
956 class PassFilter
957 {
958 double a0;
959 double a1;
960 double b1;
961
962 double last_input;
963 double last_output;
964
965 public:
966 inline PassFilter (double _a0, double _a1, double _b1)
967 : a0(_a0), a1(_a1), b1(_b1), last_input(0.0), last_output(0.0) {}
968
969 inline double filter (double input)
970 {
971 last_output = a0 * input + a1 * last_input + b1 * last_output;
972 last_input = input;
973
974 return last_output;
975 }
976
977 inline void reset ()
978 {
979 last_input = 0;
980 last_output = 0;
981 }
982 };
983
985 // MK_VIII::Mode2Handler::ClosureRateFilter (continued) /////////////////
987
988 MK_VIII *mk;
989
990 Timer timer;
991 Parameter<double> last_ra; // last radio altitude
992 Parameter<double> last_ba; // last barometric altitude
993 PassFilter ra_filter; // radio altitude rate filter
994 PassFilter ba_filter; // barometric altitude rate filter
995
996 double limit_radio_altitude_rate (double r);
997
998 public:
999 Parameter<double> output;
1000
1001 inline ClosureRateFilter (MK_VIII *device)
1002 : mk(device),
1003 ra_filter(0.05, 0, 0.95), // low-pass filter
1004 ba_filter(0.93, -0.93, 0.86) {} // high-pass-filter
1005
1006 void init ();
1007 void update ();
1008 };
1009
1011 // MK_VIII::Mode2Handler (continued) //////////////////////////////////////
1013
1014 MK_VIII *mk;
1015
1016 ClosureRateFilter closure_rate_filter;
1017
1018 Timer takeoff_timer;
1019 Timer pull_up_timer;
1020
1021 double a_start_time;
1022 Timer a_altitude_gain_timer;
1023 double a_altitude_gain_alt;
1024
1025 void check_pull_up (unsigned int preface_alert, unsigned int alert);
1026
1027 bool b_conditions ();
1028
1029 bool is_a ();
1030 bool is_b ();
1031
1032 void update_a ();
1033 void update_b ();
1034
1035 public:
1036 typedef struct
1037 {
1040 } Configuration;
1041
1042 const Configuration *conf;
1043
1044 inline Mode2Handler (MK_VIII *device)
1045 : mk(device), closure_rate_filter(device) {}
1046
1047 void boot ();
1048 void power_off ();
1049 void leave_ground ();
1050 void enter_takeoff ();
1051 void update ();
1052 };
1053
1055 // MK_VIII::Mode3Handler ////////////////////////////////////////////////////
1057
1058 class Mode3Handler
1059 {
1060 MK_VIII *mk;
1061
1062 bool armed;
1063 bool has_descent_alt;
1064 double descent_alt;
1065 double bias;
1066
1067 double max_alt_loss (double _bias);
1068 double get_bias (double initial_bias, double alt_loss);
1069 bool is (double *alt_loss);
1070
1071 public:
1072 typedef struct
1073 {
1075 int (*max_agl) (bool flap_override);
1076 double (*max_alt_loss) (bool flap_override, double agl);
1077 } Configuration;
1078
1079 const Configuration *conf;
1080
1081 inline Mode3Handler (MK_VIII *device)
1082 : mk(device), armed(false), has_descent_alt(false) {}
1083
1084 void enter_takeoff ();
1085 void update ();
1086 };
1087
1089 // MK_VIII::Mode4Handler ////////////////////////////////////////////////////
1091
1092 class Mode4Handler
1093 {
1094 public:
1095 typedef struct
1096 {
1100 double (*min_agl2) (double airspeed);
1103
1109
1110 struct
1111 {
1112 VoicePlayer::Voice *voice_too_low_gear;
1113 const ModesConfiguration *modes;
1114 } conf;
1115
1116 inline Mode4Handler (MK_VIII *device)
1117 : mk(device),ab_bias(0.0),ab_expanded_bias(0.0),c_bias(0.0) {}
1118
1119 double get_upper_agl (const EnvelopesConfiguration *c);
1120 void update ();
1121
1122 private:
1123 MK_VIII *mk;
1124
1125 double ab_bias;
1126 double ab_expanded_bias;
1127 double c_bias;
1128
1129 const EnvelopesConfiguration *get_ab_envelope ();
1130 double get_bias (double initial_bias, double min_agl);
1131 void handle_alert (unsigned int alert, double min_agl, double *bias);
1132
1133 void update_ab ();
1134 void update_ab_expanded ();
1135 void update_c ();
1136 };
1137
1139 // MK_VIII::Mode5Handler ////////////////////////////////////////////////////
1141
1142 class Mode5Handler
1143 {
1144 MK_VIII *mk;
1145
1146 Timer hard_timer;
1147 Timer soft_timer;
1148
1149 double soft_bias;
1150
1151 bool is_hard ();
1152 bool is_soft (double bias);
1153
1154 double get_soft_bias (double initial_bias);
1155
1156 void update_hard (bool is);
1157 void update_soft (bool is);
1158
1159 public:
1160 inline Mode5Handler (MK_VIII *device)
1161 : mk(device), soft_bias(0.0) {}
1162
1163 void update ();
1164 };
1165
1167 // MK_VIII::Mode6Handler ////////////////////////////////////////////////////
1169
1170 class Mode6Handler
1171 {
1172 public:
1173 // keep in sync with altitude_callout_definitions[]
1174 typedef enum
1175 {
1176 ALTITUDE_CALLOUT_2500,
1177 ALTITUDE_CALLOUT_1000,
1178 ALTITUDE_CALLOUT_500,
1179 ALTITUDE_CALLOUT_400,
1180 ALTITUDE_CALLOUT_300,
1181 ALTITUDE_CALLOUT_200,
1182 ALTITUDE_CALLOUT_100,
1183 ALTITUDE_CALLOUT_50,
1184 ALTITUDE_CALLOUT_40,
1185 ALTITUDE_CALLOUT_30,
1186 ALTITUDE_CALLOUT_20,
1187 ALTITUDE_CALLOUT_10
1188 } AltitudeCallout;
1189
1190 typedef bool (*BankAnglePredicate) (Parameter<double> *agl,
1191 double abs_roll_deg,
1192 bool ap_engaged);
1193
1194 struct
1195 {
1196 bool retard_enabled;
1197 bool minimums_above_100_enabled;
1198 bool minimums_enabled;
1199 bool smart_500_enabled;
1200 VoicePlayer::Voice *above_field_voice;
1201
1202 unsigned int altitude_callouts_enabled;
1203 bool bank_angle_enabled;
1204 BankAnglePredicate is_bank_angle;
1205 } conf;
1206
1207 static const int altitude_callout_definitions[];
1208
1209 inline Mode6Handler (MK_VIII *device)
1210 : mk(device) {}
1211
1212 void boot ();
1213 void power_off ();
1214 void enter_takeoff ();
1215 void leave_takeoff ();
1216 void set_volume (float volume);
1217 bool altitude_callouts_enabled ();
1218 void update ();
1219
1220 private:
1221 MK_VIII *mk;
1222
1223 bool last_decision_height;
1224 bool last_decision_height_100;
1225 Parameter<double> last_radio_altitude;
1226 Parameter<double> last_altitude_above_field;
1227
1228 bool altitude_callouts_issued[n_altitude_callouts];
1229 bool minimums_issued;
1230 bool minimums_above_100_issued;
1231 bool above_field_issued;
1232 bool throttle_retarded;
1233
1234 Timer runway_timer;
1235 Parameter<bool> has_runway;
1236
1237 struct
1238 {
1239 double elevation; // elevation in feet
1240 } runway;
1241
1242 void reset_minimums ();
1243 void reset_altitude_callouts ();
1244 bool is_playing_altitude_callout ();
1245 bool is_near_minimums (double callout);
1246 bool is_outside_band (double elevation, double callout);
1247 bool inhibit_smart_500 ();
1248
1249 void update_minimums ();
1250 void update_altitude_callouts ();
1251
1252 bool test_runway (const FGRunway *_runway);
1253 bool test_airport (const FGAirport *airport);
1254 void update_runway ();
1255
1256 void get_altitude_above_field (Parameter<double> *parameter);
1257 void update_above_field_callout ();
1258
1259 bool is_bank_angle (double abs_roll_angle, double bias);
1260 bool is_high_bank_angle ();
1261 unsigned int get_bank_angle_alerts ();
1262 void update_bank_angle ();
1263
1264 class AirportFilter : public FGAirport::AirportFilter
1265 {
1266 public:
1267 AirportFilter(Mode6Handler *s)
1268 : self(s) {}
1269
1270 virtual bool passAirport(FGAirport *a) const;
1271
1272 virtual FGPositioned::Type maxType() const {
1273 return FGPositioned::AIRPORT;
1274 }
1275
1276 private:
1277 Mode6Handler* self;
1278 };
1279 };
1280
1282 // MK_VIII::TCFHandler //////////////////////////////////////////////////////
1284
1285 class TCFHandler
1286 {
1287 typedef struct
1288 {
1289 SGGeod position; // position of threshold
1290 double heading; // runway heading
1291 } RunwayEdge;
1292
1293 MK_VIII *mk;
1294
1295 static const double k;
1296
1297 Timer runway_timer;
1298 bool has_runway;
1299
1300 struct
1301 {
1302 SGGeod center; // center point
1303 double elevation; // elevation in feet
1304 double half_length; // runway half length, in nautical miles
1305 double half_width_m; // runway half width, in meters
1306 RunwayEdge edge; // runway threshold
1307 SGVec3d bias_points[2]; // vertices of the bias area
1308 } runway;
1309
1310 double bias;
1311 double *reference;
1312 double initial_value;
1313
1314 void update_runway ();
1315
1316 bool is_inside_edge_triangle (RunwayEdge *edge);
1317 bool is_inside_bias_area ();
1318
1319 bool is_tcf ();
1320 bool is_rfcf ();
1321
1322 class AirportFilter : public FGAirport::AirportFilter
1323 {
1324 public:
1325 AirportFilter(MK_VIII *device)
1326 : mk(device) {}
1327
1328 virtual bool passAirport(FGAirport *a) const;
1329 private:
1330 MK_VIII* mk;
1331 };
1332
1333 public:
1334 struct
1335 {
1336 bool enabled;
1337 } conf;
1338
1339 inline TCFHandler (MK_VIII *device)
1340 : mk(device) {}
1341
1342 void update ();
1343 };
1344
1346 // MK_VIII (continued) //////////////////////////////////////////////////////
1348
1349 std::string name;
1350 int num;
1351
1352 PowerHandler power_handler;
1353 SystemHandler system_handler;
1354 ConfigurationModule configuration_module;
1355 FaultHandler fault_handler;
1356 IOHandler io_handler;
1357 VoicePlayer voice_player;
1358 SelfTestHandler self_test_handler;
1359 AlertHandler alert_handler;
1360 StateHandler state_handler;
1361 Mode1Handler mode1_handler;
1362 Mode2Handler mode2_handler;
1363 Mode3Handler mode3_handler;
1364 Mode4Handler mode4_handler;
1365 Mode5Handler mode5_handler;
1366 Mode6Handler mode6_handler;
1367 TCFHandler tcf_handler;
1368
1369 struct
1370 {
1372 } conf;
1373
1374public:
1375 MK_VIII (SGPropertyNode *node);
1376
1377 // Subsystem API.
1378 void bind() override;
1379 void init() override;
1380 void unbind() override;
1381 void update(double dt) override;
1382
1383 // Subsystem identification.
1384 static const char* staticSubsystemClassId() { return "mk-viii"; }
1385};
1386
1387#ifdef _MSC_VER
1388# pragma warning( pop )
1389#endif
double altitude
Definition ADA.cxx:46
#define throttle
Definition ADA.cxx:130
double latitude
Definition ADA.cxx:53
double longitude
Definition ADA.cxx:54
FGVoicePlayer(PropertiesHandler *properties_handler, std::string _dev_name)
void present_status_section(const char *name)
Definition mk_viii.cxx:2013
bool gpws_inhibit() const
Definition mk_viii.cxx:1810
void update_egpwc_alert_discrete_3()
Definition mk_viii.cxx:1719
void present_status_item(const char *name, const char *value=NULL)
Definition mk_viii.cxx:2019
bool get_present_status() const
Definition mk_viii.cxx:2134
void present_status_subitem(const char *name)
Definition mk_viii.cxx:2028
bool steep_approach() const
Definition mk_viii.cxx:1834
struct MK_VIII::IOHandler::_s_inputs inputs
IOHandler(MK_VIII *device)
Definition mk_viii.cxx:1020
bool real_flaps_down() const
Definition mk_viii.cxx:1816
void update_internal_latches()
Definition mk_viii.cxx:1529
struct MK_VIII::IOHandler::_s_data data
void set_present_status(bool value)
Definition mk_viii.cxx:2140
void set_lamp(Lamp lamp)
Definition mk_viii.cxx:1792
void update_egpwc_logic_discretes()
Definition mk_viii.cxx:1603
bool momentary_steep_approach_enabled() const
Definition mk_viii.cxx:1847
bool flaps_down() const
Definition mk_viii.cxx:1822
struct MK_VIII::IOHandler::_s_input_feeders input_feeders
void update_egpws_alert_discrete_1()
Definition mk_viii.cxx:1567
void update_alternate_discrete_input(bool *ptr)
Definition mk_viii.cxx:1510
void set_discrete_input(bool *ptr, bool value)
Definition mk_viii.cxx:1954
void update_egpws_alert_discrete_2()
Definition mk_viii.cxx:1698
bool flap_override() const
Definition mk_viii.cxx:1828
void update_mode6_callouts_discrete_2()
Definition mk_viii.cxx:1666
void update_input_faults()
Definition mk_viii.cxx:1406
bool get_discrete_input(bool *ptr) const
Definition mk_viii.cxx:1948
bool * get_lamp_output(Lamp lamp)
Definition mk_viii.cxx:1754
void update_mode6_callouts_discrete_1()
Definition mk_viii.cxx:1633
Voice * minimums_minimums
Definition mk_viii.hxx:694
Voice * configuration_type_invalid
Definition mk_viii.hxx:684
Voice * bank_angle_pause_bank_angle
Definition mk_viii.hxx:681
Voice * bank_angle_pause_bank_angle_3
Definition mk_viii.hxx:682
Voice * application_data_base_failed
Definition mk_viii.hxx:676
Voice * bank_angle_bank_angle
Definition mk_viii.hxx:678
Voice * dont_sink_pause_dont_sink
Definition mk_viii.hxx:686
Voice * sink_rate_pause_sink_rate
Definition mk_viii.hxx:698
VoicePlayer(MK_VIII *device)
Definition mk_viii.hxx:667
Voice * bank_angle_bank_angle_3
Definition mk_viii.hxx:679
Voice * five_hundred_above
Definition mk_viii.hxx:687
Voice * terrain_pause_terrain
Definition mk_viii.hxx:701
struct MK_VIII::VoicePlayer::@324313271375217117055266177221205376013353212253 voices
Voice * altitude_callouts[n_altitude_callouts]
Definition mk_viii.hxx:705
MK_VIII(SGPropertyNode *node)
Definition mk_viii.cxx:4602
void bind() override
Definition mk_viii.cxx:4650
static const char * staticSubsystemClassId()
Definition mk_viii.hxx:1384
void update(double dt) override
Definition mk_viii.cxx:4667
PropertiesHandler properties_handler
Definition mk_viii.hxx:192
void unbind() override
Definition mk_viii.cxx:4661
void init() override
Definition mk_viii.cxx:4643
int runway_database
Definition mk_viii.hxx:1371
FGGlobals * globals
Definition globals.cxx:142
struct MK_VIII::IOHandler::Outputs::_s_arinc429 arinc429
struct MK_VIII::IOHandler::Outputs::_s_discretes discretes
const FaultsConfiguration * faults
Definition mk_viii.hxx:420
const LampConfiguration * lamp
Definition mk_viii.hxx:419
Parameter< double > roll_angle
Definition mk_viii.hxx:532
Parameter< double > glideslope_deviation_dots
Definition mk_viii.hxx:525
Parameter< double > gps_latitude
Definition mk_viii.hxx:527
Parameter< double > gps_vertical_figure_of_merit
Definition mk_viii.hxx:529
Parameter< double > gps_longitude
Definition mk_viii.hxx:528
Parameter< double > barometric_altitude_rate
Definition mk_viii.hxx:522
Parameter< double > decision_height
Definition mk_viii.hxx:523
Parameter< double > radio_altitude
Definition mk_viii.hxx:531
Parameter< double > gps_altitude
Definition mk_viii.hxx:526
Parameter< double > geometric_altitude
Definition mk_viii.hxx:524
Parameter< double > terrain_clearance
Definition mk_viii.hxx:533
Parameter< double > localizer_deviation_dots
Definition mk_viii.hxx:530
struct MK_VIII::IOHandler::_s_input_feeders::_s_arinc429 arinc429
struct MK_VIII::IOHandler::_s_input_feeders::_s_discretes discretes
Parameter< double > gps_vertical_figure_of_merit
Definition mk_viii.hxx:483
Parameter< double > uncorrected_barometric_altitude
Definition mk_viii.hxx:478
struct MK_VIII::IOHandler::_s_inputs::_s_arinc429 arinc429
struct MK_VIII::IOHandler::_s_inputs::_s_discretes discretes
double(* max_alt_loss)(bool flap_override, double agl)
Definition mk_viii.hxx:1076
int(* max_agl)(bool flap_override)
Definition mk_viii.hxx:1075
const EnvelopesConfiguration * ac
Definition mk_viii.hxx:1106
const EnvelopesConfiguration * b
Definition mk_viii.hxx:1107