51# pragma warning( disable: 4355 )
64#include <simgear/constants.h>
65#include <simgear/sg_inlines.h>
66#include <simgear/debug/logstream.hxx>
67#include <simgear/math/SGMathFwd.hxx>
68#include <simgear/math/SGLimits.hxx>
69#include <simgear/math/SGGeometryFwd.hxx>
70#include <simgear/math/SGGeodesy.hxx>
71#include <simgear/math/sg_random.hxx>
72#include <simgear/math/SGLineSegment.hxx>
73#include <simgear/math/SGIntersect.hxx>
74#include <simgear/misc/sg_path.hxx>
75#include <simgear/sound/soundmgr.hxx>
76#include <simgear/sound/sample_group.hxx>
77#include <simgear/structure/exception.hxx>
92#define GLIDESLOPE_DOTS_TO_DDM 0.0875
93#define GLIDESLOPE_DDM_TO_DOTS (1 / GLIDESLOPE_DOTS_TO_DDM)
95#define LOCALIZER_DOTS_TO_DDM 0.0775
96#define LOCALIZER_DDM_TO_DOTS (1 / LOCALIZER_DOTS_TO_DDM)
102#define assert_not_reached() assert(false)
103#define n_elements(_array) (sizeof(_array) / sizeof((_array)[0]))
104#define test_bits(_bits, _test) (((_bits) & (_test)) != 0)
106#define mk_node(_name) (mk->properties_handler.external_properties._name)
108#define mk_dinput_feed(_name) (mk->io_handler.input_feeders.discretes._name)
109#define mk_dinput(_name) (mk->io_handler.inputs.discretes._name)
110#define mk_ainput_feed(_name) (mk->io_handler.input_feeders.arinc429._name)
111#define mk_ainput(_name) (mk->io_handler.inputs.arinc429._name)
112#define mk_doutput(_name) (mk->io_handler.outputs.discretes._name)
113#define mk_aoutput(_name) (mk->io_handler.outputs.arinc429._name)
114#define mk_data(_name) (mk->io_handler.data._name)
116#define mk_voice(_name) (mk->voice_player.voices._name)
117#define mk_altitude_voice(_i) (mk->voice_player.voices.altitude_callouts[(_i)])
119#define mk_alert(_name) (AlertHandler::ALERT_ ## _name)
120#define mk_alert_flag(_name) (AlertHandler::ALERT_FLAG_ ## _name)
121#define mk_set_alerts (mk->alert_handler.set_alerts)
122#define mk_unset_alerts (mk->alert_handler.unset_alerts)
123#define mk_repeat_alert (mk->alert_handler.repeat_alert)
124#define mk_test_alert(_name) (mk_test_alerts(mk_alert(_name)))
125#define mk_test_alerts(_test) (test_bits(mk->alert_handler.alerts, (_test)))
127const double MK_VIII::TCFHandler::k = 0.25;
132 return amplitude * pow(10.0, dB / 20.0);
138 double diff = h1 - h2;
153MK_VIII::PropertiesHandler::init ()
155 mk_node(ai_caged) =
fgGetNode(
"/instrumentation/attitude-indicator/caged-flag",
true);
156 mk_node(ai_roll) =
fgGetNode(
"/instrumentation/attitude-indicator/indicated-roll-deg",
true);
157 mk_node(ai_serviceable) =
fgGetNode(
"/instrumentation/attitude-indicator/serviceable",
true);
158 mk_node(altimeter_altitude) =
fgGetNode(
"/instrumentation/altimeter/indicated-altitude-ft",
true);
159 mk_node(altimeter_serviceable) =
fgGetNode(
"/instrumentation/altimeter/serviceable",
true);
163 mk_node(altitude_radar_agl) =
fgGetNode(
"/instrumentation/radar-altimeter/radar-altitude-ft",
true);
165 mk_node(asi_serviceable) =
fgGetNode(
"/instrumentation/airspeed-indicator/serviceable",
true);
166 mk_node(asi_speed) =
fgGetNode(
"/instrumentation/airspeed-indicator/indicated-speed-kt",
true);
167 mk_node(autopilot_heading_lock) =
fgGetNode(
"/autopilot/locks/heading",
true);
173 mk_node(nav0_cdi_serviceable) =
fgGetNode(
"/instrumentation/nav/cdi/serviceable",
true);
174 mk_node(nav0_gs_distance) =
fgGetNode(
"/instrumentation/nav/gs-distance",
true);
175 mk_node(nav0_gs_needle_deflection) =
fgGetNode(
"/instrumentation/nav/gs-needle-deflection-deg",
true);
176 mk_node(nav0_gs_serviceable) =
fgGetNode(
"/instrumentation/nav/gs/serviceable",
true);
178 mk_node(nav0_heading_needle_deflection) =
fgGetNode(
"/instrumentation/nav/heading-needle-deflection",
true);
181 mk_node(nav0_serviceable) =
fgGetNode(
"/instrumentation/nav/serviceable",
true);
182 mk_node(power) =
fgGetNode((
"/systems/electrical/outputs/" + mk->name), mk->num,
true);
192MK_VIII::PowerHandler::bind (SGPropertyNode *node)
194 mk->properties_handler.tie(node,
"serviceable", SGRawValuePointer<bool>(&serviceable));
198MK_VIII::PowerHandler::handle_abnormal_voltage (
bool abnormal,
204 if (timer->start_or_elapsed() >= max_duration)
213MK_VIII::PowerHandler::update ()
215 double voltage =
mk_node(power)->getDoubleValue();
216 bool now_powered =
true;
224 if (handle_abnormal_voltage(voltage < 20.5, &low_surge_timer, 0.03))
226 if (handle_abnormal_voltage(voltage < 22.0 || voltage > 30.3,
227 &abnormal_timer, 300))
229 if (handle_abnormal_voltage(voltage > 32.2, &high_surge_timer, 1))
231 if (handle_abnormal_voltage(voltage > 37.8, &very_high_surge_timer, 0.1))
241 power_loss_timer.stop();
243 if (power_loss_timer.start_or_elapsed() >= 0.2)
254MK_VIII::PowerHandler::power_on ()
257 mk->system_handler.power_on();
261MK_VIII::PowerHandler::power_off ()
264 mk->system_handler.power_off();
266 mk->self_test_handler.power_off();
267 mk->io_handler.power_off();
268 mk->mode2_handler.power_off();
269 mk->mode6_handler.power_off();
277MK_VIII::SystemHandler::power_on ()
279 state = STATE_BOOTING;
284 boot_delay = 3 + sg_random() * 2;
289MK_VIII::SystemHandler::power_off ()
297MK_VIII::SystemHandler::update ()
299 if (state == STATE_BOOTING)
301 if (boot_timer.elapsed() >= boot_delay)
303 last_replay_state =
mk_node(replay_state)->getIntValue();
305 mk->configuration_module.boot();
307 mk->io_handler.boot();
308 mk->fault_handler.boot();
309 mk->alert_handler.boot();
312 mk->io_handler.update_inputs();
314 mk->mode2_handler.boot();
315 mk->mode6_handler.boot();
319 mk->io_handler.post_boot();
322 else if (state != STATE_OFF && mk->configuration_module.state == ConfigurationModule::STATE_OK)
327 int replay_state =
mk_node(replay_state)->getIntValue();
328 if (replay_state != last_replay_state)
330 mk->alert_handler.reposition();
331 mk->io_handler.reposition();
333 last_replay_state = replay_state;
334 state = STATE_REPOSITION;
335 reposition_timer.start();
338 if (state == STATE_REPOSITION && reposition_timer.elapsed() >= 3)
341 mk->io_handler.update_inputs();
343 mk->state_handler.post_reposition();
354MK_VIII::ConfigurationModule::ConfigurationModule (
MK_VIII *device)
355 : state(STATE_OK), mk(device)
358 categories[CATEGORY_AIRCRAFT_MODE_TYPE_SELECT] = 0;
359 categories[CATEGORY_AIR_DATA_INPUT_SELECT] = 1;
360 categories[CATEGORY_POSITION_INPUT_SELECT] = 2;
361 categories[CATEGORY_ALTITUDE_CALLOUTS] = 13;
362 categories[CATEGORY_AUDIO_MENU_SELECT] = 0;
363 categories[CATEGORY_TERRAIN_DISPLAY_SELECT] = 1;
364 categories[CATEGORY_OPTIONS_SELECT_GROUP_1] = 124;
365 categories[CATEGORY_RADIO_ALTITUDE_INPUT_SELECT] = 2;
366 categories[CATEGORY_NAVIGATION_INPUT_SELECT] = 3;
367 categories[CATEGORY_ATTITUDE_INPUT_SELECT] = 6;
368 categories[CATEGORY_HEADING_INPUT_SELECT] = 2;
369 categories[CATEGORY_WINDSHEAR_INPUT_SELECT] = 0;
370 categories[CATEGORY_INPUT_OUTPUT_DISCRETE_TYPE_SELECT] = 7;
371 categories[CATEGORY_AUDIO_OUTPUT_LEVEL] = 0;
372 categories[CATEGORY_UNDEFINED_INPUT_SELECT_1] = 0;
373 categories[CATEGORY_UNDEFINED_INPUT_SELECT_2] = 0;
374 categories[CATEGORY_UNDEFINED_INPUT_SELECT_3] = 0;
384static int m3_t2_max_agl (
bool flap_override) {
return flap_override ? 815 : 925; }
387 int bias = agl > 700 ? 5 : 0;
390 return (9.0 + 0.184 * agl) + bias;
392 return (5.4 + 0.092 * agl) + bias;
395static double m4_t1_min_agl2 (
double airspeed) {
return -1083 + 8.333 * airspeed; }
402MK_VIII::ConfigurationModule::m6_t2_is_bank_angle (Parameter<double> *agl,
408 if (agl->ncd || agl->get() > 122)
409 return abs_roll_deg > 33;
413 if (agl->ncd || agl->get() > 2450)
414 return abs_roll_deg > 55;
415 else if (agl->get() > 150)
416 return agl->get() < 153.33333 * abs_roll_deg - 5983.3333;
420 return agl->get() < 4 * abs_roll_deg - 10;
421 else if (agl->get() > 5)
422 return abs_roll_deg > 10;
428MK_VIII::ConfigurationModule::m6_t4_is_bank_angle (Parameter<double> *agl,
434 if (agl->ncd || agl->get() > 156)
435 return abs_roll_deg > 33;
439 if (agl->ncd || agl->get() > 210)
440 return abs_roll_deg > 50;
444 return agl->get() < 5.7142857 * abs_roll_deg - 75.714286;
450MK_VIII::ConfigurationModule::read_aircraft_mode_type_select (
int value)
495 static Mode6Handler::BankAnglePredicate m6_t2 = m6_t2_is_bank_angle;
496 static Mode6Handler::BankAnglePredicate m6_t4 = m6_t4_is_bank_angle;
508 Mode6Handler::BankAnglePredicate m6;
511 } aircraft_types[] = {
512 { 0, &m1_t4, &m2_t4, &m3_t2, &m4_t6, m6_t4, &f_fast, 2000 },
513 { 1, &m1_t4, &m2_t4, &m3_t2, &m4_t8, m6_t4, &f_fast, 2000 },
514 { 2, &m1_t4, &m2_t4, &m3_t2, &m4_t5, m6_t4, &f_fast, 2000 },
515 { 3, &m1_t4, &m2_t5, &m3_t2, &m4_t7, m6_t4, &f_slow, 2000 },
516 { 4, &m1_t4, &m2_t5, &m3_t2, &m4_t9, m6_t4, &f_slow, 2000 },
517 { 254, &m1_t1, &m2_t1, &m3_t1, &m4_t1, m6_t2, &f_fast, 3500 },
518 { 255, &m1_t1, &m2_t1, &m3_t1, &m4_t1, m6_t2, &f_fast, 2000 }
523 if (aircraft_types[
i].type == value)
525 mk->mode1_handler.conf.envelopes = aircraft_types[
i].m1;
526 mk->mode2_handler.conf = aircraft_types[
i].m2;
527 mk->mode3_handler.conf = aircraft_types[
i].m3;
528 mk->mode4_handler.conf.modes = aircraft_types[
i].m4;
529 mk->mode6_handler.conf.is_bank_angle = aircraft_types[
i].m6;
530 mk->io_handler.conf.faults = aircraft_types[
i].f;
531 mk->conf.runway_database = aircraft_types[
i].runway_database;
536 state = STATE_INVALID_AIRCRAFT_TYPE;
541MK_VIII::ConfigurationModule::read_air_data_input_select (
int value)
544 return (value >= 0 && value <= 6) || (value >= 10 && value <= 13) || value == 255;
548MK_VIII::ConfigurationModule::read_position_input_select (
int value)
551 mk->io_handler.conf.use_internal_gps =
true;
552 else if ((value >= 0 && value <= 5)
553 || (value >= 10 && value <= 13)
556 mk->io_handler.conf.use_internal_gps =
false;
564MK_VIII::ConfigurationModule::read_altitude_callouts (
int value)
571 FIELD_500_ABOVE = -4,
572 MINIMUMS_ABOVE_100 = -5,
581 { 0, { MINIMUMS, SMART_500, 200, 100, 50, 40, 30, 20, 10, 0 } },
582 { 1, { MINIMUMS, SMART_500, 200, 0 } },
583 { 2, { MINIMUMS, SMART_500, 100, 50, 40, 30, 20, 10, 0 } },
584 { 3, { MINIMUMS, SMART_500, 0 } },
585 { 4, { MINIMUMS, 200, 100, 50, 40, 30, 20, 10, 0 } },
586 { 5, { MINIMUMS, 200, 0 } },
587 { 6, { MINIMUMS, 100, 50, 40, 30, 20, 10, 0 } },
589 { 8, { MINIMUMS, 0 } },
590 { 9, { MINIMUMS, 500, 200, 100, 50, 40, 30, 20, 10, 0 } },
591 { 10, { MINIMUMS, 500, 200, 0 } },
592 { 11, { MINIMUMS, 500, 100, 50, 40, 30, 20, 10, 0 } },
593 { 12, { MINIMUMS, 500, 0 } },
594 { 13, { MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30, 20, 10, 0 } },
595 { 14, { MINIMUMS, 100, 0 } },
596 { 15, { MINIMUMS, 200, 100, 0 } },
597 { 100, { FIELD_500, 0 } },
598 { 101, { FIELD_500_ABOVE, 0 } },
599 {1000, { RETARD, MINIMUMS_ABOVE_100, MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } },
600 {1001, { RETARD, MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } },
601 {1002, { MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } },
602 {1010, { RETARD, MINIMUMS_ABOVE_100, MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } },
603 {1011, { RETARD, MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } },
606 mk->mode6_handler.conf.retard_enabled =
false;
607 mk->mode6_handler.conf.minimums_above_100_enabled =
false;
608 mk->mode6_handler.conf.minimums_enabled =
false;
609 mk->mode6_handler.conf.smart_500_enabled =
false;
610 mk->mode6_handler.conf.above_field_voice = NULL;
611 mk->mode6_handler.conf.altitude_callouts_enabled = 0;
615 if (values[
i].
id == value)
617 for (
int j = 0; values[
i].callouts[j] != 0; j++)
619 switch (values[
i].callouts[j])
622 mk->mode6_handler.conf.retard_enabled =
true;
625 case MINIMUMS_ABOVE_100:
626 mk->mode6_handler.conf.minimums_above_100_enabled =
true;
630 mk->mode6_handler.conf.minimums_enabled =
true;
634 mk->mode6_handler.conf.smart_500_enabled =
true;
638 mk->mode6_handler.conf.above_field_voice =
mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_500);
641 case FIELD_500_ABOVE:
642 mk->mode6_handler.conf.above_field_voice =
mk_voice(five_hundred_above);
646 for (
unsigned k = 0; k < n_altitude_callouts; k++)
647 if (mk->mode6_handler.altitude_callout_definitions[k] == values[
i].callouts[j])
648 mk->mode6_handler.conf.altitude_callouts_enabled |= 1 << k;
660MK_VIII::ConfigurationModule::read_audio_menu_select (
int value)
662 if (value == 0 || value == 1)
663 mk->mode4_handler.conf.voice_too_low_gear =
mk_voice(too_low_gear);
664 else if (value == 2 || value == 3)
665 mk->mode4_handler.conf.voice_too_low_gear =
mk_voice(too_low_flaps);
673MK_VIII::ConfigurationModule::read_terrain_display_select (
int value)
676 mk->tcf_handler.conf.enabled =
false;
677 else if (value == 0 || value == 1 || (value >= 3 && value <= 15)
678 || (value >= 18 && value <= 20) || (value >= 235 && value <= 255))
679 mk->tcf_handler.conf.enabled =
true;
687MK_VIII::ConfigurationModule::read_options_select_group_1 (
int value)
689 if (value >= 0 && value < 128)
691 mk->io_handler.conf.flap_reversal =
test_bits(value, 1 << 1);
692 mk->mode6_handler.conf.bank_angle_enabled =
test_bits(value, 1 << 2);
693 mk->io_handler.conf.steep_approach_enabled =
test_bits(value, 1 << 6);
701MK_VIII::ConfigurationModule::read_radio_altitude_input_select (
int value)
703 mk->io_handler.conf.altitude_source = value;
704 return (value >= 0 && value <= 4) || (value >= 251 && value <= 255);
708MK_VIII::ConfigurationModule::read_navigation_input_select (
int value)
710 if (value >= 0 && value <= 2)
711 mk->io_handler.conf.localizer_enabled =
false;
712 else if ((value >= 3 && value <= 5) || (value >= 250 && value <= 255))
713 mk->io_handler.conf.localizer_enabled =
true;
721MK_VIII::ConfigurationModule::read_attitude_input_select (
int value)
724 mk->io_handler.conf.use_attitude_indicator=
true;
726 mk->io_handler.conf.use_attitude_indicator=
false;
727 return (value >= 0 && value <= 6) || value == 253 || value == 255;
731MK_VIII::ConfigurationModule::read_heading_input_select (
int value)
734 return (value >= 0 && value <= 3) || value == 254 || value == 255;
738MK_VIII::ConfigurationModule::read_windshear_input_select (
int value)
741 return value == 0 || (value >= 253 && value <= 255);
745MK_VIII::ConfigurationModule::read_input_output_discrete_type_select (
int value)
751 bool gpws_inhibit_enabled;
752 bool momentary_flap_override_enabled;
753 bool alternate_steep_approach;
755 { 0, {
false,
false },
false,
true,
true },
756 { 1, {
true,
false },
false,
true,
true },
757 { 2, {
false,
false },
true,
true,
true },
758 { 3, {
true,
false },
true,
true,
true },
759 { 4, {
false,
true },
true,
true,
true },
760 { 5, {
true,
true },
true,
true,
true },
761 { 6, {
false,
false },
true,
true,
false },
762 { 7, {
true,
false },
true,
true,
false },
763 { 254, {
false,
false },
true,
false,
true },
764 { 255, {
false,
false },
true,
false,
true }
769 if (io_types[
i].type == value)
771 mk->io_handler.conf.lamp = &io_types[
i].lamp_conf;
772 mk->io_handler.conf.gpws_inhibit_enabled = io_types[
i].gpws_inhibit_enabled;
773 mk->io_handler.conf.momentary_flap_override_enabled = io_types[
i].momentary_flap_override_enabled;
774 mk->io_handler.conf.alternate_steep_approach = io_types[
i].alternate_steep_approach;
783MK_VIII::ConfigurationModule::read_audio_output_level (
int value)
799 if (values[
i].
id == value)
801 mk->voice_player.set_volume(mk->voice_player.conf.volume =
modify_amplitude(1.0, values[
i].relative_dB));
808 mk->voice_player.set_volume(mk->voice_player.conf.volume = 1.0);
813MK_VIII::ConfigurationModule::read_undefined_input_select (
int value)
820MK_VIII::ConfigurationModule::boot ()
822 bool (MK_VIII::ConfigurationModule::*readers[N_CATEGORIES]) (int) = {
823 &MK_VIII::ConfigurationModule::read_aircraft_mode_type_select,
824 &MK_VIII::ConfigurationModule::read_air_data_input_select,
825 &MK_VIII::ConfigurationModule::read_position_input_select,
826 &MK_VIII::ConfigurationModule::read_altitude_callouts,
827 &MK_VIII::ConfigurationModule::read_audio_menu_select,
828 &MK_VIII::ConfigurationModule::read_terrain_display_select,
829 &MK_VIII::ConfigurationModule::read_options_select_group_1,
830 &MK_VIII::ConfigurationModule::read_radio_altitude_input_select,
831 &MK_VIII::ConfigurationModule::read_navigation_input_select,
832 &MK_VIII::ConfigurationModule::read_attitude_input_select,
833 &MK_VIII::ConfigurationModule::read_heading_input_select,
834 &MK_VIII::ConfigurationModule::read_windshear_input_select,
835 &MK_VIII::ConfigurationModule::read_input_output_discrete_type_select,
836 &MK_VIII::ConfigurationModule::read_audio_output_level,
837 &MK_VIII::ConfigurationModule::read_undefined_input_select,
838 &MK_VIII::ConfigurationModule::read_undefined_input_select,
839 &MK_VIII::ConfigurationModule::read_undefined_input_select
842 memcpy(effective_categories, categories,
sizeof(categories));
845 for (
int i = 0;
i < N_CATEGORIES;
i++)
847 if (! (this->*readers[
i])(effective_categories[
i]))
849 SG_LOG(SG_INSTR, SG_ALERT,
"MK VIII EGPWS configuration category " <<
i + 1 <<
": invalid value " << effective_categories[
i]);
851 if (state == STATE_OK)
852 state = STATE_INVALID_DATABASE;
863 if (mk->mode6_handler.conf.above_field_voice && ! mk->tcf_handler.conf.enabled)
866 SG_LOG(SG_INSTR, SG_ALERT,
"MK VIII EGPWS configuration module: when category 4 is set to 100 or 101, category 6 must not be set to 2");
867 state = STATE_INVALID_DATABASE;
872MK_VIII::ConfigurationModule::bind (SGPropertyNode *node)
874 for (
int i = 0;
i < N_CATEGORIES;
i++)
876 std::ostringstream name;
877 name <<
"configuration-module/category-" <<
i + 1;
878 mk->properties_handler.tie(node, name.str().c_str(), SGRawValuePointer<int>(&categories[
i]));
888const unsigned int MK_VIII::FaultHandler::fault_inops[] = {
889 INOP_GPWS | INOP_TAD,
893 INOP_GPWS | INOP_TAD,
909MK_VIII::FaultHandler::has_faults ()
const
915MK_VIII::FaultHandler::has_faults (
unsigned int inop)
920 for (
int i = 0;
i < N_FAULTS;
i++)
922 if ((faults & (1<<
i)) &&
test_bits(fault_inops[
i], inop))
930MK_VIII::FaultHandler::boot ()
936MK_VIII::FaultHandler::set_fault (Fault fault)
938 if (! (faults & (1<<fault)))
942 mk->self_test_handler.set_inop();
944 if (
test_bits(fault_inops[fault], INOP_GPWS))
949 if (
test_bits(fault_inops[fault], INOP_TAD))
958MK_VIII::FaultHandler::unset_fault (Fault fault)
960 if (faults & (1<<fault))
962 faults &= ~(1<<fault);
963 if (! has_faults(INOP_GPWS))
965 if (! has_faults(INOP_TAD))
975MK_VIII::IOHandler::TerrainClearanceFilter::update (
double agl)
985 samples_type::iterator iter;
988 for (iter = samples.begin(); iter != samples.end() &&
globals->
get_sim_time_sec() - (*iter).timestamp >= 15; iter = samples.begin())
992 samples.push_back(Sample<double>(agl));
995 double new_value = 0;
996 if (! samples.empty())
1000 for (iter = samples.begin(); iter != samples.end(); iter++)
1001 new_value += (*iter).value;
1002 new_value /= samples.size();
1006 if (new_value > value)
1013MK_VIII::IOHandler::TerrainClearanceFilter::reset ()
1021 :
mk(device), _lamp(
LAMP_NONE), last_landing_gear(false), last_real_flaps_down(false)
1024 memset(&
inputs.discretes, 0,
sizeof(
inputs.discretes));
1026 memset(&power_saved, 0,
sizeof(power_saved));
1049 if (
mk->configuration_module.state != ConfigurationModule::STATE_OK)
1057 altitude_samples.clear();
1058 reset_terrain_clearance();
1066 last_landing_gear =
mk_dinput(landing_gear);
1082 audio_inhibit_fault_timer.stop();
1083 landing_gear_fault_timer.stop();
1084 flaps_down_fault_timer.stop();
1085 momentary_flap_override_fault_timer.stop();
1086 self_test_fault_timer.stop();
1087 glideslope_cancel_fault_timer.stop();
1088 steep_approach_fault_timer.stop();
1089 gpws_inhibit_fault_timer.stop();
1090 ta_tcf_inhibit_fault_timer.stop();
1100 reset_terrain_clearance();
1102 if (
conf.momentary_flap_override_enabled)
1109 reset_terrain_clearance();
1119 if (
mk->configuration_module.state != ConfigurationModule::STATE_OK)
1129 mk_dinput(glideslope_inhibit) =
mk_node(nav0_gs_distance)->getDoubleValue() < 0;
1132 const auto mode =
mk_node(autopilot_heading_lock)->getStringValue();
1133 mk_dinput(autopilot_engaged) = !mode.empty();
1138 if (
mk_node(altimeter_serviceable)->getBoolValue())
1139 mk_ainput(uncorrected_barometric_altitude).set(
mk_node(altimeter_altitude)->getDoubleValue());
1141 mk_ainput(uncorrected_barometric_altitude).unset();
1149 mk_ainput(barometric_altitude_rate).set(
mk_node(vs)->getDoubleValue() * 60);
1153 switch (
conf.altitude_source)
1156 agl =
mk_node(altitude_gear_agl)->getDoubleValue();
1159 agl =
mk_node(altitude_radar_agl)->getDoubleValue();
1162 agl =
mk_node(altitude_agl)->getDoubleValue();
1167 mk_ainput(radio_altitude).set(SG_MAX2(0.0, agl));
1171 if (
mk_node(nav0_serviceable)->getBoolValue()
1172 &&
mk_node(nav0_gs_serviceable)->getBoolValue()
1173 &&
mk_node(nav0_in_range)->getBoolValue()
1174 &&
mk_node(nav0_has_gs)->getBoolValue())
1180 mk_ainput(glideslope_deviation).unset();
1184 if (
conf.use_attitude_indicator)
1187 if (
mk_node(ai_serviceable)->getBoolValue() && !
mk_node(ai_caged)->getBoolValue())
1200 if (
mk_node(nav0_serviceable)->getBoolValue()
1201 &&
mk_node(nav0_cdi_serviceable)->getBoolValue()
1202 &&
mk_node(nav0_in_range)->getBoolValue()
1203 &&
mk_node(nav0_nav_loc)->getBoolValue())
1213 if (
mk_node(asi_serviceable)->getBoolValue())
1231 if (!
mk_ainput(barometric_altitude_rate).ncd)
1233 mk_data(barometric_altitude_rate).set(
mk_ainput(barometric_altitude_rate).get());
1245 if (!
mk_ainput(uncorrected_barometric_altitude).ncd)
1247 if (! altitude_samples.empty() && ! altitude_samples.front().value.ncd)
1249 double elapsed =
globals->get_sim_time_sec() - altitude_samples.front().timestamp;
1253 mk_data(barometric_altitude_rate).set((
mk_ainput(uncorrected_barometric_altitude).get() - altitude_samples.front().value.get()) / elapsed * 60);
1259 mk_data(barometric_altitude_rate).unset();
1262 altitude_samples.push_back(Sample< Parameter<double> >(
mk_ainput(uncorrected_barometric_altitude)));
1267 altitude_samples_type::iterator erase_last = altitude_samples.begin();
1268 altitude_samples_type::iterator iter;
1270 for (iter = altitude_samples.begin(); iter != altitude_samples.end(); iter++)
1272 if (
globals->get_sim_time_sec() - (*iter).timestamp >= 1)
1278 if (erase_last != altitude_samples.begin())
1279 altitude_samples.erase(altitude_samples.begin(), erase_last);
1283 if (
conf.use_internal_gps)
1288 mk_data(gps_vertical_figure_of_merit).set(0.0);
1295 mk_data(gps_vertical_figure_of_merit).set(&
mk_ainput(gps_vertical_figure_of_merit));
1306 if (!
mk_data(gps_altitude).ncd)
1308 else if (!
mk_ainput(uncorrected_barometric_altitude).ncd)
1309 mk_data(geometric_altitude).set(
mk_ainput(uncorrected_barometric_altitude).get());
1311 mk_data(geometric_altitude).unset();
1314 update_terrain_clearance();
1317 if (!
mk_data(radio_altitude).ncd &&
mk_data(radio_altitude).get() < 0)
1318 mk_data(radio_altitude).unset();
1320 if (!
mk_data(decision_height).ncd &&
mk_data(decision_height).get() < 0)
1321 mk_data(decision_height).unset();
1323 if (!
mk_data(gps_latitude).ncd
1324 && (
mk_data(gps_latitude).get() < -90
1325 ||
mk_data(gps_latitude).get() > 90))
1326 mk_data(gps_latitude).unset();
1328 if (!
mk_data(gps_longitude).ncd
1329 && (
mk_data(gps_longitude).get() < -180
1330 ||
mk_data(gps_longitude).get() > 180))
1331 mk_data(gps_longitude).unset();
1334 && ((
mk_data(roll_angle).get() < -180)
1335 || (
mk_data(roll_angle).get() > 180)))
1342 && !
mk_data(decision_height).ncd
1343 &&
mk_data(radio_altitude).get() <=
mk_data(decision_height).get()+100;
1346 && !
mk_data(decision_height).ncd
1347 &&
mk_data(radio_altitude).get() <=
mk_data(decision_height).get();
1352MK_VIII::IOHandler::update_terrain_clearance ()
1354 if (!
mk_data(radio_altitude).ncd)
1355 mk_data(terrain_clearance).set(terrain_clearance_filter.update(
mk_data(radio_altitude).get()));
1357 mk_data(terrain_clearance).unset();
1361MK_VIII::IOHandler::reset_terrain_clearance ()
1363 terrain_clearance_filter.reset();
1364 update_terrain_clearance();
1370 reset_terrain_clearance();
1374MK_VIII::IOHandler::handle_input_fault (
bool test, FaultHandler::Fault fault)
1378 mk->fault_handler.set_fault(fault);
1381 mk->fault_handler.unset_fault(fault);
1385MK_VIII::IOHandler::handle_input_fault (
bool test,
1387 double max_duration,
1388 FaultHandler::Fault fault)
1392 if (! (mk->fault_handler.faults & (1<<fault)))
1394 if (timer->start_or_elapsed() >= max_duration)
1395 mk->fault_handler.set_fault(fault);
1400 mk->fault_handler.unset_fault(fault);
1408 if (
mk->configuration_module.state != ConfigurationModule::STATE_OK)
1412 handle_input_fault(
mk_dinput(audio_inhibit),
1413 &audio_inhibit_fault_timer,
1415 FaultHandler::FAULT_ALL_MODES_INHIBIT);
1418 handle_input_fault(
mk_dinput(landing_gear)
1420 &&
mk_ainput(computed_airspeed).get() >
conf.faults->max_gear_down_airspeed,
1421 &landing_gear_fault_timer,
1423 FaultHandler::FAULT_GEAR_SWITCH);
1428 &&
mk_ainput(computed_airspeed).get() >
conf.faults->max_flaps_down_airspeed,
1429 &flaps_down_fault_timer,
1431 FaultHandler::FAULT_FLAPS_SWITCH);
1434 if (
conf.momentary_flap_override_enabled)
1435 handle_input_fault(
mk_dinput(momentary_flap_override),
1436 &momentary_flap_override_fault_timer,
1438 FaultHandler::FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID);
1441 handle_input_fault(
mk_dinput(self_test),
1442 &self_test_fault_timer,
1444 FaultHandler::FAULT_SELF_TEST_INVALID);
1448 &glideslope_cancel_fault_timer,
1450 FaultHandler::FAULT_GLIDESLOPE_CANCEL_INVALID);
1455 &steep_approach_fault_timer,
1457 FaultHandler::FAULT_STEEP_APPROACH_INVALID);
1460 if (
conf.gpws_inhibit_enabled)
1462 &gpws_inhibit_fault_timer,
1464 FaultHandler::FAULT_GPWS_INHIBIT);
1468 handle_input_fault(
mk_dinput(ta_tcf_inhibit),
1469 &ta_tcf_inhibit_fault_timer,
1471 FaultHandler::FAULT_TA_TCF_INHIBIT);
1477 handle_input_fault(
mk_data(radio_altitude).ncd
1478 ||
mk_ainput(uncorrected_barometric_altitude).ncd
1479 ||
mk_data(barometric_altitude_rate).ncd
1481 ||
mk_data(terrain_clearance).ncd,
1482 FaultHandler::FAULT_MODES14_INPUTS_INVALID);
1485 handle_input_fault(
mk_data(radio_altitude).ncd,
1486 FaultHandler::FAULT_MODE5_INPUTS_INVALID);
1488 if (
mk->mode6_handler.altitude_callouts_enabled())
1489 handle_input_fault(
mk->mode6_handler.conf.above_field_voice
1492 ||
mk_data(geometric_altitude).ncd)
1493 :
mk_data(radio_altitude).ncd,
1494 FaultHandler::FAULT_MODE6_INPUTS_INVALID);
1496 if (
mk->mode6_handler.conf.bank_angle_enabled)
1497 handle_input_fault(
mk_data(roll_angle).ncd,
1498 FaultHandler::FAULT_BANK_ANGLE_INPUTS_INVALID);
1500 if (
mk->tcf_handler.conf.enabled)
1501 handle_input_fault(
mk_data(radio_altitude).ncd
1502 ||
mk_data(geometric_altitude).ncd
1505 ||
mk_data(gps_vertical_figure_of_merit).ncd,
1506 FaultHandler::FAULT_TCF_INPUTS_INVALID);
1512 assert(
mk->system_handler.state == SystemHandler::STATE_ON);
1514 if (ptr == &
mk_dinput(mode6_low_volume))
1516 if (
mk->configuration_module.state == ConfigurationModule::STATE_OK
1517 &&
mk->self_test_handler.state == SelfTestHandler::STATE_NONE)
1520 else if (ptr == &
mk_dinput(audio_inhibit))
1522 if (
mk->configuration_module.state == ConfigurationModule::STATE_OK
1523 &&
mk->self_test_handler.state == SelfTestHandler::STATE_NONE)
1524 mk->voice_player.set_volume(*ptr ? 0.0 :
mk->voice_player.conf.volume);
1531 if (
mk->configuration_module.state != ConfigurationModule::STATE_OK)
1535 if (
conf.momentary_flap_override_enabled
1537 && !
mk->state_handler.takeoff
1538 && (
mk_data(radio_altitude).ncd ||
mk_data(radio_altitude).get() <= 50))
1545 && !
mk->state_handler.takeoff
1546 && ((last_landing_gear && !
mk_dinput(landing_gear))
1553 last_landing_gear =
mk_dinput(landing_gear);
1559 && (
mk_data(glideslope_deviation_dots).ncd
1560 ||
mk_data(radio_altitude).ncd
1561 ||
mk_data(radio_altitude).get() > 2000
1562 ||
mk_data(radio_altitude).get() < 30))
1569 if (
mk->voice_player.voice)
1576 { 11,
mk_voice(sink_rate_pause_sink_rate) },
1579 { 13,
mk_voice(terrain_pause_terrain) },
1580 { 14,
mk_voice(dont_sink_pause_dont_sink) },
1586 { 19,
mk_voice(minimums_minimums) }
1591 if (voices[
i].voice ==
mk->voice_player.voice)
1593 mk_aoutput(egpws_alert_discrete_1) = 1 << voices[
i].bit;
1607 if (
mk->state_handler.takeoff)
1608 mk_aoutput(egpwc_logic_discretes) |= 1 << 18;
1613 unsigned int alerts;
1615 { 13,
mk_alert(TCF_TOO_LOW_TERRAIN) },
1628 mk_aoutput(egpwc_logic_discretes) |= 1 << logic[
i].bit;
1635 if (
mk->voice_player.voice)
1642 { 11,
mk_voice(minimums_minimums) },
1655 if (voices[
i].voice ==
mk->voice_player.voice)
1657 mk_aoutput(mode6_callouts_discrete_1) = 1 << voices[
i].bit;
1668 if (
mk->voice_player.voice)
1679 { 18,
mk_voice(bank_angle_pause_bank_angle) },
1680 { 18,
mk_voice(bank_angle_pause_bank_angle_3) },
1681 { 23,
mk_voice(five_hundred_above) }
1686 if (voices[
i].voice ==
mk->voice_player.voice)
1688 mk_aoutput(mode6_callouts_discrete_2) = 1 << voices[
i].bit;
1700 mk_aoutput(egpws_alert_discrete_2) = 1 << 27;
1703 mk_aoutput(egpws_alert_discrete_2) |= 1 << 11;
1705 mk_aoutput(egpws_alert_discrete_2) |= 1 << 12;
1707 mk_aoutput(egpws_alert_discrete_2) |= 1 << 13;
1709 mk_aoutput(egpws_alert_discrete_2) |= 1 << 14;
1711 mk_aoutput(egpws_alert_discrete_2) |= 1 << 16;
1713 mk_aoutput(egpws_alert_discrete_2) |= 1 << 24;
1714 if (
mk->fault_handler.has_faults())
1715 mk_aoutput(egpws_alert_discrete_2) |= 1 << 25;
1721 mk_aoutput(egpwc_alert_discrete_3) = 1 << 17 | 1 << 18;
1723 if (
mk->fault_handler.faults & (1<<FaultHandler::FAULT_MODES14_INPUTS_INVALID))
1724 mk_aoutput(egpwc_alert_discrete_3) |= 1 << 11;
1725 if (
mk->fault_handler.faults & (1<<FaultHandler::FAULT_MODE5_INPUTS_INVALID))
1726 mk_aoutput(egpwc_alert_discrete_3) |= 1 << 12;
1727 if (
mk->fault_handler.faults & (1<<FaultHandler::FAULT_MODE6_INPUTS_INVALID))
1728 mk_aoutput(egpwc_alert_discrete_3) |= 1 << 13;
1729 if (
mk->fault_handler.faults & (1<<FaultHandler::FAULT_BANK_ANGLE_INPUTS_INVALID))
1730 mk_aoutput(egpwc_alert_discrete_3) |= 1 << 14;
1732 mk_aoutput(egpwc_alert_discrete_3) |= 1 << 16;
1738 if (
mk->configuration_module.state != ConfigurationModule::STATE_OK)
1742 &&
mk->voice_player.voice
1743 && !
mk->voice_player.voice->element->silence;
1776 if (
mk->configuration_module.state != ConfigurationModule::STATE_OK)
1782 if (lamp_timer.elapsed() >= 60.0 / 70.0 / 2.0)
1785 *output = ! *output;
1836 if (
conf.steep_approach_enabled)
1849 return conf.steep_approach_enabled && !
conf.alternate_steep_approach;
1853MK_VIII::IOHandler::tie_input (SGPropertyNode *node,
1858 mk->properties_handler.tie(node, (
string(
"inputs/discretes/") + name).c_str(),
1861 mk->properties_handler.tie(node, (
string(
"input-feeders/discretes/") + name).c_str(), SGRawValuePointer<bool>(feed));
1865MK_VIII::IOHandler::tie_input (SGPropertyNode *node,
1867 Parameter<double> *input,
1870 mk->properties_handler.tie(node, (
string(
"inputs/arinc429/") +
name).c_str(), SGRawValuePointer<double>(input->get_pointer()));
1871 mk->properties_handler.tie(node, (
string(
"inputs/arinc429/") +
name +
"-ncd").c_str(), SGRawValuePointer<bool>(&input->ncd));
1873 mk->properties_handler.tie(node, (
string(
"input-feeders/arinc429/") +
name).c_str(), SGRawValuePointer<bool>(feed));
1877MK_VIII::IOHandler::tie_output (SGPropertyNode *node,
1881 SGPropertyNode *child = node->getNode((
string(
"outputs/discretes/") + name),
true);
1883 mk->properties_handler.tie(child, SGRawValuePointer<bool>(output));
1884 child->setAttribute(SGPropertyNode::WRITE,
false);
1888MK_VIII::IOHandler::tie_output (SGPropertyNode *node,
1892 SGPropertyNode *child = node->getNode((
string(
"outputs/arinc429/") + name),
true);
1894 mk->properties_handler.tie(child, SGRawValuePointer<int>(output));
1895 child->setAttribute(SGPropertyNode::WRITE,
false);
1905 tie_input(node,
"momentary-flap-override", &
mk_dinput(momentary_flap_override));
1906 tie_input(node,
"self-test", &
mk_dinput(self_test));
1910 tie_input(node,
"mode6-low-volume", &
mk_dinput(mode6_low_volume));
1911 tie_input(node,
"audio-inhibit", &
mk_dinput(audio_inhibit));
1912 tie_input(node,
"ta-tcf-inhibit", &
mk_dinput(ta_tcf_inhibit));
1917 tie_input(node,
"uncorrected-barometric-altitude", &
mk_ainput(uncorrected_barometric_altitude), &
mk_ainput_feed(uncorrected_barometric_altitude));
1918 tie_input(node,
"barometric-altitude-rate", &
mk_ainput(barometric_altitude_rate), &
mk_ainput_feed(barometric_altitude_rate));
1919 tie_input(node,
"gps-altitude", &
mk_ainput(gps_altitude));
1920 tie_input(node,
"gps-latitude", &
mk_ainput(gps_latitude));
1921 tie_input(node,
"gps-longitude", &
mk_ainput(gps_longitude));
1922 tie_input(node,
"gps-vertical-figure-of-merit", &
mk_ainput(gps_vertical_figure_of_merit));
1924 tie_input(node,
"glideslope-deviation", &
mk_ainput(glideslope_deviation), &
mk_ainput_feed(glideslope_deviation));
1926 tie_input(node,
"localizer-deviation", &
mk_ainput(localizer_deviation), &
mk_ainput_feed(localizer_deviation));
1930 tie_output(node,
"gpws-warning", &
mk_doutput(gpws_warning));
1931 tie_output(node,
"gpws-alert", &
mk_doutput(gpws_alert));
1932 tie_output(node,
"audio-on", &
mk_doutput(audio_on));
1933 tie_output(node,
"gpws-inop", &
mk_doutput(gpws_inop));
1934 tie_output(node,
"tad-inop", &
mk_doutput(tad_inop));
1939 tie_output(node,
"egpws-alert-discrete-1", &
mk_aoutput(egpws_alert_discrete_1));
1940 tie_output(node,
"egpwc-logic-discretes", &
mk_aoutput(egpwc_logic_discretes));
1941 tie_output(node,
"mode6-callouts-discrete-1", &
mk_aoutput(mode6_callouts_discrete_1));
1942 tie_output(node,
"mode6-callouts-discrete-2", &
mk_aoutput(mode6_callouts_discrete_2));
1943 tie_output(node,
"egpws-alert-discrete-2", &
mk_aoutput(egpws_alert_discrete_2));
1944 tie_output(node,
"egpwc-alert-discrete-3", &
mk_aoutput(egpwc_alert_discrete_3));
1959 if (
mk->system_handler.state == SystemHandler::STATE_ON)
1961 if (ptr == &
mk_dinput(momentary_flap_override))
1963 if (
mk->configuration_module.state == ConfigurationModule::STATE_OK
1964 &&
mk->self_test_handler.state == SelfTestHandler::STATE_NONE
1965 &&
conf.momentary_flap_override_enabled
1970 mk->self_test_handler.handle_button_event(value);
1973 if (
mk->configuration_module.state == ConfigurationModule::STATE_OK
1974 &&
mk->self_test_handler.state == SelfTestHandler::STATE_NONE
1985 if (!
mk_data(glideslope_deviation_dots).ncd
1986 && !
mk_data(radio_altitude).ncd
1987 &&
mk_data(radio_altitude).get() <= 2000
1988 &&
mk_data(radio_altitude).get() >= 30)
1998 if (
mk->configuration_module.state == ConfigurationModule::STATE_OK
1999 &&
mk->self_test_handler.state == SelfTestHandler::STATE_NONE
2008 if (
mk->system_handler.state == SystemHandler::STATE_ON)
2015 printf(
"%s\n", name);
2022 printf(
"\t%-32s %s\n", name, value);
2024 printf(
"\t%s\n", name);
2030 printf(
"\t\t%s\n", name);
2038 if (
mk->system_handler.state != SystemHandler::STATE_ON)
2053 if (
mk->configuration_module.state == ConfigurationModule::STATE_OK && !
mk->fault_handler.has_faults())
2057 if (
mk->configuration_module.state != ConfigurationModule::STATE_OK)
2060 switch (
mk->configuration_module.state)
2062 case ConfigurationModule::STATE_INVALID_DATABASE:
2066 case ConfigurationModule::STATE_INVALID_AIRCRAFT_TYPE:
2080 static const char *fault_names[] = {
2081 "ALL MODES INHIBIT",
2084 "MOMENTARY FLAP OVERRIDE INVALID",
2085 "SELF TEST INVALID",
2086 "GLIDESLOPE CANCEL INVALID",
2087 "STEEP APPROACH INVALID",
2090 "MODES 1-4 INPUTS INVALID",
2091 "MODE 5 INPUTS INVALID",
2092 "MODE 6 INPUTS INVALID",
2093 "BANK ANGLE INPUTS INVALID",
2094 "TCF INPUTS INVALID"
2099 if (
mk->fault_handler.faults & (1<<
i))
2108 static const char *category_names[] = {
2111 "POSITION INPUT TYPE",
2112 "CALLOUTS OPTION TYPE",
2114 "TERRAIN DISPLAY TYPE",
2116 "RADIO ALTITUDE TYPE",
2117 "NAVIGATION INPUT TYPE",
2119 "MAGNETIC HEADING TYPE",
2120 "WINDSHEAR INPUT TYPE",
2127 std::ostringstream value;
2128 value <<
"= " <<
mk->configuration_module.effective_categories[
i];
2156#define STDPAUSE 0.75
2157 make_voice(&
voices.application_data_base_failed,
"application-data-base-failed");
2160 make_voice(&
voices.bank_angle_bank_angle_3,
"bank-angle",
"bank-angle", 3.0);
2165 make_voice(&
voices.configuration_type_invalid,
"configuration-type-invalid");
2187 for (
unsigned i = 0;
i < n_altitude_callouts;
i++)
2189 std::ostringstream name;
2190 name <<
"altitude-" << MK_VIII::Mode6Handler::altitude_callout_definitions[
i];
2193 speaker.update_configuration();
2201MK_VIII::SelfTestHandler::_was_here (
int position)
2203 if (position > current)
2212MK_VIII::SelfTestHandler::Action
2213MK_VIII::SelfTestHandler::sleep (
double duration)
2215 Action _action = { ACTION_SLEEP, duration, NULL };
2219MK_VIII::SelfTestHandler::Action
2222 mk->voice_player.play(voice);
2223 Action _action = { ACTION_VOICE, 0, NULL };
2227MK_VIII::SelfTestHandler::Action
2228MK_VIII::SelfTestHandler::discrete_on (
bool *discrete,
double duration)
2231 return sleep(duration);
2234MK_VIII::SelfTestHandler::Action
2235MK_VIII::SelfTestHandler::discrete_on_off (
bool *discrete,
double duration)
2238 Action _action = { ACTION_SLEEP | ACTION_DISCRETE_ON_OFF, duration,
discrete };
2242MK_VIII::SelfTestHandler::Action
2246 mk->voice_player.play(voice);
2247 Action _action = { ACTION_VOICE | ACTION_DISCRETE_ON_OFF, 0,
discrete };
2251MK_VIII::SelfTestHandler::Action
2252MK_VIII::SelfTestHandler::done ()
2254 Action _action = { ACTION_DONE, 0, NULL };
2258MK_VIII::SelfTestHandler::Action
2259MK_VIII::SelfTestHandler::run ()
2264#define was_here() was_here_offset(0)
2265#define was_here_offset(offset) _was_here(__LINE__ * 20 + (offset))
2269 if (mk->configuration_module.state == ConfigurationModule::STATE_INVALID_DATABASE)
2270 return play(
mk_voice(application_data_base_failed));
2271 else if (mk->configuration_module.state == ConfigurationModule::STATE_INVALID_AIRCRAFT_TYPE)
2272 return play(
mk_voice(configuration_type_invalid));
2274 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
2278 return discrete_on(&
mk_doutput(gpws_inop), 0.7);
2282 return discrete_on(&
mk_doutput(tad_inop), 0.7);
2293 if (mk->io_handler.conf.momentary_flap_override_enabled)
2294 return discrete_on_off(&
mk_doutput(flap_override), 1.0);
2297 return discrete_on_off(&
mk_doutput(audio_on), 1.0);
2300 if (mk->io_handler.momentary_steep_approach_enabled())
2301 return discrete_on_off(&
mk_doutput(steep_approach), 1.0);
2307 goto glideslope_end;
2310 if (mk->fault_handler.faults & (1<<FaultHandler::FAULT_MODE5_INPUTS_INVALID))
2311 goto glideslope_inop;
2317 return discrete_on_off(&
mk_doutput(glideslope_cancel), 0.7);
2318 goto glideslope_end;
2322 return play(
mk_voice(glideslope_inop));
2327 if (mk->fault_handler.faults & (1<<FaultHandler::FAULT_MODES14_INPUTS_INVALID))
2346 if (mk->mode6_handler.conf.bank_angle_enabled
2347 && (mk->fault_handler.faults & (1<<FaultHandler::FAULT_BANK_ANGLE_INPUTS_INVALID)))
2348 return play(
mk_voice(bank_angle_inop));
2352 if (mk->mode6_handler.altitude_callouts_enabled()
2353 && (mk->fault_handler.faults & (1<<FaultHandler::FAULT_MODE6_INPUTS_INVALID)))
2354 return play(
mk_voice(callouts_inop));
2377 return play(
mk_voice(too_low_terrain));
2379 return play(mk->mode4_handler.conf.voice_too_low_gear);
2381 return play(
mk_voice(too_low_flaps));
2383 return play(
mk_voice(too_low_terrain));
2388 if (mk->mode6_handler.conf.bank_angle_enabled)
2394 if (! mk->mode6_handler.altitude_callouts_enabled())
2395 goto callouts_disabled;
2399 if (mk->mode6_handler.conf.minimums_above_100_enabled)
2400 return play(
mk_voice(minimums_100));
2404 if (mk->mode6_handler.conf.minimums_enabled)
2409 if (mk->mode6_handler.conf.above_field_voice)
2410 return play(mk->mode6_handler.conf.above_field_voice);
2412 for (
unsigned i = 0;
i < n_altitude_callouts;
i++)
2416 if (mk->mode6_handler.conf.altitude_callouts_enabled & (1<<
i))
2423 if (mk->mode6_handler.conf.smart_500_enabled)
2430 return play(
mk_voice(minimums_minimums));
2435 if (mk->tcf_handler.conf.enabled)
2436 return play(
mk_voice(too_low_terrain));
2443MK_VIII::SelfTestHandler::start ()
2445 assert(state == STATE_START);
2447 memcpy(&saved_outputs, &mk->io_handler.outputs,
sizeof(mk->io_handler.outputs));
2448 memset(&mk->io_handler.outputs, 0,
sizeof(mk->io_handler.outputs));
2452 mk->voice_player.set_volume(
modify_amplitude(mk->voice_player.conf.volume, -6));
2455 mk->mode6_handler.set_volume(1.0);
2457 state = STATE_RUNNING;
2458 cancel = CANCEL_NONE;
2459 memset(&action, 0,
sizeof(action));
2464MK_VIII::SelfTestHandler::stop ()
2466 if (state != STATE_NONE)
2468 if (state != STATE_START)
2471 mk->voice_player.set_volume(
mk_dinput(audio_inhibit) ? 0.0 : mk->voice_player.conf.volume);
2476 memcpy(&mk->io_handler.outputs, &saved_outputs,
sizeof(mk->io_handler.outputs));
2479 button_pressed =
false;
2487MK_VIII::SelfTestHandler::handle_button_event (
bool value)
2489 if (state == STATE_NONE)
2492 state = STATE_START;
2494 else if (state == STATE_START)
2499 else if (cancel == CANCEL_NONE)
2503 assert(! button_pressed);
2504 button_pressed =
true;
2512 cancel = CANCEL_SHORT;
2514 cancel = CANCEL_LONG;
2521MK_VIII::SelfTestHandler::update ()
2523 if (state == STATE_NONE)
2525 else if (state == STATE_START)
2527 if (mk->state_handler.ground && ! mk->io_handler.steep_approach())
2537 if (button_pressed && cancel == CANCEL_NONE)
2540 cancel = CANCEL_LONG;
2544 if (! mk->state_handler.ground || cancel != CANCEL_NONE)
2550 if (
test_bits(action.flags, ACTION_SLEEP))
2555 if (
test_bits(action.flags, ACTION_VOICE))
2557 if (mk->voice_player.voice)
2560 if (
test_bits(action.flags, ACTION_DISCRETE_ON_OFF))
2561 *action.discrete =
false;
2565 if (
test_bits(action.flags, ACTION_SLEEP))
2567 if (
test_bits(action.flags, ACTION_DONE))
2581MK_VIII::AlertHandler::select_voice_alerts (
unsigned int test)
2583 if (has_alerts(test))
2585 voice_alerts = alerts & test;
2590 voice_alerts &= ~test;
2591 if (voice_alerts == 0)
2592 mk->voice_player.stop();
2599MK_VIII::AlertHandler::boot ()
2605MK_VIII::AlertHandler::reposition ()
2614MK_VIII::AlertHandler::reset ()
2619 repeated_alerts = 0;
2620 altitude_callout_voice = NULL;
2624MK_VIII::AlertHandler::update ()
2626 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
2640 if (has_alerts(ALERT_MODE1_PULL_UP | ALERT_MODE2A | ALERT_MODE2B))
2642 else if (has_alerts(ALERT_MODE1_SINK_RATE
2643 | ALERT_MODE2A_PREFACE
2644 | ALERT_MODE2B_PREFACE
2645 | ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING
2646 | ALERT_MODE2A_ALTITUDE_GAIN
2647 | ALERT_MODE2B_LANDING_MODE
2649 | ALERT_MODE4_TOO_LOW_FLAPS
2650 | ALERT_MODE4_TOO_LOW_GEAR
2651 | ALERT_MODE4AB_TOO_LOW_TERRAIN
2652 | ALERT_MODE4C_TOO_LOW_TERRAIN
2653 | ALERT_TCF_TOO_LOW_TERRAIN))
2655 else if (has_alerts(ALERT_MODE5_SOFT | ALERT_MODE5_HARD))
2662 if (select_voice_alerts(ALERT_MODE1_PULL_UP))
2664 if (! has_old_alerts(ALERT_MODE1_PULL_UP))
2666 if (mk->voice_player.voice !=
mk_voice(sink_rate_pause_sink_rate))
2671 else if (select_voice_alerts(ALERT_MODE2A_PREFACE | ALERT_MODE2B_PREFACE))
2673 if (! has_old_alerts(ALERT_MODE2A_PREFACE | ALERT_MODE2B_PREFACE))
2676 else if (select_voice_alerts(ALERT_MODE2A | ALERT_MODE2B))
2678 if (mk->voice_player.voice !=
mk_voice(pull_up))
2681 else if (select_voice_alerts(ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING | ALERT_MODE2B_LANDING_MODE))
2683 if (mk->voice_player.voice !=
mk_voice(terrain))
2686 else if (select_voice_alerts(ALERT_MODE6_MINIMUMS))
2688 if (! has_old_alerts(ALERT_MODE6_MINIMUMS))
2689 mk->voice_player.play(
mk_voice(minimums_minimums));
2691 else if (select_voice_alerts(ALERT_MODE6_MINIMUMS_100))
2693 if (! has_old_alerts(ALERT_MODE6_MINIMUMS_100))
2694 mk->voice_player.play(
mk_voice(minimums_100));
2696 else if (select_voice_alerts(ALERT_MODE6_RETARD))
2698 if (must_play_voice(ALERT_MODE6_RETARD))
2701 else if (select_voice_alerts(ALERT_MODE4AB_TOO_LOW_TERRAIN | ALERT_MODE4C_TOO_LOW_TERRAIN))
2703 if (must_play_voice(ALERT_MODE4AB_TOO_LOW_TERRAIN | ALERT_MODE4C_TOO_LOW_TERRAIN))
2704 mk->voice_player.play(
mk_voice(too_low_terrain));
2706 else if (select_voice_alerts(ALERT_TCF_TOO_LOW_TERRAIN))
2708 if (must_play_voice(ALERT_TCF_TOO_LOW_TERRAIN))
2709 mk->voice_player.play(
mk_voice(too_low_terrain));
2711 else if (select_voice_alerts(ALERT_MODE6_ALTITUDE_CALLOUT))
2713 if (! has_old_alerts(ALERT_MODE6_ALTITUDE_CALLOUT))
2715 assert(altitude_callout_voice != NULL);
2716 mk->voice_player.play(altitude_callout_voice);
2717 altitude_callout_voice = NULL;
2720 else if (select_voice_alerts(ALERT_MODE4_TOO_LOW_GEAR))
2722 if (must_play_voice(ALERT_MODE4_TOO_LOW_GEAR))
2723 mk->voice_player.play(mk->mode4_handler.conf.voice_too_low_gear);
2725 else if (select_voice_alerts(ALERT_MODE4_TOO_LOW_FLAPS))
2727 if (must_play_voice(ALERT_MODE4_TOO_LOW_FLAPS))
2728 mk->voice_player.play(
mk_voice(too_low_flaps));
2730 else if (select_voice_alerts(ALERT_MODE1_SINK_RATE))
2732 if (must_play_voice(ALERT_MODE1_SINK_RATE))
2733 mk->voice_player.play(
mk_voice(sink_rate_pause_sink_rate));
2738 else if (mk->voice_player.voice !=
mk_voice(sink_rate_pause_sink_rate)
2739 && mk->voice_player.next_voice !=
mk_voice(sink_rate_pause_sink_rate))
2741 if (has_alerts(ALERT_MODE5_HARD))
2743 voice_alerts |= ALERT_MODE5_HARD;
2744 if (mk->voice_player.voice !=
mk_voice(hard_glideslope))
2747 else if (has_alerts(ALERT_MODE5_SOFT))
2749 voice_alerts |= ALERT_MODE5_SOFT;
2750 if (must_play_voice(ALERT_MODE5_SOFT))
2751 mk->voice_player.play(
mk_voice(soft_glideslope));
2755 else if (select_voice_alerts(ALERT_MODE3))
2757 if (must_play_voice(ALERT_MODE3))
2758 mk->voice_player.play(
mk_voice(dont_sink_pause_dont_sink));
2760 else if (select_voice_alerts(ALERT_MODE5_HARD))
2762 if (mk->voice_player.voice !=
mk_voice(hard_glideslope))
2765 else if (select_voice_alerts(ALERT_MODE5_SOFT))
2767 if (must_play_voice(ALERT_MODE5_SOFT))
2768 mk->voice_player.play(
mk_voice(soft_glideslope));
2770 else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_3))
2772 if (mk->voice_player.voice !=
mk_voice(bank_angle_bank_angle_3))
2775 else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_3))
2777 if (mk->voice_player.voice !=
mk_voice(bank_angle_pause_bank_angle_3))
2780 else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2))
2782 if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2 | ALERT_MODE6_HIGH_BANK_ANGLE_2))
2783 mk->voice_player.play(
mk_voice(bank_angle_bank_angle));
2785 else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_2))
2787 if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2 | ALERT_MODE6_HIGH_BANK_ANGLE_2))
2788 mk->voice_player.play(
mk_voice(bank_angle_pause_bank_angle));
2790 else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1))
2792 if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1 | ALERT_MODE6_HIGH_BANK_ANGLE_1))
2793 mk->voice_player.play(
mk_voice(bank_angle_bank_angle));
2795 else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_1))
2797 if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1 | ALERT_MODE6_HIGH_BANK_ANGLE_1))
2798 mk->voice_player.play(
mk_voice(bank_angle_pause_bank_angle));
2802 old_alerts |= voice_alerts;
2804 old_alerts &= alerts;
2805 repeated_alerts = 0;
2809MK_VIII::AlertHandler::set_alerts (
unsigned int _alerts,
2814 if (
test_bits(flags, ALERT_FLAG_REPEAT))
2815 repeated_alerts |= _alerts;
2816 if (_altitude_callout_voice)
2817 altitude_callout_voice = _altitude_callout_voice;
2821MK_VIII::AlertHandler::unset_alerts (
unsigned int _alerts)
2824 repeated_alerts &= ~_alerts;
2825 if (_alerts & ALERT_MODE6_ALTITUDE_CALLOUT)
2826 altitude_callout_voice = NULL;
2834MK_VIII::StateHandler::update_ground ()
2839 && !
mk_data(radio_altitude).ncd &&
mk_data(radio_altitude).get() > 30)
2841 if (potentially_airborne_timer.start_or_elapsed() > 1)
2845 potentially_airborne_timer.stop();
2850 && !
mk_data(radio_altitude).ncd &&
mk_data(radio_altitude).get() < 30)
2856MK_VIII::StateHandler::enter_ground ()
2859 mk->io_handler.enter_ground();
2869MK_VIII::StateHandler::leave_ground ()
2872 mk->mode2_handler.leave_ground();
2876MK_VIII::StateHandler::update_takeoff ()
2887 if (!
mk_data(terrain_clearance).ncd
2889 &&
mk_data(terrain_clearance).get() > mk->mode4_handler.get_upper_agl(mk->mode4_handler.conf.modes->ac))
2894 if (!
mk_data(radio_altitude).ncd
2895 &&
mk_data(radio_altitude).get() < mk->mode4_handler.conf.modes->b->min_agl1
2896 && mk->io_handler.flaps_down()
2903MK_VIII::StateHandler::enter_takeoff ()
2906 mk->io_handler.enter_takeoff();
2907 mk->mode2_handler.enter_takeoff();
2908 mk->mode3_handler.enter_takeoff();
2909 mk->mode6_handler.enter_takeoff();
2913MK_VIII::StateHandler::leave_takeoff ()
2916 mk->mode6_handler.leave_takeoff();
2920MK_VIII::StateHandler::post_reposition ()
2926 && !
mk_data(radio_altitude).ncd &&
mk_data(radio_altitude).get() > 30);
2928 bool _takeoff = _ground;
2930 if (ground && ! _ground)
2932 else if ((!ground) && _ground)
2935 if (takeoff && (!_takeoff))
2937 else if ((!takeoff) && _takeoff)
2942MK_VIII::StateHandler::update ()
2944 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
2956MK_VIII::Mode1Handler::get_pull_up_bias ()
2961 if (mk->io_handler.steep_approach())
2963 else if (conf.envelopes->flap_override_bias && mk->io_handler.flap_override())
2970MK_VIII::Mode1Handler::is_pull_up ()
2972 if (! mk->io_handler.gpws_inhibit()
2973 && ! mk->state_handler.ground
2974 && !
mk_data(radio_altitude).ncd
2975 && !
mk_data(barometric_altitude_rate).ncd
2976 &&
mk_data(radio_altitude).get() > conf.envelopes->min_agl)
2978 if (
mk_data(radio_altitude).get() < conf.envelopes->pull_up_max_agl1)
2980 if (
mk_data(radio_altitude).get() < conf.envelopes->pull_up_min_agl1(
mk_data(barometric_altitude_rate).get() + get_pull_up_bias()))
2983 else if (
mk_data(radio_altitude).get() < conf.envelopes->pull_up_max_agl2)
2985 if (
mk_data(radio_altitude).get() < conf.envelopes->pull_up_min_agl2(
mk_data(barometric_altitude_rate).get() + get_pull_up_bias()))
2994MK_VIII::Mode1Handler::update_pull_up ()
3003 if (mk->voice_player.voice ==
mk_voice(sink_rate_pause_sink_rate)
3004 || pull_up_timer.start_or_elapsed() >= 0.2)
3010 pull_up_timer.stop();
3016MK_VIII::Mode1Handler::get_sink_rate_bias ()
3021 if (mk->io_handler.steep_approach())
3023 else if (conf.envelopes->flap_override_bias && mk->io_handler.flap_override())
3025 else if (!
mk_data(glideslope_deviation_dots).ncd)
3029 if (
mk_data(glideslope_deviation_dots).get() <= -2)
3031 else if (
mk_data(glideslope_deviation_dots).get() < 0)
3032 bias = -150 *
mk_data(glideslope_deviation_dots).get();
3034 if (
mk_data(radio_altitude).get() < 100)
3035 bias *= 0.01 *
mk_data(radio_altitude).get();
3044MK_VIII::Mode1Handler::is_sink_rate ()
3046 return ! mk->io_handler.gpws_inhibit()
3047 && ! mk->state_handler.ground
3048 && !
mk_data(radio_altitude).ncd
3049 && !
mk_data(barometric_altitude_rate).ncd
3050 &&
mk_data(radio_altitude).get() > conf.envelopes->min_agl
3051 &&
mk_data(radio_altitude).get() < 2450
3052 &&
mk_data(radio_altitude).get() < -572 - 0.6035 * (
mk_data(barometric_altitude_rate).get() + get_sink_rate_bias());
3056MK_VIII::Mode1Handler::get_sink_rate_tti ()
3058 return mk_data(radio_altitude).get() / fabs(
mk_data(barometric_altitude_rate).get());
3062MK_VIII::Mode1Handler::update_sink_rate ()
3068 double tti = get_sink_rate_tti();
3069 if (tti <= sink_rate_tti * 0.8)
3072 sink_rate_tti = tti;
3078 if (sink_rate_timer.start_or_elapsed() >= 0.8)
3081 sink_rate_tti = get_sink_rate_tti();
3087 sink_rate_timer.stop();
3093MK_VIII::Mode1Handler::update ()
3095 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
3107MK_VIII::Mode2Handler::ClosureRateFilter::limit_radio_altitude_rate (
double r)
3114 if (!
mk_data(glideslope_deviation_dots).ncd && fabs(
mk_data(glideslope_deviation_dots).get()) <= 2)
3116 if (
mk_dinput(landing_gear) && mk->io_handler.flaps_down())
3117 SG_CLAMP_RANGE(r, -1000.0, 3000.0);
3118 else if (
mk_dinput(landing_gear) || mk->io_handler.flaps_down())
3119 SG_CLAMP_RANGE(r, 0.0, 4000.0);
3121 SG_CLAMP_RANGE(r, 1000.0, 5000.0);
3125 if (
mk_dinput(landing_gear) && mk->io_handler.flaps_down())
3126 SG_CLAMP_RANGE(r, 0.0, 4000.0);
3127 else if (
mk_dinput(landing_gear) || mk->io_handler.flaps_down())
3128 SG_CLAMP_RANGE(r, 1000.0, 5000.0);
3136MK_VIII::Mode2Handler::ClosureRateFilter::init ()
3139 last_ra.set(&
mk_data(radio_altitude));
3140 last_ba.set(&
mk_ainput(uncorrected_barometric_altitude));
3147MK_VIII::Mode2Handler::ClosureRateFilter::update ()
3149 double elapsed = timer.start_or_elapsed();
3153 if (!
mk_data(radio_altitude).ncd && !
mk_ainput(uncorrected_barometric_altitude).ncd)
3155 if (! last_ra.ncd && ! last_ba.ncd)
3158 double ra_rate = -(
mk_data(radio_altitude).get() - last_ra.get()) / elapsed * 60;
3159 double ba_rate = -(
mk_ainput(uncorrected_barometric_altitude).get() - last_ba.get()) / elapsed * 60;
3162 ra_rate = limit_radio_altitude_rate(ra_rate);
3165 ra_rate = ra_filter.filter(ra_rate);
3167 ba_rate = ba_filter.filter(ba_rate);
3170 output.set(ra_rate + ba_rate);
3183 last_ra.set(&
mk_data(radio_altitude));
3184 last_ba.set(&
mk_ainput(uncorrected_barometric_altitude));
3188MK_VIII::Mode2Handler::b_conditions ()
3190 return mk->io_handler.flaps_down()
3191 || (!
mk_data(glideslope_deviation_dots).ncd && fabs(
mk_data(glideslope_deviation_dots).get()) < 2)
3192 || takeoff_timer.running;
3196MK_VIII::Mode2Handler::is_a ()
3198 if (! mk->io_handler.gpws_inhibit()
3199 && ! mk->state_handler.ground
3200 && !
mk_data(radio_altitude).ncd
3202 && ! closure_rate_filter.output.ncd
3203 && ! b_conditions())
3205 if (
mk_data(radio_altitude).get() < 1220)
3207 if (
mk_data(radio_altitude).get() < -1579 + 0.7895 * closure_rate_filter.output.get())
3214 if (
mk_ainput(computed_airspeed).get() <= conf->airspeed1)
3216 else if (
mk_ainput(computed_airspeed).get() >= conf->airspeed2)
3219 upper_limit = 1650 + 8.9 * (
mk_ainput(computed_airspeed).get() - conf->airspeed1);
3221 if (
mk_data(radio_altitude).get() < upper_limit)
3223 if (
mk_data(radio_altitude).get() < 522 + 0.1968 * closure_rate_filter.output.get())
3233MK_VIII::Mode2Handler::is_b ()
3235 if (! mk->io_handler.gpws_inhibit()
3236 && ! mk->state_handler.ground
3237 && !
mk_data(radio_altitude).ncd
3238 && !
mk_data(barometric_altitude_rate).ncd
3239 && ! closure_rate_filter.output.ncd
3241 &&
mk_data(radio_altitude).get() < 789)
3245 if (mk->io_handler.flaps_down())
3247 if (
mk_data(barometric_altitude_rate).get() > -400)
3249 else if (
mk_data(barometric_altitude_rate).get() < -1000)
3252 lower_limit = -66.777 - 0.667 *
mk_data(barometric_altitude_rate).get();
3257 if (
mk_data(radio_altitude).get() > lower_limit)
3259 if (
mk_data(radio_altitude).get() < -1579 + 0.7895 * closure_rate_filter.output.get())
3268MK_VIII::Mode2Handler::check_pull_up (
unsigned int preface_alert,
3271 if (pull_up_timer.running)
3273 if (pull_up_timer.elapsed() >= 1)
3281 if (! mk->voice_player.voice)
3282 pull_up_timer.start();
3287MK_VIII::Mode2Handler::update_a ()
3298 pull_up_timer.stop();
3305 if (mk->io_handler.gpws_inhibit()
3306 || mk->state_handler.ground
3307 || a_altitude_gain_timer.elapsed() >= 45
3308 ||
mk_data(radio_altitude).ncd
3309 ||
mk_ainput(uncorrected_barometric_altitude).ncd
3310 ||
mk_ainput(uncorrected_barometric_altitude).get() - a_altitude_gain_alt >= 300
3314 || mk->io_handler.flaps_down())
3317 a_altitude_gain_timer.stop();
3325 if (closure_rate_filter.output.get() < 0)
3333 if (! mk->io_handler.gpws_inhibit()
3334 && ! mk->state_handler.ground
3336 && ! mk->io_handler.flaps_down()
3337 && !
mk_data(radio_altitude).ncd
3338 && !
mk_ainput(uncorrected_barometric_altitude).ncd)
3343 a_altitude_gain_timer.start();
3344 a_altitude_gain_alt =
mk_ainput(uncorrected_barometric_altitude).get();
3346 unsigned int alerts =
mk_alert(MODE2A_ALTITUDE_GAIN);
3347 if (closure_rate_filter.output.get() > 0)
3348 alerts |=
mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING);
3357MK_VIII::Mode2Handler::update_b ()
3363 if (b && (!
mk_dinput(landing_gear) || ! mk->io_handler.flaps_down()))
3370 pull_up_timer.stop();
3380 if (b &&
mk_dinput(landing_gear) && mk->io_handler.flaps_down())
3387MK_VIII::Mode2Handler::boot ()
3389 closure_rate_filter.init();
3393MK_VIII::Mode2Handler::power_off ()
3397 takeoff_timer.stop();
3401MK_VIII::Mode2Handler::leave_ground ()
3404 takeoff_timer.start();
3408MK_VIII::Mode2Handler::enter_takeoff ()
3411 takeoff_timer.start();
3415MK_VIII::Mode2Handler::update ()
3417 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
3420 closure_rate_filter.update();
3422 if (takeoff_timer.running && takeoff_timer.elapsed() >= 60)
3423 takeoff_timer.stop();
3434MK_VIII::Mode3Handler::max_alt_loss (
double _bias)
3436 return conf->max_alt_loss(mk->io_handler.flap_override(),
mk_data(radio_altitude).get()) +
mk_data(radio_altitude).get() * _bias;
3440MK_VIII::Mode3Handler::get_bias (
double initial_bias,
double alt_loss)
3443 if (
mk_data(radio_altitude).get() > 30)
3445 if (initial_bias < 0.0)
3448 while ((alt_loss > max_alt_loss(initial_bias))&&
3449 (initial_bias < 1.0))
3451 initial_bias += 0.2;
3455 return initial_bias;
3459MK_VIII::Mode3Handler::is (
double *alt_loss)
3461 if (has_descent_alt)
3463 int max_agl = conf->max_agl(mk->io_handler.flap_override());
3465 if (
mk_ainput(uncorrected_barometric_altitude).ncd
3466 ||
mk_ainput(uncorrected_barometric_altitude).get() > descent_alt
3467 ||
mk_data(radio_altitude).ncd
3468 ||
mk_data(radio_altitude).get() > max_agl)
3471 has_descent_alt =
false;
3476 if (! mk->io_handler.gpws_inhibit()
3477 && ! mk->state_handler.ground
3478 && (!
mk_dinput(landing_gear) || ! mk->io_handler.flaps_down())
3479 && !
mk_data(barometric_altitude_rate).ncd
3480 && !
mk_ainput(uncorrected_barometric_altitude).ncd
3481 && !
mk_data(radio_altitude).ncd
3482 &&
mk_data(barometric_altitude_rate).get() < 0)
3484 double _alt_loss = descent_alt -
mk_ainput(uncorrected_barometric_altitude).get();
3485 if (armed || (
mk_data(radio_altitude).get() > conf->min_agl
3486 &&
mk_data(radio_altitude).get() < max_agl
3487 && _alt_loss > max_alt_loss(0)))
3489 *alt_loss = _alt_loss;
3497 if (!
mk_data(barometric_altitude_rate).ncd
3498 && !
mk_ainput(uncorrected_barometric_altitude).ncd
3499 &&
mk_data(barometric_altitude_rate).get() < 0)
3501 has_descent_alt =
true;
3502 descent_alt =
mk_ainput(uncorrected_barometric_altitude).get();
3510MK_VIII::Mode3Handler::enter_takeoff ()
3513 has_descent_alt =
false;
3517MK_VIII::Mode3Handler::update ()
3519 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
3522 if (mk->state_handler.takeoff)
3526 if (! mk->state_handler.ground && is(&alt_loss))
3530 double new_bias = get_bias(bias, alt_loss);
3531 if (new_bias > bias)
3540 bias = get_bias(0.2, alt_loss);
3561MK_VIII::Mode4Handler::get_upper_agl (
const EnvelopesConfiguration *c)
3563 if (
mk_ainput(computed_airspeed).get() >= c->airspeed2)
3565 else if (
mk_ainput(computed_airspeed).get() >= c->airspeed1)
3566 return c->min_agl2(
mk_ainput(computed_airspeed).get());
3571const MK_VIII::Mode4Handler::EnvelopesConfiguration *
3572MK_VIII::Mode4Handler::get_ab_envelope ()
3577 return mk_dinput(landing_gear) || mk->io_handler.flaps_down()
3583MK_VIII::Mode4Handler::get_bias (
double initial_bias,
double min_agl)
3586 if (
mk_data(radio_altitude).get() > 30.0)
3588 if (initial_bias < 0.0)
3590 while ((
mk_data(radio_altitude).get() < min_agl - min_agl * initial_bias)&&
3591 (initial_bias < 1.0))
3592 initial_bias += 0.2;
3595 return initial_bias;
3599MK_VIII::Mode4Handler::handle_alert (
unsigned int alert,
3605 double new_bias = get_bias(*bias, min_agl);
3606 if (new_bias > *bias)
3614 *bias = get_bias(0.2, min_agl);
3620MK_VIII::Mode4Handler::update_ab ()
3622 if (! mk->io_handler.gpws_inhibit()
3623 && ! mk->state_handler.ground
3624 && ! mk->state_handler.takeoff
3625 && !
mk_data(radio_altitude).ncd
3627 &&
mk_data(radio_altitude).get() > 30)
3629 const EnvelopesConfiguration *c = get_ab_envelope();
3630 if (
mk_ainput(computed_airspeed).get() < c->airspeed1)
3634 if (! mk->io_handler.flaps_down() &&
mk_data(radio_altitude).get() < c->min_agl1)
3636 handle_alert(
mk_alert(MODE4_TOO_LOW_FLAPS), c->min_agl1, &ab_bias);
3642 if (
mk_data(radio_altitude).get() < c->min_agl1)
3644 handle_alert(
mk_alert(MODE4_TOO_LOW_GEAR), c->min_agl1, &ab_bias);
3656MK_VIII::Mode4Handler::update_ab_expanded ()
3658 if (! mk->io_handler.gpws_inhibit()
3659 && ! mk->state_handler.ground
3660 && ! mk->state_handler.takeoff
3661 && !
mk_data(radio_altitude).ncd
3663 &&
mk_data(radio_altitude).get() > 30)
3665 const EnvelopesConfiguration *c = get_ab_envelope();
3666 if (
mk_ainput(computed_airspeed).get() >= c->airspeed1)
3668 double min_agl = get_upper_agl(c);
3669 if (
mk_data(radio_altitude).get() < min_agl)
3671 handle_alert(
mk_alert(MODE4AB_TOO_LOW_TERRAIN), min_agl, &ab_expanded_bias);
3678 ab_expanded_bias=0.0;
3682MK_VIII::Mode4Handler::update_c ()
3684 if (! mk->io_handler.gpws_inhibit()
3685 && ! mk->state_handler.ground
3686 && mk->state_handler.takeoff
3687 && !
mk_data(radio_altitude).ncd
3688 && !
mk_data(terrain_clearance).ncd
3689 &&
mk_data(radio_altitude).get() > 30
3690 && (!
mk_dinput(landing_gear) || ! mk->io_handler.flaps_down())
3691 &&
mk_data(radio_altitude).get() < get_upper_agl(conf.modes->ac)
3692 &&
mk_data(radio_altitude).get() <
mk_data(terrain_clearance).get())
3694 handle_alert(
mk_alert(MODE4C_TOO_LOW_TERRAIN),
mk_data(terrain_clearance).get(), &c_bias);
3704MK_VIII::Mode4Handler::update ()
3706 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
3710 update_ab_expanded();
3719MK_VIII::Mode5Handler::is_hard ()
3721 if (
mk_data(radio_altitude).get() > 30
3722 &&
mk_data(radio_altitude).get() < 300
3723 &&
mk_data(glideslope_deviation_dots).get() > 2)
3725 if (
mk_data(radio_altitude).get() < 150)
3727 if (
mk_data(radio_altitude).get() > 293 - 71.43 *
mk_data(glideslope_deviation_dots).get())
3738MK_VIII::Mode5Handler::is_soft (
double bias)
3741 if (
mk_data(radio_altitude).get() > 30)
3743 double bias_dots = 1.3 * bias;
3744 if (
mk_data(glideslope_deviation_dots).get() > 1.3 + bias_dots)
3746 if (
mk_data(radio_altitude).get() < 150)
3748 if (
mk_data(radio_altitude).get() > 243 - 71.43 * (
mk_data(glideslope_deviation_dots).get() - bias_dots))
3755 if (
mk_data(barometric_altitude_rate).ncd)
3759 if (
mk_data(barometric_altitude_rate).get() >= 0)
3761 else if (
mk_data(barometric_altitude_rate).get() < -500)
3764 upper_limit = -
mk_data(barometric_altitude_rate).get() + 500;
3767 if (
mk_data(radio_altitude).get() < upper_limit)
3777MK_VIII::Mode5Handler::get_soft_bias (
double initial_bias)
3779 if (initial_bias < 0.0)
3782 while ((is_soft(initial_bias))&&
3783 (initial_bias < 1.0))
3785 initial_bias += 0.2;
3788 return initial_bias;
3792MK_VIII::Mode5Handler::update_hard (
bool is)
3798 if (hard_timer.start_or_elapsed() >= 0.8)
3810MK_VIII::Mode5Handler::update_soft (
bool is)
3816 double new_bias = get_soft_bias(soft_bias);
3817 if (new_bias > soft_bias)
3819 soft_bias = new_bias;
3825 if (soft_timer.start_or_elapsed() >= 0.8)
3827 soft_bias = get_soft_bias(0.2);
3840MK_VIII::Mode5Handler::update ()
3842 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
3845 if (! mk->io_handler.gpws_inhibit()
3846 && ! mk->state_handler.ground
3848 && !
mk_data(radio_altitude).ncd
3849 && !
mk_data(glideslope_deviation_dots).ncd
3850 && (! mk->io_handler.conf.localizer_enabled
3851 ||
mk_data(localizer_deviation_dots).ncd
3852 ||
mk_data(radio_altitude).get() < 500
3853 || fabs(
mk_data(localizer_deviation_dots).get()) < 2)
3854 && (! mk->state_handler.takeoff || mk->io_handler.flaps_down())
3858 update_hard(is_hard());
3859 update_soft(is_soft(0));
3873const int MK_VIII::Mode6Handler::altitude_callout_definitions[] =
3874 { 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30, 20, 10 };
3877MK_VIII::Mode6Handler::reset_minimums ()
3879 minimums_issued =
false;
3880 minimums_above_100_issued =
false;
3884MK_VIII::Mode6Handler::reset_altitude_callouts ()
3886 for (
unsigned i = 0;
i < n_altitude_callouts;
i++)
3887 altitude_callouts_issued[
i] =
false;
3888 throttle_retarded =
false;
3892MK_VIII::Mode6Handler::is_playing_altitude_callout ()
3894 for (
unsigned i = 0;
i < n_altitude_callouts;
i++)
3904MK_VIII::Mode6Handler::is_near_minimums (
double callout)
3908 if (!
mk_data(decision_height).ncd)
3910 double diff = callout -
mk_data(decision_height).get();
3912 if (
mk_data(radio_altitude).get() >= 200)
3914 if (fabs(diff) <= 30)
3919 if (diff >= -3 && diff <= 6)
3928MK_VIII::Mode6Handler::is_outside_band (
double elevation,
double callout)
3931 return elevation < callout - (elevation > 150 ? 20 : 10);
3935MK_VIII::Mode6Handler::inhibit_smart_500 ()
3939 if (!
mk_data(glideslope_deviation_dots).ncd
3943 if (mk->io_handler.conf.localizer_enabled
3944 && !
mk_data(localizer_deviation_dots).ncd)
3946 if (fabs(
mk_data(localizer_deviation_dots).get()) <= 2)
3951 if (fabs(
mk_data(glideslope_deviation_dots).get()) <= 2)
3960MK_VIII::Mode6Handler::boot ()
3962 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
3965 last_decision_height =
mk_dinput(decision_height);
3966 last_radio_altitude.set(&
mk_data(radio_altitude));
3969 for (
unsigned i = 0;
i < n_altitude_callouts;
i++)
3970 altitude_callouts_issued[
i] = !
mk_data(radio_altitude).ncd
3971 &&
mk_data(radio_altitude).get() <= altitude_callout_definitions[
i];
3974 minimums_issued =
mk_dinput(decision_height);
3976 if (conf.above_field_voice)
3979 get_altitude_above_field(&last_altitude_above_field);
3981 above_field_issued = ! last_altitude_above_field.ncd
3982 && last_altitude_above_field.get() < 550;
3987MK_VIII::Mode6Handler::power_off ()
3989 runway_timer.stop();
3993MK_VIII::Mode6Handler::enter_takeoff ()
3995 reset_altitude_callouts();
4000MK_VIII::Mode6Handler::leave_takeoff ()
4002 reset_altitude_callouts();
4007MK_VIII::Mode6Handler::set_volume (
float volume)
4009 mk_voice(minimums_minimums)->set_volume(volume);
4010 mk_voice(five_hundred_above)->set_volume(volume);
4011 for (
unsigned i = 0;
i < n_altitude_callouts;
i++)
4016MK_VIII::Mode6Handler::altitude_callouts_enabled ()
4018 if (conf.minimums_enabled || conf.smart_500_enabled || conf.above_field_voice)
4021 return (conf.altitude_callouts_enabled != 0);
4025MK_VIII::Mode6Handler::update_minimums ()
4027 if (! mk->io_handler.gpws_inhibit()
4028 && (mk->voice_player.voice ==
mk_voice(minimums_minimums)
4029 || mk->voice_player.next_voice ==
mk_voice(minimums_minimums)))
4034 if (! mk->io_handler.gpws_inhibit()
4035 && ! mk->state_handler.ground
4036 && conf.minimums_enabled
4037 && ! minimums_issued
4039 && ! last_decision_height)
4043 minimums_issued =
true;
4052 if (is_playing_altitude_callout())
4059 if (conf.minimums_above_100_enabled && (!minimums_above_100_issued) &&
4062 minimums_above_100_issued =
true;
4064 if (is_playing_altitude_callout())
4078 last_decision_height =
mk_dinput(decision_height);
4079 last_decision_height_100 =
mk_dinput(decision_height_100);
4083MK_VIII::Mode6Handler::update_altitude_callouts ()
4085 if (! mk->io_handler.gpws_inhibit() && is_playing_altitude_callout())
4088 if (! mk->io_handler.gpws_inhibit())
4090 if (mk->mode6_handler.conf.retard_enabled &&
4091 (!throttle_retarded)&&
4092 (
mk_data(radio_altitude).get() < 25))
4100 throttle_retarded =
true;
4104 if (! mk->state_handler.ground
4105 && !
mk_data(radio_altitude).ncd)
4107 for (
unsigned i = 0;
i < n_altitude_callouts &&
mk_data(radio_altitude).get() <= altitude_callout_definitions[
i];
i++)
4109 if (((conf.altitude_callouts_enabled & (1<<
i))
4110 || (altitude_callout_definitions[
i] == 500
4111 && conf.smart_500_enabled))
4112 && ! altitude_callouts_issued[
i]
4113 && (last_radio_altitude.ncd
4114 || last_radio_altitude.get() > altitude_callout_definitions[
i]))
4117 for (
unsigned j = 0; j <=
i; j++)
4118 altitude_callouts_issued[j] =
true;
4120 altitude_callouts_issued[
i] =
true;
4121 if (! is_near_minimums(altitude_callout_definitions[
i])
4122 && ! is_outside_band(
mk_data(radio_altitude).get(), altitude_callout_definitions[
i])
4123 && (! conf.smart_500_enabled
4124 || altitude_callout_definitions[
i] != 500
4125 || ! inhibit_smart_500()))
4138 last_radio_altitude.set(&
mk_data(radio_altitude));
4142MK_VIII::Mode6Handler::test_runway (
const FGRunway *_runway)
4144 if (_runway->
lengthFt() < mk->conf.runway_database)
4148 SGGeod::fromDeg(
mk_data(gps_longitude).get(),
mk_data(gps_latitude).get()));
4151 return SGGeodesy::distanceNm(pos, _runway->
threshold()) <= 5;
4155MK_VIII::Mode6Handler::test_airport (
const FGAirport *airport)
4157 for (
unsigned int r=0; r<airport->
numRunways(); ++r)
4161 if (test_runway(rwy))
4168bool MK_VIII::Mode6Handler::AirportFilter::passAirport(FGAirport* a)
const
4170 bool ok = self->test_airport(a);
4175MK_VIII::Mode6Handler::update_runway ()
4188 AirportFilter filter(
this);
4190 SGGeod::fromDeg(
mk_data(gps_longitude).get(),
mk_data(gps_latitude).get()),
4194 runway.elevation = apt->elevation();
4197 has_runway.set(apt != NULL);
4201MK_VIII::Mode6Handler::get_altitude_above_field (Parameter<double> *parameter)
4203 if (! has_runway.ncd && has_runway.get() && !
mk_data(geometric_altitude).ncd)
4204 parameter->set(
mk_data(geometric_altitude).get() - runway.elevation);
4210MK_VIII::Mode6Handler::update_above_field_callout ()
4212 if (! conf.above_field_voice)
4219 if (runway_timer.start_or_elapsed() >= 3)
4222 runway_timer.start();
4225 Parameter<double> altitude_above_field;
4226 get_altitude_above_field(&altitude_above_field);
4228 if (! mk->io_handler.gpws_inhibit()
4229 && (mk->voice_player.voice == conf.above_field_voice
4230 || mk->voice_player.next_voice == conf.above_field_voice))
4234 if (above_field_issued)
4236 if ((! has_runway.ncd && ! has_runway.get())
4237 || (! altitude_above_field.ncd && altitude_above_field.get() > 700))
4238 above_field_issued =
false;
4241 if (! mk->io_handler.gpws_inhibit()
4242 && ! mk->state_handler.ground
4243 && ! above_field_issued
4244 && ! altitude_above_field.ncd
4245 && altitude_above_field.get() < 550
4246 && (last_altitude_above_field.ncd
4247 || last_altitude_above_field.get() >= 550))
4249 above_field_issued =
true;
4251 if (! is_outside_band(altitude_above_field.get(), 500))
4253 mk->alert_handler.set_altitude_callout_alert(conf.above_field_voice);
4261 last_altitude_above_field.set(&altitude_above_field);
4265MK_VIII::Mode6Handler::is_bank_angle (
double abs_roll_angle,
double bias)
4267 return conf.is_bank_angle(&
mk_data(radio_altitude),
4268 abs_roll_angle - abs_roll_angle * bias,
4273MK_VIII::Mode6Handler::is_high_bank_angle ()
4275 return mk_data(radio_altitude).ncd ||
mk_data(radio_altitude).get() >= 210;
4279MK_VIII::Mode6Handler::get_bank_angle_alerts ()
4281 if (! mk->io_handler.gpws_inhibit()
4282 && ! mk->state_handler.ground
4285 double abs_roll_angle = fabs(
mk_data(roll_angle).get());
4287 if (is_bank_angle(abs_roll_angle, 0.4))
4288 return is_high_bank_angle()
4291 else if (is_bank_angle(abs_roll_angle, 0.2))
4292 return is_high_bank_angle()
4295 else if (is_bank_angle(abs_roll_angle, 0))
4296 return is_high_bank_angle()
4297 ?
mk_alert(MODE6_HIGH_BANK_ANGLE_1)
4298 :
mk_alert(MODE6_LOW_BANK_ANGLE_1);
4305MK_VIII::Mode6Handler::update_bank_angle ()
4307 if (! conf.bank_angle_enabled)
4310 unsigned int alerts = get_bank_angle_alerts();
4325 |
mk_alert(MODE6_HIGH_BANK_ANGLE_1)
4327 |
mk_alert(MODE6_HIGH_BANK_ANGLE_2));
4331MK_VIII::Mode6Handler::update ()
4333 if (mk->configuration_module.state != ConfigurationModule::STATE_OK)
4336 if (! mk->state_handler.takeoff
4337 && !
mk_data(radio_altitude).ncd
4338 &&
mk_data(radio_altitude).get() > 1000)
4340 reset_altitude_callouts();
4345 update_altitude_callouts();
4346 update_above_field_callout();
4347 update_bank_angle();
4354bool MK_VIII::TCFHandler::AirportFilter::passAirport(FGAirport* aApt)
const
4360MK_VIII::TCFHandler::update_runway ()
4373 AirportFilter filter(mk);
4374 SGGeod apos = SGGeod::fromDeg(
mk_data(gps_longitude).get(),
mk_data(gps_latitude).get());
4393 runway.half_width_m = _runway->
widthM() * 0.5;
4394 double half_length_m = _runway->
lengthM() * 0.5;
4395 runway.half_length = half_length_m * SG_METER_TO_NM;
4406 runway.edge.position = _runway->
begin();
4409 runway.bias_points[0] = _runway->
cart();
4420MK_VIII::TCFHandler::is_inside_edge_triangle (RunwayEdge *edge)
4422 double az = SGGeodesy::courseDeg( SGGeod::fromDeg(
mk_data(gps_longitude).get(),
4431MK_VIII::TCFHandler::is_inside_bias_area ()
4433 double half_bias_width_m = k * SG_NM_TO_METER + runway.half_width_m;
4434 SGVec3d cpos = SGVec3d::fromGeod( SGGeod::fromDegFt(
mk_data(gps_longitude).get(),
4436 runway.elevation) );
4437 SGLineSegmentd bias_line = SGLineSegmentd(runway.bias_points[0], runway.bias_points[1]);
4438 return dist(cpos, bias_line) < half_bias_width_m;
4442MK_VIII::TCFHandler::is_tcf ()
4444 if (
mk_data(radio_altitude).get() > 10)
4448 double distance = SGGeodesy::distanceNm( SGGeod::fromDegFt(
mk_data(gps_longitude).get(),
4454 double edge_distance = distance - runway.half_length - k;
4456 if (edge_distance > 15)
4458 if (
mk_data(radio_altitude).get() < 700)
4462 if (edge_distance > 12)
4464 if (
mk_data(radio_altitude).get() < 100 * edge_distance - 800)
4468 if (edge_distance > 4)
4470 if (
mk_data(radio_altitude).get() < 400)
4474 if (edge_distance > 2.45)
4476 if (
mk_data(radio_altitude).get() < 100 * edge_distance)
4480 if ( is_inside_edge_triangle(&runway.edge) && (edge_distance > 0.01) )
4482 if (
mk_data(radio_altitude).get() < 100 * edge_distance)
4486 if (! is_inside_bias_area())
4488 if (
mk_data(radio_altitude).get() < 245)
4493 if (
mk_data(radio_altitude).get() < 700)
4502MK_VIII::TCFHandler::is_rfcf ()
4506 double distance = SGGeodesy::distanceNm( SGGeod::fromDegFt(
mk_data(gps_longitude).get(),
4510 distance -= runway.half_length;
4514 double krf = k +
mk_data(gps_vertical_figure_of_merit).get() / 200;
4516 double altitude_above_field =
mk_data(geometric_altitude).get() - runway.elevation;
4518 if ( (distance > 1.5) && (altitude_above_field < 300.0) )
4520 else if ( (distance > 0.0) && (altitude_above_field < 200 * distance) )
4529MK_VIII::TCFHandler::update ()
4531 if (mk->configuration_module.state != ConfigurationModule::STATE_OK || ! conf.enabled)
4537 if (! runway_timer.running || runway_timer.elapsed() >= 3)
4540 runway_timer.start();
4544 && ! mk->state_handler.ground
4545 && !
mk_data(gps_latitude).ncd
4546 && !
mk_data(gps_longitude).ncd
4547 && !
mk_data(radio_altitude).ncd
4548 && !
mk_data(geometric_altitude).ncd
4549 && !
mk_data(gps_vertical_figure_of_merit).ncd)
4554 _reference =
mk_data(radio_altitude).get_pointer();
4556 _reference =
mk_data(geometric_altitude).get_pointer();
4564 double new_bias = bias;
4566 if (
mk_data(radio_altitude).get() > 30)
4570 while ((*reference < initial_value - initial_value * new_bias)&&
4577 if (new_bias > bias)
4586 reference = _reference;
4587 initial_value = *reference;
4606 power_handler(this),
4607 system_handler(this),
4608 configuration_module(this),
4609 fault_handler(this),
4612 self_test_handler(this),
4613 alert_handler(this),
4614 state_handler(this),
4615 mode1_handler(this),
4616 mode2_handler(this),
4617 mode3_handler(this),
4618 mode4_handler(this),
4619 mode5_handler(this),
4620 mode6_handler(this),
4623 for (
int i = 0;
i < node->nChildren(); ++
i)
4625 SGPropertyNode *child = node->getChild(
i);
4626 string cname = child->getNameString();
4627 string cval = child->getStringValue();
4629 if (cname ==
"name")
4631 else if (cname ==
"number")
4632 num = child->getIntValue();
4635 SG_LOG(SG_INSTR, SG_WARN,
"Error in mk-viii config logic");
4637 SG_LOG(SG_INSTR, SG_WARN,
"Section = " << name);
4646 voice_player.init();
4652 SGPropertyNode *node =
fgGetNode((
"/instrumentation/" + name), num,
true);
4654 configuration_module.bind(node);
4655 power_handler.bind(node);
4656 io_handler.bind(node);
4657 voice_player.bind(node,
"Sounds/mk-viii/");
4669 power_handler.update();
4670 system_handler.update();
4672 if (system_handler.state != SystemHandler::STATE_ON)
4675 io_handler.update_inputs();
4676 io_handler.update_input_faults();
4678 voice_player.update();
4679 state_handler.update();
4681 if (self_test_handler.update())
4684 io_handler.update_internal_latches();
4685 io_handler.update_lamps();
4687 mode1_handler.update();
4688 mode2_handler.update();
4689 mode3_handler.update();
4690 mode4_handler.update();
4691 mode5_handler.update();
4692 mode6_handler.update();
4693 tcf_handler.update();
4695 alert_handler.update();
4696 io_handler.update_outputs();
4702SGSubsystemMgr::InstancedRegistrant<MK_VIII> registrantMK_VIII(
4703 SGSubsystemMgr::FDM,
4704 {{
"instrumentation", SGSubsystemMgr::Dependency::HARD}},
SGSharedPtr< FGPositioned > FGPositionedRef
unsigned int numRunways() const
FGRunwayRef findBestRunwayForPos(const SGGeod &aPos) const
return the most likely target runway based on a position.
FGRunwayRef getRunwayByIndex(unsigned int aIndex) const
bool hasHardRunwayOfLengthFt(double aLengthFt) const
Useful predicate for FMS/GPS/NAV displays and similar - check if this airport has a hard-surfaced run...
static FGAirportRef findClosest(const SGGeod &aPos, double aCuttofNm, Filter *filter=NULL)
Syntactic wrapper around FGPositioned::findClosest - find the closest match for filter,...
double get_sim_time_sec() const
virtual const SGVec3d & cart() const
The cartesian position associated with this object.
static FGPositionedRef findClosest(const SGGeod &aPos, double aCutoffNm, Filter *aFilter=NULL)
Find the closest item to a position, which pass the specified filter A cutoff range in NM must be spe...
double headingDeg() const
Runway heading in degrees.
SGGeod pointOnCenterline(double aOffset) const
Retrieve a position on the extended centerline.
SGGeod threshold() const
Get the (possibly displaced) threshold point.
FGRunway * reciprocalRunway() const
SGGeod begin() const
Get the runway beginning point - this is syntatic sugar, equivalent to calling pointOnCenterline(0....
void make_voice(Voice **voice)
SGSoundSample * get_sample(const char *name)
void present_status_section(const char *name)
bool gpws_inhibit() const
void bind(SGPropertyNode *node)
void update_egpwc_alert_discrete_3()
void present_status_item(const char *name, const char *value=NULL)
bool get_present_status() const
void present_status_subitem(const char *name)
bool steep_approach() const
struct MK_VIII::IOHandler::_s_inputs inputs
IOHandler(MK_VIII *device)
bool real_flaps_down() const
void update_internal_latches()
struct MK_VIII::IOHandler::_s_Conf conf
void set_present_status(bool value)
void update_egpwc_logic_discretes()
bool momentary_steep_approach_enabled() const
struct MK_VIII::IOHandler::_s_input_feeders input_feeders
void update_egpws_alert_discrete_1()
void update_alternate_discrete_input(bool *ptr)
void set_discrete_input(bool *ptr, bool value)
void update_egpws_alert_discrete_2()
bool flap_override() const
void update_mode6_callouts_discrete_2()
void update_input_faults()
bool get_discrete_input(bool *ptr) const
bool * get_lamp_output(Lamp lamp)
void update_mode6_callouts_discrete_1()
struct MK_VIII::VoicePlayer::@324313271375217117055266177221205376013353212253 voices
MK_VIII(SGPropertyNode *node)
void update(double dt) override
PropertiesHandler properties_handler
#define mk_dinput_feed(_name)
#define GLIDESLOPE_DDM_TO_DOTS
#define mk_aoutput(_name)
#define LOCALIZER_DOTS_TO_DDM
static double m3_t2_max_alt_loss(bool flap_override, double agl)
#define mk_test_alerts(_test)
static double get_heading_difference(double h1, double h2)
#define was_here_offset(offset)
static double m4_t79_b_min_agl2(double airspeed)
#define n_elements(_array)
#define GLIDESLOPE_DOTS_TO_DDM
#define mk_test_alert(_name)
#define mk_doutput(_name)
static int m3_t1_max_agl(bool flap_override)
static double m4_t1_min_agl2(double airspeed)
#define test_bits(_bits, _test)
static double m1_t1_min_agl2(double vs)
#define assert_not_reached()
#define LOCALIZER_DDM_TO_DOTS
static double modify_amplitude(double amplitude, double dB)
static double m4_t79_a_min_agl2(double airspeed)
#define mk_ainput_feed(_name)
static double m1_t4_min_agl2(double vs)
static double m1_t4_min_agl1(double vs)
static double m4_t568_b_min_agl2(double airspeed)
static double m3_t1_max_alt_loss(bool flap_override, double agl)
static double m1_t1_min_agl1(double vs)
static double m4_t568_a_min_agl2(double airspeed)
#define mk_altitude_voice(_i)
static int m3_t2_max_agl(bool flap_override)
double getDoubleValue(const char *spec, double default_)
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.