From f37715f334d433d8f1e0e61e987af097c4004b58 Mon Sep 17 00:00:00 2001 From: ThorstenB Date: Sun, 28 Jan 2018 21:13:01 +0100 Subject: [PATCH] GPWS: clean up white-space (TAB vs space) and indentation mess --- src/Instrumentation/mk_viii.cxx | 5821 ++++++++++++++++--------------- src/Instrumentation/mk_viii.hxx | 2279 ++++++------ 2 files changed, 4079 insertions(+), 4021 deletions(-) diff --git a/src/Instrumentation/mk_viii.cxx b/src/Instrumentation/mk_viii.cxx index 7be9ec68d..9f60dd7f3 100644 --- a/src/Instrumentation/mk_viii.cxx +++ b/src/Instrumentation/mk_viii.cxx @@ -22,30 +22,30 @@ // // References: // -// [PILOT] Honeywell International Inc., "MK VI and MK VIII, -// Enhanced Ground Proximity Warning System (EGPWS), -// Pilot's Guide", May 2004 +// [PILOT] Honeywell International Inc., "MK VI and MK VIII, +// Enhanced Ground Proximity Warning System (EGPWS), +// Pilot's Guide", May 2004 // -// http://www.egpws.com/engineering_support/documents/pilot_guides/060-4314-000.pdf +// http://www.egpws.com/engineering_support/documents/pilot_guides/060-4314-000.pdf // -// [SPEC] Honeywell International Inc., "Product Specification -// for the MK VI and MK VIII Enhanced Ground Proximity -// Warning System (EGPWS)", June 2004 +// [SPEC] Honeywell International Inc., "Product Specification +// for the MK VI and MK VIII Enhanced Ground Proximity +// Warning System (EGPWS)", June 2004 // -// http://www.egpws.com/engineering_support/documents/specs/965-1180-601.pdf +// http://www.egpws.com/engineering_support/documents/specs/965-1180-601.pdf // -// [INSTALL] Honeywell Inc., "MK VI, MK VIII, Enhanced Ground -// Proximity Warning System (Class A TAWS), Installation -// Design Guide", July 2003 +// [INSTALL] Honeywell Inc., "MK VI, MK VIII, Enhanced Ground +// Proximity Warning System (Class A TAWS), Installation +// Design Guide", July 2003 // -// http://www.egpws.com/engineering_support/documents/install/060-4314-150.pdf +// http://www.egpws.com/engineering_support/documents/install/060-4314-150.pdf // // Notes: // -// [1] [SPEC] does not specify the "must be airborne" -// condition; we use it to make sure that the alert -// will not trigger when on the ground, since it would -// make no sense. +// [1] [SPEC] does not specify the "must be airborne" +// condition; we use it to make sure that the alert +// will not trigger when on the ground, since it would +// make no sense. #ifdef _MSC_VER # pragma warning( disable: 4355 ) @@ -92,60 +92,60 @@ using std::string; // constants ////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -#define GLIDESLOPE_DOTS_TO_DDM 0.0875 // [INSTALL] 6.2.30 -#define GLIDESLOPE_DDM_TO_DOTS (1 / GLIDESLOPE_DOTS_TO_DDM) +#define GLIDESLOPE_DOTS_TO_DDM 0.0875 // [INSTALL] 6.2.30 +#define GLIDESLOPE_DDM_TO_DOTS (1 / GLIDESLOPE_DOTS_TO_DDM) -#define LOCALIZER_DOTS_TO_DDM 0.0775 // [INSTALL] 6.2.33 -#define LOCALIZER_DDM_TO_DOTS (1 / LOCALIZER_DOTS_TO_DDM) +#define LOCALIZER_DOTS_TO_DDM 0.0775 // [INSTALL] 6.2.33 +#define LOCALIZER_DDM_TO_DOTS (1 / LOCALIZER_DOTS_TO_DDM) /////////////////////////////////////////////////////////////////////////////// // helpers //////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -#define assert_not_reached() assert(false) -#define n_elements(_array) (sizeof(_array) / sizeof((_array)[0])) -#define test_bits(_bits, _test) (((_bits) & (_test)) != 0) +#define assert_not_reached() assert(false) +#define n_elements(_array) (sizeof(_array) / sizeof((_array)[0])) +#define test_bits(_bits, _test) (((_bits) & (_test)) != 0) -#define mk_node(_name) (mk->properties_handler.external_properties._name) +#define mk_node(_name) (mk->properties_handler.external_properties._name) -#define mk_dinput_feed(_name) (mk->io_handler.input_feeders.discretes._name) -#define mk_dinput(_name) (mk->io_handler.inputs.discretes._name) -#define mk_ainput_feed(_name) (mk->io_handler.input_feeders.arinc429._name) -#define mk_ainput(_name) (mk->io_handler.inputs.arinc429._name) -#define mk_doutput(_name) (mk->io_handler.outputs.discretes._name) -#define mk_aoutput(_name) (mk->io_handler.outputs.arinc429._name) -#define mk_data(_name) (mk->io_handler.data._name) +#define mk_dinput_feed(_name) (mk->io_handler.input_feeders.discretes._name) +#define mk_dinput(_name) (mk->io_handler.inputs.discretes._name) +#define mk_ainput_feed(_name) (mk->io_handler.input_feeders.arinc429._name) +#define mk_ainput(_name) (mk->io_handler.inputs.arinc429._name) +#define mk_doutput(_name) (mk->io_handler.outputs.discretes._name) +#define mk_aoutput(_name) (mk->io_handler.outputs.arinc429._name) +#define mk_data(_name) (mk->io_handler.data._name) -#define mk_voice(_name) (mk->voice_player.voices._name) -#define mk_altitude_voice(_i) (mk->voice_player.voices.altitude_callouts[(_i)]) +#define mk_voice(_name) (mk->voice_player.voices._name) +#define mk_altitude_voice(_i) (mk->voice_player.voices.altitude_callouts[(_i)]) -#define mk_alert(_name) (AlertHandler::ALERT_ ## _name) -#define mk_alert_flag(_name) (AlertHandler::ALERT_FLAG_ ## _name) -#define mk_set_alerts (mk->alert_handler.set_alerts) -#define mk_unset_alerts (mk->alert_handler.unset_alerts) -#define mk_repeat_alert (mk->alert_handler.repeat_alert) -#define mk_test_alert(_name) (mk_test_alerts(mk_alert(_name))) -#define mk_test_alerts(_test) (test_bits(mk->alert_handler.alerts, (_test))) +#define mk_alert(_name) (AlertHandler::ALERT_ ## _name) +#define mk_alert_flag(_name) (AlertHandler::ALERT_FLAG_ ## _name) +#define mk_set_alerts (mk->alert_handler.set_alerts) +#define mk_unset_alerts (mk->alert_handler.unset_alerts) +#define mk_repeat_alert (mk->alert_handler.repeat_alert) +#define mk_test_alert(_name) (mk_test_alerts(mk_alert(_name))) +#define mk_test_alerts(_test) (test_bits(mk->alert_handler.alerts, (_test))) const double MK_VIII::TCFHandler::k = 0.25; static double modify_amplitude (double amplitude, double dB) { - return amplitude * pow(10.0, dB / 20.0); + return amplitude * pow(10.0, dB / 20.0); } static double get_heading_difference (double h1, double h2) { - double diff = h1 - h2; + double diff = h1 - h2; - if (diff < -180) - diff += 360; - else if (diff > 180) - diff -= 360; + if (diff < -180) + diff += 360; + else if (diff > 180) + diff -= 360; - return fabs(diff); + return fabs(diff); } /////////////////////////////////////////////////////////////////////////////// @@ -155,36 +155,36 @@ get_heading_difference (double h1, double h2) void MK_VIII::PropertiesHandler::init () { - mk_node(ai_caged) = fgGetNode("/instrumentation/attitude-indicator/caged-flag", true); - mk_node(ai_roll) = fgGetNode("/instrumentation/attitude-indicator/indicated-roll-deg", true); - mk_node(ai_serviceable) = fgGetNode("/instrumentation/attitude-indicator/serviceable", true); - mk_node(altimeter_altitude) = fgGetNode("/instrumentation/altimeter/indicated-altitude-ft", true); - mk_node(altimeter_serviceable) = fgGetNode("/instrumentation/altimeter/serviceable", true); - mk_node(altitude) = fgGetNode("/position/altitude-ft", true); - mk_node(altitude_agl) = fgGetNode("/position/altitude-agl-ft", true); - mk_node(altitude_gear_agl) = fgGetNode("/position/gear-agl-ft", true); - mk_node(altitude_radar_agl) = fgGetNode("/instrumentation/radar-altimeter/radar-altitude-ft", true); - mk_node(orientation_roll) = fgGetNode("/orientation/roll-deg", true); - mk_node(asi_serviceable) = fgGetNode("/instrumentation/airspeed-indicator/serviceable", true); - mk_node(asi_speed) = fgGetNode("/instrumentation/airspeed-indicator/indicated-speed-kt", true); - mk_node(autopilot_heading_lock) = fgGetNode("/autopilot/locks/heading", true); - mk_node(flaps) = fgGetNode("/controls/flight/flaps", true); - mk_node(gear_down) = fgGetNode("/controls/gear/gear-down", true); - mk_node(throttle) = fgGetNode("/controls/engines/engine/throttle", true); - mk_node(latitude) = fgGetNode("/position/latitude-deg", true); - mk_node(longitude) = fgGetNode("/position/longitude-deg", true); - mk_node(nav0_cdi_serviceable) = fgGetNode("/instrumentation/nav/cdi/serviceable", true); - mk_node(nav0_gs_distance) = fgGetNode("/instrumentation/nav/gs-distance", true); - mk_node(nav0_gs_needle_deflection) = fgGetNode("/instrumentation/nav/gs-needle-deflection-deg", true); - mk_node(nav0_gs_serviceable) = fgGetNode("/instrumentation/nav/gs/serviceable", true); - mk_node(nav0_has_gs) = fgGetNode("/instrumentation/nav/has-gs", true); - mk_node(nav0_heading_needle_deflection) = fgGetNode("/instrumentation/nav/heading-needle-deflection", true); - mk_node(nav0_in_range) = fgGetNode("/instrumentation/nav/in-range", true); - mk_node(nav0_nav_loc) = fgGetNode("/instrumentation/nav/nav-loc", true); - mk_node(nav0_serviceable) = fgGetNode("/instrumentation/nav/serviceable", true); - mk_node(power) = fgGetNode(("/systems/electrical/outputs/" + mk->name).c_str(), mk->num, true); - mk_node(replay_state) = fgGetNode("/sim/freeze/replay-state", true); - mk_node(vs) = fgGetNode("/velocities/vertical-speed-fps", true); + mk_node(ai_caged) = fgGetNode("/instrumentation/attitude-indicator/caged-flag", true); + mk_node(ai_roll) = fgGetNode("/instrumentation/attitude-indicator/indicated-roll-deg", true); + mk_node(ai_serviceable) = fgGetNode("/instrumentation/attitude-indicator/serviceable", true); + mk_node(altimeter_altitude) = fgGetNode("/instrumentation/altimeter/indicated-altitude-ft", true); + mk_node(altimeter_serviceable) = fgGetNode("/instrumentation/altimeter/serviceable", true); + mk_node(altitude) = fgGetNode("/position/altitude-ft", true); + mk_node(altitude_agl) = fgGetNode("/position/altitude-agl-ft", true); + mk_node(altitude_gear_agl) = fgGetNode("/position/gear-agl-ft", true); + mk_node(altitude_radar_agl) = fgGetNode("/instrumentation/radar-altimeter/radar-altitude-ft", true); + mk_node(orientation_roll) = fgGetNode("/orientation/roll-deg", true); + mk_node(asi_serviceable) = fgGetNode("/instrumentation/airspeed-indicator/serviceable", true); + mk_node(asi_speed) = fgGetNode("/instrumentation/airspeed-indicator/indicated-speed-kt", true); + mk_node(autopilot_heading_lock) = fgGetNode("/autopilot/locks/heading", true); + mk_node(flaps) = fgGetNode("/controls/flight/flaps", true); + mk_node(gear_down) = fgGetNode("/controls/gear/gear-down", true); + mk_node(throttle) = fgGetNode("/controls/engines/engine/throttle", true); + mk_node(latitude) = fgGetNode("/position/latitude-deg", true); + mk_node(longitude) = fgGetNode("/position/longitude-deg", true); + mk_node(nav0_cdi_serviceable) = fgGetNode("/instrumentation/nav/cdi/serviceable", true); + mk_node(nav0_gs_distance) = fgGetNode("/instrumentation/nav/gs-distance", true); + mk_node(nav0_gs_needle_deflection) = fgGetNode("/instrumentation/nav/gs-needle-deflection-deg", true); + mk_node(nav0_gs_serviceable) = fgGetNode("/instrumentation/nav/gs/serviceable", true); + mk_node(nav0_has_gs) = fgGetNode("/instrumentation/nav/has-gs", true); + mk_node(nav0_heading_needle_deflection) = fgGetNode("/instrumentation/nav/heading-needle-deflection", true); + mk_node(nav0_in_range) = fgGetNode("/instrumentation/nav/in-range", true); + mk_node(nav0_nav_loc) = fgGetNode("/instrumentation/nav/nav-loc", true); + mk_node(nav0_serviceable) = fgGetNode("/instrumentation/nav/serviceable", true); + mk_node(power) = fgGetNode(("/systems/electrical/outputs/" + mk->name).c_str(), mk->num, true); + mk_node(replay_state) = fgGetNode("/sim/freeze/replay-state", true); + mk_node(vs) = fgGetNode("/velocities/vertical-speed-fps", true); } /////////////////////////////////////////////////////////////////////////////// @@ -194,84 +194,82 @@ MK_VIII::PropertiesHandler::init () void MK_VIII::PowerHandler::bind (SGPropertyNode *node) { - mk->properties_handler.tie(node, "serviceable", SGRawValuePointer(&serviceable)); + mk->properties_handler.tie(node, "serviceable", SGRawValuePointer(&serviceable)); } bool MK_VIII::PowerHandler::handle_abnormal_voltage (bool abnormal, - Timer *timer, - double max_duration) + Timer *timer, + double max_duration) { - if (abnormal) + if (abnormal) { - if (timer->start_or_elapsed() >= max_duration) - return true; // power loss - } - else - timer->stop(); + if (timer->start_or_elapsed() >= max_duration) + return true; // power loss + } else + timer->stop(); - return false; + return false; } void MK_VIII::PowerHandler::update () { - double voltage = mk_node(power)->getDoubleValue(); - bool now_powered = true; + double voltage = mk_node(power)->getDoubleValue(); + bool now_powered = true; - // [SPEC] 3.2.1 + // [SPEC] 3.2.1 - if (! serviceable) - now_powered = false; - if (voltage < 15) - now_powered = false; - if (handle_abnormal_voltage(voltage < 20.5, &low_surge_timer, 0.03)) - now_powered = false; - if (handle_abnormal_voltage(voltage < 22.0 || voltage > 30.3, &abnormal_timer, 300)) - now_powered = false; - if (handle_abnormal_voltage(voltage > 32.2, &high_surge_timer, 1)) - now_powered = false; - if (handle_abnormal_voltage(voltage > 37.8, &very_high_surge_timer, 0.1)) - now_powered = false; - if (voltage > 46.3) - now_powered = false; + if (!serviceable) + now_powered = false; + if (voltage < 15) + now_powered = false; + if (handle_abnormal_voltage(voltage < 20.5, &low_surge_timer, 0.03)) + now_powered = false; + if (handle_abnormal_voltage(voltage < 22.0 || voltage > 30.3, + &abnormal_timer, 300)) + now_powered = false; + if (handle_abnormal_voltage(voltage > 32.2, &high_surge_timer, 1)) + now_powered = false; + if (handle_abnormal_voltage(voltage > 37.8, &very_high_surge_timer, 0.1)) + now_powered = false; + if (voltage > 46.3) + now_powered = false; - if (powered) + if (powered) { - // [SPEC] 3.5.2 + // [SPEC] 3.5.2 - if (now_powered) - power_loss_timer.stop(); - else - { - if (power_loss_timer.start_or_elapsed() >= 0.2) - power_off(); - } - } - else + if (now_powered) + power_loss_timer.stop(); + else { + if (power_loss_timer.start_or_elapsed() >= 0.2) + power_off(); + } + } else { - if (now_powered) - power_on(); + if (now_powered) + power_on(); } } void MK_VIII::PowerHandler::power_on () { - powered = true; - mk->system_handler.power_on(); + powered = true; + mk->system_handler.power_on(); } void MK_VIII::PowerHandler::power_off () { - powered = false; - mk->system_handler.power_off(); - mk->voice_player.stop(VoicePlayer::STOP_NOW); - mk->self_test_handler.power_off(); // run before IOHandler::power_off() - mk->io_handler.power_off(); - mk->mode2_handler.power_off(); - mk->mode6_handler.power_off(); + powered = false; + mk->system_handler.power_off(); + mk->voice_player.stop(VoicePlayer::STOP_NOW); + mk->self_test_handler.power_off(); // run before IOHandler::power_off() + mk->io_handler.power_off(); + mk->mode2_handler.power_off(); + mk->mode6_handler.power_off(); } /////////////////////////////////////////////////////////////////////////////// @@ -281,74 +279,74 @@ MK_VIII::PowerHandler::power_off () void MK_VIII::SystemHandler::power_on () { - state = STATE_BOOTING; + state = STATE_BOOTING; - // [SPEC] 3.5.2 mentions a 20 seconds maximum boot delay. We use a - // random delay between 3 and 5 seconds. + // [SPEC] 3.5.2 mentions a 20 seconds maximum boot delay. We use a + // random delay between 3 and 5 seconds. - boot_delay = 3 + sg_random() * 2; - boot_timer.start(); + boot_delay = 3 + sg_random() * 2; + boot_timer.start(); } void MK_VIII::SystemHandler::power_off () { - state = STATE_OFF; + state = STATE_OFF; - boot_timer.stop(); + boot_timer.stop(); } void MK_VIII::SystemHandler::update () { - if (state == STATE_BOOTING) + if (state == STATE_BOOTING) { - if (boot_timer.elapsed() >= boot_delay) - { - last_replay_state = mk_node(replay_state)->getIntValue(); + if (boot_timer.elapsed() >= boot_delay) + { + last_replay_state = mk_node(replay_state)->getIntValue(); - mk->configuration_module.boot(); + mk->configuration_module.boot(); - mk->io_handler.boot(); - mk->fault_handler.boot(); - mk->alert_handler.boot(); + mk->io_handler.boot(); + mk->fault_handler.boot(); + mk->alert_handler.boot(); - // inputs are needed by the following boot() routines - mk->io_handler.update_inputs(); + // inputs are needed by the following boot() routines + mk->io_handler.update_inputs(); - mk->mode2_handler.boot(); - mk->mode6_handler.boot(); + mk->mode2_handler.boot(); + mk->mode6_handler.boot(); - state = STATE_ON; + state = STATE_ON; - mk->io_handler.post_boot(); - } + mk->io_handler.post_boot(); + } } - else if (state != STATE_OFF && mk->configuration_module.state == ConfigurationModule::STATE_OK) + else if (state != STATE_OFF && mk->configuration_module.state == ConfigurationModule::STATE_OK) { - // If the replay state changes, switch to reposition mode for 3 - // seconds ([SPEC] 6.0.5) to avoid spurious alerts. + // If the replay state changes, switch to reposition mode for 3 + // seconds ([SPEC] 6.0.5) to avoid spurious alerts. - int replay_state = mk_node(replay_state)->getIntValue(); - if (replay_state != last_replay_state) - { - mk->alert_handler.reposition(); - mk->io_handler.reposition(); + int replay_state = mk_node(replay_state)->getIntValue(); + if (replay_state != last_replay_state) + { + mk->alert_handler.reposition(); + mk->io_handler.reposition(); - last_replay_state = replay_state; - state = STATE_REPOSITION; - reposition_timer.start(); - } + last_replay_state = replay_state; + state = STATE_REPOSITION; + reposition_timer.start(); + } - if (state == STATE_REPOSITION && reposition_timer.elapsed() >= 3) - { - // inputs are needed by StateHandler::post_reposition() - mk->io_handler.update_inputs(); + if (state == STATE_REPOSITION && reposition_timer.elapsed() >= 3) + { + // inputs are needed by StateHandler::post_reposition() + mk->io_handler.update_inputs(); - mk->state_handler.post_reposition(); + mk->state_handler.post_reposition(); - state = STATE_ON; - } + state = STATE_ON; + } } } @@ -357,26 +355,26 @@ MK_VIII::SystemHandler::update () /////////////////////////////////////////////////////////////////////////////// MK_VIII::ConfigurationModule::ConfigurationModule (MK_VIII *device) - : state(STATE_OK), mk(device) + : state(STATE_OK), mk(device) { - // arbitrary defaults - categories[CATEGORY_AIRCRAFT_MODE_TYPE_SELECT] = 0; - categories[CATEGORY_AIR_DATA_INPUT_SELECT] = 1; - categories[CATEGORY_POSITION_INPUT_SELECT] = 2; - categories[CATEGORY_ALTITUDE_CALLOUTS] = 13; - categories[CATEGORY_AUDIO_MENU_SELECT] = 0; - categories[CATEGORY_TERRAIN_DISPLAY_SELECT] = 1; - categories[CATEGORY_OPTIONS_SELECT_GROUP_1] = 124; - categories[CATEGORY_RADIO_ALTITUDE_INPUT_SELECT] = 2; - categories[CATEGORY_NAVIGATION_INPUT_SELECT] = 3; - categories[CATEGORY_ATTITUDE_INPUT_SELECT] = 6; - categories[CATEGORY_HEADING_INPUT_SELECT] = 2; - categories[CATEGORY_WINDSHEAR_INPUT_SELECT] = 0; - categories[CATEGORY_INPUT_OUTPUT_DISCRETE_TYPE_SELECT] = 7; - categories[CATEGORY_AUDIO_OUTPUT_LEVEL] = 0; - categories[CATEGORY_UNDEFINED_INPUT_SELECT_1] = 0; - categories[CATEGORY_UNDEFINED_INPUT_SELECT_2] = 0; - categories[CATEGORY_UNDEFINED_INPUT_SELECT_3] = 0; + // arbitrary defaults + categories[CATEGORY_AIRCRAFT_MODE_TYPE_SELECT] = 0; + categories[CATEGORY_AIR_DATA_INPUT_SELECT] = 1; + categories[CATEGORY_POSITION_INPUT_SELECT] = 2; + categories[CATEGORY_ALTITUDE_CALLOUTS] = 13; + categories[CATEGORY_AUDIO_MENU_SELECT] = 0; + categories[CATEGORY_TERRAIN_DISPLAY_SELECT] = 1; + categories[CATEGORY_OPTIONS_SELECT_GROUP_1] = 124; + categories[CATEGORY_RADIO_ALTITUDE_INPUT_SELECT] = 2; + categories[CATEGORY_NAVIGATION_INPUT_SELECT] = 3; + categories[CATEGORY_ATTITUDE_INPUT_SELECT] = 6; + categories[CATEGORY_HEADING_INPUT_SELECT] = 2; + categories[CATEGORY_WINDSHEAR_INPUT_SELECT] = 0; + categories[CATEGORY_INPUT_OUTPUT_DISCRETE_TYPE_SELECT] = 7; + categories[CATEGORY_AUDIO_OUTPUT_LEVEL] = 0; + categories[CATEGORY_UNDEFINED_INPUT_SELECT_1] = 0; + categories[CATEGORY_UNDEFINED_INPUT_SELECT_2] = 0; + categories[CATEGORY_UNDEFINED_INPUT_SELECT_3] = 0; } static double m1_t1_min_agl1 (double vs) { return -1620 - 1.1133 * vs; } @@ -389,12 +387,12 @@ static double m3_t1_max_alt_loss (bool flap_override, double agl) { return 5.4 + static int m3_t2_max_agl (bool flap_override) { return flap_override ? 815 : 925; } static double m3_t2_max_alt_loss (bool flap_override, double agl) { - int bias = agl > 700 ? 5 : 0; + int bias = agl > 700 ? 5 : 0; - if (flap_override) - return (9.0 + 0.184 * agl) + bias; - else - return (5.4 + 0.092 * agl) + bias; + if (flap_override) + return (9.0 + 0.184 * agl) + bias; + else + return (5.4 + 0.092 * agl) + bias; } static double m4_t1_min_agl2 (double airspeed) { return -1083 + 8.333 * airspeed; } @@ -405,471 +403,482 @@ static double m4_t79_b_min_agl2 (double airspeed) { return -1222 + 11.6 * airspe bool MK_VIII::ConfigurationModule::m6_t2_is_bank_angle (Parameter *agl, - double abs_roll_deg, - bool ap_engaged) + double abs_roll_deg, + bool ap_engaged) { - if (ap_engaged) + if (ap_engaged) { - if (agl->ncd || agl->get() > 122) - return abs_roll_deg > 33; + if (agl->ncd || agl->get() > 122) + return abs_roll_deg > 33; } - else + else { - if (agl->ncd || agl->get() > 2450) - return abs_roll_deg > 55; - else if (agl->get() > 150) - return agl->get() < 153.33333 * abs_roll_deg - 5983.3333; + if (agl->ncd || agl->get() > 2450) + return abs_roll_deg > 55; + else if (agl->get() > 150) + return agl->get() < 153.33333 * abs_roll_deg - 5983.3333; } - if (agl->get() > 30) - return agl->get() < 4 * abs_roll_deg - 10; - else if (agl->get() > 5) - return abs_roll_deg > 10; + if (agl->get() > 30) + return agl->get() < 4 * abs_roll_deg - 10; + else if (agl->get() > 5) + return abs_roll_deg > 10; - return false; + return false; } bool MK_VIII::ConfigurationModule::m6_t4_is_bank_angle (Parameter *agl, - double abs_roll_deg, - bool ap_engaged) + double abs_roll_deg, + bool ap_engaged) { - if (ap_engaged) + if (ap_engaged) { - if (agl->ncd || agl->get() > 156) - return abs_roll_deg > 33; + if (agl->ncd || agl->get() > 156) + return abs_roll_deg > 33; } - else + else { - if (agl->ncd || agl->get() > 210) - return abs_roll_deg > 50; + if (agl->ncd || agl->get() > 210) + return abs_roll_deg > 50; } - if (agl->get() > 10) - return agl->get() < 5.7142857 * abs_roll_deg - 75.714286; + if (agl->get() > 10) + return agl->get() < 5.7142857 * abs_roll_deg - 75.714286; - return false; + return false; } bool MK_VIII::ConfigurationModule::read_aircraft_mode_type_select (int value) { - static const Mode1Handler::EnvelopesConfiguration m1_t1 = - { false, 10, m1_t1_min_agl1, 284, m1_t1_min_agl2, 2450 }; - static const Mode1Handler::EnvelopesConfiguration m1_t4 = - { true, 50, m1_t4_min_agl1, 346, m1_t4_min_agl2, 1958 }; + static const Mode1Handler::EnvelopesConfiguration m1_t1 = + { false, 10, m1_t1_min_agl1, 284, m1_t1_min_agl2, 2450 }; + static const Mode1Handler::EnvelopesConfiguration m1_t4 = + { true, 50, m1_t4_min_agl1, 346, m1_t4_min_agl2, 1958 }; - static const Mode2Handler::Configuration m2_t1 = { 190, 280 }; - static const Mode2Handler::Configuration m2_t4 = { 220, 310 }; - static const Mode2Handler::Configuration m2_t5 = { 220, 310 }; + static const Mode2Handler::Configuration m2_t1 = { 190, 280 }; + static const Mode2Handler::Configuration m2_t4 = { 220, 310 }; + static const Mode2Handler::Configuration m2_t5 = { 220, 310 }; - static const Mode3Handler::Configuration m3_t1 = - { 30, m3_t1_max_agl, m3_t1_max_alt_loss }; - static const Mode3Handler::Configuration m3_t2 = - { 50, m3_t2_max_agl, m3_t2_max_alt_loss }; + static const Mode3Handler::Configuration m3_t1 = + { 30, m3_t1_max_agl, m3_t1_max_alt_loss }; + static const Mode3Handler::Configuration m3_t2 = + { 50, m3_t2_max_agl, m3_t2_max_alt_loss }; - static const Mode4Handler::EnvelopesConfiguration m4_t1_ac = - { 190, 250, 500, m4_t1_min_agl2, 1000 }; - static const Mode4Handler::EnvelopesConfiguration m4_t5_ac = - { 178, 200, 500, m4_t568_a_min_agl2, 1000 }; - static const Mode4Handler::EnvelopesConfiguration m4_t68_ac = - { 178, 200, 500, m4_t568_a_min_agl2, 750 }; - static const Mode4Handler::EnvelopesConfiguration m4_t79_ac = - { 148, 170, 500, m4_t79_a_min_agl2, 750 }; + static const Mode4Handler::EnvelopesConfiguration m4_t1_ac = + { 190, 250, 500, m4_t1_min_agl2, 1000 }; + static const Mode4Handler::EnvelopesConfiguration m4_t5_ac = + { 178, 200, 500, m4_t568_a_min_agl2, 1000 }; + static const Mode4Handler::EnvelopesConfiguration m4_t68_ac = + { 178, 200, 500, m4_t568_a_min_agl2, 750 }; + static const Mode4Handler::EnvelopesConfiguration m4_t79_ac = + { 148, 170, 500, m4_t79_a_min_agl2, 750 }; - static const Mode4Handler::EnvelopesConfiguration m4_t1_b = - { 159, 250, 245, m4_t1_min_agl2, 1000 }; - static const Mode4Handler::EnvelopesConfiguration m4_t5_b = - { 148, 200, 200, m4_t568_b_min_agl2, 1000 }; - static const Mode4Handler::EnvelopesConfiguration m4_t6_b = - { 150, 200, 170, m4_t568_b_min_agl2, 750 }; - static const Mode4Handler::EnvelopesConfiguration m4_t7_b = - { 120, 170, 170, m4_t79_b_min_agl2, 750 }; - static const Mode4Handler::EnvelopesConfiguration m4_t8_b = - { 148, 200, 150, m4_t568_b_min_agl2, 750 }; - static const Mode4Handler::EnvelopesConfiguration m4_t9_b = - { 118, 170, 150, m4_t79_b_min_agl2, 750 }; + static const Mode4Handler::EnvelopesConfiguration m4_t1_b = + { 159, 250, 245, m4_t1_min_agl2, 1000 }; + static const Mode4Handler::EnvelopesConfiguration m4_t5_b = + { 148, 200, 200, m4_t568_b_min_agl2, 1000 }; + static const Mode4Handler::EnvelopesConfiguration m4_t6_b = + { 150, 200, 170, m4_t568_b_min_agl2, 750 }; + static const Mode4Handler::EnvelopesConfiguration m4_t7_b = + { 120, 170, 170, m4_t79_b_min_agl2, 750 }; + static const Mode4Handler::EnvelopesConfiguration m4_t8_b = + { 148, 200, 150, m4_t568_b_min_agl2, 750 }; + static const Mode4Handler::EnvelopesConfiguration m4_t9_b = + { 118, 170, 150, m4_t79_b_min_agl2, 750 }; - static const Mode4Handler::ModesConfiguration m4_t1 = { &m4_t1_ac, &m4_t1_b }; - static const Mode4Handler::ModesConfiguration m4_t5 = { &m4_t5_ac, &m4_t5_b }; - static const Mode4Handler::ModesConfiguration m4_t6 = { &m4_t68_ac, &m4_t6_b }; - static const Mode4Handler::ModesConfiguration m4_t7 = { &m4_t79_ac, &m4_t7_b }; - static const Mode4Handler::ModesConfiguration m4_t8 = { &m4_t68_ac, &m4_t8_b }; - static const Mode4Handler::ModesConfiguration m4_t9 = { &m4_t79_ac, &m4_t9_b }; + static const Mode4Handler::ModesConfiguration m4_t1 = { &m4_t1_ac, &m4_t1_b }; + static const Mode4Handler::ModesConfiguration m4_t5 = { &m4_t5_ac, &m4_t5_b }; + static const Mode4Handler::ModesConfiguration m4_t6 = { &m4_t68_ac, &m4_t6_b }; + static const Mode4Handler::ModesConfiguration m4_t7 = { &m4_t79_ac, &m4_t7_b }; + static const Mode4Handler::ModesConfiguration m4_t8 = { &m4_t68_ac, &m4_t8_b }; + static const Mode4Handler::ModesConfiguration m4_t9 = { &m4_t79_ac, &m4_t9_b }; - static Mode6Handler::BankAnglePredicate m6_t2 = m6_t2_is_bank_angle; - static Mode6Handler::BankAnglePredicate m6_t4 = m6_t4_is_bank_angle; + static Mode6Handler::BankAnglePredicate m6_t2 = m6_t2_is_bank_angle; + static Mode6Handler::BankAnglePredicate m6_t4 = m6_t4_is_bank_angle; - static const IOHandler::FaultsConfiguration f_slow = { 180, 200 }; - static const IOHandler::FaultsConfiguration f_fast = { 250, 290 }; + static const IOHandler::FaultsConfiguration f_slow = { 180, 200 }; + static const IOHandler::FaultsConfiguration f_fast = { 250, 290 }; - static const struct - { - int type; - const Mode1Handler::EnvelopesConfiguration *m1; - const Mode2Handler::Configuration *m2; - const Mode3Handler::Configuration *m3; - const Mode4Handler::ModesConfiguration *m4; - Mode6Handler::BankAnglePredicate m6; - const IOHandler::FaultsConfiguration *f; - int runway_database; - } aircraft_types[] = { - { 0, &m1_t4, &m2_t4, &m3_t2, &m4_t6, m6_t4, &f_fast, 2000 }, - { 1, &m1_t4, &m2_t4, &m3_t2, &m4_t8, m6_t4, &f_fast, 2000 }, - { 2, &m1_t4, &m2_t4, &m3_t2, &m4_t5, m6_t4, &f_fast, 2000 }, - { 3, &m1_t4, &m2_t5, &m3_t2, &m4_t7, m6_t4, &f_slow, 2000 }, - { 4, &m1_t4, &m2_t5, &m3_t2, &m4_t9, m6_t4, &f_slow, 2000 }, - { 254, &m1_t1, &m2_t1, &m3_t1, &m4_t1, m6_t2, &f_fast, 3500 }, - { 255, &m1_t1, &m2_t1, &m3_t1, &m4_t1, m6_t2, &f_fast, 2000 } - }; + static const struct + { + int type; + const Mode1Handler::EnvelopesConfiguration *m1; + const Mode2Handler::Configuration *m2; + const Mode3Handler::Configuration *m3; + const Mode4Handler::ModesConfiguration *m4; + Mode6Handler::BankAnglePredicate m6; + const IOHandler::FaultsConfiguration *f; + int runway_database; + } aircraft_types[] = { + { 0, &m1_t4, &m2_t4, &m3_t2, &m4_t6, m6_t4, &f_fast, 2000 }, + { 1, &m1_t4, &m2_t4, &m3_t2, &m4_t8, m6_t4, &f_fast, 2000 }, + { 2, &m1_t4, &m2_t4, &m3_t2, &m4_t5, m6_t4, &f_fast, 2000 }, + { 3, &m1_t4, &m2_t5, &m3_t2, &m4_t7, m6_t4, &f_slow, 2000 }, + { 4, &m1_t4, &m2_t5, &m3_t2, &m4_t9, m6_t4, &f_slow, 2000 }, + { 254, &m1_t1, &m2_t1, &m3_t1, &m4_t1, m6_t2, &f_fast, 3500 }, + { 255, &m1_t1, &m2_t1, &m3_t1, &m4_t1, m6_t2, &f_fast, 2000 } + }; - for (size_t i = 0; i < n_elements(aircraft_types); i++) - if (aircraft_types[i].type == value) - { - mk->mode1_handler.conf.envelopes = aircraft_types[i].m1; - mk->mode2_handler.conf = aircraft_types[i].m2; - mk->mode3_handler.conf = aircraft_types[i].m3; - mk->mode4_handler.conf.modes = aircraft_types[i].m4; - mk->mode6_handler.conf.is_bank_angle = aircraft_types[i].m6; - mk->io_handler.conf.faults = aircraft_types[i].f; - mk->conf.runway_database = aircraft_types[i].runway_database; - return true; - } + for (size_t i = 0; i < n_elements(aircraft_types); i++) + { + if (aircraft_types[i].type == value) + { + mk->mode1_handler.conf.envelopes = aircraft_types[i].m1; + mk->mode2_handler.conf = aircraft_types[i].m2; + mk->mode3_handler.conf = aircraft_types[i].m3; + mk->mode4_handler.conf.modes = aircraft_types[i].m4; + mk->mode6_handler.conf.is_bank_angle = aircraft_types[i].m6; + mk->io_handler.conf.faults = aircraft_types[i].f; + mk->conf.runway_database = aircraft_types[i].runway_database; + return true; + } + } - state = STATE_INVALID_AIRCRAFT_TYPE; - return false; + state = STATE_INVALID_AIRCRAFT_TYPE; + return false; } bool MK_VIII::ConfigurationModule::read_air_data_input_select (int value) { - // unimplemented - return (value >= 0 && value <= 6) || (value >= 10 && value <= 13) || value == 255; + // unimplemented + return (value >= 0 && value <= 6) || (value >= 10 && value <= 13) || value == 255; } bool MK_VIII::ConfigurationModule::read_position_input_select (int value) { - if (value == 2) - mk->io_handler.conf.use_internal_gps = true; - else if ((value >= 0 && value <= 5) - || (value >= 10 && value <= 13) - || (value == 253) - || (value == 255)) - mk->io_handler.conf.use_internal_gps = false; - else - return false; + if (value == 2) + mk->io_handler.conf.use_internal_gps = true; + else if ((value >= 0 && value <= 5) + || (value >= 10 && value <= 13) + || (value == 253) + || (value == 255)) + mk->io_handler.conf.use_internal_gps = false; + else + return false; - return true; + return true; } bool MK_VIII::ConfigurationModule::read_altitude_callouts (int value) { - enum - { - MINIMUMS = -1, - SMART_500 = -2, - FIELD_500 = -3, - FIELD_500_ABOVE = -4, - MINIMUMS_ABOVE_100 = -5, - RETARD = -6 - }; + enum + { + MINIMUMS = -1, + SMART_500 = -2, + FIELD_500 = -3, + FIELD_500_ABOVE = -4, + MINIMUMS_ABOVE_100 = -5, + RETARD = -6 + }; - static const struct - { - int id; - int callouts[16]; - } values[] = { - { 0, { MINIMUMS, SMART_500, 200, 100, 50, 40, 30, 20, 10, 0 } }, - { 1, { MINIMUMS, SMART_500, 200, 0 } }, - { 2, { MINIMUMS, SMART_500, 100, 50, 40, 30, 20, 10, 0 } }, - { 3, { MINIMUMS, SMART_500, 0 } }, - { 4, { MINIMUMS, 200, 100, 50, 40, 30, 20, 10, 0 } }, - { 5, { MINIMUMS, 200, 0 } }, - { 6, { MINIMUMS, 100, 50, 40, 30, 20, 10, 0 } }, - { 7, { 0 } }, - { 8, { MINIMUMS, 0 } }, - { 9, { MINIMUMS, 500, 200, 100, 50, 40, 30, 20, 10, 0 } }, - { 10, { MINIMUMS, 500, 200, 0 } }, - { 11, { MINIMUMS, 500, 100, 50, 40, 30, 20, 10, 0 } }, - { 12, { MINIMUMS, 500, 0 } }, - { 13, { MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30, 20, 10, 0 } }, - { 14, { MINIMUMS, 100, 0 } }, - { 15, { MINIMUMS, 200, 100, 0 } }, - { 100, { FIELD_500, 0 } }, - { 101, { FIELD_500_ABOVE, 0 } }, - {1000, { RETARD, MINIMUMS_ABOVE_100, MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, - {1001, { RETARD, MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, - {1002, { MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, - {1010, { RETARD, MINIMUMS_ABOVE_100, MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, - {1011, { RETARD, MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, - }; + static const struct + { + int id; + int callouts[16]; + } values[] = { + { 0, { MINIMUMS, SMART_500, 200, 100, 50, 40, 30, 20, 10, 0 } }, + { 1, { MINIMUMS, SMART_500, 200, 0 } }, + { 2, { MINIMUMS, SMART_500, 100, 50, 40, 30, 20, 10, 0 } }, + { 3, { MINIMUMS, SMART_500, 0 } }, + { 4, { MINIMUMS, 200, 100, 50, 40, 30, 20, 10, 0 } }, + { 5, { MINIMUMS, 200, 0 } }, + { 6, { MINIMUMS, 100, 50, 40, 30, 20, 10, 0 } }, + { 7, { 0 } }, + { 8, { MINIMUMS, 0 } }, + { 9, { MINIMUMS, 500, 200, 100, 50, 40, 30, 20, 10, 0 } }, + { 10, { MINIMUMS, 500, 200, 0 } }, + { 11, { MINIMUMS, 500, 100, 50, 40, 30, 20, 10, 0 } }, + { 12, { MINIMUMS, 500, 0 } }, + { 13, { MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30, 20, 10, 0 } }, + { 14, { MINIMUMS, 100, 0 } }, + { 15, { MINIMUMS, 200, 100, 0 } }, + { 100, { FIELD_500, 0 } }, + { 101, { FIELD_500_ABOVE, 0 } }, + {1000, { RETARD, MINIMUMS_ABOVE_100, MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, + {1001, { RETARD, MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, + {1002, { MINIMUMS, 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, + {1010, { RETARD, MINIMUMS_ABOVE_100, MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, + {1011, { RETARD, MINIMUMS, 1000, 500, 400, 300, 200, 100, 50, 40, 30,20, 10, 0 } }, + }; - mk->mode6_handler.conf.retard_enabled = false; - mk->mode6_handler.conf.minimums_above_100_enabled = false; - mk->mode6_handler.conf.minimums_enabled = false; - mk->mode6_handler.conf.smart_500_enabled = false; - mk->mode6_handler.conf.above_field_voice = NULL; - mk->mode6_handler.conf.altitude_callouts_enabled = 0; + mk->mode6_handler.conf.retard_enabled = false; + mk->mode6_handler.conf.minimums_above_100_enabled = false; + mk->mode6_handler.conf.minimums_enabled = false; + mk->mode6_handler.conf.smart_500_enabled = false; + mk->mode6_handler.conf.above_field_voice = NULL; + mk->mode6_handler.conf.altitude_callouts_enabled = 0; - for (unsigned int i = 0; i < n_elements(values); i++) - if (values[i].id == value) - { - for (int j = 0; values[i].callouts[j] != 0; j++) - switch (values[i].callouts[j]) - { - case RETARD: - mk->mode6_handler.conf.retard_enabled = true; - break; + for (unsigned int i = 0; i < n_elements(values); i++) + { + if (values[i].id == value) + { + for (int j = 0; values[i].callouts[j] != 0; j++) + { + switch (values[i].callouts[j]) + { + case RETARD: + mk->mode6_handler.conf.retard_enabled = true; + break; - case MINIMUMS_ABOVE_100: - mk->mode6_handler.conf.minimums_above_100_enabled = true; - break; + case MINIMUMS_ABOVE_100: + mk->mode6_handler.conf.minimums_above_100_enabled = true; + break; - case MINIMUMS: - mk->mode6_handler.conf.minimums_enabled = true; - break; + case MINIMUMS: + mk->mode6_handler.conf.minimums_enabled = true; + break; - case SMART_500: - mk->mode6_handler.conf.smart_500_enabled = true; - break; + case SMART_500: + mk->mode6_handler.conf.smart_500_enabled = true; + break; - case FIELD_500: - mk->mode6_handler.conf.above_field_voice = mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_500); - break; + case FIELD_500: + mk->mode6_handler.conf.above_field_voice = mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_500); + break; - case FIELD_500_ABOVE: - mk->mode6_handler.conf.above_field_voice = mk_voice(five_hundred_above); - break; + case FIELD_500_ABOVE: + mk->mode6_handler.conf.above_field_voice = mk_voice(five_hundred_above); + break; - default: - for (unsigned k = 0; k < n_altitude_callouts; k++) - if (mk->mode6_handler.altitude_callout_definitions[k] == values[i].callouts[j]) - mk->mode6_handler.conf.altitude_callouts_enabled |= 1 << k; - break; - } + default: + for (unsigned k = 0; k < n_altitude_callouts; k++) + if (mk->mode6_handler.altitude_callout_definitions[k] == values[i].callouts[j]) + mk->mode6_handler.conf.altitude_callouts_enabled |= 1 << k; + break; + } + } - return true; - } - - return false; + return true; + } + } + return false; } bool MK_VIII::ConfigurationModule::read_audio_menu_select (int value) { - if (value == 0 || value == 1) - mk->mode4_handler.conf.voice_too_low_gear = mk_voice(too_low_gear); - else if (value == 2 || value == 3) - mk->mode4_handler.conf.voice_too_low_gear = mk_voice(too_low_flaps); - else - return false; + if (value == 0 || value == 1) + mk->mode4_handler.conf.voice_too_low_gear = mk_voice(too_low_gear); + else if (value == 2 || value == 3) + mk->mode4_handler.conf.voice_too_low_gear = mk_voice(too_low_flaps); + else + return false; - return true; + return true; } bool MK_VIII::ConfigurationModule::read_terrain_display_select (int value) { - if (value == 2) - mk->tcf_handler.conf.enabled = false; - else if (value == 0 || value == 1 || (value >= 3 && value <= 15) - || (value >= 18 && value <= 20) || (value >= 235 && value <= 255)) - mk->tcf_handler.conf.enabled = true; - else - return false; + if (value == 2) + mk->tcf_handler.conf.enabled = false; + else if (value == 0 || value == 1 || (value >= 3 && value <= 15) + || (value >= 18 && value <= 20) || (value >= 235 && value <= 255)) + mk->tcf_handler.conf.enabled = true; + else + return false; - return true; + return true; } bool MK_VIII::ConfigurationModule::read_options_select_group_1 (int value) { - if (value >= 0 && value < 128) + if (value >= 0 && value < 128) { - mk->io_handler.conf.flap_reversal = test_bits(value, 1 << 1); - mk->mode6_handler.conf.bank_angle_enabled = test_bits(value, 1 << 2); - mk->io_handler.conf.steep_approach_enabled = test_bits(value, 1 << 6); - return true; + mk->io_handler.conf.flap_reversal = test_bits(value, 1 << 1); + mk->mode6_handler.conf.bank_angle_enabled = test_bits(value, 1 << 2); + mk->io_handler.conf.steep_approach_enabled = test_bits(value, 1 << 6); + return true; } - else + return false; } bool MK_VIII::ConfigurationModule::read_radio_altitude_input_select (int value) { - mk->io_handler.conf.altitude_source = value; - return (value >= 0 && value <= 4) || (value >= 251 && value <= 255); + mk->io_handler.conf.altitude_source = value; + return (value >= 0 && value <= 4) || (value >= 251 && value <= 255); } bool MK_VIII::ConfigurationModule::read_navigation_input_select (int value) { - if (value >= 0 && value <= 2) - mk->io_handler.conf.localizer_enabled = false; - else if ((value >= 3 && value <= 5) || (value >= 250 && value <= 255)) - mk->io_handler.conf.localizer_enabled = true; - else - return false; + if (value >= 0 && value <= 2) + mk->io_handler.conf.localizer_enabled = false; + else if ((value >= 3 && value <= 5) || (value >= 250 && value <= 255)) + mk->io_handler.conf.localizer_enabled = true; + else + return false; - return true; + return true; } bool MK_VIII::ConfigurationModule::read_attitude_input_select (int value) { - if (value == 2) - mk->io_handler.conf.use_attitude_indicator=true; - else - mk->io_handler.conf.use_attitude_indicator=false; - return (value >= 0 && value <= 6) || value == 253 || value == 255; + if (value == 2) + mk->io_handler.conf.use_attitude_indicator=true; + else + mk->io_handler.conf.use_attitude_indicator=false; + return (value >= 0 && value <= 6) || value == 253 || value == 255; } bool MK_VIII::ConfigurationModule::read_heading_input_select (int value) { - // unimplemented - return (value >= 0 && value <= 3) || value == 254 || value == 255; + // unimplemented + return (value >= 0 && value <= 3) || value == 254 || value == 255; } bool MK_VIII::ConfigurationModule::read_windshear_input_select (int value) { - // unimplemented - return value == 0 || (value >= 253 && value <= 255); + // unimplemented + return value == 0 || (value >= 253 && value <= 255); } bool MK_VIII::ConfigurationModule::read_input_output_discrete_type_select (int value) { - static const struct - { - int type; - IOHandler::LampConfiguration lamp_conf; - bool gpws_inhibit_enabled; - bool momentary_flap_override_enabled; - bool alternate_steep_approach; - } io_types[] = { - { 0, { false, false }, false, true, true }, - { 1, { true, false }, false, true, true }, - { 2, { false, false }, true, true, true }, - { 3, { true, false }, true, true, true }, - { 4, { false, true }, true, true, true }, - { 5, { true, true }, true, true, true }, - { 6, { false, false }, true, true, false }, - { 7, { true, false }, true, true, false }, - { 254, { false, false }, true, false, true }, - { 255, { false, false }, true, false, true } - }; + static const struct + { + int type; + IOHandler::LampConfiguration lamp_conf; + bool gpws_inhibit_enabled; + bool momentary_flap_override_enabled; + bool alternate_steep_approach; + } io_types[] = { + { 0, { false, false }, false, true, true }, + { 1, { true, false }, false, true, true }, + { 2, { false, false }, true, true, true }, + { 3, { true, false }, true, true, true }, + { 4, { false, true }, true, true, true }, + { 5, { true, true }, true, true, true }, + { 6, { false, false }, true, true, false }, + { 7, { true, false }, true, true, false }, + { 254, { false, false }, true, false, true }, + { 255, { false, false }, true, false, true } + }; - for (size_t i = 0; i < n_elements(io_types); i++) - if (io_types[i].type == value) - { - mk->io_handler.conf.lamp = &io_types[i].lamp_conf; - mk->io_handler.conf.gpws_inhibit_enabled = io_types[i].gpws_inhibit_enabled; - mk->io_handler.conf.momentary_flap_override_enabled = io_types[i].momentary_flap_override_enabled; - mk->io_handler.conf.alternate_steep_approach = io_types[i].alternate_steep_approach; - return true; - } + for (size_t i = 0; i < n_elements(io_types); i++) + { + if (io_types[i].type == value) + { + mk->io_handler.conf.lamp = &io_types[i].lamp_conf; + mk->io_handler.conf.gpws_inhibit_enabled = io_types[i].gpws_inhibit_enabled; + mk->io_handler.conf.momentary_flap_override_enabled = io_types[i].momentary_flap_override_enabled; + mk->io_handler.conf.alternate_steep_approach = io_types[i].alternate_steep_approach; + return true; + } + } - return false; + return false; } bool MK_VIII::ConfigurationModule::read_audio_output_level (int value) { - static const struct - { - int id; - int relative_dB; - } values[] = { - { 0, 0 }, - { 1, -6 }, - { 2, -12 }, - { 3, -18 }, - { 4, -24 } - }; + static const struct + { + int id; + int relative_dB; + } values[] = { + { 0, 0 }, + { 1, -6 }, + { 2, -12 }, + { 3, -18 }, + { 4, -24 } + }; - for (size_t i = 0; i < n_elements(values); i++) - if (values[i].id == value) - { - mk->voice_player.set_volume(mk->voice_player.conf.volume = modify_amplitude(1.0, values[i].relative_dB)); - return true; - } + for (size_t i = 0; i < n_elements(values); i++) + { + if (values[i].id == value) + { + mk->voice_player.set_volume(mk->voice_player.conf.volume = modify_amplitude(1.0, values[i].relative_dB)); + return true; + } + } - // The self test needs the voice player even when the configuration - // is invalid, so set a default value. - mk->voice_player.set_volume(mk->voice_player.conf.volume = 1.0); - return false; + // The self test needs the voice player even when the configuration + // is invalid, so set a default value. + mk->voice_player.set_volume(mk->voice_player.conf.volume = 1.0); + return false; } bool MK_VIII::ConfigurationModule::read_undefined_input_select (int value) { - // unimplemented - return value == 0; + // unimplemented + return value == 0; } void MK_VIII::ConfigurationModule::boot () { - bool (MK_VIII::ConfigurationModule::*readers[N_CATEGORIES]) (int) = { - &MK_VIII::ConfigurationModule::read_aircraft_mode_type_select, - &MK_VIII::ConfigurationModule::read_air_data_input_select, - &MK_VIII::ConfigurationModule::read_position_input_select, - &MK_VIII::ConfigurationModule::read_altitude_callouts, - &MK_VIII::ConfigurationModule::read_audio_menu_select, - &MK_VIII::ConfigurationModule::read_terrain_display_select, - &MK_VIII::ConfigurationModule::read_options_select_group_1, - &MK_VIII::ConfigurationModule::read_radio_altitude_input_select, - &MK_VIII::ConfigurationModule::read_navigation_input_select, - &MK_VIII::ConfigurationModule::read_attitude_input_select, - &MK_VIII::ConfigurationModule::read_heading_input_select, - &MK_VIII::ConfigurationModule::read_windshear_input_select, - &MK_VIII::ConfigurationModule::read_input_output_discrete_type_select, - &MK_VIII::ConfigurationModule::read_audio_output_level, - &MK_VIII::ConfigurationModule::read_undefined_input_select, - &MK_VIII::ConfigurationModule::read_undefined_input_select, - &MK_VIII::ConfigurationModule::read_undefined_input_select - }; + bool (MK_VIII::ConfigurationModule::*readers[N_CATEGORIES]) (int) = { + &MK_VIII::ConfigurationModule::read_aircraft_mode_type_select, + &MK_VIII::ConfigurationModule::read_air_data_input_select, + &MK_VIII::ConfigurationModule::read_position_input_select, + &MK_VIII::ConfigurationModule::read_altitude_callouts, + &MK_VIII::ConfigurationModule::read_audio_menu_select, + &MK_VIII::ConfigurationModule::read_terrain_display_select, + &MK_VIII::ConfigurationModule::read_options_select_group_1, + &MK_VIII::ConfigurationModule::read_radio_altitude_input_select, + &MK_VIII::ConfigurationModule::read_navigation_input_select, + &MK_VIII::ConfigurationModule::read_attitude_input_select, + &MK_VIII::ConfigurationModule::read_heading_input_select, + &MK_VIII::ConfigurationModule::read_windshear_input_select, + &MK_VIII::ConfigurationModule::read_input_output_discrete_type_select, + &MK_VIII::ConfigurationModule::read_audio_output_level, + &MK_VIII::ConfigurationModule::read_undefined_input_select, + &MK_VIII::ConfigurationModule::read_undefined_input_select, + &MK_VIII::ConfigurationModule::read_undefined_input_select + }; - memcpy(effective_categories, categories, sizeof(categories)); - state = STATE_OK; + memcpy(effective_categories, categories, sizeof(categories)); + state = STATE_OK; - for (int i = 0; i < N_CATEGORIES; i++) - if (! (this->*readers[i])(effective_categories[i])) - { - SG_LOG(SG_INSTR, SG_ALERT, "MK VIII EGPWS configuration category " << i + 1 << ": invalid value " << effective_categories[i]); - - if (state == STATE_OK) - state = STATE_INVALID_DATABASE; - - mk_doutput(gpws_inop) = true; - mk_doutput(tad_inop) = true; - - return; - } - - // handle conflicts - - if (mk->mode6_handler.conf.above_field_voice && ! mk->tcf_handler.conf.enabled) + for (int i = 0; i < N_CATEGORIES; i++) { - // [INSTALL] 3.6 - 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"); - state = STATE_INVALID_DATABASE; + if (! (this->*readers[i])(effective_categories[i])) + { + SG_LOG(SG_INSTR, SG_ALERT, "MK VIII EGPWS configuration category " << i + 1 << ": invalid value " << effective_categories[i]); + + if (state == STATE_OK) + state = STATE_INVALID_DATABASE; + + mk_doutput(gpws_inop) = true; + mk_doutput(tad_inop) = true; + + return; + } + } + + // handle conflicts + + if (mk->mode6_handler.conf.above_field_voice && ! mk->tcf_handler.conf.enabled) + { + // [INSTALL] 3.6 + 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"); + state = STATE_INVALID_DATABASE; } } void MK_VIII::ConfigurationModule::bind (SGPropertyNode *node) { - for (int i = 0; i < N_CATEGORIES; i++) + for (int i = 0; i < N_CATEGORIES; i++) { - std::ostringstream name; - name << "configuration-module/category-" << i + 1; - mk->properties_handler.tie(node, name.str().c_str(), SGRawValuePointer(&categories[i])); + std::ostringstream name; + name << "configuration-module/category-" << i + 1; + mk->properties_handler.tie(node, name.str().c_str(), SGRawValuePointer(&categories[i])); } } @@ -880,23 +889,23 @@ MK_VIII::ConfigurationModule::bind (SGPropertyNode *node) // [INSTALL] only specifies that the faults cause a GPWS INOP // indication. We arbitrarily set a TAD INOP when it makes sense. const unsigned int MK_VIII::FaultHandler::fault_inops[] = { - INOP_GPWS | INOP_TAD, // [INSTALL] 3.15.1.3 - INOP_GPWS, // [INSTALL] appendix E 6.6.2 - INOP_GPWS, // [INSTALL] appendix E 6.6.4 - INOP_GPWS, // [INSTALL] appendix E 6.6.6 - INOP_GPWS | INOP_TAD, // [INSTALL] appendix E 6.6.7 - INOP_GPWS, // [INSTALL] appendix E 6.6.13 - INOP_GPWS, // [INSTALL] appendix E 6.6.25 - INOP_GPWS, // [INSTALL] appendix E 6.6.27 - INOP_TAD, // unspecified - INOP_GPWS, // unspecified - INOP_GPWS, // unspecified - // [INSTALL] 2.3.10.1 specifies that GPWS INOP is "activated during - // any detected partial or total failure of the GPWS modes 1-5", so - // do not set any INOP for mode 6 and bank angle. - 0, // unspecified - 0, // unspecified - INOP_TAD // unspecified + INOP_GPWS | INOP_TAD, // [INSTALL] 3.15.1.3 + INOP_GPWS, // [INSTALL] appendix E 6.6.2 + INOP_GPWS, // [INSTALL] appendix E 6.6.4 + INOP_GPWS, // [INSTALL] appendix E 6.6.6 + INOP_GPWS | INOP_TAD, // [INSTALL] appendix E 6.6.7 + INOP_GPWS, // [INSTALL] appendix E 6.6.13 + INOP_GPWS, // [INSTALL] appendix E 6.6.25 + INOP_GPWS, // [INSTALL] appendix E 6.6.27 + INOP_TAD, // unspecified + INOP_GPWS, // unspecified + INOP_GPWS, // unspecified + // [INSTALL] 2.3.10.1 specifies that GPWS INOP is "activated during + // any detected partial or total failure of the GPWS modes 1-5", so + // do not set any INOP for mode 6 and bank angle. + 0, // unspecified + 0, // unspecified + INOP_TAD // unspecified }; bool @@ -908,55 +917,57 @@ MK_VIII::FaultHandler::has_faults () const bool MK_VIII::FaultHandler::has_faults (unsigned int inop) { - if (!faults) - return false; + if (!faults) + return false; - for (int i = 0; i < N_FAULTS; i++) - if ((faults & (1<self_test_handler.set_inop(); + mk->self_test_handler.set_inop(); - if (test_bits(fault_inops[fault], INOP_GPWS)) - { - mk_unset_alerts(~mk_alert(TCF_TOO_LOW_TERRAIN)); - mk_doutput(gpws_inop) = true; - } - if (test_bits(fault_inops[fault], INOP_TAD)) - { - mk_unset_alerts(mk_alert(TCF_TOO_LOW_TERRAIN)); - mk_doutput(tad_inop) = true; - } + if (test_bits(fault_inops[fault], INOP_GPWS)) + { + mk_unset_alerts(~mk_alert(TCF_TOO_LOW_TERRAIN)); + mk_doutput(gpws_inop) = true; + } + if (test_bits(fault_inops[fault], INOP_TAD)) + { + mk_unset_alerts(mk_alert(TCF_TOO_LOW_TERRAIN)); + mk_doutput(tad_inop) = true; + } } } void MK_VIII::FaultHandler::unset_fault (Fault fault) { - if (faults & (1<get_sim_time_sec() - last_update < 0.2) - return value; - last_update = globals->get_sim_time_sec(); + // no updates when simulation is paused (dt=0.0), and add 5 samples/second only + if (globals->get_sim_time_sec() - last_update < 0.2) + return value; + last_update = globals->get_sim_time_sec(); - samples_type::iterator iter; + samples_type::iterator iter; - // remove samples older than 15 seconds - for (iter = samples.begin(); iter != samples.end() && globals->get_sim_time_sec() - (*iter).timestamp >= 15; iter = samples.begin()) - samples.erase(iter); + // remove samples older than 15 seconds + for (iter = samples.begin(); iter != samples.end() && globals->get_sim_time_sec() - (*iter).timestamp >= 15; iter = samples.begin()) + samples.erase(iter); - // append new sample - samples.push_back(Sample(agl)); + // append new sample + samples.push_back(Sample(agl)); - // calculate average - double new_value = 0; - if (! samples.empty()) + // calculate average + double new_value = 0; + if (! samples.empty()) { - // time consuming loop => queue limited to 75 samples - // (= 15seconds * 5samples/second) - for (iter = samples.begin(); iter != samples.end(); iter++) - new_value += (*iter).value; - new_value /= samples.size(); + // time consuming loop => queue limited to 75 samples + // (= 15seconds * 5samples/second) + for (iter = samples.begin(); iter != samples.end(); iter++) + new_value += (*iter).value; + new_value /= samples.size(); } - new_value *= 0.75; + new_value *= 0.75; - if (new_value > value) - value = new_value; + if (new_value > value) + value = new_value; - return value; + return value; } void MK_VIII::IOHandler::TerrainClearanceFilter::reset () { - samples.clear(); - value = 0; - last_update = -1.0; + samples.clear(); + value = 0; + last_update = -1.0; } MK_VIII::IOHandler::IOHandler (MK_VIII *device) - : mk(device), _lamp(LAMP_NONE), last_landing_gear(false), last_real_flaps_down(false) + : mk(device), _lamp(LAMP_NONE), last_landing_gear(false), last_real_flaps_down(false) { - memset(&input_feeders, 0, sizeof(input_feeders)); - memset(&inputs.discretes, 0, sizeof(inputs.discretes)); - memset(&outputs, 0, sizeof(outputs)); - memset(&power_saved, 0, sizeof(power_saved)); + memset(&input_feeders, 0, sizeof(input_feeders)); + memset(&inputs.discretes, 0, sizeof(inputs.discretes)); + memset(&outputs, 0, sizeof(outputs)); + memset(&power_saved, 0, sizeof(power_saved)); - mk_dinput_feed(landing_gear) = true; - mk_dinput_feed(landing_flaps) = true; - mk_dinput_feed(glideslope_inhibit) = true; - mk_dinput_feed(decision_height) = true; - mk_dinput_feed(autopilot_engaged) = true; - mk_ainput_feed(uncorrected_barometric_altitude) = true; - mk_ainput_feed(barometric_altitude_rate) = true; - mk_ainput_feed(radio_altitude) = true; - mk_ainput_feed(glideslope_deviation) = true; - mk_ainput_feed(roll_angle) = true; - mk_ainput_feed(localizer_deviation) = true; - mk_ainput_feed(computed_airspeed) = true; + mk_dinput_feed(landing_gear) = true; + mk_dinput_feed(landing_flaps) = true; + mk_dinput_feed(glideslope_inhibit) = true; + mk_dinput_feed(decision_height) = true; + mk_dinput_feed(autopilot_engaged) = true; + mk_ainput_feed(uncorrected_barometric_altitude) = true; + mk_ainput_feed(barometric_altitude_rate) = true; + mk_ainput_feed(radio_altitude) = true; + mk_ainput_feed(glideslope_deviation) = true; + mk_ainput_feed(roll_angle) = true; + mk_ainput_feed(localizer_deviation) = true; + mk_ainput_feed(computed_airspeed) = true; - // will be unset on power on - mk_doutput(gpws_inop) = true; - mk_doutput(tad_inop) = true; + // will be unset on power on + mk_doutput(gpws_inop) = true; + mk_doutput(tad_inop) = true; } void MK_VIII::IOHandler::boot () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - mk_doutput(gpws_inop) = false; - mk_doutput(tad_inop) = false; + mk_doutput(gpws_inop) = false; + mk_doutput(tad_inop) = false; - mk_doutput(glideslope_cancel) = power_saved.glideslope_cancel; + mk_doutput(glideslope_cancel) = power_saved.glideslope_cancel; - altitude_samples.clear(); - reset_terrain_clearance(); + altitude_samples.clear(); + reset_terrain_clearance(); } void MK_VIII::IOHandler::post_boot () { - if (momentary_steep_approach_enabled()) + if (momentary_steep_approach_enabled()) { - last_landing_gear = mk_dinput(landing_gear); - last_real_flaps_down = real_flaps_down(); + last_landing_gear = mk_dinput(landing_gear); + last_real_flaps_down = real_flaps_down(); } - // read externally-latching input discretes - update_alternate_discrete_input(&mk_dinput(mode6_low_volume)); - update_alternate_discrete_input(&mk_dinput(audio_inhibit)); + // read externally-latching input discretes + update_alternate_discrete_input(&mk_dinput(mode6_low_volume)); + update_alternate_discrete_input(&mk_dinput(audio_inhibit)); } void MK_VIII::IOHandler::power_off () { - power_saved.glideslope_cancel = mk_doutput(glideslope_cancel); // [SPEC] 6.2.5 + power_saved.glideslope_cancel = mk_doutput(glideslope_cancel); // [SPEC] 6.2.5 - memset(&outputs, 0, sizeof(outputs)); + memset(&outputs, 0, sizeof(outputs)); - audio_inhibit_fault_timer.stop(); - landing_gear_fault_timer.stop(); - flaps_down_fault_timer.stop(); - momentary_flap_override_fault_timer.stop(); - self_test_fault_timer.stop(); - glideslope_cancel_fault_timer.stop(); - steep_approach_fault_timer.stop(); - gpws_inhibit_fault_timer.stop(); - ta_tcf_inhibit_fault_timer.stop(); + audio_inhibit_fault_timer.stop(); + landing_gear_fault_timer.stop(); + flaps_down_fault_timer.stop(); + momentary_flap_override_fault_timer.stop(); + self_test_fault_timer.stop(); + glideslope_cancel_fault_timer.stop(); + steep_approach_fault_timer.stop(); + gpws_inhibit_fault_timer.stop(); + ta_tcf_inhibit_fault_timer.stop(); - // [SPEC] 6.9.3.5 - mk_doutput(gpws_inop) = true; - mk_doutput(tad_inop) = true; + // [SPEC] 6.9.3.5 + mk_doutput(gpws_inop) = true; + mk_doutput(tad_inop) = true; } void MK_VIII::IOHandler::enter_ground () { - reset_terrain_clearance(); + reset_terrain_clearance(); - if (conf.momentary_flap_override_enabled) - mk_doutput(flap_override) = false; // [INSTALL] 3.15.1.6 + if (conf.momentary_flap_override_enabled) + mk_doutput(flap_override) = false; // [INSTALL] 3.15.1.6 } void MK_VIII::IOHandler::enter_takeoff () { - reset_terrain_clearance(); + reset_terrain_clearance(); - if (momentary_steep_approach_enabled()) // landing or go-around, disable steep approach as per [SPEC] 6.2.1 - mk_doutput(steep_approach) = false; + if (momentary_steep_approach_enabled()) + mk_doutput(steep_approach) = false; } void MK_VIII::IOHandler::update_inputs () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - // 1. process input feeders + // 1. process input feeders - if (mk_dinput_feed(landing_gear)) - mk_dinput(landing_gear) = mk_node(gear_down)->getBoolValue(); - if (mk_dinput_feed(landing_flaps)) - mk_dinput(landing_flaps) = mk_node(flaps)->getDoubleValue() < 1; - if (mk_dinput_feed(glideslope_inhibit)) - mk_dinput(glideslope_inhibit) = mk_node(nav0_gs_distance)->getDoubleValue() < 0; - if (mk_dinput_feed(autopilot_engaged)) + if (mk_dinput_feed(landing_gear)) + mk_dinput(landing_gear) = mk_node(gear_down)->getBoolValue(); + if (mk_dinput_feed(landing_flaps)) + mk_dinput(landing_flaps) = mk_node(flaps)->getDoubleValue() < 1; + if (mk_dinput_feed(glideslope_inhibit)) + mk_dinput(glideslope_inhibit) = mk_node(nav0_gs_distance)->getDoubleValue() < 0; + if (mk_dinput_feed(autopilot_engaged)) { - const char *mode; + const char *mode; - mode = mk_node(autopilot_heading_lock)->getStringValue(); - mk_dinput(autopilot_engaged) = mode && *mode; + mode = mk_node(autopilot_heading_lock)->getStringValue(); + mk_dinput(autopilot_engaged) = mode && *mode; } - if (mk_ainput_feed(uncorrected_barometric_altitude)) + if (mk_ainput_feed(uncorrected_barometric_altitude)) { - if (mk_node(altimeter_serviceable)->getBoolValue()) - mk_ainput(uncorrected_barometric_altitude).set(mk_node(altimeter_altitude)->getDoubleValue()); - else - mk_ainput(uncorrected_barometric_altitude).unset(); + if (mk_node(altimeter_serviceable)->getBoolValue()) + mk_ainput(uncorrected_barometric_altitude).set(mk_node(altimeter_altitude)->getDoubleValue()); + else + mk_ainput(uncorrected_barometric_altitude).unset(); } - if (mk_ainput_feed(barometric_altitude_rate)) - // Do not use the vsi, because it is pressure-based only, and - // therefore too laggy for GPWS alerting purposes. I guess that - // a real ADC combines pressure-based and inerta-based altitude - // rates to provide a non-laggy rate. That non-laggy rate is - // best emulated by /velocities/vertical-speed-fps * 60. - mk_ainput(barometric_altitude_rate).set(mk_node(vs)->getDoubleValue() * 60); - if (mk_ainput_feed(radio_altitude)) + if (mk_ainput_feed(barometric_altitude_rate)) + // Do not use the vsi, because it is pressure-based only, and + // therefore too laggy for GPWS alerting purposes. I guess that + // a real ADC combines pressure-based and inerta-based altitude + // rates to provide a non-laggy rate. That non-laggy rate is + // best emulated by /velocities/vertical-speed-fps * 60. + mk_ainput(barometric_altitude_rate).set(mk_node(vs)->getDoubleValue() * 60); + if (mk_ainput_feed(radio_altitude)) { - double agl; - switch (conf.altitude_source) - { - case 3: - agl = mk_node(altitude_gear_agl)->getDoubleValue(); - break; - case 4: - agl = mk_node(altitude_radar_agl)->getDoubleValue(); - break; - default: // 0,1,2 (and any currently unsupported values) - agl = mk_node(altitude_agl)->getDoubleValue(); - break; - } - // Some flight models may return negative values when on the - // ground or after a crash; do not allow them. - mk_ainput(radio_altitude).set(SG_MAX2(0.0, agl)); + double agl; + switch (conf.altitude_source) + { + case 3: + agl = mk_node(altitude_gear_agl)->getDoubleValue(); + break; + case 4: + agl = mk_node(altitude_radar_agl)->getDoubleValue(); + break; + default: // 0,1,2 (and any currently unsupported values) + agl = mk_node(altitude_agl)->getDoubleValue(); + break; + } + // Some flight models may return negative values when on the + // ground or after a crash; do not allow them. + mk_ainput(radio_altitude).set(SG_MAX2(0.0, agl)); } - if (mk_ainput_feed(glideslope_deviation)) + if (mk_ainput_feed(glideslope_deviation)) { - if (mk_node(nav0_serviceable)->getBoolValue() - && mk_node(nav0_gs_serviceable)->getBoolValue() - && mk_node(nav0_in_range)->getBoolValue() - && mk_node(nav0_has_gs)->getBoolValue()) - // gs-needle-deflection is expressed in degrees, and 1 dot = - // 0.32 degrees (according to - // http://www.ntsb.gov/Recs/letters/2000/A00_41_45.pdf) - mk_ainput(glideslope_deviation).set(mk_node(nav0_gs_needle_deflection)->getDoubleValue() / 0.32 * GLIDESLOPE_DOTS_TO_DDM); - else - mk_ainput(glideslope_deviation).unset(); + if (mk_node(nav0_serviceable)->getBoolValue() + && mk_node(nav0_gs_serviceable)->getBoolValue() + && mk_node(nav0_in_range)->getBoolValue() + && mk_node(nav0_has_gs)->getBoolValue()) + // gs-needle-deflection is expressed in degrees, and 1 dot = + // 0.32 degrees (according to + // http://www.ntsb.gov/Recs/letters/2000/A00_41_45.pdf) + mk_ainput(glideslope_deviation).set(mk_node(nav0_gs_needle_deflection)->getDoubleValue() / 0.32 * GLIDESLOPE_DOTS_TO_DDM); + else + mk_ainput(glideslope_deviation).unset(); } - if (mk_ainput_feed(roll_angle)) + if (mk_ainput_feed(roll_angle)) { - if (conf.use_attitude_indicator) - { - // read data from attitude indicator instrument (requires vacuum system to work) - if (mk_node(ai_serviceable)->getBoolValue() && ! mk_node(ai_caged)->getBoolValue()) - mk_ainput(roll_angle).set(mk_node(ai_roll)->getDoubleValue()); - else - mk_ainput(roll_angle).unset(); + if (conf.use_attitude_indicator) + { + // read data from attitude indicator instrument (requires vacuum system to work) + if (mk_node(ai_serviceable)->getBoolValue() && ! mk_node(ai_caged)->getBoolValue()) + mk_ainput(roll_angle).set(mk_node(ai_roll)->getDoubleValue()); + else + mk_ainput(roll_angle).unset(); + } + else + { + // use simulator source + mk_ainput(roll_angle).set(mk_node(orientation_roll)->getDoubleValue()); + } } - else - { - // use simulator source - mk_ainput(roll_angle).set(mk_node(orientation_roll)->getDoubleValue()); - } - } - if (mk_ainput_feed(localizer_deviation)) + if (mk_ainput_feed(localizer_deviation)) { - if (mk_node(nav0_serviceable)->getBoolValue() - && mk_node(nav0_cdi_serviceable)->getBoolValue() - && mk_node(nav0_in_range)->getBoolValue() - && mk_node(nav0_nav_loc)->getBoolValue()) - // heading-needle-deflection is expressed in degrees, and 1 - // dot = 2 degrees (0.5 degrees for ILS, but navradio.cxx - // performs the conversion) - mk_ainput(localizer_deviation).set(mk_node(nav0_heading_needle_deflection)->getDoubleValue() / 2 * LOCALIZER_DOTS_TO_DDM); - else - mk_ainput(localizer_deviation).unset(); + if (mk_node(nav0_serviceable)->getBoolValue() + && mk_node(nav0_cdi_serviceable)->getBoolValue() + && mk_node(nav0_in_range)->getBoolValue() + && mk_node(nav0_nav_loc)->getBoolValue()) + // heading-needle-deflection is expressed in degrees, and 1 + // dot = 2 degrees (0.5 degrees for ILS, but navradio.cxx + // performs the conversion) + mk_ainput(localizer_deviation).set(mk_node(nav0_heading_needle_deflection)->getDoubleValue() / 2 * LOCALIZER_DOTS_TO_DDM); + else + mk_ainput(localizer_deviation).unset(); } - if (mk_ainput_feed(computed_airspeed)) + if (mk_ainput_feed(computed_airspeed)) { - if (mk_node(asi_serviceable)->getBoolValue()) - mk_ainput(computed_airspeed).set(mk_node(asi_speed)->getDoubleValue()); - else - mk_ainput(computed_airspeed).unset(); + if (mk_node(asi_serviceable)->getBoolValue()) + mk_ainput(computed_airspeed).set(mk_node(asi_speed)->getDoubleValue()); + else + mk_ainput(computed_airspeed).unset(); } - // 2. compute data + // 2. compute data - mk_data(decision_height).set(&mk_ainput(decision_height)); - mk_data(radio_altitude).set(&mk_ainput(radio_altitude)); - mk_data(roll_angle).set(&mk_ainput(roll_angle)); + mk_data(decision_height).set(&mk_ainput(decision_height)); + mk_data(radio_altitude).set(&mk_ainput(radio_altitude)); + mk_data(roll_angle).set(&mk_ainput(roll_angle)); - // update barometric_altitude_rate as per [SPEC] 6.2.1: "During - // normal conditions, the system will base Mode 1 computations upon - // barometric rate from the ADC. If this computed data is not valid - // or available then the system will use internally computed - // barometric altitude rate." + // update barometric_altitude_rate as per [SPEC] 6.2.1: "During + // normal conditions, the system will base Mode 1 computations upon + // barometric rate from the ADC. If this computed data is not valid + // or available then the system will use internally computed + // barometric altitude rate." - if (! mk_ainput(barometric_altitude_rate).ncd) - // the altitude rate input is valid, use it - mk_data(barometric_altitude_rate).set(mk_ainput(barometric_altitude_rate).get()); - else - { - bool has = false; - - // The altitude rate input is invalid. We can compute an - // altitude rate if all the following conditions are true: - // - // - the altitude input is valid - // - there is an altitude sample with age >= 1 second - // - that altitude sample is valid - - if (! mk_ainput(uncorrected_barometric_altitude).ncd) - { - if (! altitude_samples.empty() && ! altitude_samples.front().value.ncd) - { - double elapsed = globals->get_sim_time_sec() - altitude_samples.front().timestamp; - if (elapsed >= 1) - { - has = true; - mk_data(barometric_altitude_rate).set((mk_ainput(uncorrected_barometric_altitude).get() - altitude_samples.front().value.get()) / elapsed * 60); - } - } - } - - if (! has) - mk_data(barometric_altitude_rate).unset(); - } - - altitude_samples.push_back(Sample< Parameter >(mk_ainput(uncorrected_barometric_altitude))); - - // Erase everything from the beginning of the list up to the sample - // preceding the most recent sample whose age is >= 1 second. - - altitude_samples_type::iterator erase_last = altitude_samples.begin(); - altitude_samples_type::iterator iter; - - for (iter = altitude_samples.begin(); iter != altitude_samples.end(); iter++) - if (globals->get_sim_time_sec() - (*iter).timestamp >= 1) - erase_last = iter; + if (! mk_ainput(barometric_altitude_rate).ncd) + // the altitude rate input is valid, use it + mk_data(barometric_altitude_rate).set(mk_ainput(barometric_altitude_rate).get()); else - break; - - if (erase_last != altitude_samples.begin()) - altitude_samples.erase(altitude_samples.begin(), erase_last); - - // update GPS data - - if (conf.use_internal_gps) { - mk_data(gps_altitude).set(mk_node(altitude)->getDoubleValue()); - mk_data(gps_latitude).set(mk_node(latitude)->getDoubleValue()); - mk_data(gps_longitude).set(mk_node(longitude)->getDoubleValue()); - mk_data(gps_vertical_figure_of_merit).set(0.0); - } - else - { - mk_data(gps_altitude).set(&mk_ainput(gps_altitude)); - mk_data(gps_latitude).set(&mk_ainput(gps_latitude)); - mk_data(gps_longitude).set(&mk_ainput(gps_longitude)); - mk_data(gps_vertical_figure_of_merit).set(&mk_ainput(gps_vertical_figure_of_merit)); + bool has = false; + + // The altitude rate input is invalid. We can compute an + // altitude rate if all the following conditions are true: + // + // - the altitude input is valid + // - there is an altitude sample with age >= 1 second + // - that altitude sample is valid + + if (! mk_ainput(uncorrected_barometric_altitude).ncd) + { + if (! altitude_samples.empty() && ! altitude_samples.front().value.ncd) + { + double elapsed = globals->get_sim_time_sec() - altitude_samples.front().timestamp; + if (elapsed >= 1) + { + has = true; + mk_data(barometric_altitude_rate).set((mk_ainput(uncorrected_barometric_altitude).get() - altitude_samples.front().value.get()) / elapsed * 60); + } + } + } + + if (! has) + mk_data(barometric_altitude_rate).unset(); } - // update glideslope and localizer + altitude_samples.push_back(Sample< Parameter >(mk_ainput(uncorrected_barometric_altitude))); - mk_data(glideslope_deviation_dots).set(&mk_ainput(glideslope_deviation), GLIDESLOPE_DDM_TO_DOTS); - mk_data(localizer_deviation_dots).set(&mk_ainput(localizer_deviation), LOCALIZER_DDM_TO_DOTS); + // Erase everything from the beginning of the list up to the sample + // preceding the most recent sample whose age is >= 1 second. - // Update geometric altitude; [SPEC] 6.7.8 provides an overview of a - // complex algorithm which combines several input sources to - // calculate the geometric altitude. Since the exact algorithm is - // not given, we fallback to a much simpler method. + altitude_samples_type::iterator erase_last = altitude_samples.begin(); + altitude_samples_type::iterator iter; - if (! mk_data(gps_altitude).ncd) - mk_data(geometric_altitude).set(mk_data(gps_altitude).get()); - else if (! mk_ainput(uncorrected_barometric_altitude).ncd) - mk_data(geometric_altitude).set(mk_ainput(uncorrected_barometric_altitude).get()); - else - mk_data(geometric_altitude).unset(); + for (iter = altitude_samples.begin(); iter != altitude_samples.end(); iter++) + { + if (globals->get_sim_time_sec() - (*iter).timestamp >= 1) + erase_last = iter; + else + break; + } - // update terrain clearance + if (erase_last != altitude_samples.begin()) + altitude_samples.erase(altitude_samples.begin(), erase_last); - update_terrain_clearance(); + // update GPS data - // 3. perform sanity checks + if (conf.use_internal_gps) + { + mk_data(gps_altitude).set(mk_node(altitude)->getDoubleValue()); + mk_data(gps_latitude).set(mk_node(latitude)->getDoubleValue()); + mk_data(gps_longitude).set(mk_node(longitude)->getDoubleValue()); + mk_data(gps_vertical_figure_of_merit).set(0.0); + } + else + { + mk_data(gps_altitude).set(&mk_ainput(gps_altitude)); + mk_data(gps_latitude).set(&mk_ainput(gps_latitude)); + mk_data(gps_longitude).set(&mk_ainput(gps_longitude)); + mk_data(gps_vertical_figure_of_merit).set(&mk_ainput(gps_vertical_figure_of_merit)); + } - if (! mk_data(radio_altitude).ncd && mk_data(radio_altitude).get() < 0) - mk_data(radio_altitude).unset(); + // update glideslope and localizer + mk_data(glideslope_deviation_dots).set(&mk_ainput(glideslope_deviation), GLIDESLOPE_DDM_TO_DOTS); + mk_data(localizer_deviation_dots).set(&mk_ainput(localizer_deviation), LOCALIZER_DDM_TO_DOTS); - if (! mk_data(decision_height).ncd && mk_data(decision_height).get() < 0) - mk_data(decision_height).unset(); + // Update geometric altitude; [SPEC] 6.7.8 provides an overview of a + // complex algorithm which combines several input sources to + // calculate the geometric altitude. Since the exact algorithm is + // not given, we fallback to a much simpler method. + if (! mk_data(gps_altitude).ncd) + mk_data(geometric_altitude).set(mk_data(gps_altitude).get()); + else if (! mk_ainput(uncorrected_barometric_altitude).ncd) + mk_data(geometric_altitude).set(mk_ainput(uncorrected_barometric_altitude).get()); + else + mk_data(geometric_altitude).unset(); - if (! mk_data(gps_latitude).ncd - && (mk_data(gps_latitude).get() < -90 - || mk_data(gps_latitude).get() > 90)) - mk_data(gps_latitude).unset(); + // update terrain clearance + update_terrain_clearance(); - if (! mk_data(gps_longitude).ncd - && (mk_data(gps_longitude).get() < -180 - || mk_data(gps_longitude).get() > 180)) - mk_data(gps_longitude).unset(); + // 3. perform sanity checks + if (! mk_data(radio_altitude).ncd && mk_data(radio_altitude).get() < 0) + mk_data(radio_altitude).unset(); - if (! mk_data(roll_angle).ncd - && ((mk_data(roll_angle).get() < -180) - || (mk_data(roll_angle).get() > 180))) - mk_data(roll_angle).unset(); + if (! mk_data(decision_height).ncd && mk_data(decision_height).get() < 0) + mk_data(decision_height).unset(); - // 4. process input feeders requiring data computed above + if (! mk_data(gps_latitude).ncd + && (mk_data(gps_latitude).get() < -90 + || mk_data(gps_latitude).get() > 90)) + mk_data(gps_latitude).unset(); - if (mk_dinput_feed(decision_height)) - { - mk_dinput(decision_height_100) = ! mk_data(radio_altitude).ncd - && ! mk_data(decision_height).ncd - && mk_data(radio_altitude).get() <= mk_data(decision_height).get()+100; + if (! mk_data(gps_longitude).ncd + && (mk_data(gps_longitude).get() < -180 + || mk_data(gps_longitude).get() > 180)) + mk_data(gps_longitude).unset(); - mk_dinput(decision_height) = ! mk_data(radio_altitude).ncd - && ! mk_data(decision_height).ncd - && mk_data(radio_altitude).get() <= mk_data(decision_height).get(); - } + if (! mk_data(roll_angle).ncd + && ((mk_data(roll_angle).get() < -180) + || (mk_data(roll_angle).get() > 180))) + mk_data(roll_angle).unset(); + + // 4. process input feeders requiring data computed above + if (mk_dinput_feed(decision_height)) + { + mk_dinput(decision_height_100) = ! mk_data(radio_altitude).ncd + && ! mk_data(decision_height).ncd + && mk_data(radio_altitude).get() <= mk_data(decision_height).get()+100; + + mk_dinput(decision_height) = ! mk_data(radio_altitude).ncd + && ! mk_data(decision_height).ncd + && mk_data(radio_altitude).get() <= mk_data(decision_height).get(); + } } void MK_VIII::IOHandler::update_terrain_clearance () { - if (! mk_data(radio_altitude).ncd) - mk_data(terrain_clearance).set(terrain_clearance_filter.update(mk_data(radio_altitude).get())); - else - mk_data(terrain_clearance).unset(); + if (! mk_data(radio_altitude).ncd) + mk_data(terrain_clearance).set(terrain_clearance_filter.update(mk_data(radio_altitude).get())); + else + mk_data(terrain_clearance).unset(); } void MK_VIII::IOHandler::reset_terrain_clearance () { - terrain_clearance_filter.reset(); - update_terrain_clearance(); + terrain_clearance_filter.reset(); + update_terrain_clearance(); } void MK_VIII::IOHandler::reposition () { - reset_terrain_clearance(); + reset_terrain_clearance(); } void MK_VIII::IOHandler::handle_input_fault (bool test, FaultHandler::Fault fault) { - if (test) + if (test) { - if (! (mk->fault_handler.faults & (1<fault_handler.set_fault(fault); + if (! (mk->fault_handler.faults & (1<fault_handler.set_fault(fault); } - else - mk->fault_handler.unset_fault(fault); + else + mk->fault_handler.unset_fault(fault); } void MK_VIII::IOHandler::handle_input_fault (bool test, - Timer *timer, - double max_duration, - FaultHandler::Fault fault) + Timer *timer, + double max_duration, + FaultHandler::Fault fault) { - if (test) + if (test) { - if (! (mk->fault_handler.faults & (1<start_or_elapsed() >= max_duration) - mk->fault_handler.set_fault(fault); - } + if (! (mk->fault_handler.faults & (1<start_or_elapsed() >= max_duration) + mk->fault_handler.set_fault(fault); + } } - else + else { - mk->fault_handler.unset_fault(fault); - timer->stop(); + mk->fault_handler.unset_fault(fault); + timer->stop(); } } void MK_VIII::IOHandler::update_input_faults () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - // [INSTALL] 3.15.1.3 - handle_input_fault(mk_dinput(audio_inhibit), - &audio_inhibit_fault_timer, - 60, - FaultHandler::FAULT_ALL_MODES_INHIBIT); + // [INSTALL] 3.15.1.3 + handle_input_fault(mk_dinput(audio_inhibit), + &audio_inhibit_fault_timer, + 60, + FaultHandler::FAULT_ALL_MODES_INHIBIT); - // [INSTALL] appendix E 6.6.2 - handle_input_fault(mk_dinput(landing_gear) - && ! mk_ainput(computed_airspeed).ncd - && mk_ainput(computed_airspeed).get() > conf.faults->max_gear_down_airspeed, - &landing_gear_fault_timer, - 60, - FaultHandler::FAULT_GEAR_SWITCH); + // [INSTALL] appendix E 6.6.2 + handle_input_fault(mk_dinput(landing_gear) + && ! mk_ainput(computed_airspeed).ncd + && mk_ainput(computed_airspeed).get() > conf.faults->max_gear_down_airspeed, + &landing_gear_fault_timer, + 60, + FaultHandler::FAULT_GEAR_SWITCH); - // [INSTALL] appendix E 6.6.4 - handle_input_fault(flaps_down() - && ! mk_ainput(computed_airspeed).ncd - && mk_ainput(computed_airspeed).get() > conf.faults->max_flaps_down_airspeed, - &flaps_down_fault_timer, - 60, - FaultHandler::FAULT_FLAPS_SWITCH); + // [INSTALL] appendix E 6.6.4 + handle_input_fault(flaps_down() + && ! mk_ainput(computed_airspeed).ncd + && mk_ainput(computed_airspeed).get() > conf.faults->max_flaps_down_airspeed, + &flaps_down_fault_timer, + 60, + FaultHandler::FAULT_FLAPS_SWITCH); - // [INSTALL] appendix E 6.6.6 - if (conf.momentary_flap_override_enabled) - handle_input_fault(mk_dinput(momentary_flap_override), - &momentary_flap_override_fault_timer, - 15, - FaultHandler::FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID); + // [INSTALL] appendix E 6.6.6 + if (conf.momentary_flap_override_enabled) + handle_input_fault(mk_dinput(momentary_flap_override), + &momentary_flap_override_fault_timer, + 15, + FaultHandler::FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID); - // [INSTALL] appendix E 6.6.7 - handle_input_fault(mk_dinput(self_test), - &self_test_fault_timer, - 60, - FaultHandler::FAULT_SELF_TEST_INVALID); + // [INSTALL] appendix E 6.6.7 + handle_input_fault(mk_dinput(self_test), + &self_test_fault_timer, + 60, + FaultHandler::FAULT_SELF_TEST_INVALID); - // [INSTALL] appendix E 6.6.13 - handle_input_fault(mk_dinput(glideslope_cancel), - &glideslope_cancel_fault_timer, - 15, - FaultHandler::FAULT_GLIDESLOPE_CANCEL_INVALID); + // [INSTALL] appendix E 6.6.13 + handle_input_fault(mk_dinput(glideslope_cancel), + &glideslope_cancel_fault_timer, + 15, + FaultHandler::FAULT_GLIDESLOPE_CANCEL_INVALID); - // [INSTALL] appendix E 6.6.25 - if (momentary_steep_approach_enabled()) - handle_input_fault(mk_dinput(steep_approach), - &steep_approach_fault_timer, - 15, - FaultHandler::FAULT_STEEP_APPROACH_INVALID); + // [INSTALL] appendix E 6.6.25 + if (momentary_steep_approach_enabled()) + handle_input_fault(mk_dinput(steep_approach), + &steep_approach_fault_timer, + 15, + FaultHandler::FAULT_STEEP_APPROACH_INVALID); - // [INSTALL] appendix E 6.6.27 - if (conf.gpws_inhibit_enabled) - handle_input_fault(mk_dinput(gpws_inhibit), - &gpws_inhibit_fault_timer, - 5, - FaultHandler::FAULT_GPWS_INHIBIT); + // [INSTALL] appendix E 6.6.27 + if (conf.gpws_inhibit_enabled) + handle_input_fault(mk_dinput(gpws_inhibit), + &gpws_inhibit_fault_timer, + 5, + FaultHandler::FAULT_GPWS_INHIBIT); - // [INSTALL] does not specify a fault for this one, but it makes - // sense to have it behave like GPWS inhibit - handle_input_fault(mk_dinput(ta_tcf_inhibit), - &ta_tcf_inhibit_fault_timer, - 5, - FaultHandler::FAULT_TA_TCF_INHIBIT); + // [INSTALL] does not specify a fault for this one, but it makes + // sense to have it behave like GPWS inhibit + handle_input_fault(mk_dinput(ta_tcf_inhibit), + &ta_tcf_inhibit_fault_timer, + 5, + FaultHandler::FAULT_TA_TCF_INHIBIT); - // [PILOT] page 48: "In the event that required data for a - // particular function is not available, then that function is - // automatically inhibited and annunciated" + // [PILOT] page 48: "In the event that required data for a + // particular function is not available, then that function is + // automatically inhibited and annunciated" - handle_input_fault(mk_data(radio_altitude).ncd - || mk_ainput(uncorrected_barometric_altitude).ncd - || mk_data(barometric_altitude_rate).ncd - || mk_ainput(computed_airspeed).ncd - || mk_data(terrain_clearance).ncd, - FaultHandler::FAULT_MODES14_INPUTS_INVALID); - - if (! mk_dinput(glideslope_inhibit)) - handle_input_fault(mk_data(radio_altitude).ncd, - FaultHandler::FAULT_MODE5_INPUTS_INVALID); - - if (mk->mode6_handler.altitude_callouts_enabled()) - handle_input_fault(mk->mode6_handler.conf.above_field_voice - ? (mk_data(gps_latitude).ncd - || mk_data(gps_longitude).ncd - || mk_data(geometric_altitude).ncd) - : mk_data(radio_altitude).ncd, - FaultHandler::FAULT_MODE6_INPUTS_INVALID); - - if (mk->mode6_handler.conf.bank_angle_enabled) - handle_input_fault(mk_data(roll_angle).ncd, - FaultHandler::FAULT_BANK_ANGLE_INPUTS_INVALID); - - if (mk->tcf_handler.conf.enabled) handle_input_fault(mk_data(radio_altitude).ncd - || mk_data(geometric_altitude).ncd - || mk_data(gps_latitude).ncd - || mk_data(gps_longitude).ncd - || mk_data(gps_vertical_figure_of_merit).ncd, - FaultHandler::FAULT_TCF_INPUTS_INVALID); + || mk_ainput(uncorrected_barometric_altitude).ncd + || mk_data(barometric_altitude_rate).ncd + || mk_ainput(computed_airspeed).ncd + || mk_data(terrain_clearance).ncd, + FaultHandler::FAULT_MODES14_INPUTS_INVALID); + + if (! mk_dinput(glideslope_inhibit)) + handle_input_fault(mk_data(radio_altitude).ncd, + FaultHandler::FAULT_MODE5_INPUTS_INVALID); + + if (mk->mode6_handler.altitude_callouts_enabled()) + handle_input_fault(mk->mode6_handler.conf.above_field_voice + ? (mk_data(gps_latitude).ncd + || mk_data(gps_longitude).ncd + || mk_data(geometric_altitude).ncd) + : mk_data(radio_altitude).ncd, + FaultHandler::FAULT_MODE6_INPUTS_INVALID); + + if (mk->mode6_handler.conf.bank_angle_enabled) + handle_input_fault(mk_data(roll_angle).ncd, + FaultHandler::FAULT_BANK_ANGLE_INPUTS_INVALID); + + if (mk->tcf_handler.conf.enabled) + handle_input_fault(mk_data(radio_altitude).ncd + || mk_data(geometric_altitude).ncd + || mk_data(gps_latitude).ncd + || mk_data(gps_longitude).ncd + || mk_data(gps_vertical_figure_of_merit).ncd, + FaultHandler::FAULT_TCF_INPUTS_INVALID); } void MK_VIII::IOHandler::update_alternate_discrete_input (bool *ptr) { - assert(mk->system_handler.state == SystemHandler::STATE_ON); + assert(mk->system_handler.state == SystemHandler::STATE_ON); - if (ptr == &mk_dinput(mode6_low_volume)) + if (ptr == &mk_dinput(mode6_low_volume)) { - if (mk->configuration_module.state == ConfigurationModule::STATE_OK - && mk->self_test_handler.state == SelfTestHandler::STATE_NONE) - mk->mode6_handler.set_volume(*ptr ? modify_amplitude(1.0, -6) : 1.0); + if (mk->configuration_module.state == ConfigurationModule::STATE_OK + && mk->self_test_handler.state == SelfTestHandler::STATE_NONE) + mk->mode6_handler.set_volume(*ptr ? modify_amplitude(1.0, -6) : 1.0); } - else if (ptr == &mk_dinput(audio_inhibit)) + else if (ptr == &mk_dinput(audio_inhibit)) { - if (mk->configuration_module.state == ConfigurationModule::STATE_OK - && mk->self_test_handler.state == SelfTestHandler::STATE_NONE) - mk->voice_player.set_volume(*ptr ? 0.0 : mk->voice_player.conf.volume); + if (mk->configuration_module.state == ConfigurationModule::STATE_OK + && mk->self_test_handler.state == SelfTestHandler::STATE_NONE) + mk->voice_player.set_volume(*ptr ? 0.0 : mk->voice_player.conf.volume); } } void MK_VIII::IOHandler::update_internal_latches () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - // [SPEC] 6.2.1 - if (conf.momentary_flap_override_enabled + // [SPEC] 6.2.1 + if (conf.momentary_flap_override_enabled && mk_doutput(flap_override) && ! mk->state_handler.takeoff && (mk_data(radio_altitude).ncd || mk_data(radio_altitude).get() <= 50)) - mk_doutput(flap_override) = false; + mk_doutput(flap_override) = false; - // [SPEC] 6.2.1 - if (momentary_steep_approach_enabled()) + // [SPEC] 6.2.1 + if (momentary_steep_approach_enabled()) { - if (mk_doutput(steep_approach) - && ! mk->state_handler.takeoff - && ((last_landing_gear && ! mk_dinput(landing_gear)) - || (last_real_flaps_down && ! real_flaps_down()))) - // gear or flaps raised during approach: it's a go-around - mk_doutput(steep_approach) = false; + if (mk_doutput(steep_approach) + && ! mk->state_handler.takeoff + && ((last_landing_gear && ! mk_dinput(landing_gear)) + || (last_real_flaps_down && ! real_flaps_down()))) + { + // gear or flaps raised during approach: it's a go-around + mk_doutput(steep_approach) = false; + } - last_landing_gear = mk_dinput(landing_gear); - last_real_flaps_down = real_flaps_down(); + last_landing_gear = mk_dinput(landing_gear); + last_real_flaps_down = real_flaps_down(); } - // [SPEC] 6.2.5 - if (mk_doutput(glideslope_cancel) - && (mk_data(glideslope_deviation_dots).ncd - || mk_data(radio_altitude).ncd - || mk_data(radio_altitude).get() > 2000 - || mk_data(radio_altitude).get() < 30)) - mk_doutput(glideslope_cancel) = false; + // [SPEC] 6.2.5 + if (mk_doutput(glideslope_cancel) + && (mk_data(glideslope_deviation_dots).ncd + || mk_data(radio_altitude).ncd + || mk_data(radio_altitude).get() > 2000 + || mk_data(radio_altitude).get() < 30)) + mk_doutput(glideslope_cancel) = false; } void MK_VIII::IOHandler::update_egpws_alert_discrete_1 () { - if (mk->voice_player.voice) + if (mk->voice_player.voice) { - const struct - { - int bit; - VoicePlayer::Voice *voice; - } voices[] = { - { 11, mk_voice(sink_rate_pause_sink_rate) }, - { 12, mk_voice(pull_up) }, - { 13, mk_voice(terrain) }, - { 13, mk_voice(terrain_pause_terrain) }, - { 14, mk_voice(dont_sink_pause_dont_sink) }, - { 15, mk_voice(too_low_gear) }, - { 16, mk_voice(too_low_flaps) }, - { 17, mk_voice(too_low_terrain) }, - { 18, mk_voice(soft_glideslope) }, - { 18, mk_voice(hard_glideslope) }, - { 19, mk_voice(minimums_minimums) } - }; + const struct + { + int bit; + VoicePlayer::Voice *voice; + } voices[] = { + { 11, mk_voice(sink_rate_pause_sink_rate) }, + { 12, mk_voice(pull_up) }, + { 13, mk_voice(terrain) }, + { 13, mk_voice(terrain_pause_terrain) }, + { 14, mk_voice(dont_sink_pause_dont_sink) }, + { 15, mk_voice(too_low_gear) }, + { 16, mk_voice(too_low_flaps) }, + { 17, mk_voice(too_low_terrain) }, + { 18, mk_voice(soft_glideslope) }, + { 18, mk_voice(hard_glideslope) }, + { 19, mk_voice(minimums_minimums) } + }; - for (size_t i = 0; i < n_elements(voices); i++) - if (voices[i].voice == mk->voice_player.voice) - { - mk_aoutput(egpws_alert_discrete_1) = 1 << voices[i].bit; - return; - } + for (size_t i = 0; i < n_elements(voices); i++) + { + if (voices[i].voice == mk->voice_player.voice) + { + mk_aoutput(egpws_alert_discrete_1) = 1 << voices[i].bit; + return; + } + } } - mk_aoutput(egpws_alert_discrete_1) = 0; + mk_aoutput(egpws_alert_discrete_1) = 0; } void MK_VIII::IOHandler::update_egpwc_logic_discretes () { - mk_aoutput(egpwc_logic_discretes) = 0; + mk_aoutput(egpwc_logic_discretes) = 0; - if (mk->state_handler.takeoff) - mk_aoutput(egpwc_logic_discretes) |= 1 << 18; + if (mk->state_handler.takeoff) + mk_aoutput(egpwc_logic_discretes) |= 1 << 18; - static const struct - { - int bit; - unsigned int alerts; - } logic[] = { - { 13, mk_alert(TCF_TOO_LOW_TERRAIN) }, - { 19, mk_alert(MODE1_SINK_RATE) }, - { 20, mk_alert(MODE1_PULL_UP) }, - { 21, mk_alert(MODE2A_PREFACE) | mk_alert(MODE2B_PREFACE) | mk_alert(MODE2B_LANDING_MODE) | mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING) }, - { 22, mk_alert(MODE2A) | mk_alert(MODE2B) }, - { 23, mk_alert(MODE3) }, - { 24, mk_alert(MODE4_TOO_LOW_FLAPS) | mk_alert(MODE4_TOO_LOW_GEAR) | mk_alert(MODE4AB_TOO_LOW_TERRAIN) | mk_alert(MODE4C_TOO_LOW_TERRAIN) }, - { 25, mk_alert(MODE5_SOFT) | mk_alert(MODE5_HARD) } - }; + static const struct + { + int bit; + unsigned int alerts; + } logic[] = { + { 13, mk_alert(TCF_TOO_LOW_TERRAIN) }, + { 19, mk_alert(MODE1_SINK_RATE) }, + { 20, mk_alert(MODE1_PULL_UP) }, + { 21, mk_alert(MODE2A_PREFACE) | mk_alert(MODE2B_PREFACE) | mk_alert(MODE2B_LANDING_MODE) | mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING) }, + { 22, mk_alert(MODE2A) | mk_alert(MODE2B) }, + { 23, mk_alert(MODE3) }, + { 24, mk_alert(MODE4_TOO_LOW_FLAPS) | mk_alert(MODE4_TOO_LOW_GEAR) | mk_alert(MODE4AB_TOO_LOW_TERRAIN) | mk_alert(MODE4C_TOO_LOW_TERRAIN) }, + { 25, mk_alert(MODE5_SOFT) | mk_alert(MODE5_HARD) } + }; - for (size_t i = 0; i < n_elements(logic); i++) - if (mk_test_alerts(logic[i].alerts)) - mk_aoutput(egpwc_logic_discretes) |= 1 << logic[i].bit; + for (size_t i = 0; i < n_elements(logic); i++) + { + if (mk_test_alerts(logic[i].alerts)) + mk_aoutput(egpwc_logic_discretes) |= 1 << logic[i].bit; + } } void MK_VIII::IOHandler::update_mode6_callouts_discrete_1 () { - if (mk->voice_player.voice) + if (mk->voice_player.voice) { - const struct - { - int bit; - VoicePlayer::Voice *voice; - } voices[] = { - { 11, mk_voice(minimums_minimums) }, - { 16, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_10) }, - { 17, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_20) }, - { 18, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_30) }, - { 19, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_40) }, - { 20, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_50) }, - { 23, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_100) }, - { 24, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_200) }, - { 25, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_300) } - }; + const struct + { + int bit; + VoicePlayer::Voice *voice; + } voices[] = { + { 11, mk_voice(minimums_minimums) }, + { 16, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_10) }, + { 17, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_20) }, + { 18, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_30) }, + { 19, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_40) }, + { 20, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_50) }, + { 23, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_100) }, + { 24, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_200) }, + { 25, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_300) } + }; - for (size_t i = 0; i < n_elements(voices); i++) - if (voices[i].voice == mk->voice_player.voice) - { - mk_aoutput(mode6_callouts_discrete_1) = 1 << voices[i].bit; - return; - } + for (size_t i = 0; i < n_elements(voices); i++) + { + if (voices[i].voice == mk->voice_player.voice) + { + mk_aoutput(mode6_callouts_discrete_1) = 1 << voices[i].bit; + return; + } + } } - - mk_aoutput(mode6_callouts_discrete_1) = 0; + mk_aoutput(mode6_callouts_discrete_1) = 0; } void MK_VIII::IOHandler::update_mode6_callouts_discrete_2 () { - if (mk->voice_player.voice) + if (mk->voice_player.voice) { - const struct - { - int bit; - VoicePlayer::Voice *voice; - } voices[] = { - { 11, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_400) }, - { 12, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_500) }, - { 13, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_1000) }, - { 14, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_2500) }, - { 18, mk_voice(bank_angle_pause_bank_angle) }, - { 18, mk_voice(bank_angle_pause_bank_angle_3) }, - { 23, mk_voice(five_hundred_above) } - }; + const struct + { + int bit; + VoicePlayer::Voice *voice; + } voices[] = { + { 11, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_400) }, + { 12, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_500) }, + { 13, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_1000) }, + { 14, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_2500) }, + { 18, mk_voice(bank_angle_pause_bank_angle) }, + { 18, mk_voice(bank_angle_pause_bank_angle_3) }, + { 23, mk_voice(five_hundred_above) } + }; - for (size_t i = 0; i < n_elements(voices); i++) - if (voices[i].voice == mk->voice_player.voice) - { - mk_aoutput(mode6_callouts_discrete_2) = 1 << voices[i].bit; - return; - } + for (size_t i = 0; i < n_elements(voices); i++) + { + if (voices[i].voice == mk->voice_player.voice) + { + mk_aoutput(mode6_callouts_discrete_2) = 1 << voices[i].bit; + return; + } + } } - mk_aoutput(mode6_callouts_discrete_2) = 0; + mk_aoutput(mode6_callouts_discrete_2) = 0; } void MK_VIII::IOHandler::update_egpws_alert_discrete_2 () { - mk_aoutput(egpws_alert_discrete_2) = 1 << 27; // Terrain NA + mk_aoutput(egpws_alert_discrete_2) = 1 << 27; // Terrain NA - if (mk_doutput(glideslope_cancel)) - mk_aoutput(egpws_alert_discrete_2) |= 1 << 11; - if (mk_doutput(gpws_alert)) - mk_aoutput(egpws_alert_discrete_2) |= 1 << 12; - if (mk_doutput(gpws_warning)) - mk_aoutput(egpws_alert_discrete_2) |= 1 << 13; - if (mk_doutput(gpws_inop)) - mk_aoutput(egpws_alert_discrete_2) |= 1 << 14; - if (mk_doutput(audio_on)) - mk_aoutput(egpws_alert_discrete_2) |= 1 << 16; - if (mk_doutput(tad_inop)) - mk_aoutput(egpws_alert_discrete_2) |= 1 << 24; - if (mk->fault_handler.has_faults()) - mk_aoutput(egpws_alert_discrete_2) |= 1 << 25; + if (mk_doutput(glideslope_cancel)) + mk_aoutput(egpws_alert_discrete_2) |= 1 << 11; + if (mk_doutput(gpws_alert)) + mk_aoutput(egpws_alert_discrete_2) |= 1 << 12; + if (mk_doutput(gpws_warning)) + mk_aoutput(egpws_alert_discrete_2) |= 1 << 13; + if (mk_doutput(gpws_inop)) + mk_aoutput(egpws_alert_discrete_2) |= 1 << 14; + if (mk_doutput(audio_on)) + mk_aoutput(egpws_alert_discrete_2) |= 1 << 16; + if (mk_doutput(tad_inop)) + mk_aoutput(egpws_alert_discrete_2) |= 1 << 24; + if (mk->fault_handler.has_faults()) + mk_aoutput(egpws_alert_discrete_2) |= 1 << 25; } void MK_VIII::IOHandler::update_egpwc_alert_discrete_3 () { - mk_aoutput(egpwc_alert_discrete_3) = 1 << 17 | 1 << 18; + mk_aoutput(egpwc_alert_discrete_3) = 1 << 17 | 1 << 18; - if (mk->fault_handler.faults & (1<fault_handler.faults & (1<fault_handler.faults & (1<fault_handler.faults & (1<fault_handler.faults & (1<fault_handler.faults & (1<fault_handler.faults & (1<fault_handler.faults & (1<configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - mk_doutput(audio_on) = ! mk_dinput(audio_inhibit) - && mk->voice_player.voice - && ! mk->voice_player.voice->element->silence; + mk_doutput(audio_on) = ! mk_dinput(audio_inhibit) + && mk->voice_player.voice + && ! mk->voice_player.voice->element->silence; - update_egpws_alert_discrete_1(); - update_egpwc_logic_discretes(); - update_mode6_callouts_discrete_1(); - update_mode6_callouts_discrete_2(); - update_egpws_alert_discrete_2(); - update_egpwc_alert_discrete_3(); + update_egpws_alert_discrete_1(); + update_egpwc_logic_discretes(); + update_mode6_callouts_discrete_1(); + update_mode6_callouts_discrete_2(); + update_egpws_alert_discrete_2(); + update_egpwc_alert_discrete_3(); } bool * MK_VIII::IOHandler::get_lamp_output (Lamp lamp) { - switch (lamp) + switch (lamp) { case LAMP_GLIDESLOPE: - return &mk_doutput(gpws_alert); + return &mk_doutput(gpws_alert); case LAMP_CAUTION: - return conf.lamp->format2 ? &mk_doutput(gpws_alert) : &mk_doutput(gpws_warning); + return conf.lamp->format2 ? &mk_doutput(gpws_alert) : &mk_doutput(gpws_warning); case LAMP_WARNING: - return &mk_doutput(gpws_warning); + return &mk_doutput(gpws_warning); default: - assert_not_reached(); - return NULL; + assert_not_reached(); + return NULL; } } void MK_VIII::IOHandler::update_lamps () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - if (_lamp != LAMP_NONE && conf.lamp->flashing) + if (_lamp != LAMP_NONE && conf.lamp->flashing) { - // [SPEC] 6.9.3: 70 cycles per minute - if (lamp_timer.elapsed() >= 60.0 / 70.0 / 2.0) - { - bool *output = get_lamp_output(_lamp); - *output = ! *output; - lamp_timer.start(); - } + // [SPEC] 6.9.3: 70 cycles per minute + if (lamp_timer.elapsed() >= 60.0 / 70.0 / 2.0) + { + bool *output = get_lamp_output(_lamp); + *output = ! *output; + lamp_timer.start(); + } } } void MK_VIII::IOHandler::set_lamp (Lamp lamp) { - if (lamp == _lamp) - return; + if (lamp == _lamp) + return; - _lamp = lamp; + _lamp = lamp; - mk_doutput(gpws_warning) = false; - mk_doutput(gpws_alert) = false; + mk_doutput(gpws_warning) = false; + mk_doutput(gpws_alert) = false; - if (lamp != LAMP_NONE) + if (lamp != LAMP_NONE) { - *get_lamp_output(lamp) = true; - lamp_timer.start(); + *get_lamp_output(lamp) = true; + lamp_timer.start(); } } bool MK_VIII::IOHandler::gpws_inhibit () const { - return conf.gpws_inhibit_enabled && mk_dinput(gpws_inhibit); + return conf.gpws_inhibit_enabled && mk_dinput(gpws_inhibit); } bool MK_VIII::IOHandler::real_flaps_down () const { - return conf.flap_reversal ? mk_dinput(landing_flaps) : ! mk_dinput(landing_flaps); + return conf.flap_reversal ? mk_dinput(landing_flaps) : ! mk_dinput(landing_flaps); } bool MK_VIII::IOHandler::flaps_down () const { - return flap_override() ? true : real_flaps_down(); + return flap_override() ? true : real_flaps_down(); } bool MK_VIII::IOHandler::flap_override () const { - return conf.momentary_flap_override_enabled ? mk_doutput(flap_override) : false; + return conf.momentary_flap_override_enabled ? mk_doutput(flap_override) : false; } bool MK_VIII::IOHandler::steep_approach () const { - if (conf.steep_approach_enabled) - // If alternate action was configured in category 13, we return - // the value of the input discrete (which should be connected to a - // latching steep approach cockpit switch). Otherwise, we return - // the value of the output discrete. - return conf.alternate_steep_approach ? mk_dinput(steep_approach) : mk_doutput(steep_approach); - else - return false; + if (conf.steep_approach_enabled) + // If alternate action was configured in category 13, we return + // the value of the input discrete (which should be connected to a + // latching steep approach cockpit switch). Otherwise, we return + // the value of the output discrete. + return conf.alternate_steep_approach ? mk_dinput(steep_approach) : mk_doutput(steep_approach); + else + return false; } bool MK_VIII::IOHandler::momentary_steep_approach_enabled () const { - return conf.steep_approach_enabled && ! conf.alternate_steep_approach; + return conf.steep_approach_enabled && ! conf.alternate_steep_approach; } void MK_VIII::IOHandler::tie_input (SGPropertyNode *node, - const char *name, - bool *input, - bool *feed) + const char *name, + bool *input, + bool *feed) { - mk->properties_handler.tie(node, (string("inputs/discretes/") + name).c_str(), - FGVoicePlayer::RawValueMethodsData(*this, input, &MK_VIII::IOHandler::get_discrete_input, &MK_VIII::IOHandler::set_discrete_input)); - if (feed) - mk->properties_handler.tie(node, (string("input-feeders/discretes/") + name).c_str(), SGRawValuePointer(feed)); + mk->properties_handler.tie(node, (string("inputs/discretes/") + name).c_str(), + FGVoicePlayer::RawValueMethodsData(*this, input, &MK_VIII::IOHandler::get_discrete_input, &MK_VIII::IOHandler::set_discrete_input)); + if (feed) + mk->properties_handler.tie(node, (string("input-feeders/discretes/") + name).c_str(), SGRawValuePointer(feed)); } void MK_VIII::IOHandler::tie_input (SGPropertyNode *node, - const char *name, - Parameter *input, - bool *feed) + const char *name, + Parameter *input, + bool *feed) { - mk->properties_handler.tie(node, (string("inputs/arinc429/") + name).c_str(), SGRawValuePointer(input->get_pointer())); - mk->properties_handler.tie(node, (string("inputs/arinc429/") + name + "-ncd").c_str(), SGRawValuePointer(&input->ncd)); - if (feed) - mk->properties_handler.tie(node, (string("input-feeders/arinc429/") + name).c_str(), SGRawValuePointer(feed)); + mk->properties_handler.tie(node, (string("inputs/arinc429/") + name).c_str(), SGRawValuePointer(input->get_pointer())); + mk->properties_handler.tie(node, (string("inputs/arinc429/") + name + "-ncd").c_str(), SGRawValuePointer(&input->ncd)); + if (feed) + mk->properties_handler.tie(node, (string("input-feeders/arinc429/") + name).c_str(), SGRawValuePointer(feed)); } void MK_VIII::IOHandler::tie_output (SGPropertyNode *node, - const char *name, - bool *output) + const char *name, + bool *output) { - SGPropertyNode *child = node->getNode((string("outputs/discretes/") + name).c_str(), true); + SGPropertyNode *child = node->getNode((string("outputs/discretes/") + name).c_str(), true); - mk->properties_handler.tie(child, SGRawValuePointer(output)); - child->setAttribute(SGPropertyNode::WRITE, false); + mk->properties_handler.tie(child, SGRawValuePointer(output)); + child->setAttribute(SGPropertyNode::WRITE, false); } void MK_VIII::IOHandler::tie_output (SGPropertyNode *node, - const char *name, - int *output) + const char *name, + int *output) { - SGPropertyNode *child = node->getNode((string("outputs/arinc429/") + name).c_str(), true); + SGPropertyNode *child = node->getNode((string("outputs/arinc429/") + name).c_str(), true); - mk->properties_handler.tie(child, SGRawValuePointer(output)); - child->setAttribute(SGPropertyNode::WRITE, false); + mk->properties_handler.tie(child, SGRawValuePointer(output)); + child->setAttribute(SGPropertyNode::WRITE, false); } void MK_VIII::IOHandler::bind (SGPropertyNode *node) { - mk->properties_handler.tie(node, "inputs/rs-232/present-status", SGRawValueMethods(*this, &MK_VIII::IOHandler::get_present_status, &MK_VIII::IOHandler::set_present_status)); + mk->properties_handler.tie(node, "inputs/rs-232/present-status", SGRawValueMethods(*this, &MK_VIII::IOHandler::get_present_status, &MK_VIII::IOHandler::set_present_status)); - tie_input(node, "landing-gear", &mk_dinput(landing_gear), &mk_dinput_feed(landing_gear)); - tie_input(node, "landing-flaps", &mk_dinput(landing_flaps), &mk_dinput_feed(landing_flaps)); - tie_input(node, "momentary-flap-override", &mk_dinput(momentary_flap_override)); - tie_input(node, "self-test", &mk_dinput(self_test)); - tie_input(node, "glideslope-inhibit", &mk_dinput(glideslope_inhibit), &mk_dinput_feed(glideslope_inhibit)); - tie_input(node, "glideslope-cancel", &mk_dinput(glideslope_cancel)); - tie_input(node, "decision-height", &mk_dinput(decision_height), &mk_dinput_feed(decision_height)); - tie_input(node, "mode6-low-volume", &mk_dinput(mode6_low_volume)); - tie_input(node, "audio-inhibit", &mk_dinput(audio_inhibit)); - tie_input(node, "ta-tcf-inhibit", &mk_dinput(ta_tcf_inhibit)); - tie_input(node, "autopilot-engaged", &mk_dinput(autopilot_engaged), &mk_dinput_feed(autopilot_engaged)); - tie_input(node, "steep-approach", &mk_dinput(steep_approach)); - tie_input(node, "gpws-inhibit", &mk_dinput(gpws_inhibit)); + tie_input(node, "landing-gear", &mk_dinput(landing_gear), &mk_dinput_feed(landing_gear)); + tie_input(node, "landing-flaps", &mk_dinput(landing_flaps), &mk_dinput_feed(landing_flaps)); + tie_input(node, "momentary-flap-override", &mk_dinput(momentary_flap_override)); + tie_input(node, "self-test", &mk_dinput(self_test)); + tie_input(node, "glideslope-inhibit", &mk_dinput(glideslope_inhibit), &mk_dinput_feed(glideslope_inhibit)); + tie_input(node, "glideslope-cancel", &mk_dinput(glideslope_cancel)); + tie_input(node, "decision-height", &mk_dinput(decision_height), &mk_dinput_feed(decision_height)); + tie_input(node, "mode6-low-volume", &mk_dinput(mode6_low_volume)); + tie_input(node, "audio-inhibit", &mk_dinput(audio_inhibit)); + tie_input(node, "ta-tcf-inhibit", &mk_dinput(ta_tcf_inhibit)); + tie_input(node, "autopilot-engaged", &mk_dinput(autopilot_engaged), &mk_dinput_feed(autopilot_engaged)); + tie_input(node, "steep-approach", &mk_dinput(steep_approach)); + tie_input(node, "gpws-inhibit", &mk_dinput(gpws_inhibit)); - tie_input(node, "uncorrected-barometric-altitude", &mk_ainput(uncorrected_barometric_altitude), &mk_ainput_feed(uncorrected_barometric_altitude)); - tie_input(node, "barometric-altitude-rate", &mk_ainput(barometric_altitude_rate), &mk_ainput_feed(barometric_altitude_rate)); - tie_input(node, "gps-altitude", &mk_ainput(gps_altitude)); - tie_input(node, "gps-latitude", &mk_ainput(gps_latitude)); - tie_input(node, "gps-longitude", &mk_ainput(gps_longitude)); - tie_input(node, "gps-vertical-figure-of-merit", &mk_ainput(gps_vertical_figure_of_merit)); - tie_input(node, "radio-altitude", &mk_ainput(radio_altitude), &mk_ainput_feed(radio_altitude)); - tie_input(node, "glideslope-deviation", &mk_ainput(glideslope_deviation), &mk_ainput_feed(glideslope_deviation)); - tie_input(node, "roll-angle", &mk_ainput(roll_angle), &mk_ainput_feed(roll_angle)); - tie_input(node, "localizer-deviation", &mk_ainput(localizer_deviation), &mk_ainput_feed(localizer_deviation)); - tie_input(node, "computed-airspeed", &mk_ainput(computed_airspeed), &mk_ainput_feed(computed_airspeed)); - tie_input(node, "decision-height", &mk_ainput(decision_height), &mk_ainput_feed(decision_height)); + tie_input(node, "uncorrected-barometric-altitude", &mk_ainput(uncorrected_barometric_altitude), &mk_ainput_feed(uncorrected_barometric_altitude)); + tie_input(node, "barometric-altitude-rate", &mk_ainput(barometric_altitude_rate), &mk_ainput_feed(barometric_altitude_rate)); + tie_input(node, "gps-altitude", &mk_ainput(gps_altitude)); + tie_input(node, "gps-latitude", &mk_ainput(gps_latitude)); + tie_input(node, "gps-longitude", &mk_ainput(gps_longitude)); + tie_input(node, "gps-vertical-figure-of-merit", &mk_ainput(gps_vertical_figure_of_merit)); + tie_input(node, "radio-altitude", &mk_ainput(radio_altitude), &mk_ainput_feed(radio_altitude)); + tie_input(node, "glideslope-deviation", &mk_ainput(glideslope_deviation), &mk_ainput_feed(glideslope_deviation)); + tie_input(node, "roll-angle", &mk_ainput(roll_angle), &mk_ainput_feed(roll_angle)); + tie_input(node, "localizer-deviation", &mk_ainput(localizer_deviation), &mk_ainput_feed(localizer_deviation)); + tie_input(node, "computed-airspeed", &mk_ainput(computed_airspeed), &mk_ainput_feed(computed_airspeed)); + tie_input(node, "decision-height", &mk_ainput(decision_height), &mk_ainput_feed(decision_height)); - tie_output(node, "gpws-warning", &mk_doutput(gpws_warning)); - tie_output(node, "gpws-alert", &mk_doutput(gpws_alert)); - tie_output(node, "audio-on", &mk_doutput(audio_on)); - tie_output(node, "gpws-inop", &mk_doutput(gpws_inop)); - tie_output(node, "tad-inop", &mk_doutput(tad_inop)); - tie_output(node, "flap-override", &mk_doutput(flap_override)); - tie_output(node, "glideslope-cancel", &mk_doutput(glideslope_cancel)); - tie_output(node, "steep-approach", &mk_doutput(steep_approach)); + tie_output(node, "gpws-warning", &mk_doutput(gpws_warning)); + tie_output(node, "gpws-alert", &mk_doutput(gpws_alert)); + tie_output(node, "audio-on", &mk_doutput(audio_on)); + tie_output(node, "gpws-inop", &mk_doutput(gpws_inop)); + tie_output(node, "tad-inop", &mk_doutput(tad_inop)); + tie_output(node, "flap-override", &mk_doutput(flap_override)); + tie_output(node, "glideslope-cancel", &mk_doutput(glideslope_cancel)); + tie_output(node, "steep-approach", &mk_doutput(steep_approach)); - tie_output(node, "egpws-alert-discrete-1", &mk_aoutput(egpws_alert_discrete_1)); - tie_output(node, "egpwc-logic-discretes", &mk_aoutput(egpwc_logic_discretes)); - tie_output(node, "mode6-callouts-discrete-1", &mk_aoutput(mode6_callouts_discrete_1)); - tie_output(node, "mode6-callouts-discrete-2", &mk_aoutput(mode6_callouts_discrete_2)); - tie_output(node, "egpws-alert-discrete-2", &mk_aoutput(egpws_alert_discrete_2)); - tie_output(node, "egpwc-alert-discrete-3", &mk_aoutput(egpwc_alert_discrete_3)); + tie_output(node, "egpws-alert-discrete-1", &mk_aoutput(egpws_alert_discrete_1)); + tie_output(node, "egpwc-logic-discretes", &mk_aoutput(egpwc_logic_discretes)); + tie_output(node, "mode6-callouts-discrete-1", &mk_aoutput(mode6_callouts_discrete_1)); + tie_output(node, "mode6-callouts-discrete-2", &mk_aoutput(mode6_callouts_discrete_2)); + tie_output(node, "egpws-alert-discrete-2", &mk_aoutput(egpws_alert_discrete_2)); + tie_output(node, "egpwc-alert-discrete-3", &mk_aoutput(egpwc_alert_discrete_3)); } bool MK_VIII::IOHandler::get_discrete_input (bool *ptr) const { - return *ptr; + return *ptr; } void MK_VIII::IOHandler::set_discrete_input (bool *ptr, bool value) { - if (value == *ptr) - return; + if (value == *ptr) + return; - if (mk->system_handler.state == SystemHandler::STATE_ON) + if (mk->system_handler.state == SystemHandler::STATE_ON) { - if (ptr == &mk_dinput(momentary_flap_override)) - { - if (mk->configuration_module.state == ConfigurationModule::STATE_OK - && mk->self_test_handler.state == SelfTestHandler::STATE_NONE - && conf.momentary_flap_override_enabled - && value) - mk_doutput(flap_override) = ! mk_doutput(flap_override); - } - else if (ptr == &mk_dinput(self_test)) - mk->self_test_handler.handle_button_event(value); - else if (ptr == &mk_dinput(glideslope_cancel)) - { - if (mk->configuration_module.state == ConfigurationModule::STATE_OK - && mk->self_test_handler.state == SelfTestHandler::STATE_NONE - && value) - { - if (! mk_doutput(glideslope_cancel)) - { - // [SPEC] 6.2.5 + if (ptr == &mk_dinput(momentary_flap_override)) + { + if (mk->configuration_module.state == ConfigurationModule::STATE_OK + && mk->self_test_handler.state == SelfTestHandler::STATE_NONE + && conf.momentary_flap_override_enabled + && value) + mk_doutput(flap_override) = ! mk_doutput(flap_override); + } + else if (ptr == &mk_dinput(self_test)) + mk->self_test_handler.handle_button_event(value); + else if (ptr == &mk_dinput(glideslope_cancel)) + { + if (mk->configuration_module.state == ConfigurationModule::STATE_OK + && mk->self_test_handler.state == SelfTestHandler::STATE_NONE + && value) + { + if (! mk_doutput(glideslope_cancel)) + { + // [SPEC] 6.2.5 - // Although we are not called from update(), we are - // sure that the inputs we use here are defined, - // since state is STATE_ON. + // Although we are not called from update(), we are + // sure that the inputs we use here are defined, + // since state is STATE_ON. - if (! mk_data(glideslope_deviation_dots).ncd - && ! mk_data(radio_altitude).ncd - && mk_data(radio_altitude).get() <= 2000 - && mk_data(radio_altitude).get() >= 30) - mk_doutput(glideslope_cancel) = true; - } - // else do nothing ([PILOT] page 22: "Glideslope Cancel - // can not be deselected (reset) by again pressing the - // Glideslope Cancel switch.") - } - } - else if (ptr == &mk_dinput(steep_approach)) - { - if (mk->configuration_module.state == ConfigurationModule::STATE_OK - && mk->self_test_handler.state == SelfTestHandler::STATE_NONE - && momentary_steep_approach_enabled() - && value) - mk_doutput(steep_approach) = ! mk_doutput(steep_approach); - } + if (! mk_data(glideslope_deviation_dots).ncd + && ! mk_data(radio_altitude).ncd + && mk_data(radio_altitude).get() <= 2000 + && mk_data(radio_altitude).get() >= 30) + mk_doutput(glideslope_cancel) = true; + } + // else do nothing ([PILOT] page 22: "Glideslope Cancel + // can not be deselected (reset) by again pressing the + // Glideslope Cancel switch.") + } + } + else if (ptr == &mk_dinput(steep_approach)) + { + if (mk->configuration_module.state == ConfigurationModule::STATE_OK + && mk->self_test_handler.state == SelfTestHandler::STATE_NONE + && momentary_steep_approach_enabled() + && value) + mk_doutput(steep_approach) = ! mk_doutput(steep_approach); + } } - *ptr = value; + *ptr = value; - if (mk->system_handler.state == SystemHandler::STATE_ON) - update_alternate_discrete_input(ptr); + if (mk->system_handler.state == SystemHandler::STATE_ON) + update_alternate_discrete_input(ptr); } void MK_VIII::IOHandler::present_status_section (const char *name) { - printf("%s\n", name); + printf("%s\n", name); } void MK_VIII::IOHandler::present_status_item (const char *name, const char *value) { - if (value) - printf("\t%-32s %s\n", name, value); - else - printf("\t%s\n", name); + if (value) + printf("\t%-32s %s\n", name, value); + else + printf("\t%s\n", name); } void @@ -2022,111 +2039,114 @@ MK_VIII::IOHandler::present_status_subitem (const char *name) void MK_VIII::IOHandler::present_status () { - // [SPEC] 6.10.13 + // [SPEC] 6.10.13 - if (mk->system_handler.state != SystemHandler::STATE_ON) - return; + if (mk->system_handler.state != SystemHandler::STATE_ON) + return; - present_status_section("EGPWC CONFIGURATION"); - present_status_item("PART NUMBER:", "965-1220-000"); // [SPEC] 1.1 - present_status_item("MOD STATUS:", "N/A"); - present_status_item("SERIAL NUMBER:", "N/A"); - printf("\n"); - present_status_item("APPLICATION S/W VERSION:", FLIGHTGEAR_VERSION); - present_status_item("TERRAIN DATABASE VERSION:", FLIGHTGEAR_VERSION); - present_status_item("ENVELOPE MOD DATABASE VERSION:", "N/A"); - present_status_item("BOOT CODE VERSION:", FLIGHTGEAR_VERSION); - printf("\n"); + present_status_section("EGPWC CONFIGURATION"); + present_status_item("PART NUMBER:", "965-1220-000"); // [SPEC] 1.1 + present_status_item("MOD STATUS:", "N/A"); + present_status_item("SERIAL NUMBER:", "N/A"); + printf("\n"); + present_status_item("APPLICATION S/W VERSION:", FLIGHTGEAR_VERSION); + present_status_item("TERRAIN DATABASE VERSION:", FLIGHTGEAR_VERSION); + present_status_item("ENVELOPE MOD DATABASE VERSION:", "N/A"); + present_status_item("BOOT CODE VERSION:", FLIGHTGEAR_VERSION); + printf("\n"); - present_status_section("CURRENT FAULTS"); - if (mk->configuration_module.state == ConfigurationModule::STATE_OK && ! mk->fault_handler.has_faults()) - present_status_item("NO FAULTS"); - else + present_status_section("CURRENT FAULTS"); + if (mk->configuration_module.state == ConfigurationModule::STATE_OK && ! mk->fault_handler.has_faults()) + present_status_item("NO FAULTS"); + else { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - { - present_status_item("GPWS COMPUTER FAULTS:"); - switch (mk->configuration_module.state) - { - case ConfigurationModule::STATE_INVALID_DATABASE: - present_status_subitem("APPLICATION DATABASE FAILED"); - break; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + { + present_status_item("GPWS COMPUTER FAULTS:"); + switch (mk->configuration_module.state) + { + case ConfigurationModule::STATE_INVALID_DATABASE: + present_status_subitem("APPLICATION DATABASE FAILED"); + break; - case ConfigurationModule::STATE_INVALID_AIRCRAFT_TYPE: - present_status_subitem("CONFIGURATION TYPE INVALID"); - break; + case ConfigurationModule::STATE_INVALID_AIRCRAFT_TYPE: + present_status_subitem("CONFIGURATION TYPE INVALID"); + break; - default: - assert_not_reached(); - break; - } - } - else - { - present_status_item("GPWS COMPUTER OK"); - present_status_item("GPWS EXTERNAL FAULTS:"); + default: + assert_not_reached(); + break; + } + } + else + { + present_status_item("GPWS COMPUTER OK"); + present_status_item("GPWS EXTERNAL FAULTS:"); - static const char *fault_names[] = { - "ALL MODES INHIBIT", - "GEAR SWITCH", - "FLAPS SWITCH", - "MOMENTARY FLAP OVERRIDE INVALID", - "SELF TEST INVALID", - "GLIDESLOPE CANCEL INVALID", - "STEEP APPROACH INVALID", - "GPWS INHIBIT", - "TA & TCF INHIBIT", - "MODES 1-4 INPUTS INVALID", - "MODE 5 INPUTS INVALID", - "MODE 6 INPUTS INVALID", - "BANK ANGLE INPUTS INVALID", - "TCF INPUTS INVALID" - }; + static const char *fault_names[] = { + "ALL MODES INHIBIT", + "GEAR SWITCH", + "FLAPS SWITCH", + "MOMENTARY FLAP OVERRIDE INVALID", + "SELF TEST INVALID", + "GLIDESLOPE CANCEL INVALID", + "STEEP APPROACH INVALID", + "GPWS INHIBIT", + "TA & TCF INHIBIT", + "MODES 1-4 INPUTS INVALID", + "MODE 5 INPUTS INVALID", + "MODE 6 INPUTS INVALID", + "BANK ANGLE INPUTS INVALID", + "TCF INPUTS INVALID" + }; - for (size_t i = 0; i < n_elements(fault_names); i++) - if (mk->fault_handler.faults & (1<fault_handler.faults & (1<configuration_module.effective_categories[i]; + present_status_item(category_names[i], value.str().c_str()); } } bool MK_VIII::IOHandler::get_present_status () const { - return false; + return false; } void MK_VIII::IOHandler::set_present_status (bool value) -{ - if (value) present_status(); +{ + if (value) + present_status(); } @@ -2186,372 +2206,377 @@ MK_VIII::VoicePlayer::init () bool MK_VIII::SelfTestHandler::_was_here (int position) { - if (position > current) + if (position > current) { - current = position; - return false; + current = position; + return false; } - else + return true; } MK_VIII::SelfTestHandler::Action MK_VIII::SelfTestHandler::sleep (double duration) { - Action _action = { ACTION_SLEEP, duration, NULL }; - return _action; + Action _action = { ACTION_SLEEP, duration, NULL }; + return _action; } MK_VIII::SelfTestHandler::Action MK_VIII::SelfTestHandler::play (VoicePlayer::Voice *voice) { - mk->voice_player.play(voice); - Action _action = { ACTION_VOICE, 0, NULL }; - return _action; + mk->voice_player.play(voice); + Action _action = { ACTION_VOICE, 0, NULL }; + return _action; } MK_VIII::SelfTestHandler::Action MK_VIII::SelfTestHandler::discrete_on (bool *discrete, double duration) { - *discrete = true; - return sleep(duration); + *discrete = true; + return sleep(duration); } MK_VIII::SelfTestHandler::Action MK_VIII::SelfTestHandler::discrete_on_off (bool *discrete, double duration) { - *discrete = true; - Action _action = { ACTION_SLEEP | ACTION_DISCRETE_ON_OFF, duration, discrete }; - return _action; + *discrete = true; + Action _action = { ACTION_SLEEP | ACTION_DISCRETE_ON_OFF, duration, discrete }; + return _action; } MK_VIII::SelfTestHandler::Action MK_VIII::SelfTestHandler::discrete_on_off (bool *discrete, VoicePlayer::Voice *voice) { - *discrete = true; - mk->voice_player.play(voice); - Action _action = { ACTION_VOICE | ACTION_DISCRETE_ON_OFF, 0, discrete }; - return _action; + *discrete = true; + mk->voice_player.play(voice); + Action _action = { ACTION_VOICE | ACTION_DISCRETE_ON_OFF, 0, discrete }; + return _action; } MK_VIII::SelfTestHandler::Action MK_VIII::SelfTestHandler::done () { - Action _action = { ACTION_DONE, 0, NULL }; - return _action; + Action _action = { ACTION_DONE, 0, NULL }; + return _action; } MK_VIII::SelfTestHandler::Action MK_VIII::SelfTestHandler::run () { - // Note that "Terrain INOP" and "Terrain NA" are or'ed to the same - // output discrete (see [SPEC] 6.9.3.5). + // Note that "Terrain INOP" and "Terrain NA" are or'ed to the same + // output discrete (see [SPEC] 6.9.3.5). -#define was_here() was_here_offset(0) -#define was_here_offset(offset) _was_here(__LINE__ * 20 + (offset)) +#define was_here() was_here_offset(0) +#define was_here_offset(offset) _was_here(__LINE__ * 20 + (offset)) - if (! was_here()) + if (! was_here()) { - if (mk->configuration_module.state == ConfigurationModule::STATE_INVALID_DATABASE) - return play(mk_voice(application_data_base_failed)); - else if (mk->configuration_module.state == ConfigurationModule::STATE_INVALID_AIRCRAFT_TYPE) - return play(mk_voice(configuration_type_invalid)); + if (mk->configuration_module.state == ConfigurationModule::STATE_INVALID_DATABASE) + return play(mk_voice(application_data_base_failed)); + else if (mk->configuration_module.state == ConfigurationModule::STATE_INVALID_AIRCRAFT_TYPE) + return play(mk_voice(configuration_type_invalid)); } - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return done(); + + if (! was_here()) + return discrete_on(&mk_doutput(gpws_inop), 0.7); + if (! was_here()) + return sleep(0.7); // W/S INOP + if (! was_here()) + return discrete_on(&mk_doutput(tad_inop), 0.7); + if (! was_here()) + { + mk_doutput(gpws_inop) = false; + // do not disable tad_inop since we must enable Terrain NA + // do not disable W/S INOP since we do not emulate it + return sleep(0.7); // Terrain NA + } + if (! was_here()) + { + mk_doutput(tad_inop) = false; // disable Terrain NA + if (mk->io_handler.conf.momentary_flap_override_enabled) + return discrete_on_off(&mk_doutput(flap_override), 1.0); + } + if (! was_here()) + return discrete_on_off(&mk_doutput(audio_on), 1.0); + if (! was_here()) + { + if (mk->io_handler.momentary_steep_approach_enabled()) + return discrete_on_off(&mk_doutput(steep_approach), 1.0); + } + + if (! was_here()) + { + if (mk_dinput(glideslope_inhibit)) + goto glideslope_end; + else + { + if (mk->fault_handler.faults & (1<fault_handler.faults & (1<mode6_handler.conf.bank_angle_enabled + && (mk->fault_handler.faults & (1<mode6_handler.altitude_callouts_enabled() + && (mk->fault_handler.faults & (1<mode4_handler.conf.voice_too_low_gear); + if (! was_here()) + return play(mk_voice(too_low_flaps)); + if (! was_here()) + return play(mk_voice(too_low_terrain)); + if (! was_here()) + return play(mk_voice(glideslope)); + if (! was_here()) + { + if (mk->mode6_handler.conf.bank_angle_enabled) + return play(mk_voice(bank_angle)); + } + + if (! was_here()) + { + if (! mk->mode6_handler.altitude_callouts_enabled()) + goto callouts_disabled; + } + if (! was_here()) + { + if (mk->mode6_handler.conf.minimums_above_100_enabled) + return play(mk_voice(minimums_100)); + } + if (! was_here()) + { + if (mk->mode6_handler.conf.minimums_enabled) + return play(mk_voice(minimums)); + } + if (! was_here()) + { + if (mk->mode6_handler.conf.above_field_voice) + return play(mk->mode6_handler.conf.above_field_voice); + } + for (unsigned i = 0; i < n_altitude_callouts; i++) + { + if (! was_here_offset(i)) + { + if (mk->mode6_handler.conf.altitude_callouts_enabled & (1<mode6_handler.conf.smart_500_enabled) + return play(mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_500)); + } + goto callouts_end; + +callouts_disabled: + if (! was_here()) + return play(mk_voice(minimums_minimums)); + +callouts_end: + if (! was_here()) + { + if (mk->tcf_handler.conf.enabled) + return play(mk_voice(too_low_terrain)); + } + return done(); - - if (! was_here()) - return discrete_on(&mk_doutput(gpws_inop), 0.7); - if (! was_here()) - return sleep(0.7); // W/S INOP - if (! was_here()) - return discrete_on(&mk_doutput(tad_inop), 0.7); - if (! was_here()) - { - mk_doutput(gpws_inop) = false; - // do not disable tad_inop since we must enable Terrain NA - // do not disable W/S INOP since we do not emulate it - return sleep(0.7); // Terrain NA - } - if (! was_here()) - { - mk_doutput(tad_inop) = false; // disable Terrain NA - if (mk->io_handler.conf.momentary_flap_override_enabled) - return discrete_on_off(&mk_doutput(flap_override), 1.0); - } - if (! was_here()) - return discrete_on_off(&mk_doutput(audio_on), 1.0); - if (! was_here()) - { - if (mk->io_handler.momentary_steep_approach_enabled()) - return discrete_on_off(&mk_doutput(steep_approach), 1.0); - } - - if (! was_here()) - { - if (mk_dinput(glideslope_inhibit)) - goto glideslope_end; - else - { - if (mk->fault_handler.faults & (1<fault_handler.faults & (1<mode6_handler.conf.bank_angle_enabled - && (mk->fault_handler.faults & (1<mode6_handler.altitude_callouts_enabled() - && (mk->fault_handler.faults & (1<mode4_handler.conf.voice_too_low_gear); - if (! was_here()) - return play(mk_voice(too_low_flaps)); - if (! was_here()) - return play(mk_voice(too_low_terrain)); - if (! was_here()) - return play(mk_voice(glideslope)); - if (! was_here()) - { - if (mk->mode6_handler.conf.bank_angle_enabled) - return play(mk_voice(bank_angle)); - } - - if (! was_here()) - { - if (! mk->mode6_handler.altitude_callouts_enabled()) - goto callouts_disabled; - } - if (! was_here()) - { - if (mk->mode6_handler.conf.minimums_above_100_enabled) - return play(mk_voice(minimums_100)); - } - if (! was_here()) - { - if (mk->mode6_handler.conf.minimums_enabled) - return play(mk_voice(minimums)); - } - if (! was_here()) - { - if (mk->mode6_handler.conf.above_field_voice) - return play(mk->mode6_handler.conf.above_field_voice); - } - for (unsigned i = 0; i < n_altitude_callouts; i++) - if (! was_here_offset(i)) - { - if (mk->mode6_handler.conf.altitude_callouts_enabled & (1<mode6_handler.conf.smart_500_enabled) - return play(mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_500)); - } - goto callouts_end; - callouts_disabled: - if (! was_here()) - return play(mk_voice(minimums_minimums)); - callouts_end: - - if (! was_here()) - { - if (mk->tcf_handler.conf.enabled) - return play(mk_voice(too_low_terrain)); - } - - return done(); } void MK_VIII::SelfTestHandler::start () { - assert(state == STATE_START); + assert(state == STATE_START); - memcpy(&saved_outputs, &mk->io_handler.outputs, sizeof(mk->io_handler.outputs)); - memset(&mk->io_handler.outputs, 0, sizeof(mk->io_handler.outputs)); + memcpy(&saved_outputs, &mk->io_handler.outputs, sizeof(mk->io_handler.outputs)); + memset(&mk->io_handler.outputs, 0, sizeof(mk->io_handler.outputs)); - // [SPEC] 6.10.6: "The self-test results are annunciated, at 6db - // lower than the normal audio level selected for the aircraft" - mk->voice_player.set_volume(modify_amplitude(mk->voice_player.conf.volume, -6)); + // [SPEC] 6.10.6: "The self-test results are annunciated, at 6db + // lower than the normal audio level selected for the aircraft" + mk->voice_player.set_volume(modify_amplitude(mk->voice_player.conf.volume, -6)); - if (mk_dinput(mode6_low_volume)) - mk->mode6_handler.set_volume(1.0); + if (mk_dinput(mode6_low_volume)) + mk->mode6_handler.set_volume(1.0); - state = STATE_RUNNING; - cancel = CANCEL_NONE; - memset(&action, 0, sizeof(action)); - current = 0; + state = STATE_RUNNING; + cancel = CANCEL_NONE; + memset(&action, 0, sizeof(action)); + current = 0; } void MK_VIII::SelfTestHandler::stop () { - if (state != STATE_NONE) + if (state != STATE_NONE) { - if (state != STATE_START) - { - mk->voice_player.stop(VoicePlayer::STOP_NOW); - mk->voice_player.set_volume(mk_dinput(audio_inhibit) ? 0.0 : mk->voice_player.conf.volume); + if (state != STATE_START) + { + mk->voice_player.stop(VoicePlayer::STOP_NOW); + mk->voice_player.set_volume(mk_dinput(audio_inhibit) ? 0.0 : mk->voice_player.conf.volume); - if (mk_dinput(mode6_low_volume)) - mk->mode6_handler.set_volume(modify_amplitude(1.0, -6)); + if (mk_dinput(mode6_low_volume)) + mk->mode6_handler.set_volume(modify_amplitude(1.0, -6)); - memcpy(&mk->io_handler.outputs, &saved_outputs, sizeof(mk->io_handler.outputs)); - } + memcpy(&mk->io_handler.outputs, &saved_outputs, sizeof(mk->io_handler.outputs)); + } - button_pressed = false; - state = STATE_NONE; - // reset self-test handler position - current=0; + button_pressed = false; + state = STATE_NONE; + // reset self-test handler position + current = 0; } } void MK_VIII::SelfTestHandler::handle_button_event (bool value) { - if (state == STATE_NONE) + if (state == STATE_NONE) { - if (value) - state = STATE_START; + if (value) + state = STATE_START; } - else if (state == STATE_START) + else if (state == STATE_START) { - if (value) - state = STATE_NONE; // cancel the not-yet-started test + if (value) + state = STATE_NONE; // cancel the not-yet-started test } - else if (cancel == CANCEL_NONE) + else if (cancel == CANCEL_NONE) { - if (value) - { - assert(! button_pressed); - button_pressed = true; - button_press_timestamp = globals->get_sim_time_sec(); - } - else - { - if (button_pressed) - { - if (globals->get_sim_time_sec() - button_press_timestamp < 2) - cancel = CANCEL_SHORT; - else - cancel = CANCEL_LONG; - } - } + if (value) + { + assert(! button_pressed); + button_pressed = true; + button_press_timestamp = globals->get_sim_time_sec(); + } + else + { + if (button_pressed) + { + if (globals->get_sim_time_sec() - button_press_timestamp < 2) + cancel = CANCEL_SHORT; + else + cancel = CANCEL_LONG; + } + } } } bool MK_VIII::SelfTestHandler::update () { - if (state == STATE_NONE) - return false; - else if (state == STATE_START) + if (state == STATE_NONE) + return false; + else if (state == STATE_START) { - if (mk->state_handler.ground && ! mk->io_handler.steep_approach()) - start(); - else - { - state = STATE_NONE; - return false; - } + if (mk->state_handler.ground && ! mk->io_handler.steep_approach()) + start(); + else + { + state = STATE_NONE; + return false; + } } - else + else { - if (button_pressed && cancel == CANCEL_NONE) - { - if (globals->get_sim_time_sec() - button_press_timestamp >= 2) - cancel = CANCEL_LONG; - } + if (button_pressed && cancel == CANCEL_NONE) + { + if (globals->get_sim_time_sec() - button_press_timestamp >= 2) + cancel = CANCEL_LONG; + } } - if (! mk->state_handler.ground || cancel != CANCEL_NONE) + if (! mk->state_handler.ground || cancel != CANCEL_NONE) { - stop(); - return false; + stop(); + return false; } - if (test_bits(action.flags, ACTION_SLEEP)) + if (test_bits(action.flags, ACTION_SLEEP)) { - if (globals->get_sim_time_sec() - sleep_start < action.sleep_duration) - return true; + if (globals->get_sim_time_sec() - sleep_start < action.sleep_duration) + return true; } - if (test_bits(action.flags, ACTION_VOICE)) + if (test_bits(action.flags, ACTION_VOICE)) { - if (mk->voice_player.voice) - return true; + if (mk->voice_player.voice) + return true; } - if (test_bits(action.flags, ACTION_DISCRETE_ON_OFF)) - *action.discrete = false; + if (test_bits(action.flags, ACTION_DISCRETE_ON_OFF)) + *action.discrete = false; - action = run(); + action = run(); - if (test_bits(action.flags, ACTION_SLEEP)) - sleep_start = globals->get_sim_time_sec(); - if (test_bits(action.flags, ACTION_DONE)) + if (test_bits(action.flags, ACTION_SLEEP)) + sleep_start = globals->get_sim_time_sec(); + if (test_bits(action.flags, ACTION_DONE)) { - stop(); - return false; + stop(); + return false; } - return true; + return true; } /////////////////////////////////////////////////////////////////////////////// @@ -2561,250 +2586,250 @@ MK_VIII::SelfTestHandler::update () bool MK_VIII::AlertHandler::select_voice_alerts (unsigned int test) { - if (has_alerts(test)) + if (has_alerts(test)) { - voice_alerts = alerts & test; - return true; + voice_alerts = alerts & test; + return true; } - else + else { - voice_alerts &= ~test; - if (voice_alerts == 0) - mk->voice_player.stop(); + voice_alerts &= ~test; + if (voice_alerts == 0) + mk->voice_player.stop(); - return false; + return false; } } void MK_VIII::AlertHandler::boot () { - reset(); + reset(); } void MK_VIII::AlertHandler::reposition () { - reset(); + reset(); - mk->io_handler.set_lamp(IOHandler::LAMP_NONE); - mk->voice_player.stop(VoicePlayer::STOP_NOW); + mk->io_handler.set_lamp(IOHandler::LAMP_NONE); + mk->voice_player.stop(VoicePlayer::STOP_NOW); } void MK_VIII::AlertHandler::reset () { - alerts = 0; - old_alerts = 0; - voice_alerts = 0; - repeated_alerts = 0; - altitude_callout_voice = NULL; + alerts = 0; + old_alerts = 0; + voice_alerts = 0; + repeated_alerts = 0; + altitude_callout_voice = NULL; } void MK_VIII::AlertHandler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - // Lamps and voices are prioritized according to [SPEC] 6.9.2. - // - // Voices which can interrupt other voices (VoicePlayer::PLAY_NOW) - // are specified by [INSTALL] appendix E 5.3.5. - // - // When a voice is overriden by a higher priority voice and the - // overriding voice stops, we restore the previous voice if it was - // looped (this is not specified by [SPEC] but seems to make sense). + // Lamps and voices are prioritized according to [SPEC] 6.9.2. + // + // Voices which can interrupt other voices (VoicePlayer::PLAY_NOW) + // are specified by [INSTALL] appendix E 5.3.5. + // + // When a voice is overriden by a higher priority voice and the + // overriding voice stops, we restore the previous voice if it was + // looped (this is not specified by [SPEC] but seems to make sense). - // update lamp + // update lamp - if (has_alerts(ALERT_MODE1_PULL_UP | ALERT_MODE2A | ALERT_MODE2B)) - mk->io_handler.set_lamp(IOHandler::LAMP_WARNING); - else if (has_alerts(ALERT_MODE1_SINK_RATE - | ALERT_MODE2A_PREFACE - | ALERT_MODE2B_PREFACE - | ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING - | ALERT_MODE2A_ALTITUDE_GAIN - | ALERT_MODE2B_LANDING_MODE - | ALERT_MODE3 - | ALERT_MODE4_TOO_LOW_FLAPS - | ALERT_MODE4_TOO_LOW_GEAR - | ALERT_MODE4AB_TOO_LOW_TERRAIN - | ALERT_MODE4C_TOO_LOW_TERRAIN - | ALERT_TCF_TOO_LOW_TERRAIN)) - mk->io_handler.set_lamp(IOHandler::LAMP_CAUTION); - else if (has_alerts(ALERT_MODE5_SOFT | ALERT_MODE5_HARD)) - mk->io_handler.set_lamp(IOHandler::LAMP_GLIDESLOPE); - else - mk->io_handler.set_lamp(IOHandler::LAMP_NONE); + if (has_alerts(ALERT_MODE1_PULL_UP | ALERT_MODE2A | ALERT_MODE2B)) + mk->io_handler.set_lamp(IOHandler::LAMP_WARNING); + else if (has_alerts(ALERT_MODE1_SINK_RATE + | ALERT_MODE2A_PREFACE + | ALERT_MODE2B_PREFACE + | ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING + | ALERT_MODE2A_ALTITUDE_GAIN + | ALERT_MODE2B_LANDING_MODE + | ALERT_MODE3 + | ALERT_MODE4_TOO_LOW_FLAPS + | ALERT_MODE4_TOO_LOW_GEAR + | ALERT_MODE4AB_TOO_LOW_TERRAIN + | ALERT_MODE4C_TOO_LOW_TERRAIN + | ALERT_TCF_TOO_LOW_TERRAIN)) + mk->io_handler.set_lamp(IOHandler::LAMP_CAUTION); + else if (has_alerts(ALERT_MODE5_SOFT | ALERT_MODE5_HARD)) + mk->io_handler.set_lamp(IOHandler::LAMP_GLIDESLOPE); + else + mk->io_handler.set_lamp(IOHandler::LAMP_NONE); - // update voice + // update voice - if (select_voice_alerts(ALERT_MODE1_PULL_UP)) + if (select_voice_alerts(ALERT_MODE1_PULL_UP)) { - if (! has_old_alerts(ALERT_MODE1_PULL_UP)) - { - if (mk->voice_player.voice != mk_voice(sink_rate_pause_sink_rate)) - mk->voice_player.play(mk_voice(sink_rate), VoicePlayer::PLAY_NOW); - mk->voice_player.play(mk_voice(pull_up), VoicePlayer::PLAY_LOOPED); - } + if (! has_old_alerts(ALERT_MODE1_PULL_UP)) + { + if (mk->voice_player.voice != mk_voice(sink_rate_pause_sink_rate)) + mk->voice_player.play(mk_voice(sink_rate), VoicePlayer::PLAY_NOW); + mk->voice_player.play(mk_voice(pull_up), VoicePlayer::PLAY_LOOPED); + } } - else if (select_voice_alerts(ALERT_MODE2A_PREFACE | ALERT_MODE2B_PREFACE)) + else if (select_voice_alerts(ALERT_MODE2A_PREFACE | ALERT_MODE2B_PREFACE)) { - if (! has_old_alerts(ALERT_MODE2A_PREFACE | ALERT_MODE2B_PREFACE)) - mk->voice_player.play(mk_voice(terrain_pause_terrain), VoicePlayer::PLAY_NOW); + if (! has_old_alerts(ALERT_MODE2A_PREFACE | ALERT_MODE2B_PREFACE)) + mk->voice_player.play(mk_voice(terrain_pause_terrain), VoicePlayer::PLAY_NOW); } - else if (select_voice_alerts(ALERT_MODE2A | ALERT_MODE2B)) + else if (select_voice_alerts(ALERT_MODE2A | ALERT_MODE2B)) { - if (mk->voice_player.voice != mk_voice(pull_up)) - mk->voice_player.play(mk_voice(pull_up), VoicePlayer::PLAY_NOW | VoicePlayer::PLAY_LOOPED); + if (mk->voice_player.voice != mk_voice(pull_up)) + mk->voice_player.play(mk_voice(pull_up), VoicePlayer::PLAY_NOW | VoicePlayer::PLAY_LOOPED); } - else if (select_voice_alerts(ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING | ALERT_MODE2B_LANDING_MODE)) + else if (select_voice_alerts(ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING | ALERT_MODE2B_LANDING_MODE)) { - if (mk->voice_player.voice != mk_voice(terrain)) - mk->voice_player.play(mk_voice(terrain), VoicePlayer::PLAY_LOOPED); + if (mk->voice_player.voice != mk_voice(terrain)) + mk->voice_player.play(mk_voice(terrain), VoicePlayer::PLAY_LOOPED); } - else if (select_voice_alerts(ALERT_MODE6_MINIMUMS)) + else if (select_voice_alerts(ALERT_MODE6_MINIMUMS)) { - if (! has_old_alerts(ALERT_MODE6_MINIMUMS)) - mk->voice_player.play(mk_voice(minimums_minimums)); + if (! has_old_alerts(ALERT_MODE6_MINIMUMS)) + mk->voice_player.play(mk_voice(minimums_minimums)); } - else if (select_voice_alerts(ALERT_MODE6_MINIMUMS_100)) + else if (select_voice_alerts(ALERT_MODE6_MINIMUMS_100)) { - if (! has_old_alerts(ALERT_MODE6_MINIMUMS_100)) - mk->voice_player.play(mk_voice(minimums_100)); + if (! has_old_alerts(ALERT_MODE6_MINIMUMS_100)) + mk->voice_player.play(mk_voice(minimums_100)); } - else if (select_voice_alerts(ALERT_MODE6_RETARD)) + else if (select_voice_alerts(ALERT_MODE6_RETARD)) { - if (must_play_voice(ALERT_MODE6_RETARD)) - mk->voice_player.play(mk_voice(retard), VoicePlayer::PLAY_LOOPED); + if (must_play_voice(ALERT_MODE6_RETARD)) + mk->voice_player.play(mk_voice(retard), VoicePlayer::PLAY_LOOPED); } - else if (select_voice_alerts(ALERT_MODE4AB_TOO_LOW_TERRAIN | ALERT_MODE4C_TOO_LOW_TERRAIN)) + else if (select_voice_alerts(ALERT_MODE4AB_TOO_LOW_TERRAIN | ALERT_MODE4C_TOO_LOW_TERRAIN)) { - if (must_play_voice(ALERT_MODE4AB_TOO_LOW_TERRAIN | ALERT_MODE4C_TOO_LOW_TERRAIN)) - mk->voice_player.play(mk_voice(too_low_terrain)); + if (must_play_voice(ALERT_MODE4AB_TOO_LOW_TERRAIN | ALERT_MODE4C_TOO_LOW_TERRAIN)) + mk->voice_player.play(mk_voice(too_low_terrain)); } - else if (select_voice_alerts(ALERT_TCF_TOO_LOW_TERRAIN)) + else if (select_voice_alerts(ALERT_TCF_TOO_LOW_TERRAIN)) { - if (must_play_voice(ALERT_TCF_TOO_LOW_TERRAIN)) - mk->voice_player.play(mk_voice(too_low_terrain)); + if (must_play_voice(ALERT_TCF_TOO_LOW_TERRAIN)) + mk->voice_player.play(mk_voice(too_low_terrain)); } - else if (select_voice_alerts(ALERT_MODE6_ALTITUDE_CALLOUT)) + else if (select_voice_alerts(ALERT_MODE6_ALTITUDE_CALLOUT)) { - if (! has_old_alerts(ALERT_MODE6_ALTITUDE_CALLOUT)) - { - assert(altitude_callout_voice != NULL); - mk->voice_player.play(altitude_callout_voice); - altitude_callout_voice = NULL; - } + if (! has_old_alerts(ALERT_MODE6_ALTITUDE_CALLOUT)) + { + assert(altitude_callout_voice != NULL); + mk->voice_player.play(altitude_callout_voice); + altitude_callout_voice = NULL; + } } - else if (select_voice_alerts(ALERT_MODE4_TOO_LOW_GEAR)) + else if (select_voice_alerts(ALERT_MODE4_TOO_LOW_GEAR)) { - if (must_play_voice(ALERT_MODE4_TOO_LOW_GEAR)) - mk->voice_player.play(mk->mode4_handler.conf.voice_too_low_gear); + if (must_play_voice(ALERT_MODE4_TOO_LOW_GEAR)) + mk->voice_player.play(mk->mode4_handler.conf.voice_too_low_gear); } - else if (select_voice_alerts(ALERT_MODE4_TOO_LOW_FLAPS)) + else if (select_voice_alerts(ALERT_MODE4_TOO_LOW_FLAPS)) { - if (must_play_voice(ALERT_MODE4_TOO_LOW_FLAPS)) - mk->voice_player.play(mk_voice(too_low_flaps)); + if (must_play_voice(ALERT_MODE4_TOO_LOW_FLAPS)) + mk->voice_player.play(mk_voice(too_low_flaps)); } - else if (select_voice_alerts(ALERT_MODE1_SINK_RATE)) + else if (select_voice_alerts(ALERT_MODE1_SINK_RATE)) { - if (must_play_voice(ALERT_MODE1_SINK_RATE)) - mk->voice_player.play(mk_voice(sink_rate_pause_sink_rate)); - // [SPEC] 6.2.1: "During the time that the voice message for the - // outer envelope is inhibited and the caution/warning lamp is - // on, the Mode 5 alert message is allowed to annunciate for - // excessive glideslope deviation conditions." - else if (mk->voice_player.voice != mk_voice(sink_rate_pause_sink_rate) - && mk->voice_player.next_voice != mk_voice(sink_rate_pause_sink_rate)) - { - if (has_alerts(ALERT_MODE5_HARD)) - { - voice_alerts |= ALERT_MODE5_HARD; - if (mk->voice_player.voice != mk_voice(hard_glideslope)) - mk->voice_player.play(mk_voice(hard_glideslope), VoicePlayer::PLAY_LOOPED); - } - else if (has_alerts(ALERT_MODE5_SOFT)) - { - voice_alerts |= ALERT_MODE5_SOFT; - if (must_play_voice(ALERT_MODE5_SOFT)) - mk->voice_player.play(mk_voice(soft_glideslope)); - } - } + if (must_play_voice(ALERT_MODE1_SINK_RATE)) + mk->voice_player.play(mk_voice(sink_rate_pause_sink_rate)); + // [SPEC] 6.2.1: "During the time that the voice message for the + // outer envelope is inhibited and the caution/warning lamp is + // on, the Mode 5 alert message is allowed to annunciate for + // excessive glideslope deviation conditions." + else if (mk->voice_player.voice != mk_voice(sink_rate_pause_sink_rate) + && mk->voice_player.next_voice != mk_voice(sink_rate_pause_sink_rate)) + { + if (has_alerts(ALERT_MODE5_HARD)) + { + voice_alerts |= ALERT_MODE5_HARD; + if (mk->voice_player.voice != mk_voice(hard_glideslope)) + mk->voice_player.play(mk_voice(hard_glideslope), VoicePlayer::PLAY_LOOPED); + } + else if (has_alerts(ALERT_MODE5_SOFT)) + { + voice_alerts |= ALERT_MODE5_SOFT; + if (must_play_voice(ALERT_MODE5_SOFT)) + mk->voice_player.play(mk_voice(soft_glideslope)); + } + } } - else if (select_voice_alerts(ALERT_MODE3)) + else if (select_voice_alerts(ALERT_MODE3)) { - if (must_play_voice(ALERT_MODE3)) - mk->voice_player.play(mk_voice(dont_sink_pause_dont_sink)); + if (must_play_voice(ALERT_MODE3)) + mk->voice_player.play(mk_voice(dont_sink_pause_dont_sink)); } - else if (select_voice_alerts(ALERT_MODE5_HARD)) + else if (select_voice_alerts(ALERT_MODE5_HARD)) { - if (mk->voice_player.voice != mk_voice(hard_glideslope)) - mk->voice_player.play(mk_voice(hard_glideslope), VoicePlayer::PLAY_LOOPED); + if (mk->voice_player.voice != mk_voice(hard_glideslope)) + mk->voice_player.play(mk_voice(hard_glideslope), VoicePlayer::PLAY_LOOPED); } - else if (select_voice_alerts(ALERT_MODE5_SOFT)) + else if (select_voice_alerts(ALERT_MODE5_SOFT)) { - if (must_play_voice(ALERT_MODE5_SOFT)) - mk->voice_player.play(mk_voice(soft_glideslope)); + if (must_play_voice(ALERT_MODE5_SOFT)) + mk->voice_player.play(mk_voice(soft_glideslope)); } - else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_3)) + else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_3)) { - if (mk->voice_player.voice != mk_voice(bank_angle_bank_angle_3)) - mk->voice_player.play(mk_voice(bank_angle_bank_angle_3), VoicePlayer::PLAY_LOOPED); + if (mk->voice_player.voice != mk_voice(bank_angle_bank_angle_3)) + mk->voice_player.play(mk_voice(bank_angle_bank_angle_3), VoicePlayer::PLAY_LOOPED); } - else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_3)) + else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_3)) { - if (mk->voice_player.voice != mk_voice(bank_angle_pause_bank_angle_3)) - mk->voice_player.play(mk_voice(bank_angle_pause_bank_angle_3), VoicePlayer::PLAY_LOOPED); + if (mk->voice_player.voice != mk_voice(bank_angle_pause_bank_angle_3)) + mk->voice_player.play(mk_voice(bank_angle_pause_bank_angle_3), VoicePlayer::PLAY_LOOPED); } - else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2)) + else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2)) { - if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2 | ALERT_MODE6_HIGH_BANK_ANGLE_2)) - mk->voice_player.play(mk_voice(bank_angle_bank_angle)); + if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2 | ALERT_MODE6_HIGH_BANK_ANGLE_2)) + mk->voice_player.play(mk_voice(bank_angle_bank_angle)); } - else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_2)) + else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_2)) { - if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2 | ALERT_MODE6_HIGH_BANK_ANGLE_2)) - mk->voice_player.play(mk_voice(bank_angle_pause_bank_angle)); + if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_2 | ALERT_MODE6_HIGH_BANK_ANGLE_2)) + mk->voice_player.play(mk_voice(bank_angle_pause_bank_angle)); } - else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1)) + else if (select_voice_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1)) { - if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1 | ALERT_MODE6_HIGH_BANK_ANGLE_1)) - mk->voice_player.play(mk_voice(bank_angle_bank_angle)); + if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1 | ALERT_MODE6_HIGH_BANK_ANGLE_1)) + mk->voice_player.play(mk_voice(bank_angle_bank_angle)); } - else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_1)) + else if (select_voice_alerts(ALERT_MODE6_HIGH_BANK_ANGLE_1)) { - if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1 | ALERT_MODE6_HIGH_BANK_ANGLE_1)) - mk->voice_player.play(mk_voice(bank_angle_pause_bank_angle)); + if (! has_old_alerts(ALERT_MODE6_LOW_BANK_ANGLE_1 | ALERT_MODE6_HIGH_BANK_ANGLE_1)) + mk->voice_player.play(mk_voice(bank_angle_pause_bank_angle)); } - // remember all alerts voiced so far... - old_alerts |= voice_alerts; - // ... forget those no longer active - old_alerts &= alerts; - repeated_alerts = 0; + // remember all alerts voiced so far... + old_alerts |= voice_alerts; + // ... forget those no longer active + old_alerts &= alerts; + repeated_alerts = 0; } void MK_VIII::AlertHandler::set_alerts (unsigned int _alerts, - unsigned int flags, - VoicePlayer::Voice *_altitude_callout_voice) + unsigned int flags, + VoicePlayer::Voice *_altitude_callout_voice) { - alerts |= _alerts; - if (test_bits(flags, ALERT_FLAG_REPEAT)) - repeated_alerts |= _alerts; - if (_altitude_callout_voice) - altitude_callout_voice = _altitude_callout_voice; + alerts |= _alerts; + if (test_bits(flags, ALERT_FLAG_REPEAT)) + repeated_alerts |= _alerts; + if (_altitude_callout_voice) + altitude_callout_voice = _altitude_callout_voice; } void MK_VIII::AlertHandler::unset_alerts (unsigned int _alerts) { - alerts &= ~_alerts; - repeated_alerts &= ~_alerts; - if (_alerts & ALERT_MODE6_ALTITUDE_CALLOUT) - altitude_callout_voice = NULL; + alerts &= ~_alerts; + repeated_alerts &= ~_alerts; + if (_alerts & ALERT_MODE6_ALTITUDE_CALLOUT) + altitude_callout_voice = NULL; } /////////////////////////////////////////////////////////////////////////////// @@ -2814,119 +2839,119 @@ MK_VIII::AlertHandler::unset_alerts (unsigned int _alerts) void MK_VIII::StateHandler::update_ground () { - if (ground) + if (ground) { - if (! mk_ainput(computed_airspeed).ncd && mk_ainput(computed_airspeed).get() > 60 - && ! mk_data(radio_altitude).ncd && mk_data(radio_altitude).get() > 30) - { - if (potentially_airborne_timer.start_or_elapsed() > 1) - leave_ground(); - } - else - potentially_airborne_timer.stop(); + if (! mk_ainput(computed_airspeed).ncd && mk_ainput(computed_airspeed).get() > 60 + && ! mk_data(radio_altitude).ncd && mk_data(radio_altitude).get() > 30) + { + if (potentially_airborne_timer.start_or_elapsed() > 1) + leave_ground(); + } + else + potentially_airborne_timer.stop(); } - else + else { - if (! mk_ainput(computed_airspeed).ncd && mk_ainput(computed_airspeed).get() < 40 - && ! mk_data(radio_altitude).ncd && mk_data(radio_altitude).get() < 30) - enter_ground(); + if (! mk_ainput(computed_airspeed).ncd && mk_ainput(computed_airspeed).get() < 40 + && ! mk_data(radio_altitude).ncd && mk_data(radio_altitude).get() < 30) + enter_ground(); } } void MK_VIII::StateHandler::enter_ground () { - ground = true; - mk->io_handler.enter_ground(); + ground = true; + mk->io_handler.enter_ground(); - // [SPEC] 6.0.1 does not specify this, but it seems to be an - // omission; at this point, we must make sure that we are in takeoff - // mode (otherwise the next takeoff might happen in approach mode). - if (! takeoff) - enter_takeoff(); + // [SPEC] 6.0.1 does not specify this, but it seems to be an + // omission; at this point, we must make sure that we are in takeoff + // mode (otherwise the next takeoff might happen in approach mode). + if (! takeoff) + enter_takeoff(); } void MK_VIII::StateHandler::leave_ground () { - ground = false; - mk->mode2_handler.leave_ground(); + ground = false; + mk->mode2_handler.leave_ground(); } void MK_VIII::StateHandler::update_takeoff () { - if (takeoff) + if (takeoff) { - // [SPEC] 6.0.2 is somewhat confusing: it mentions hardcoded - // terrain clearance (500, 750) and airspeed (178, 200) values, - // but it also mentions the mode 4A boundary, which varies as a - // function of aircraft type. We consider that the mentioned - // values are examples, and that we should use the mode 4A upper - // boundary. + // [SPEC] 6.0.2 is somewhat confusing: it mentions hardcoded + // terrain clearance (500, 750) and airspeed (178, 200) values, + // but it also mentions the mode 4A boundary, which varies as a + // function of aircraft type. We consider that the mentioned + // values are examples, and that we should use the mode 4A upper + // boundary. - if (! mk_data(terrain_clearance).ncd - && ! mk_ainput(computed_airspeed).ncd - && mk_data(terrain_clearance).get() > mk->mode4_handler.get_upper_agl(mk->mode4_handler.conf.modes->ac)) - leave_takeoff(); + if (! mk_data(terrain_clearance).ncd + && ! mk_ainput(computed_airspeed).ncd + && mk_data(terrain_clearance).get() > mk->mode4_handler.get_upper_agl(mk->mode4_handler.conf.modes->ac)) + leave_takeoff(); } - else + else { - if (! mk_data(radio_altitude).ncd - && mk_data(radio_altitude).get() < mk->mode4_handler.conf.modes->b->min_agl1 - && mk->io_handler.flaps_down() - && mk_dinput(landing_gear)) - enter_takeoff(); + if (! mk_data(radio_altitude).ncd + && mk_data(radio_altitude).get() < mk->mode4_handler.conf.modes->b->min_agl1 + && mk->io_handler.flaps_down() + && mk_dinput(landing_gear)) + enter_takeoff(); } } void MK_VIII::StateHandler::enter_takeoff () { - takeoff = true; - mk->io_handler.enter_takeoff(); - mk->mode2_handler.enter_takeoff(); - mk->mode3_handler.enter_takeoff(); - mk->mode6_handler.enter_takeoff(); + takeoff = true; + mk->io_handler.enter_takeoff(); + mk->mode2_handler.enter_takeoff(); + mk->mode3_handler.enter_takeoff(); + mk->mode6_handler.enter_takeoff(); } void MK_VIII::StateHandler::leave_takeoff () { - takeoff = false; - mk->mode6_handler.leave_takeoff(); + takeoff = false; + mk->mode6_handler.leave_takeoff(); } void MK_VIII::StateHandler::post_reposition () { - // Synchronize the state with the current situation. + // Synchronize the state with the current situation. - bool _ground = ! - (! mk_ainput(computed_airspeed).ncd && mk_ainput(computed_airspeed).get() > 60 - && ! mk_data(radio_altitude).ncd && mk_data(radio_altitude).get() > 30); + bool _ground = ! + (! mk_ainput(computed_airspeed).ncd && mk_ainput(computed_airspeed).get() > 60 + && ! mk_data(radio_altitude).ncd && mk_data(radio_altitude).get() > 30); - bool _takeoff = _ground; + bool _takeoff = _ground; - if (ground && ! _ground) - leave_ground(); - else if ((!ground) && _ground) - enter_ground(); + if (ground && ! _ground) + leave_ground(); + else if ((!ground) && _ground) + enter_ground(); - if (takeoff && (!_takeoff)) - leave_takeoff(); - else if ((!takeoff) && _takeoff) - enter_takeoff(); + if (takeoff && (!_takeoff)) + leave_takeoff(); + else if ((!takeoff) && _takeoff) + enter_takeoff(); } void MK_VIII::StateHandler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - update_ground(); - update_takeoff(); + update_ground(); + update_takeoff(); } /////////////////////////////////////////////////////////////////////////////// @@ -2936,148 +2961,148 @@ MK_VIII::StateHandler::update () double MK_VIII::Mode1Handler::get_pull_up_bias () { - // [PILOT] page 54: "Steep Approach has priority over Flap Override - // if selected simultaneously." + // [PILOT] page 54: "Steep Approach has priority over Flap Override + // if selected simultaneously." - if (mk->io_handler.steep_approach()) - return 200; - else if (conf.envelopes->flap_override_bias && mk->io_handler.flap_override()) - return 300; - else - return 0; + if (mk->io_handler.steep_approach()) + return 200; + else if (conf.envelopes->flap_override_bias && mk->io_handler.flap_override()) + return 300; + else + return 0; } bool MK_VIII::Mode1Handler::is_pull_up () { - if (! mk->io_handler.gpws_inhibit() + if (! mk->io_handler.gpws_inhibit() && ! mk->state_handler.ground // [1] && ! mk_data(radio_altitude).ncd && ! mk_data(barometric_altitude_rate).ncd && mk_data(radio_altitude).get() > conf.envelopes->min_agl) { - if (mk_data(radio_altitude).get() < conf.envelopes->pull_up_max_agl1) - { - if (mk_data(radio_altitude).get() < conf.envelopes->pull_up_min_agl1(mk_data(barometric_altitude_rate).get() + get_pull_up_bias())) - return true; - } - else if (mk_data(radio_altitude).get() < conf.envelopes->pull_up_max_agl2) - { - if (mk_data(radio_altitude).get() < conf.envelopes->pull_up_min_agl2(mk_data(barometric_altitude_rate).get() + get_pull_up_bias())) - return true; - } + if (mk_data(radio_altitude).get() < conf.envelopes->pull_up_max_agl1) + { + if (mk_data(radio_altitude).get() < conf.envelopes->pull_up_min_agl1(mk_data(barometric_altitude_rate).get() + get_pull_up_bias())) + return true; + } + else if (mk_data(radio_altitude).get() < conf.envelopes->pull_up_max_agl2) + { + if (mk_data(radio_altitude).get() < conf.envelopes->pull_up_min_agl2(mk_data(barometric_altitude_rate).get() + get_pull_up_bias())) + return true; + } } - return false; + return false; } void MK_VIII::Mode1Handler::update_pull_up () { - if (is_pull_up()) + if (is_pull_up()) { - if (! mk_test_alert(MODE1_PULL_UP)) - { - // [SPEC] 6.2.1: at least one sink rate must be issued - // before switching to pull up; if no sink rate has - // occurred, a 0.2 second delay is used. - if (mk->voice_player.voice == mk_voice(sink_rate_pause_sink_rate) - || pull_up_timer.start_or_elapsed() >= 0.2) - mk_set_alerts(mk_alert(MODE1_PULL_UP)); - } + if (! mk_test_alert(MODE1_PULL_UP)) + { + // [SPEC] 6.2.1: at least one sink rate must be issued + // before switching to pull up; if no sink rate has + // occurred, a 0.2 second delay is used. + if (mk->voice_player.voice == mk_voice(sink_rate_pause_sink_rate) + || pull_up_timer.start_or_elapsed() >= 0.2) + mk_set_alerts(mk_alert(MODE1_PULL_UP)); + } } - else + else { - pull_up_timer.stop(); - mk_unset_alerts(mk_alert(MODE1_PULL_UP)); + pull_up_timer.stop(); + mk_unset_alerts(mk_alert(MODE1_PULL_UP)); } } double MK_VIII::Mode1Handler::get_sink_rate_bias () { - // [PILOT] page 54: "Steep Approach has priority over Flap Override - // if selected simultaneously." + // [PILOT] page 54: "Steep Approach has priority over Flap Override + // if selected simultaneously." - if (mk->io_handler.steep_approach()) - return 500; - else if (conf.envelopes->flap_override_bias && mk->io_handler.flap_override()) - return 300; - else if (! mk_data(glideslope_deviation_dots).ncd) + if (mk->io_handler.steep_approach()) + return 500; + else if (conf.envelopes->flap_override_bias && mk->io_handler.flap_override()) + return 300; + else if (! mk_data(glideslope_deviation_dots).ncd) { - double bias = 0; + double bias = 0; - if (mk_data(glideslope_deviation_dots).get() <= -2) - bias = 300; - else if (mk_data(glideslope_deviation_dots).get() < 0) - bias = -150 * mk_data(glideslope_deviation_dots).get(); + if (mk_data(glideslope_deviation_dots).get() <= -2) + bias = 300; + else if (mk_data(glideslope_deviation_dots).get() < 0) + bias = -150 * mk_data(glideslope_deviation_dots).get(); - if (mk_data(radio_altitude).get() < 100) - bias *= 0.01 * mk_data(radio_altitude).get(); + if (mk_data(radio_altitude).get() < 100) + bias *= 0.01 * mk_data(radio_altitude).get(); - return bias; + return bias; } - else - return 0; + else + return 0; } bool MK_VIII::Mode1Handler::is_sink_rate () { - return ! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && ! mk_data(radio_altitude).ncd - && ! mk_data(barometric_altitude_rate).ncd - && mk_data(radio_altitude).get() > conf.envelopes->min_agl - && mk_data(radio_altitude).get() < 2450 - && mk_data(radio_altitude).get() < -572 - 0.6035 * (mk_data(barometric_altitude_rate).get() + get_sink_rate_bias()); + return ! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && ! mk_data(radio_altitude).ncd + && ! mk_data(barometric_altitude_rate).ncd + && mk_data(radio_altitude).get() > conf.envelopes->min_agl + && mk_data(radio_altitude).get() < 2450 + && mk_data(radio_altitude).get() < -572 - 0.6035 * (mk_data(barometric_altitude_rate).get() + get_sink_rate_bias()); } double MK_VIII::Mode1Handler::get_sink_rate_tti () { - return mk_data(radio_altitude).get() / fabs(mk_data(barometric_altitude_rate).get()); + return mk_data(radio_altitude).get() / fabs(mk_data(barometric_altitude_rate).get()); } void MK_VIII::Mode1Handler::update_sink_rate () { - if (is_sink_rate()) + if (is_sink_rate()) { - if (mk_test_alert(MODE1_SINK_RATE)) - { - double tti = get_sink_rate_tti(); - if (tti <= sink_rate_tti * 0.8) - { - // ~20% degradation, warn again and store the new reference tti - sink_rate_tti = tti; - mk_repeat_alert(mk_alert(MODE1_SINK_RATE)); - } - } - else - { - if (sink_rate_timer.start_or_elapsed() >= 0.8) - { - mk_set_alerts(mk_alert(MODE1_SINK_RATE)); - sink_rate_tti = get_sink_rate_tti(); - } - } + if (mk_test_alert(MODE1_SINK_RATE)) + { + double tti = get_sink_rate_tti(); + if (tti <= sink_rate_tti * 0.8) + { + // ~20% degradation, warn again and store the new reference tti + sink_rate_tti = tti; + mk_repeat_alert(mk_alert(MODE1_SINK_RATE)); + } + } + else + { + if (sink_rate_timer.start_or_elapsed() >= 0.8) + { + mk_set_alerts(mk_alert(MODE1_SINK_RATE)); + sink_rate_tti = get_sink_rate_tti(); + } + } } - else + else { - sink_rate_timer.stop(); - mk_unset_alerts(mk_alert(MODE1_SINK_RATE)); + sink_rate_timer.stop(); + mk_unset_alerts(mk_alert(MODE1_SINK_RATE)); } } void MK_VIII::Mode1Handler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - update_pull_up(); - update_sink_rate(); + update_pull_up(); + update_sink_rate(); } /////////////////////////////////////////////////////////////////////////////// @@ -3087,324 +3112,324 @@ MK_VIII::Mode1Handler::update () double MK_VIII::Mode2Handler::ClosureRateFilter::limit_radio_altitude_rate (double r) { - // Limit radio altitude rate according to aircraft configuration, - // allowing maximum sensitivity during cruise while providing - // progressively less sensitivity during the landing phases of - // flight. + // Limit radio altitude rate according to aircraft configuration, + // allowing maximum sensitivity during cruise while providing + // progressively less sensitivity during the landing phases of + // flight. - if (! mk_data(glideslope_deviation_dots).ncd && fabs(mk_data(glideslope_deviation_dots).get()) <= 2) - { // gs deviation <= +- 2 dots - if (mk_dinput(landing_gear) && mk->io_handler.flaps_down()) - SG_CLAMP_RANGE(r, -1000.0, 3000.0); - else if (mk_dinput(landing_gear) || mk->io_handler.flaps_down()) - SG_CLAMP_RANGE(r, 0.0, 4000.0); - else - SG_CLAMP_RANGE(r, 1000.0, 5000.0); + if (! mk_data(glideslope_deviation_dots).ncd && fabs(mk_data(glideslope_deviation_dots).get()) <= 2) + { // gs deviation <= +- 2 dots + if (mk_dinput(landing_gear) && mk->io_handler.flaps_down()) + SG_CLAMP_RANGE(r, -1000.0, 3000.0); + else if (mk_dinput(landing_gear) || mk->io_handler.flaps_down()) + SG_CLAMP_RANGE(r, 0.0, 4000.0); + else + SG_CLAMP_RANGE(r, 1000.0, 5000.0); } - else - { // no ILS, or gs deviation > +- 2 dots - if (mk_dinput(landing_gear) && mk->io_handler.flaps_down()) - SG_CLAMP_RANGE(r, 0.0, 4000.0); - else if (mk_dinput(landing_gear) || mk->io_handler.flaps_down()) - SG_CLAMP_RANGE(r, 1000.0, 5000.0); - // else no clamp + else + { // no ILS, or gs deviation > +- 2 dots + if (mk_dinput(landing_gear) && mk->io_handler.flaps_down()) + SG_CLAMP_RANGE(r, 0.0, 4000.0); + else if (mk_dinput(landing_gear) || mk->io_handler.flaps_down()) + SG_CLAMP_RANGE(r, 1000.0, 5000.0); + // else no clamp } - return r; + return r; } void MK_VIII::Mode2Handler::ClosureRateFilter::init () { - timer.stop(); - last_ra.set(&mk_data(radio_altitude)); - last_ba.set(&mk_ainput(uncorrected_barometric_altitude)); - ra_filter.reset(); - ba_filter.reset(); - output.unset(); + timer.stop(); + last_ra.set(&mk_data(radio_altitude)); + last_ba.set(&mk_ainput(uncorrected_barometric_altitude)); + ra_filter.reset(); + ba_filter.reset(); + output.unset(); } void MK_VIII::Mode2Handler::ClosureRateFilter::update () { - double elapsed = timer.start_or_elapsed(); - if (elapsed < 1) - return; + double elapsed = timer.start_or_elapsed(); + if (elapsed < 1) + return; - if (! mk_data(radio_altitude).ncd && ! mk_ainput(uncorrected_barometric_altitude).ncd) + if (! mk_data(radio_altitude).ncd && ! mk_ainput(uncorrected_barometric_altitude).ncd) { - if (! last_ra.ncd && ! last_ba.ncd) - { - // compute radio and barometric altitude rates (positive value = descent) - double ra_rate = -(mk_data(radio_altitude).get() - last_ra.get()) / elapsed * 60; - double ba_rate = -(mk_ainput(uncorrected_barometric_altitude).get() - last_ba.get()) / elapsed * 60; + if (! last_ra.ncd && ! last_ba.ncd) + { + // compute radio and barometric altitude rates (positive value = descent) + double ra_rate = -(mk_data(radio_altitude).get() - last_ra.get()) / elapsed * 60; + double ba_rate = -(mk_ainput(uncorrected_barometric_altitude).get() - last_ba.get()) / elapsed * 60; - // limit radio altitude rate according to aircraft configuration - ra_rate = limit_radio_altitude_rate(ra_rate); + // limit radio altitude rate according to aircraft configuration + ra_rate = limit_radio_altitude_rate(ra_rate); - // apply a low-pass filter to the radio altitude rate - ra_rate = ra_filter.filter(ra_rate); - // apply a high-pass filter to the barometric altitude rate - ba_rate = ba_filter.filter(ba_rate); + // apply a low-pass filter to the radio altitude rate + ra_rate = ra_filter.filter(ra_rate); + // apply a high-pass filter to the barometric altitude rate + ba_rate = ba_filter.filter(ba_rate); - // combine both rates to obtain a closure rate - output.set(ra_rate + ba_rate); - } - else - output.unset(); + // combine both rates to obtain a closure rate + output.set(ra_rate + ba_rate); + } + else + output.unset(); } - else + else { - ra_filter.reset(); - ba_filter.reset(); - output.unset(); + ra_filter.reset(); + ba_filter.reset(); + output.unset(); } - timer.start(); - last_ra.set(&mk_data(radio_altitude)); - last_ba.set(&mk_ainput(uncorrected_barometric_altitude)); + timer.start(); + last_ra.set(&mk_data(radio_altitude)); + last_ba.set(&mk_ainput(uncorrected_barometric_altitude)); } bool MK_VIII::Mode2Handler::b_conditions () { - return mk->io_handler.flaps_down() - || (! mk_data(glideslope_deviation_dots).ncd && fabs(mk_data(glideslope_deviation_dots).get()) < 2) - || takeoff_timer.running; + return mk->io_handler.flaps_down() + || (! mk_data(glideslope_deviation_dots).ncd && fabs(mk_data(glideslope_deviation_dots).get()) < 2) + || takeoff_timer.running; } bool MK_VIII::Mode2Handler::is_a () { - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && ! mk_data(radio_altitude).ncd - && ! mk_ainput(computed_airspeed).ncd - && ! closure_rate_filter.output.ncd - && ! b_conditions()) + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && ! mk_data(radio_altitude).ncd + && ! mk_ainput(computed_airspeed).ncd + && ! closure_rate_filter.output.ncd + && ! b_conditions()) { - if (mk_data(radio_altitude).get() < 1220) - { - if (mk_data(radio_altitude).get() < -1579 + 0.7895 * closure_rate_filter.output.get()) - return true; - } - else - { - double upper_limit; + if (mk_data(radio_altitude).get() < 1220) + { + if (mk_data(radio_altitude).get() < -1579 + 0.7895 * closure_rate_filter.output.get()) + return true; + } + else + { + double upper_limit; - if (mk_ainput(computed_airspeed).get() <= conf->airspeed1) - upper_limit = 1650; - else if (mk_ainput(computed_airspeed).get() >= conf->airspeed2) - upper_limit = 2450; - else - upper_limit = 1650 + 8.9 * (mk_ainput(computed_airspeed).get() - conf->airspeed1); + if (mk_ainput(computed_airspeed).get() <= conf->airspeed1) + upper_limit = 1650; + else if (mk_ainput(computed_airspeed).get() >= conf->airspeed2) + upper_limit = 2450; + else + upper_limit = 1650 + 8.9 * (mk_ainput(computed_airspeed).get() - conf->airspeed1); - if (mk_data(radio_altitude).get() < upper_limit) - { - if (mk_data(radio_altitude).get() < 522 + 0.1968 * closure_rate_filter.output.get()) - return true; - } - } + if (mk_data(radio_altitude).get() < upper_limit) + { + if (mk_data(radio_altitude).get() < 522 + 0.1968 * closure_rate_filter.output.get()) + return true; + } + } } - return false; + return false; } bool MK_VIII::Mode2Handler::is_b () { - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && ! mk_data(radio_altitude).ncd - && ! mk_data(barometric_altitude_rate).ncd - && ! closure_rate_filter.output.ncd - && b_conditions() - && mk_data(radio_altitude).get() < 789) + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && ! mk_data(radio_altitude).ncd + && ! mk_data(barometric_altitude_rate).ncd + && ! closure_rate_filter.output.ncd + && b_conditions() + && mk_data(radio_altitude).get() < 789) { - double lower_limit; + double lower_limit; - if (mk->io_handler.flaps_down()) - { - if (mk_data(barometric_altitude_rate).get() > -400) - lower_limit = 200; - else if (mk_data(barometric_altitude_rate).get() < -1000) - lower_limit = 600; - else - lower_limit = -66.777 - 0.667 * mk_data(barometric_altitude_rate).get(); - } - else - lower_limit = 30; + if (mk->io_handler.flaps_down()) + { + if (mk_data(barometric_altitude_rate).get() > -400) + lower_limit = 200; + else if (mk_data(barometric_altitude_rate).get() < -1000) + lower_limit = 600; + else + lower_limit = -66.777 - 0.667 * mk_data(barometric_altitude_rate).get(); + } + else + lower_limit = 30; - if (mk_data(radio_altitude).get() > lower_limit) - { - if (mk_data(radio_altitude).get() < -1579 + 0.7895 * closure_rate_filter.output.get()) - return true; - } + if (mk_data(radio_altitude).get() > lower_limit) + { + if (mk_data(radio_altitude).get() < -1579 + 0.7895 * closure_rate_filter.output.get()) + return true; + } } - return false; + return false; } void MK_VIII::Mode2Handler::check_pull_up (unsigned int preface_alert, - unsigned int alert) + unsigned int alert) { - if (pull_up_timer.running) + if (pull_up_timer.running) { - if (pull_up_timer.elapsed() >= 1) - { - mk_unset_alerts(preface_alert); - mk_set_alerts(alert); - } + if (pull_up_timer.elapsed() >= 1) + { + mk_unset_alerts(preface_alert); + mk_set_alerts(alert); + } } - else + else { - if (! mk->voice_player.voice) - pull_up_timer.start(); + if (! mk->voice_player.voice) + pull_up_timer.start(); } } void MK_VIII::Mode2Handler::update_a () { - if (is_a()) + if (is_a()) { - if (mk_test_alert(MODE2A_PREFACE)) - check_pull_up(mk_alert(MODE2A_PREFACE), mk_alert(MODE2A)); - else if (! mk_test_alert(MODE2A)) - { - mk_unset_alerts(mk_alert(MODE2A_ALTITUDE_GAIN) | mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING)); - mk_set_alerts(mk_alert(MODE2A_PREFACE)); - a_start_time = globals->get_sim_time_sec(); - pull_up_timer.stop(); - } + if (mk_test_alert(MODE2A_PREFACE)) + check_pull_up(mk_alert(MODE2A_PREFACE), mk_alert(MODE2A)); + else if (! mk_test_alert(MODE2A)) + { + mk_unset_alerts(mk_alert(MODE2A_ALTITUDE_GAIN) | mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING)); + mk_set_alerts(mk_alert(MODE2A_PREFACE)); + a_start_time = globals->get_sim_time_sec(); + pull_up_timer.stop(); + } } - else + else { - if (mk_test_alert(MODE2A_ALTITUDE_GAIN)) - { - if (mk->io_handler.gpws_inhibit() - || mk->state_handler.ground // [1] - || a_altitude_gain_timer.elapsed() >= 45 - || mk_data(radio_altitude).ncd - || mk_ainput(uncorrected_barometric_altitude).ncd - || mk_ainput(uncorrected_barometric_altitude).get() - a_altitude_gain_alt >= 300 - // [PILOT] page 12: "the visual alert will remain on - // until [...] landing flaps or the flap override switch - // is activated" - || mk->io_handler.flaps_down()) - { - // exit altitude gain mode - a_altitude_gain_timer.stop(); - mk_unset_alerts(mk_alert(MODE2A_ALTITUDE_GAIN) | mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING)); - } - else - { - // [SPEC] 6.2.2.2: "If the terrain starts to fall away - // during this altitude gain time, the voice will shut - // off" - if (closure_rate_filter.output.get() < 0) - mk_unset_alerts(mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING)); - } - } - else if (mk_test_alerts(mk_alert(MODE2A_PREFACE) | mk_alert(MODE2A))) - { - mk_unset_alerts(mk_alert(MODE2A_PREFACE) | mk_alert(MODE2A)); + if (mk_test_alert(MODE2A_ALTITUDE_GAIN)) + { + if (mk->io_handler.gpws_inhibit() + || mk->state_handler.ground // [1] + || a_altitude_gain_timer.elapsed() >= 45 + || mk_data(radio_altitude).ncd + || mk_ainput(uncorrected_barometric_altitude).ncd + || mk_ainput(uncorrected_barometric_altitude).get() - a_altitude_gain_alt >= 300 + // [PILOT] page 12: "the visual alert will remain on + // until [...] landing flaps or the flap override switch + // is activated" + || mk->io_handler.flaps_down()) + { + // exit altitude gain mode + a_altitude_gain_timer.stop(); + mk_unset_alerts(mk_alert(MODE2A_ALTITUDE_GAIN) | mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING)); + } + else + { + // [SPEC] 6.2.2.2: "If the terrain starts to fall away + // during this altitude gain time, the voice will shut + // off" + if (closure_rate_filter.output.get() < 0) + mk_unset_alerts(mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING)); + } + } + else if (mk_test_alerts(mk_alert(MODE2A_PREFACE) | mk_alert(MODE2A))) + { + mk_unset_alerts(mk_alert(MODE2A_PREFACE) | mk_alert(MODE2A)); - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && globals->get_sim_time_sec() - a_start_time > 3 - && ! mk->io_handler.flaps_down() - && ! mk_data(radio_altitude).ncd - && ! mk_ainput(uncorrected_barometric_altitude).ncd) - { - // [SPEC] 6.2.2.2: mode 2A envelope violated for more - // than 3 seconds, enable altitude gain feature + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && globals->get_sim_time_sec() - a_start_time > 3 + && ! mk->io_handler.flaps_down() + && ! mk_data(radio_altitude).ncd + && ! mk_ainput(uncorrected_barometric_altitude).ncd) + { + // [SPEC] 6.2.2.2: mode 2A envelope violated for more + // than 3 seconds, enable altitude gain feature - a_altitude_gain_timer.start(); - a_altitude_gain_alt = mk_ainput(uncorrected_barometric_altitude).get(); + a_altitude_gain_timer.start(); + a_altitude_gain_alt = mk_ainput(uncorrected_barometric_altitude).get(); - unsigned int alerts = mk_alert(MODE2A_ALTITUDE_GAIN); - if (closure_rate_filter.output.get() > 0) - alerts |= mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING); + unsigned int alerts = mk_alert(MODE2A_ALTITUDE_GAIN); + if (closure_rate_filter.output.get() > 0) + alerts |= mk_alert(MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING); - mk_set_alerts(alerts); - } - } + mk_set_alerts(alerts); + } + } } } void MK_VIII::Mode2Handler::update_b () { - bool b = is_b(); + bool b = is_b(); - // handle normal mode + // handle normal mode - if (b && (! mk_dinput(landing_gear) || ! mk->io_handler.flaps_down())) + if (b && (! mk_dinput(landing_gear) || ! mk->io_handler.flaps_down())) { - if (mk_test_alert(MODE2B_PREFACE)) - check_pull_up(mk_alert(MODE2B_PREFACE), mk_alert(MODE2B)); - else if (! mk_test_alert(MODE2B)) - { - mk_set_alerts(mk_alert(MODE2B_PREFACE)); - pull_up_timer.stop(); - } + if (mk_test_alert(MODE2B_PREFACE)) + check_pull_up(mk_alert(MODE2B_PREFACE), mk_alert(MODE2B)); + else if (! mk_test_alert(MODE2B)) + { + mk_set_alerts(mk_alert(MODE2B_PREFACE)); + pull_up_timer.stop(); + } } - else - mk_unset_alerts(mk_alert(MODE2B_PREFACE) | mk_alert(MODE2B)); + else + mk_unset_alerts(mk_alert(MODE2B_PREFACE) | mk_alert(MODE2B)); - // handle landing mode ([SPEC] 6.2.2.3: "If both landing gear and - // flaps are in the landing configuration, then the message will be - // Terrain") + // handle landing mode ([SPEC] 6.2.2.3: "If both landing gear and + // flaps are in the landing configuration, then the message will be + // Terrain") - if (b && mk_dinput(landing_gear) && mk->io_handler.flaps_down()) - mk_set_alerts(mk_alert(MODE2B_LANDING_MODE)); - else - mk_unset_alerts(mk_alert(MODE2B_LANDING_MODE)); + if (b && mk_dinput(landing_gear) && mk->io_handler.flaps_down()) + mk_set_alerts(mk_alert(MODE2B_LANDING_MODE)); + else + mk_unset_alerts(mk_alert(MODE2B_LANDING_MODE)); } void MK_VIII::Mode2Handler::boot () { - closure_rate_filter.init(); + closure_rate_filter.init(); } void MK_VIII::Mode2Handler::power_off () { - // [SPEC] 6.0.4: "This latching function is not power saved and a - // system reset will force it false." - takeoff_timer.stop(); + // [SPEC] 6.0.4: "This latching function is not power saved and a + // system reset will force it false." + takeoff_timer.stop(); } void MK_VIII::Mode2Handler::leave_ground () { - // takeoff, reset timer - takeoff_timer.start(); + // takeoff, reset timer + takeoff_timer.start(); } void MK_VIII::Mode2Handler::enter_takeoff () { - // reset timer, in case it's a go-around - takeoff_timer.start(); + // reset timer, in case it's a go-around + takeoff_timer.start(); } void MK_VIII::Mode2Handler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - closure_rate_filter.update(); + closure_rate_filter.update(); - if (takeoff_timer.running && takeoff_timer.elapsed() >= 60) - takeoff_timer.stop(); + if (takeoff_timer.running && takeoff_timer.elapsed() >= 60) + takeoff_timer.stop(); - update_a(); - update_b(); + update_a(); + update_b(); } /////////////////////////////////////////////////////////////////////////////// @@ -3414,117 +3439,119 @@ MK_VIII::Mode2Handler::update () double MK_VIII::Mode3Handler::max_alt_loss (double _bias) { - return conf->max_alt_loss(mk->io_handler.flap_override(), mk_data(radio_altitude).get()) + mk_data(radio_altitude).get() * _bias; + return conf->max_alt_loss(mk->io_handler.flap_override(), mk_data(radio_altitude).get()) + mk_data(radio_altitude).get() * _bias; } double MK_VIII::Mode3Handler::get_bias (double initial_bias, double alt_loss) { - // do not repeat altitude-loss alerts below 30ft agl - if (mk_data(radio_altitude).get() > 30) - { - if (initial_bias < 0.0) // sanity check - initial_bias = 0.0; - // mk-viii spec: repeat alerts whenever losing 20% of initial altitude - while ((alt_loss > max_alt_loss(initial_bias))&& - (initial_bias < 1.0)) - initial_bias += 0.2; - } + // do not repeat altitude-loss alerts below 30ft agl + if (mk_data(radio_altitude).get() > 30) + { + if (initial_bias < 0.0) // sanity check + initial_bias = 0.0; + // mk-viii spec: repeat alerts whenever losing 20% of initial altitude + while ((alt_loss > max_alt_loss(initial_bias))&& + (initial_bias < 1.0)) + { + initial_bias += 0.2; + } + } - return initial_bias; + return initial_bias; } bool MK_VIII::Mode3Handler::is (double *alt_loss) { - if (has_descent_alt) + if (has_descent_alt) { - int max_agl = conf->max_agl(mk->io_handler.flap_override()); + int max_agl = conf->max_agl(mk->io_handler.flap_override()); - if (mk_ainput(uncorrected_barometric_altitude).ncd - || mk_ainput(uncorrected_barometric_altitude).get() > descent_alt - || mk_data(radio_altitude).ncd - || mk_data(radio_altitude).get() > max_agl) - { - armed = false; - has_descent_alt = false; - } - else - { - // gear/flaps: [SPEC] 1.3.1.3 - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && (! mk_dinput(landing_gear) || ! mk->io_handler.flaps_down()) - && ! mk_data(barometric_altitude_rate).ncd - && ! mk_ainput(uncorrected_barometric_altitude).ncd - && ! mk_data(radio_altitude).ncd - && mk_data(barometric_altitude_rate).get() < 0) - { - double _alt_loss = descent_alt - mk_ainput(uncorrected_barometric_altitude).get(); - if (armed || (mk_data(radio_altitude).get() > conf->min_agl - && mk_data(radio_altitude).get() < max_agl - && _alt_loss > max_alt_loss(0))) - { - *alt_loss = _alt_loss; - return true; - } - } - } + if (mk_ainput(uncorrected_barometric_altitude).ncd + || mk_ainput(uncorrected_barometric_altitude).get() > descent_alt + || mk_data(radio_altitude).ncd + || mk_data(radio_altitude).get() > max_agl) + { + armed = false; + has_descent_alt = false; + } + else + { + // gear/flaps: [SPEC] 1.3.1.3 + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && (! mk_dinput(landing_gear) || ! mk->io_handler.flaps_down()) + && ! mk_data(barometric_altitude_rate).ncd + && ! mk_ainput(uncorrected_barometric_altitude).ncd + && ! mk_data(radio_altitude).ncd + && mk_data(barometric_altitude_rate).get() < 0) + { + double _alt_loss = descent_alt - mk_ainput(uncorrected_barometric_altitude).get(); + if (armed || (mk_data(radio_altitude).get() > conf->min_agl + && mk_data(radio_altitude).get() < max_agl + && _alt_loss > max_alt_loss(0))) + { + *alt_loss = _alt_loss; + return true; + } + } + } } - else + else { - if (! mk_data(barometric_altitude_rate).ncd - && ! mk_ainput(uncorrected_barometric_altitude).ncd - && mk_data(barometric_altitude_rate).get() < 0) - { - has_descent_alt = true; - descent_alt = mk_ainput(uncorrected_barometric_altitude).get(); - } + if (! mk_data(barometric_altitude_rate).ncd + && ! mk_ainput(uncorrected_barometric_altitude).ncd + && mk_data(barometric_altitude_rate).get() < 0) + { + has_descent_alt = true; + descent_alt = mk_ainput(uncorrected_barometric_altitude).get(); + } } - return false; + return false; } void MK_VIII::Mode3Handler::enter_takeoff () { - armed = false; - has_descent_alt = false; + armed = false; + has_descent_alt = false; } void MK_VIII::Mode3Handler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - if (mk->state_handler.takeoff) + if (mk->state_handler.takeoff) { - double alt_loss; + double alt_loss; - if (! mk->state_handler.ground /* [1] */ && is(&alt_loss)) - { - if (mk_test_alert(MODE3)) - { - double new_bias = get_bias(bias, alt_loss); - if (new_bias > bias) - { - bias = new_bias; - mk_repeat_alert(mk_alert(MODE3)); - } - } - else - { - armed = true; - bias = get_bias(0.2, alt_loss); - mk_set_alerts(mk_alert(MODE3)); - } + if (! mk->state_handler.ground /* [1] */ && is(&alt_loss)) + { + if (mk_test_alert(MODE3)) + { + double new_bias = get_bias(bias, alt_loss); + if (new_bias > bias) + { + bias = new_bias; + mk_repeat_alert(mk_alert(MODE3)); + } + } + else + { + armed = true; + bias = get_bias(0.2, alt_loss); + mk_set_alerts(mk_alert(MODE3)); + } - return; - } + return; + } } - mk_unset_alerts(mk_alert(MODE3)); + mk_unset_alerts(mk_alert(MODE3)); } /////////////////////////////////////////////////////////////////////////////// @@ -3539,153 +3566,155 @@ MK_VIII::Mode3Handler::update () double MK_VIII::Mode4Handler::get_upper_agl (const EnvelopesConfiguration *c) { - if (mk_ainput(computed_airspeed).get() >= c->airspeed2) - return c->min_agl3; - else if (mk_ainput(computed_airspeed).get() >= c->airspeed1) - return c->min_agl2(mk_ainput(computed_airspeed).get()); - else - return c->min_agl1; + if (mk_ainput(computed_airspeed).get() >= c->airspeed2) + return c->min_agl3; + else if (mk_ainput(computed_airspeed).get() >= c->airspeed1) + return c->min_agl2(mk_ainput(computed_airspeed).get()); + else + return c->min_agl1; } const MK_VIII::Mode4Handler::EnvelopesConfiguration * MK_VIII::Mode4Handler::get_ab_envelope () { - // [SPEC] 6.2.4.1: "The Mode 4B envelope can also be selected by - // setting flaps to landing configuration or by selecting flap - // override." - return mk_dinput(landing_gear) || mk->io_handler.flaps_down() - ? conf.modes->b - : conf.modes->ac; + // [SPEC] 6.2.4.1: "The Mode 4B envelope can also be selected by + // setting flaps to landing configuration or by selecting flap + // override." + return mk_dinput(landing_gear) || mk->io_handler.flaps_down() + ? conf.modes->b + : conf.modes->ac; } double MK_VIII::Mode4Handler::get_bias (double initial_bias, double min_agl) { - // do not repeat terrain/gear/flap alerts below 30ft agl - if (mk_data(radio_altitude).get() > 30.0) - { - if (initial_bias < 0.0) // sanity check - initial_bias = 0.0; - while ((mk_data(radio_altitude).get() < min_agl - min_agl * initial_bias)&& - (initial_bias < 1.0)) - initial_bias += 0.2; - } + // do not repeat terrain/gear/flap alerts below 30ft agl + if (mk_data(radio_altitude).get() > 30.0) + { + if (initial_bias < 0.0) // sanity check + initial_bias = 0.0; + while ((mk_data(radio_altitude).get() < min_agl - min_agl * initial_bias)&& + (initial_bias < 1.0)) + initial_bias += 0.2; + } - return initial_bias; + return initial_bias; } void MK_VIII::Mode4Handler::handle_alert (unsigned int alert, - double min_agl, - double *bias) + double min_agl, + double *bias) { - if (mk_test_alerts(alert)) + if (mk_test_alerts(alert)) { - double new_bias = get_bias(*bias, min_agl); - if (new_bias > *bias) - { - *bias = new_bias; - mk_repeat_alert(alert); - } + double new_bias = get_bias(*bias, min_agl); + if (new_bias > *bias) + { + *bias = new_bias; + mk_repeat_alert(alert); + } } - else + else { - *bias = get_bias(0.2, min_agl); - mk_set_alerts(alert); + *bias = get_bias(0.2, min_agl); + mk_set_alerts(alert); } } void MK_VIII::Mode4Handler::update_ab () { - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground - && ! mk->state_handler.takeoff - && ! mk_data(radio_altitude).ncd - && ! mk_ainput(computed_airspeed).ncd - && mk_data(radio_altitude).get() > 30) + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground + && ! mk->state_handler.takeoff + && ! mk_data(radio_altitude).ncd + && ! mk_ainput(computed_airspeed).ncd + && mk_data(radio_altitude).get() > 30) { - const EnvelopesConfiguration *c = get_ab_envelope(); - if (mk_ainput(computed_airspeed).get() < c->airspeed1) - { - if (mk_dinput(landing_gear)) - { - if (! mk->io_handler.flaps_down() && mk_data(radio_altitude).get() < c->min_agl1) - { - handle_alert(mk_alert(MODE4_TOO_LOW_FLAPS), c->min_agl1, &ab_bias); - return; - } - } - else - { - if (mk_data(radio_altitude).get() < c->min_agl1) - { - handle_alert(mk_alert(MODE4_TOO_LOW_GEAR), c->min_agl1, &ab_bias); - return; - } - } - } + const EnvelopesConfiguration *c = get_ab_envelope(); + if (mk_ainput(computed_airspeed).get() < c->airspeed1) + { + if (mk_dinput(landing_gear)) + { + if (! mk->io_handler.flaps_down() && mk_data(radio_altitude).get() < c->min_agl1) + { + handle_alert(mk_alert(MODE4_TOO_LOW_FLAPS), c->min_agl1, &ab_bias); + return; + } + } + else + { + if (mk_data(radio_altitude).get() < c->min_agl1) + { + handle_alert(mk_alert(MODE4_TOO_LOW_GEAR), c->min_agl1, &ab_bias); + return; + } + } + } } - mk_unset_alerts(mk_alert(MODE4_TOO_LOW_FLAPS) | mk_alert(MODE4_TOO_LOW_GEAR)); - ab_bias=0.0; + mk_unset_alerts(mk_alert(MODE4_TOO_LOW_FLAPS) | mk_alert(MODE4_TOO_LOW_GEAR)); + ab_bias=0.0; } void MK_VIII::Mode4Handler::update_ab_expanded () { - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground - && ! mk->state_handler.takeoff - && ! mk_data(radio_altitude).ncd - && ! mk_ainput(computed_airspeed).ncd - && mk_data(radio_altitude).get() > 30) + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground + && ! mk->state_handler.takeoff + && ! mk_data(radio_altitude).ncd + && ! mk_ainput(computed_airspeed).ncd + && mk_data(radio_altitude).get() > 30) { - const EnvelopesConfiguration *c = get_ab_envelope(); - if (mk_ainput(computed_airspeed).get() >= c->airspeed1) - { - double min_agl = get_upper_agl(c); - if (mk_data(radio_altitude).get() < min_agl) - { - handle_alert(mk_alert(MODE4AB_TOO_LOW_TERRAIN), min_agl, &ab_expanded_bias); - return; - } - } + const EnvelopesConfiguration *c = get_ab_envelope(); + if (mk_ainput(computed_airspeed).get() >= c->airspeed1) + { + double min_agl = get_upper_agl(c); + if (mk_data(radio_altitude).get() < min_agl) + { + handle_alert(mk_alert(MODE4AB_TOO_LOW_TERRAIN), min_agl, &ab_expanded_bias); + return; + } + } } - mk_unset_alerts(mk_alert(MODE4AB_TOO_LOW_TERRAIN)); - ab_expanded_bias=0.0; + mk_unset_alerts(mk_alert(MODE4AB_TOO_LOW_TERRAIN)); + ab_expanded_bias=0.0; } void MK_VIII::Mode4Handler::update_c () { - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && mk->state_handler.takeoff - && ! mk_data(radio_altitude).ncd - && ! mk_data(terrain_clearance).ncd - && mk_data(radio_altitude).get() > 30 - && (! mk_dinput(landing_gear) || ! mk->io_handler.flaps_down()) - && mk_data(radio_altitude).get() < get_upper_agl(conf.modes->ac) - && mk_data(radio_altitude).get() < mk_data(terrain_clearance).get()) - handle_alert(mk_alert(MODE4C_TOO_LOW_TERRAIN), mk_data(terrain_clearance).get(), &c_bias); - else - { - mk_unset_alerts(mk_alert(MODE4C_TOO_LOW_TERRAIN)); - c_bias=0.0; - } + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && mk->state_handler.takeoff + && ! mk_data(radio_altitude).ncd + && ! mk_data(terrain_clearance).ncd + && mk_data(radio_altitude).get() > 30 + && (! mk_dinput(landing_gear) || ! mk->io_handler.flaps_down()) + && mk_data(radio_altitude).get() < get_upper_agl(conf.modes->ac) + && mk_data(radio_altitude).get() < mk_data(terrain_clearance).get()) + { + handle_alert(mk_alert(MODE4C_TOO_LOW_TERRAIN), mk_data(terrain_clearance).get(), &c_bias); + } + else + { + mk_unset_alerts(mk_alert(MODE4C_TOO_LOW_TERRAIN)); + c_bias = 0.0; + } } void MK_VIII::Mode4Handler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - update_ab(); - update_ab_expanded(); - update_c(); + update_ab(); + update_ab_expanded(); + update_c(); } /////////////////////////////////////////////////////////////////////////////// @@ -3695,147 +3724,150 @@ MK_VIII::Mode4Handler::update () bool MK_VIII::Mode5Handler::is_hard () { - if (mk_data(radio_altitude).get() > 30 + if (mk_data(radio_altitude).get() > 30 && mk_data(radio_altitude).get() < 300 && mk_data(glideslope_deviation_dots).get() > 2) { - if (mk_data(radio_altitude).get() < 150) - { - if (mk_data(radio_altitude).get() > 293 - 71.43 * mk_data(glideslope_deviation_dots).get()) - return true; - } - else - return true; + if (mk_data(radio_altitude).get() < 150) + { + if (mk_data(radio_altitude).get() > 293 - 71.43 * mk_data(glideslope_deviation_dots).get()) + return true; + } + else + return true; } - return false; + return false; } bool MK_VIII::Mode5Handler::is_soft (double bias) { - // do not repeat glide-slope alerts below 30ft agl - if (mk_data(radio_altitude).get() > 30) + // do not repeat glide-slope alerts below 30ft agl + if (mk_data(radio_altitude).get() > 30) { - double bias_dots = 1.3 * bias; - if (mk_data(glideslope_deviation_dots).get() > 1.3 + bias_dots) - { - if (mk_data(radio_altitude).get() < 150) - { - if (mk_data(radio_altitude).get() > 243 - 71.43 * (mk_data(glideslope_deviation_dots).get() - bias_dots)) - return true; - } - else - { - double upper_limit; + double bias_dots = 1.3 * bias; + if (mk_data(glideslope_deviation_dots).get() > 1.3 + bias_dots) + { + if (mk_data(radio_altitude).get() < 150) + { + if (mk_data(radio_altitude).get() > 243 - 71.43 * (mk_data(glideslope_deviation_dots).get() - bias_dots)) + return true; + } + else + { + double upper_limit; - if (mk_data(barometric_altitude_rate).ncd) - upper_limit = 1000; - else - { - if (mk_data(barometric_altitude_rate).get() >= 0) - upper_limit = 500; - else if (mk_data(barometric_altitude_rate).get() < -500) - upper_limit = 1000; - else - upper_limit = -mk_data(barometric_altitude_rate).get() + 500; - } + if (mk_data(barometric_altitude_rate).ncd) + upper_limit = 1000; + else + { + if (mk_data(barometric_altitude_rate).get() >= 0) + upper_limit = 500; + else if (mk_data(barometric_altitude_rate).get() < -500) + upper_limit = 1000; + else + upper_limit = -mk_data(barometric_altitude_rate).get() + 500; + } - if (mk_data(radio_altitude).get() < upper_limit) - return true; - } - } + if (mk_data(radio_altitude).get() < upper_limit) + return true; + } + } } - return false; + return false; } double MK_VIII::Mode5Handler::get_soft_bias (double initial_bias) { - if (initial_bias < 0.0) // sanity check - initial_bias = 0.0; - while ((is_soft(initial_bias))&& - (initial_bias < 1.0)) - initial_bias += 0.2; + if (initial_bias < 0.0) // sanity check + initial_bias = 0.0; - return initial_bias; + while ((is_soft(initial_bias))&& + (initial_bias < 1.0)) + { + initial_bias += 0.2; + } + + return initial_bias; } void MK_VIII::Mode5Handler::update_hard (bool is) { - if (is) + if (is) { - if (! mk_test_alert(MODE5_HARD)) - { - if (hard_timer.start_or_elapsed() >= 0.8) - mk_set_alerts(mk_alert(MODE5_HARD)); - } + if (! mk_test_alert(MODE5_HARD)) + { + if (hard_timer.start_or_elapsed() >= 0.8) + mk_set_alerts(mk_alert(MODE5_HARD)); + } } - else + else { - hard_timer.stop(); - mk_unset_alerts(mk_alert(MODE5_HARD)); + hard_timer.stop(); + mk_unset_alerts(mk_alert(MODE5_HARD)); } } void MK_VIII::Mode5Handler::update_soft (bool is) { - if (is) + if (is) { - if (! mk_test_alert(MODE5_SOFT)) - { - double new_bias = get_soft_bias(soft_bias); - if (new_bias > soft_bias) - { - soft_bias = new_bias; - mk_repeat_alert(mk_alert(MODE5_SOFT)); - } - } - else - { - if (soft_timer.start_or_elapsed() >= 0.8) - { - soft_bias = get_soft_bias(0.2); - mk_set_alerts(mk_alert(MODE5_SOFT)); - } - } + if (! mk_test_alert(MODE5_SOFT)) + { + double new_bias = get_soft_bias(soft_bias); + if (new_bias > soft_bias) + { + soft_bias = new_bias; + mk_repeat_alert(mk_alert(MODE5_SOFT)); + } + } + else + { + if (soft_timer.start_or_elapsed() >= 0.8) + { + soft_bias = get_soft_bias(0.2); + mk_set_alerts(mk_alert(MODE5_SOFT)); + } + } } - else + else { - soft_timer.stop(); - mk_unset_alerts(mk_alert(MODE5_SOFT)); + soft_timer.stop(); + mk_unset_alerts(mk_alert(MODE5_SOFT)); } } void MK_VIII::Mode5Handler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && ! mk_dinput(glideslope_inhibit) // not on backcourse - && ! mk_data(radio_altitude).ncd - && ! mk_data(glideslope_deviation_dots).ncd - && (! mk->io_handler.conf.localizer_enabled - || mk_data(localizer_deviation_dots).ncd - || mk_data(radio_altitude).get() < 500 - || fabs(mk_data(localizer_deviation_dots).get()) < 2) - && (! mk->state_handler.takeoff || mk->io_handler.flaps_down()) - && mk_dinput(landing_gear) - && ! mk_doutput(glideslope_cancel)) + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && ! mk_dinput(glideslope_inhibit) // not on backcourse + && ! mk_data(radio_altitude).ncd + && ! mk_data(glideslope_deviation_dots).ncd + && (! mk->io_handler.conf.localizer_enabled + || mk_data(localizer_deviation_dots).ncd + || mk_data(radio_altitude).get() < 500 + || fabs(mk_data(localizer_deviation_dots).get()) < 2) + && (! mk->state_handler.takeoff || mk->io_handler.flaps_down()) + && mk_dinput(landing_gear) + && ! mk_doutput(glideslope_cancel)) { - update_hard(is_hard()); - update_soft(is_soft(0)); + update_hard(is_hard()); + update_soft(is_soft(0)); } - else + else { - update_hard(false); - update_soft(false); + update_hard(false); + update_soft(false); } } @@ -3844,86 +3876,87 @@ MK_VIII::Mode5Handler::update () /////////////////////////////////////////////////////////////////////////////// // keep sorted in descending order -const int MK_VIII::Mode6Handler::altitude_callout_definitions[] = - { 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30, 20, 10 }; +const int MK_VIII::Mode6Handler::altitude_callout_definitions[] = + { 2500, 1000, 500, 400, 300, 200, 100, 50, 40, 30, 20, 10 }; void MK_VIII::Mode6Handler::reset_minimums () { - minimums_issued = false; - minimums_above_100_issued = false; + minimums_issued = false; + minimums_above_100_issued = false; } void MK_VIII::Mode6Handler::reset_altitude_callouts () { - for (unsigned i = 0; i < n_altitude_callouts; i++) - altitude_callouts_issued[i] = false; - throttle_retarded = false; + for (unsigned i = 0; i < n_altitude_callouts; i++) + altitude_callouts_issued[i] = false; + throttle_retarded = false; } bool MK_VIII::Mode6Handler::is_playing_altitude_callout () { - for (unsigned i = 0; i < n_altitude_callouts; i++) - if (mk->voice_player.voice == mk_altitude_voice(i) - || mk->voice_player.next_voice == mk_altitude_voice(i)) - return true; - - return false; + for (unsigned i = 0; i < n_altitude_callouts; i++) + { + if (mk->voice_player.voice == mk_altitude_voice(i) + || mk->voice_player.next_voice == mk_altitude_voice(i)) + return true; + } + return false; } bool MK_VIII::Mode6Handler::is_near_minimums (double callout) { - // [SPEC] 6.4.2 + // [SPEC] 6.4.2 - if (! mk_data(decision_height).ncd) + if (! mk_data(decision_height).ncd) { - double diff = callout - mk_data(decision_height).get(); + double diff = callout - mk_data(decision_height).get(); - if (mk_data(radio_altitude).get() >= 200) - { - if (fabs(diff) <= 30) - return true; - } - else - { - if (diff >= -3 && diff <= 6) - return true; - } + if (mk_data(radio_altitude).get() >= 200) + { + if (fabs(diff) <= 30) + return true; + } + else + { + if (diff >= -3 && diff <= 6) + return true; + } } - return false; + return false; } bool MK_VIII::Mode6Handler::is_outside_band (double elevation, double callout) { - // [SPEC] 6.4.2 - return elevation < callout - (elevation > 150 ? 20 : 10); + // [SPEC] 6.4.2 + return elevation < callout - (elevation > 150 ? 20 : 10); } bool MK_VIII::Mode6Handler::inhibit_smart_500 () { - // [SPEC] 6.4.3 + // [SPEC] 6.4.3 - if (! mk_data(glideslope_deviation_dots).ncd - && ! mk_dinput(glideslope_inhibit) // backcourse - && ! mk_doutput(glideslope_cancel)) + if (! mk_data(glideslope_deviation_dots).ncd + && ! mk_dinput(glideslope_inhibit) // backcourse + && ! mk_doutput(glideslope_cancel)) { - if (mk->io_handler.conf.localizer_enabled - && ! mk_data(localizer_deviation_dots).ncd) - { - if (fabs(mk_data(localizer_deviation_dots).get()) <= 2) - return true; - } - else - { - if (fabs(mk_data(glideslope_deviation_dots).get()) <= 2) - return true; - } + if (mk->io_handler.conf.localizer_enabled + && ! mk_data(localizer_deviation_dots).ncd) + { + if (fabs(mk_data(localizer_deviation_dots).get()) <= 2) + return true; + } + else + { + if (fabs(mk_data(glideslope_deviation_dots).get()) <= 2) + return true; + } } return false; @@ -3932,383 +3965,392 @@ MK_VIII::Mode6Handler::inhibit_smart_500 () void MK_VIII::Mode6Handler::boot () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - last_decision_height = mk_dinput(decision_height); - last_radio_altitude.set(&mk_data(radio_altitude)); + last_decision_height = mk_dinput(decision_height); + last_radio_altitude.set(&mk_data(radio_altitude)); - // [SPEC] 6.4.2 - for (unsigned i = 0; i < n_altitude_callouts; i++) - altitude_callouts_issued[i] = ! mk_data(radio_altitude).ncd - && mk_data(radio_altitude).get() <= altitude_callout_definitions[i]; + // [SPEC] 6.4.2 + for (unsigned i = 0; i < n_altitude_callouts; i++) + altitude_callouts_issued[i] = ! mk_data(radio_altitude).ncd + && mk_data(radio_altitude).get() <= altitude_callout_definitions[i]; - // extrapolated from [SPEC] 6.4.2 - minimums_issued = mk_dinput(decision_height); + // extrapolated from [SPEC] 6.4.2 + minimums_issued = mk_dinput(decision_height); - if (conf.above_field_voice) + if (conf.above_field_voice) { - update_runway(); - get_altitude_above_field(&last_altitude_above_field); - // extrapolated from [SPEC] 6.4.2 - above_field_issued = ! last_altitude_above_field.ncd - && last_altitude_above_field.get() < 550; + update_runway(); + get_altitude_above_field(&last_altitude_above_field); + // extrapolated from [SPEC] 6.4.2 + above_field_issued = ! last_altitude_above_field.ncd + && last_altitude_above_field.get() < 550; } } void MK_VIII::Mode6Handler::power_off () { - runway_timer.stop(); + runway_timer.stop(); } void MK_VIII::Mode6Handler::enter_takeoff () { - reset_altitude_callouts(); // [SPEC] 6.4.2 - reset_minimums(); // omitted by [SPEC]; common sense + reset_altitude_callouts(); // [SPEC] 6.4.2 + reset_minimums(); // omitted by [SPEC]; common sense } void MK_VIII::Mode6Handler::leave_takeoff () { - reset_altitude_callouts(); // [SPEC] 6.0.2 - reset_minimums(); // [SPEC] 6.0.2 + reset_altitude_callouts(); // [SPEC] 6.0.2 + reset_minimums(); // [SPEC] 6.0.2 } void MK_VIII::Mode6Handler::set_volume (float volume) { - mk_voice(minimums_minimums)->set_volume(volume); - mk_voice(five_hundred_above)->set_volume(volume); - for (unsigned i = 0; i < n_altitude_callouts; i++) - mk_altitude_voice(i)->set_volume(volume); + mk_voice(minimums_minimums)->set_volume(volume); + mk_voice(five_hundred_above)->set_volume(volume); + for (unsigned i = 0; i < n_altitude_callouts; i++) + mk_altitude_voice(i)->set_volume(volume); } bool MK_VIII::Mode6Handler::altitude_callouts_enabled () { - if (conf.minimums_enabled || conf.smart_500_enabled || conf.above_field_voice) - return true; + if (conf.minimums_enabled || conf.smart_500_enabled || conf.above_field_voice) + return true; - return (conf.altitude_callouts_enabled != 0); + return (conf.altitude_callouts_enabled != 0); } void MK_VIII::Mode6Handler::update_minimums () { - if (! mk->io_handler.gpws_inhibit() + if (! mk->io_handler.gpws_inhibit() && (mk->voice_player.voice == mk_voice(minimums_minimums) - || mk->voice_player.next_voice == mk_voice(minimums_minimums))) - goto end; + || mk->voice_player.next_voice == mk_voice(minimums_minimums))) + { + goto end; + } - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && conf.minimums_enabled - && ! minimums_issued - && mk_dinput(landing_gear) - && ! last_decision_height) - { - if (mk_dinput(decision_height)) - { - minimums_issued = true; + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && conf.minimums_enabled + && ! minimums_issued + && mk_dinput(landing_gear) + && ! last_decision_height) + { + if (mk_dinput(decision_height)) + { + minimums_issued = true; - // If an altitude callout is playing, stop it now so that the - // minimums callout can be played (note that proper connection - // and synchronization of the radio-altitude ARINC 529 input, - // decision-height discrete and decision-height ARINC 529 input - // will prevent an altitude callout from being played near the - // decision height). + // If an altitude callout is playing, stop it now so that the + // minimums callout can be played (note that proper connection + // and synchronization of the radio-altitude ARINC 529 input, + // decision-height discrete and decision-height ARINC 529 input + // will prevent an altitude callout from being played near the + // decision height). - if (is_playing_altitude_callout()) - mk->voice_player.stop(VoicePlayer::STOP_NOW); + if (is_playing_altitude_callout()) + mk->voice_player.stop(VoicePlayer::STOP_NOW); - mk_unset_alerts(mk_alert(MODE6_MINIMUMS_100)); - mk_set_alerts(mk_alert(MODE6_MINIMUMS)); - } - else - if (conf.minimums_above_100_enabled && (!minimums_above_100_issued) && - mk_dinput(decision_height_100)) - { - minimums_above_100_issued = true; + mk_unset_alerts(mk_alert(MODE6_MINIMUMS_100)); + mk_set_alerts(mk_alert(MODE6_MINIMUMS)); + } + else + if (conf.minimums_above_100_enabled && (!minimums_above_100_issued) && + mk_dinput(decision_height_100)) + { + minimums_above_100_issued = true; - if (is_playing_altitude_callout()) - mk->voice_player.stop(VoicePlayer::STOP_NOW); + if (is_playing_altitude_callout()) + mk->voice_player.stop(VoicePlayer::STOP_NOW); - mk_unset_alerts(mk_alert(MODE6_MINIMUMS)); - mk_set_alerts(mk_alert(MODE6_MINIMUMS_100)); - } - } - else - { - mk_unset_alerts(mk_alert(MODE6_MINIMUMS)); - mk_unset_alerts(mk_alert(MODE6_MINIMUMS_100)); - } + mk_unset_alerts(mk_alert(MODE6_MINIMUMS)); + mk_set_alerts(mk_alert(MODE6_MINIMUMS_100)); + } + } + else + { + mk_unset_alerts(mk_alert(MODE6_MINIMUMS)); + mk_unset_alerts(mk_alert(MODE6_MINIMUMS_100)); + } - end: - last_decision_height = mk_dinput(decision_height); - last_decision_height_100 = mk_dinput(decision_height_100); +end: + last_decision_height = mk_dinput(decision_height); + last_decision_height_100 = mk_dinput(decision_height_100); } void MK_VIII::Mode6Handler::update_altitude_callouts () { - if (! mk->io_handler.gpws_inhibit() && is_playing_altitude_callout()) - goto end; + if (! mk->io_handler.gpws_inhibit() && is_playing_altitude_callout()) + goto end; - if (! mk->io_handler.gpws_inhibit()) - { - if (mk->mode6_handler.conf.retard_enabled && - (!throttle_retarded)&& - (mk_data(radio_altitude).get() < 25)) + if (! mk->io_handler.gpws_inhibit()) { - if (mk_node(throttle)->getDoubleValue() > 0.05) + if (mk->mode6_handler.conf.retard_enabled && + (!throttle_retarded)&& + (mk_data(radio_altitude).get() < 25)) { - mk_repeat_alert(mk_alert(MODE6_RETARD)); - goto end; + if (mk_node(throttle)->getDoubleValue() > 0.05) + { + mk_repeat_alert(mk_alert(MODE6_RETARD)); + goto end; + } + // throttle was closed + throttle_retarded = true; + } + mk_unset_alerts(mk_alert(MODE6_RETARD)); + + if (! mk->state_handler.ground // [1] + && ! mk_data(radio_altitude).ncd) + { + for (unsigned i = 0; i < n_altitude_callouts && mk_data(radio_altitude).get() <= altitude_callout_definitions[i]; i++) + { + if (((conf.altitude_callouts_enabled & (1< altitude_callout_definitions[i])) + { + // lock out all callouts superior or equal to this one + for (unsigned j = 0; j <= i; j++) + altitude_callouts_issued[j] = true; + + altitude_callouts_issued[i] = true; + if (! is_near_minimums(altitude_callout_definitions[i]) + && ! is_outside_band(mk_data(radio_altitude).get(), altitude_callout_definitions[i]) + && (! conf.smart_500_enabled + || altitude_callout_definitions[i] != 500 + || ! inhibit_smart_500())) + { + mk->alert_handler.set_altitude_callout_alert(mk_altitude_voice(i)); + goto end; + } + } + } } - // throttle was closed - throttle_retarded = true; } - mk_unset_alerts(mk_alert(MODE6_RETARD)); - if (! mk->state_handler.ground // [1] - && ! mk_data(radio_altitude).ncd) - for (unsigned i = 0; i < n_altitude_callouts && mk_data(radio_altitude).get() <= altitude_callout_definitions[i]; i++) - if (((conf.altitude_callouts_enabled & (1< altitude_callout_definitions[i])) - { - // lock out all callouts superior or equal to this one - for (unsigned j = 0; j <= i; j++) - altitude_callouts_issued[j] = true; + mk_unset_alerts(mk_alert(MODE6_ALTITUDE_CALLOUT)); - altitude_callouts_issued[i] = true; - if (! is_near_minimums(altitude_callout_definitions[i]) - && ! is_outside_band(mk_data(radio_altitude).get(), altitude_callout_definitions[i]) - && (! conf.smart_500_enabled - || altitude_callout_definitions[i] != 500 - || ! inhibit_smart_500())) - { - mk->alert_handler.set_altitude_callout_alert(mk_altitude_voice(i)); - goto end; - } - } - } - - mk_unset_alerts(mk_alert(MODE6_ALTITUDE_CALLOUT)); - - end: - last_radio_altitude.set(&mk_data(radio_altitude)); +end: + last_radio_altitude.set(&mk_data(radio_altitude)); } bool MK_VIII::Mode6Handler::test_runway (const FGRunway *_runway) { - if (_runway->lengthFt() < mk->conf.runway_database) - return false; + if (_runway->lengthFt() < mk->conf.runway_database) + return false; - SGGeod pos( - SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get())); - - // get distance to threshold - return SGGeodesy::distanceNm(pos, _runway->threshold()) <= 5; + SGGeod pos( + SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get())); + + // get distance to threshold + return SGGeodesy::distanceNm(pos, _runway->threshold()) <= 5; } bool MK_VIII::Mode6Handler::test_airport (const FGAirport *airport) { - for (unsigned int r=0; rnumRunways(); ++r) { - FGRunway* rwy(airport->getRunwayByIndex(r)); - - if (test_runway(rwy)) return true; - } + for (unsigned int r=0; rnumRunways(); ++r) + { + FGRunway* rwy(airport->getRunwayByIndex(r)); - return false; + if (test_runway(rwy)) + return true; + } + + return false; } bool MK_VIII::Mode6Handler::AirportFilter::passAirport(FGAirport* a) const { - bool ok = self->test_airport(a); - return ok; + bool ok = self->test_airport(a); + return ok; } void MK_VIII::Mode6Handler::update_runway () { - - if (mk_data(gps_latitude).ncd || mk_data(gps_longitude).ncd) { - has_runway.unset(); - return; - } + if (mk_data(gps_latitude).ncd || mk_data(gps_longitude).ncd) + { + has_runway.unset(); + return; + } - // Search for the closest runway threshold in range 5 - // nm. Passing 30nm to - // get_closest_airport() provides enough margin for large - // airports, which may have a runway located far away from the - // airport's reference point. - AirportFilter filter(this); - FGPositionedRef apt = FGPositioned::findClosest( - SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()), - 30.0, &filter); - if (apt) { - runway.elevation = apt->elevation(); - } - - has_runway.set(apt != NULL); + // Search for the closest runway threshold in range 5 + // nm. Passing 30nm to + // get_closest_airport() provides enough margin for large + // airports, which may have a runway located far away from the + // airport's reference point. + AirportFilter filter(this); + FGPositionedRef apt = FGPositioned::findClosest( + SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()), + 30.0, &filter); + if (apt) + { + runway.elevation = apt->elevation(); + } + + has_runway.set(apt != NULL); } void MK_VIII::Mode6Handler::get_altitude_above_field (Parameter *parameter) { - if (! has_runway.ncd && has_runway.get() && ! mk_data(geometric_altitude).ncd) - parameter->set(mk_data(geometric_altitude).get() - runway.elevation); - else - parameter->unset(); + if (! has_runway.ncd && has_runway.get() && ! mk_data(geometric_altitude).ncd) + parameter->set(mk_data(geometric_altitude).get() - runway.elevation); + else + parameter->unset(); } void MK_VIII::Mode6Handler::update_above_field_callout () { - if (! conf.above_field_voice) - return; + if (! conf.above_field_voice) + return; - // update_runway() has to iterate over the whole runway database - // (which contains thousands of runways), so it would be unwise to - // run it every frame. Run it every 3 seconds. Note that the first - // iteration is run in boot(). - if (runway_timer.start_or_elapsed() >= 3) + // update_runway() has to iterate over the whole runway database + // (which contains thousands of runways), so it would be unwise to + // run it every frame. Run it every 3 seconds. Note that the first + // iteration is run in boot(). + if (runway_timer.start_or_elapsed() >= 3) { - update_runway(); - runway_timer.start(); + update_runway(); + runway_timer.start(); } - Parameter altitude_above_field; - get_altitude_above_field(&altitude_above_field); + Parameter altitude_above_field; + get_altitude_above_field(&altitude_above_field); - if (! mk->io_handler.gpws_inhibit() - && (mk->voice_player.voice == conf.above_field_voice - || mk->voice_player.next_voice == conf.above_field_voice)) - goto end; + if (! mk->io_handler.gpws_inhibit() + && (mk->voice_player.voice == conf.above_field_voice + || mk->voice_player.next_voice == conf.above_field_voice)) + goto end; - // handle reset term - if (above_field_issued) + // handle reset term + if (above_field_issued) { - if ((! has_runway.ncd && ! has_runway.get()) - || (! altitude_above_field.ncd && altitude_above_field.get() > 700)) - above_field_issued = false; + if ((! has_runway.ncd && ! has_runway.get()) + || (! altitude_above_field.ncd && altitude_above_field.get() > 700)) + above_field_issued = false; } - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && ! above_field_issued - && ! altitude_above_field.ncd - && altitude_above_field.get() < 550 - && (last_altitude_above_field.ncd - || last_altitude_above_field.get() >= 550)) + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && ! above_field_issued + && ! altitude_above_field.ncd + && altitude_above_field.get() < 550 + && (last_altitude_above_field.ncd + || last_altitude_above_field.get() >= 550)) { - above_field_issued = true; + above_field_issued = true; - if (! is_outside_band(altitude_above_field.get(), 500)) - { - mk->alert_handler.set_altitude_callout_alert(conf.above_field_voice); - goto end; - } + if (! is_outside_band(altitude_above_field.get(), 500)) + { + mk->alert_handler.set_altitude_callout_alert(conf.above_field_voice); + goto end; + } } - mk_unset_alerts(mk_alert(MODE6_ALTITUDE_CALLOUT)); + mk_unset_alerts(mk_alert(MODE6_ALTITUDE_CALLOUT)); - end: - last_altitude_above_field.set(&altitude_above_field); +end: + last_altitude_above_field.set(&altitude_above_field); } bool MK_VIII::Mode6Handler::is_bank_angle (double abs_roll_angle, double bias) { - return conf.is_bank_angle(&mk_data(radio_altitude), - abs_roll_angle - abs_roll_angle * bias, - mk_dinput(autopilot_engaged)); + return conf.is_bank_angle(&mk_data(radio_altitude), + abs_roll_angle - abs_roll_angle * bias, + mk_dinput(autopilot_engaged)); } bool MK_VIII::Mode6Handler::is_high_bank_angle () { - return mk_data(radio_altitude).ncd || mk_data(radio_altitude).get() >= 210; + return mk_data(radio_altitude).ncd || mk_data(radio_altitude).get() >= 210; } unsigned int MK_VIII::Mode6Handler::get_bank_angle_alerts () { - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] - && ! mk_data(roll_angle).ncd) + if (! mk->io_handler.gpws_inhibit() + && ! mk->state_handler.ground // [1] + && ! mk_data(roll_angle).ncd) { - double abs_roll_angle = fabs(mk_data(roll_angle).get()); + double abs_roll_angle = fabs(mk_data(roll_angle).get()); - if (is_bank_angle(abs_roll_angle, 0.4)) - return is_high_bank_angle() - ? (mk_alert(MODE6_HIGH_BANK_ANGLE_1) | mk_alert(MODE6_HIGH_BANK_ANGLE_2) | mk_alert(MODE6_HIGH_BANK_ANGLE_3)) - : (mk_alert(MODE6_LOW_BANK_ANGLE_1) | mk_alert(MODE6_LOW_BANK_ANGLE_2) | mk_alert(MODE6_LOW_BANK_ANGLE_3)); - else if (is_bank_angle(abs_roll_angle, 0.2)) - return is_high_bank_angle() - ? (mk_alert(MODE6_HIGH_BANK_ANGLE_1) | mk_alert(MODE6_HIGH_BANK_ANGLE_2)) - : (mk_alert(MODE6_LOW_BANK_ANGLE_1) | mk_alert(MODE6_LOW_BANK_ANGLE_2)); - else if (is_bank_angle(abs_roll_angle, 0)) - return is_high_bank_angle() - ? mk_alert(MODE6_HIGH_BANK_ANGLE_1) - : mk_alert(MODE6_LOW_BANK_ANGLE_1); + if (is_bank_angle(abs_roll_angle, 0.4)) + return is_high_bank_angle() + ? (mk_alert(MODE6_HIGH_BANK_ANGLE_1) | mk_alert(MODE6_HIGH_BANK_ANGLE_2) | mk_alert(MODE6_HIGH_BANK_ANGLE_3)) + : (mk_alert(MODE6_LOW_BANK_ANGLE_1) | mk_alert(MODE6_LOW_BANK_ANGLE_2) | mk_alert(MODE6_LOW_BANK_ANGLE_3)); + else if (is_bank_angle(abs_roll_angle, 0.2)) + return is_high_bank_angle() + ? (mk_alert(MODE6_HIGH_BANK_ANGLE_1) | mk_alert(MODE6_HIGH_BANK_ANGLE_2)) + : (mk_alert(MODE6_LOW_BANK_ANGLE_1) | mk_alert(MODE6_LOW_BANK_ANGLE_2)); + else if (is_bank_angle(abs_roll_angle, 0)) + return is_high_bank_angle() + ? mk_alert(MODE6_HIGH_BANK_ANGLE_1) + : mk_alert(MODE6_LOW_BANK_ANGLE_1); } - return 0; + return 0; } void MK_VIII::Mode6Handler::update_bank_angle () { - if (! conf.bank_angle_enabled) - return; + if (! conf.bank_angle_enabled) + return; - unsigned int alerts = get_bank_angle_alerts(); + unsigned int alerts = get_bank_angle_alerts(); - // [SPEC] 6.4.4 specifies that the non-continuous alerts - // (MODE6_*_BANK_ANGLE_1 and MODE6_*_BANK_ANGLE_2) are locked out - // until the initial envelope is exited. + // [SPEC] 6.4.4 specifies that the non-continuous alerts + // (MODE6_*_BANK_ANGLE_1 and MODE6_*_BANK_ANGLE_2) are locked out + // until the initial envelope is exited. - if (! test_bits(alerts, mk_alert(MODE6_LOW_BANK_ANGLE_3))) - mk_unset_alerts(mk_alert(MODE6_LOW_BANK_ANGLE_3)); - if (! test_bits(alerts, mk_alert(MODE6_HIGH_BANK_ANGLE_3))) - mk_unset_alerts(mk_alert(MODE6_HIGH_BANK_ANGLE_3)); + if (! test_bits(alerts, mk_alert(MODE6_LOW_BANK_ANGLE_3))) + mk_unset_alerts(mk_alert(MODE6_LOW_BANK_ANGLE_3)); + if (! test_bits(alerts, mk_alert(MODE6_HIGH_BANK_ANGLE_3))) + mk_unset_alerts(mk_alert(MODE6_HIGH_BANK_ANGLE_3)); - if (alerts != 0) - mk_set_alerts(alerts); - else - mk_unset_alerts(mk_alert(MODE6_LOW_BANK_ANGLE_1) - | mk_alert(MODE6_HIGH_BANK_ANGLE_1) - | mk_alert(MODE6_LOW_BANK_ANGLE_2) - | mk_alert(MODE6_HIGH_BANK_ANGLE_2)); + if (alerts != 0) + mk_set_alerts(alerts); + else + mk_unset_alerts(mk_alert(MODE6_LOW_BANK_ANGLE_1) + | mk_alert(MODE6_HIGH_BANK_ANGLE_1) + | mk_alert(MODE6_LOW_BANK_ANGLE_2) + | mk_alert(MODE6_HIGH_BANK_ANGLE_2)); } void MK_VIII::Mode6Handler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK) + return; - if (! mk->state_handler.takeoff - && ! mk_data(radio_altitude).ncd - && mk_data(radio_altitude).get() > 1000) + if (! mk->state_handler.takeoff + && ! mk_data(radio_altitude).ncd + && mk_data(radio_altitude).get() > 1000) { - reset_altitude_callouts(); // [SPEC] 6.4.2 - reset_minimums(); // common sense + reset_altitude_callouts(); // [SPEC] 6.4.2 + reset_minimums(); // common sense } - update_minimums(); - update_altitude_callouts(); - update_above_field_callout(); - update_bank_angle(); + update_minimums(); + update_altitude_callouts(); + update_above_field_callout(); + update_bank_angle(); } /////////////////////////////////////////////////////////////////////////////// @@ -4317,56 +4359,61 @@ MK_VIII::Mode6Handler::update () bool MK_VIII::TCFHandler::AirportFilter::passAirport(FGAirport* aApt) const { - return aApt->hasHardRunwayOfLengthFt(mk->conf.runway_database); + return aApt->hasHardRunwayOfLengthFt(mk->conf.runway_database); } - + void MK_VIII::TCFHandler::update_runway () { - has_runway = false; - if (mk_data(gps_latitude).ncd || mk_data(gps_longitude).ncd) { - return; - } + has_runway = false; + if (mk_data(gps_latitude).ncd || mk_data(gps_longitude).ncd) + { + return; + } - // Search for the intended destination runway of the closest - // airport in range 15 nm. Passing 30nm to get_closest_airport() - // provides enough margin for - // large airports, which may have a runway located far away from - // the airport's reference point. - AirportFilter filter(mk); - SGGeod apos = SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()); - FGAirport* apt = FGAirport::findClosest(apos, 30.0, &filter); - - if (!apt) return; - - FGRunway* _runway = apt->findBestRunwayForPos(apos).get(); - - if (!_runway) return; + // Search for the intended destination runway of the closest + // airport in range 15 nm. Passing 30nm to get_closest_airport() + // provides enough margin for + // large airports, which may have a runway located far away from + // the airport's reference point. + AirportFilter filter(mk); + SGGeod apos = SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()); + FGAirport* apt = FGAirport::findClosest(apos, 30.0, &filter); + if (!apt) + { + return; + } - has_runway = true; + FGRunway* _runway = apt->findBestRunwayForPos(apos).get(); + if (!_runway) + { + return; + } - runway.center = _runway->pointOnCenterline(_runway->lengthM() * 0.5); + has_runway = true; - runway.elevation = apt->elevation(); + runway.center = _runway->pointOnCenterline(_runway->lengthM() * 0.5); - runway.half_width_m = _runway->widthM() * 0.5; - double half_length_m = _runway->lengthM() * 0.5; - runway.half_length = half_length_m * SG_METER_TO_NM; + runway.elevation = apt->elevation(); - // _________ - // | - // <<<widthM() * 0.5; + double half_length_m = _runway->lengthM() * 0.5; + runway.half_length = half_length_m * SG_METER_TO_NM; - // get heading of runway end (h0) - runway.edge.heading = _runway->headingDeg(); + // _________ + // | + // <<<begin(); + // get heading of runway end (h0) + runway.edge.heading = _runway->headingDeg(); - // get cartesian coordinates of both runway ends - runway.bias_points[0] = _runway->cart(); - runway.bias_points[1] = _runway->reciprocalRunway()->cart(); + // get position of runway threshold (e0) + runway.edge.position = _runway->begin(); + + // get cartesian coordinates of both runway ends + runway.bias_points[0] = _runway->cart(); + runway.bias_points[1] = _runway->reciprocalRunway()->cart(); } // Returns true if the current GPS position is inside the edge @@ -4378,10 +4425,10 @@ MK_VIII::TCFHandler::update_runway () bool MK_VIII::TCFHandler::is_inside_edge_triangle (RunwayEdge *edge) { - double az = SGGeodesy::courseDeg( SGGeod::fromDeg(mk_data(gps_longitude).get(), - mk_data(gps_latitude).get()), - edge->position); - return get_heading_difference(az, edge->heading) <= 45; + double az = SGGeodesy::courseDeg( SGGeod::fromDeg(mk_data(gps_longitude).get(), + mk_data(gps_latitude).get()), + edge->position); + return get_heading_difference(az, edge->heading) <= 45; } // Returns true if the current GPS position is inside the bias area of @@ -4389,161 +4436,169 @@ MK_VIII::TCFHandler::is_inside_edge_triangle (RunwayEdge *edge) bool MK_VIII::TCFHandler::is_inside_bias_area () { - double half_bias_width_m = k * SG_NM_TO_METER + runway.half_width_m; - SGVec3d cpos = SGVec3d::fromGeod( SGGeod::fromDegFt(mk_data(gps_longitude).get(), - mk_data(gps_latitude).get(), - runway.elevation) ); - SGLineSegmentd bias_line = SGLineSegmentd(runway.bias_points[0], runway.bias_points[1]); - return dist(cpos, bias_line) < half_bias_width_m; + double half_bias_width_m = k * SG_NM_TO_METER + runway.half_width_m; + SGVec3d cpos = SGVec3d::fromGeod( SGGeod::fromDegFt(mk_data(gps_longitude).get(), + mk_data(gps_latitude).get(), + runway.elevation) ); + SGLineSegmentd bias_line = SGLineSegmentd(runway.bias_points[0], runway.bias_points[1]); + return dist(cpos, bias_line) < half_bias_width_m; } bool MK_VIII::TCFHandler::is_tcf () { - if (mk_data(radio_altitude).get() > 10) - { - if (has_runway) + if (mk_data(radio_altitude).get() > 10) { - double distance = SGGeodesy::distanceNm( SGGeod::fromDegFt(mk_data(gps_longitude).get(), - mk_data(gps_latitude).get(), - runway.elevation), - runway.center); + if (has_runway) + { + double distance = SGGeodesy::distanceNm( SGGeod::fromDegFt(mk_data(gps_longitude).get(), + mk_data(gps_latitude).get(), + runway.elevation), + runway.center); - // distance to the inner envelope edge - double edge_distance = distance - runway.half_length - k; + // distance to the inner envelope edge + double edge_distance = distance - runway.half_length - k; - if (edge_distance > 15) - { + if (edge_distance > 15) + { + if (mk_data(radio_altitude).get() < 700) + return true; + } + else + if (edge_distance > 12) + { + if (mk_data(radio_altitude).get() < 100 * edge_distance - 800) + return true; + } + else + if (edge_distance > 4) + { + if (mk_data(radio_altitude).get() < 400) + return true; + } + else + if (edge_distance > 2.45) + { + if (mk_data(radio_altitude).get() < 100 * edge_distance) + return true; + } + else + if ( is_inside_edge_triangle(&runway.edge) && (edge_distance > 0.01) ) + { + if (mk_data(radio_altitude).get() < 100 * edge_distance) + return true; + } + else + if (! is_inside_bias_area()) + { + if (mk_data(radio_altitude).get() < 245) + return true; + } + } + else if (mk_data(radio_altitude).get() < 700) - return true; - } - else if (edge_distance > 12) - { - if (mk_data(radio_altitude).get() < 100 * edge_distance - 800) - return true; - } - else if (edge_distance > 4) - { - if (mk_data(radio_altitude).get() < 400) - return true; - } - else if (edge_distance > 2.45) - { - if (mk_data(radio_altitude).get() < 100 * edge_distance) - return true; - } - else if ( is_inside_edge_triangle(&runway.edge) && (edge_distance > 0.01) ) - { - if (mk_data(radio_altitude).get() < 100 * edge_distance) - return true; - } - else if (! is_inside_bias_area()) - { - if (mk_data(radio_altitude).get() < 245) - return true; - } + { + return true; + } } - else if (mk_data(radio_altitude).get() < 700) - { - return true; - } - } - return false; + return false; } bool MK_VIII::TCFHandler::is_rfcf () { - if (has_runway) - { - double distance = SGGeodesy::distanceNm( SGGeod::fromDegFt(mk_data(gps_longitude).get(), - mk_data(gps_latitude).get(), - runway.elevation), - runway.center); - distance -= runway.half_length; - - if (distance < 5.0) + if (has_runway) { - double krf = k + mk_data(gps_vertical_figure_of_merit).get() / 200; - distance -= krf; - double altitude_above_field = mk_data(geometric_altitude).get() - runway.elevation; + double distance = SGGeodesy::distanceNm( SGGeod::fromDegFt(mk_data(gps_longitude).get(), + mk_data(gps_latitude).get(), + runway.elevation), + runway.center); + distance -= runway.half_length; - if ( (distance > 1.5) && (altitude_above_field < 300.0) ) - return true; - else if ( (distance > 0.0) && (altitude_above_field < 200 * distance) ) - return true; + if (distance < 5.0) + { + double krf = k + mk_data(gps_vertical_figure_of_merit).get() / 200; + distance -= krf; + double altitude_above_field = mk_data(geometric_altitude).get() - runway.elevation; + + if ( (distance > 1.5) && (altitude_above_field < 300.0) ) + return true; + else if ( (distance > 0.0) && (altitude_above_field < 200 * distance) ) + return true; + } } - } - return false; + return false; } void MK_VIII::TCFHandler::update () { - if (mk->configuration_module.state != ConfigurationModule::STATE_OK || ! conf.enabled) - return; + if (mk->configuration_module.state != ConfigurationModule::STATE_OK || ! conf.enabled) + return; - // update_runway() has to iterate over the whole runway database - // (which contains thousands of runways), so it would be unwise to - // run it every frame. Run it every 3 seconds. - if (! runway_timer.running || runway_timer.elapsed() >= 3) + // update_runway() has to iterate over the whole runway database + // (which contains thousands of runways), so it would be unwise to + // run it every frame. Run it every 3 seconds. + if (! runway_timer.running || runway_timer.elapsed() >= 3) { - update_runway(); - runway_timer.start(); + update_runway(); + runway_timer.start(); } - if (! mk_dinput(ta_tcf_inhibit) - && ! mk->state_handler.ground // [1] - && ! mk_data(gps_latitude).ncd - && ! mk_data(gps_longitude).ncd - && ! mk_data(radio_altitude).ncd - && ! mk_data(geometric_altitude).ncd - && ! mk_data(gps_vertical_figure_of_merit).ncd) + if (! mk_dinput(ta_tcf_inhibit) + && ! mk->state_handler.ground // [1] + && ! mk_data(gps_latitude).ncd + && ! mk_data(gps_longitude).ncd + && ! mk_data(radio_altitude).ncd + && ! mk_data(geometric_altitude).ncd + && ! mk_data(gps_vertical_figure_of_merit).ncd) { - double *_reference; + double *_reference; - if (is_tcf()) - _reference = mk_data(radio_altitude).get_pointer(); - else if (is_rfcf()) - _reference = mk_data(geometric_altitude).get_pointer(); - else - _reference = NULL; + if (is_tcf()) + _reference = mk_data(radio_altitude).get_pointer(); + else if (is_rfcf()) + _reference = mk_data(geometric_altitude).get_pointer(); + else + _reference = NULL; - if (_reference) - { - if (mk_test_alert(TCF_TOO_LOW_TERRAIN)) - { - double new_bias = bias; - // do not repeat terrain alerts below 30ft agl - if (mk_data(radio_altitude).get() > 30) - { - if (new_bias < 0.0) // sanity check - new_bias = 0.0; - while ((*reference < initial_value - initial_value * new_bias)&& - (new_bias < 1.0)) - new_bias += 0.2; - } + if (_reference) + { + if (mk_test_alert(TCF_TOO_LOW_TERRAIN)) + { + double new_bias = bias; + // do not repeat terrain alerts below 30ft agl + if (mk_data(radio_altitude).get() > 30) + { + if (new_bias < 0.0) // sanity check + new_bias = 0.0; + while ((*reference < initial_value - initial_value * new_bias)&& + (new_bias < 1.0)) + { + new_bias += 0.2; + } + } - if (new_bias > bias) - { - bias = new_bias; - mk_repeat_alert(mk_alert(TCF_TOO_LOW_TERRAIN)); - } - } - else - { - bias = 0.2; - reference = _reference; - initial_value = *reference; - mk_set_alerts(mk_alert(TCF_TOO_LOW_TERRAIN)); - } + if (new_bias > bias) + { + bias = new_bias; + mk_repeat_alert(mk_alert(TCF_TOO_LOW_TERRAIN)); + } + } + else + { + bias = 0.2; + reference = _reference; + initial_value = *reference; + mk_set_alerts(mk_alert(TCF_TOO_LOW_TERRAIN)); + } - return; - } + return; + } } - mk_unset_alerts(mk_alert(TCF_TOO_LOW_TERRAIN)); + mk_unset_alerts(mk_alert(TCF_TOO_LOW_TERRAIN)); } /////////////////////////////////////////////////////////////////////////////// @@ -4571,78 +4626,78 @@ MK_VIII::MK_VIII (SGPropertyNode *node) mode6_handler(this), tcf_handler(this) { - for (int i = 0; i < node->nChildren(); ++i) + for (int i = 0; i < node->nChildren(); ++i) { - SGPropertyNode *child = node->getChild(i); - string cname = child->getName(); - string cval = child->getStringValue(); + SGPropertyNode *child = node->getChild(i); + string cname = child->getName(); + string cval = child->getStringValue(); - if (cname == "name") - name = cval; - else if (cname == "number") - num = child->getIntValue(); - else - { - SG_LOG(SG_INSTR, SG_WARN, "Error in mk-viii config logic"); - if (name.length()) - SG_LOG(SG_INSTR, SG_WARN, "Section = " << name); - } + if (cname == "name") + name = cval; + else if (cname == "number") + num = child->getIntValue(); + else + { + SG_LOG(SG_INSTR, SG_WARN, "Error in mk-viii config logic"); + if (name.length()) + SG_LOG(SG_INSTR, SG_WARN, "Section = " << name); + } } } void MK_VIII::init () { - properties_handler.init(); - voice_player.init(); + properties_handler.init(); + voice_player.init(); } void MK_VIII::bind () { - SGPropertyNode *node = fgGetNode(("/instrumentation/" + name).c_str(), num, true); + SGPropertyNode *node = fgGetNode(("/instrumentation/" + name).c_str(), num, true); - configuration_module.bind(node); - power_handler.bind(node); - io_handler.bind(node); - voice_player.bind(node, "Sounds/mk-viii/"); + configuration_module.bind(node); + power_handler.bind(node); + io_handler.bind(node); + voice_player.bind(node, "Sounds/mk-viii/"); } void MK_VIII::unbind () { - properties_handler.unbind(); + properties_handler.unbind(); } void MK_VIII::update (double dt) { - power_handler.update(); - system_handler.update(); + power_handler.update(); + system_handler.update(); - if (system_handler.state != SystemHandler::STATE_ON) - return; + if (system_handler.state != SystemHandler::STATE_ON) + return; - io_handler.update_inputs(); - io_handler.update_input_faults(); + io_handler.update_inputs(); + io_handler.update_input_faults(); - voice_player.update(); - state_handler.update(); + voice_player.update(); + state_handler.update(); - if (self_test_handler.update()) - return; + if (self_test_handler.update()) + return; - io_handler.update_internal_latches(); - io_handler.update_lamps(); + io_handler.update_internal_latches(); + io_handler.update_lamps(); - mode1_handler.update(); - mode2_handler.update(); - mode3_handler.update(); - mode4_handler.update(); - mode5_handler.update(); - mode6_handler.update(); - tcf_handler.update(); + mode1_handler.update(); + mode2_handler.update(); + mode3_handler.update(); + mode4_handler.update(); + mode5_handler.update(); + mode6_handler.update(); + tcf_handler.update(); - alert_handler.update(); - io_handler.update_outputs(); + alert_handler.update(); + io_handler.update_outputs(); } diff --git a/src/Instrumentation/mk_viii.hxx b/src/Instrumentation/mk_viii.hxx index 4c807e1af..8919a6f50 100644 --- a/src/Instrumentation/mk_viii.hxx +++ b/src/Instrumentation/mk_viii.hxx @@ -18,7 +18,6 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - #ifndef __INSTRUMENTS_MK_VIII_HXX #define __INSTRUMENTS_MK_VIII_HXX @@ -54,815 +53,818 @@ class SGSampleGroup; class MK_VIII : public SGSubsystem { - // keep in sync with Mode6Handler::altitude_callout_definitions[] - static const unsigned n_altitude_callouts = 12; + // keep in sync with Mode6Handler::altitude_callout_definitions[] + static const unsigned n_altitude_callouts = 12; - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::Parameter /////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::Parameter /////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// - template - class Parameter - { - T _value; - - public: - bool ncd; - - inline Parameter () - : _value(0), ncd(true) {} - - inline T get () const { assert(! ncd); return _value; } - inline T *get_pointer () { return &_value; } - inline void set (T value) { ncd = false; _value = value; } - inline void unset () { ncd = true; } - - inline void set (const Parameter *parameter) + template + class Parameter { - if (parameter->ncd) - unset(); - else - set(parameter->get()); - } - - inline void set (const Parameter *parameter, double factor) - { - if (parameter->ncd) - unset(); - else - set(parameter->get() * factor); - } - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::Sample ////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - template - class Sample - { - public: - double timestamp; - T value; - - inline Sample (T _value) - : timestamp(globals->get_sim_time_sec()), value(_value) {} - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::Timer /////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class Timer - { - double start_time; - - public: - bool running; - - inline Timer () - : start_time(0.0), running(false) {} - - inline void start () { running = true; start_time = globals->get_sim_time_sec(); } - inline void stop () { running = false; } - inline double elapsed () const { assert(running); return globals->get_sim_time_sec() - start_time; } - inline double start_or_elapsed () - { - if (running) - return elapsed(); - else - { - start(); - return 0; - } - } - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::PropertiesHandler /////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class PropertiesHandler : public FGVoicePlayer::PropertiesHandler - { - MK_VIII *mk; - - public: - struct - { - SGPropertyNode_ptr ai_caged; - SGPropertyNode_ptr ai_roll; - SGPropertyNode_ptr ai_serviceable; - SGPropertyNode_ptr altimeter_altitude; - SGPropertyNode_ptr altimeter_serviceable; - SGPropertyNode_ptr altitude; - SGPropertyNode_ptr altitude_agl; - SGPropertyNode_ptr altitude_gear_agl; - SGPropertyNode_ptr altitude_radar_agl; - SGPropertyNode_ptr orientation_roll; - SGPropertyNode_ptr asi_serviceable; - SGPropertyNode_ptr asi_speed; - SGPropertyNode_ptr autopilot_heading_lock; - SGPropertyNode_ptr flaps; - SGPropertyNode_ptr gear_down; - SGPropertyNode_ptr throttle; - SGPropertyNode_ptr latitude; - SGPropertyNode_ptr longitude; - SGPropertyNode_ptr nav0_cdi_serviceable; - SGPropertyNode_ptr nav0_gs_distance; - SGPropertyNode_ptr nav0_gs_needle_deflection; - SGPropertyNode_ptr nav0_gs_serviceable; - SGPropertyNode_ptr nav0_has_gs; - SGPropertyNode_ptr nav0_heading_needle_deflection; - SGPropertyNode_ptr nav0_in_range; - SGPropertyNode_ptr nav0_nav_loc; - SGPropertyNode_ptr nav0_serviceable; - SGPropertyNode_ptr power; - SGPropertyNode_ptr replay_state; - SGPropertyNode_ptr vs; - } external_properties; - - inline PropertiesHandler (MK_VIII *device) - : FGVoicePlayer::PropertiesHandler(), mk(device) {} - - PropertiesHandler() : FGVoicePlayer::PropertiesHandler(), mk(NULL) {} - - void init (); - }; - -public: - PropertiesHandler properties_handler; - -private: - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::PowerHandler //////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class PowerHandler - { - MK_VIII *mk; - - bool serviceable; - bool powered; - - Timer power_loss_timer; - Timer abnormal_timer; - Timer low_surge_timer; - Timer high_surge_timer; - Timer very_high_surge_timer; - - bool handle_abnormal_voltage (bool abnormal, - Timer *timer, - double max_duration); - - void power_on (); - void power_off (); - - public: - inline PowerHandler (MK_VIII *device) - : mk(device), serviceable(false), powered(false) {} - - void bind (SGPropertyNode *node); - void update (); - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::SystemHandler /////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class SystemHandler - { - MK_VIII *mk; - - double boot_delay; - Timer boot_timer; - - int last_replay_state; - Timer reposition_timer; - - public: - typedef enum - { - STATE_OFF, - STATE_BOOTING, - STATE_ON, - STATE_REPOSITION - } State; - - State state; - - inline SystemHandler (MK_VIII *device) - : mk(device), state(STATE_OFF) {} - - void power_on (); - void power_off (); - void update (); - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::ConfigurationModule ///////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class ConfigurationModule - { - public: - // keep in sync with IOHandler::present_status() - typedef enum - { - CATEGORY_AIRCRAFT_MODE_TYPE_SELECT, - CATEGORY_AIR_DATA_INPUT_SELECT, - CATEGORY_POSITION_INPUT_SELECT, - CATEGORY_ALTITUDE_CALLOUTS, - CATEGORY_AUDIO_MENU_SELECT, - CATEGORY_TERRAIN_DISPLAY_SELECT, - CATEGORY_OPTIONS_SELECT_GROUP_1, - CATEGORY_RADIO_ALTITUDE_INPUT_SELECT, - CATEGORY_NAVIGATION_INPUT_SELECT, - CATEGORY_ATTITUDE_INPUT_SELECT, - CATEGORY_HEADING_INPUT_SELECT, - CATEGORY_WINDSHEAR_INPUT_SELECT, - CATEGORY_INPUT_OUTPUT_DISCRETE_TYPE_SELECT, - CATEGORY_AUDIO_OUTPUT_LEVEL, - CATEGORY_UNDEFINED_INPUT_SELECT_1, - CATEGORY_UNDEFINED_INPUT_SELECT_2, - CATEGORY_UNDEFINED_INPUT_SELECT_3, - N_CATEGORIES - } Category; - - typedef enum - { - STATE_OK, - STATE_INVALID_DATABASE, - STATE_INVALID_AIRCRAFT_TYPE - } State; - State state; - - int effective_categories[N_CATEGORIES]; - - ConfigurationModule (MK_VIII *device); - - void boot (); - void bind (SGPropertyNode *node); - - private: - MK_VIII *mk; - - int categories[N_CATEGORIES]; - - bool read_aircraft_mode_type_select (int value); - bool read_air_data_input_select (int value); - bool read_position_input_select (int value); - bool read_altitude_callouts (int value); - bool read_audio_menu_select (int value); - bool read_terrain_display_select (int value); - bool read_options_select_group_1 (int value); - bool read_radio_altitude_input_select (int value); - bool read_navigation_input_select (int value); - bool read_attitude_input_select (int value); - bool read_heading_input_select (int value); - bool read_windshear_input_select (int value); - bool read_input_output_discrete_type_select (int value); - bool read_audio_output_level (int value); - bool read_undefined_input_select (int value); - - static bool m6_t2_is_bank_angle (Parameter *agl, - double abs_roll_deg, - bool ap_engaged); - static bool m6_t4_is_bank_angle (Parameter *agl, - double abs_roll_deg, - bool ap_engaged); - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::FaultHandler //////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class FaultHandler - { - enum - { - INOP_GPWS = 1 << 0, - INOP_TAD = 1 << 1 - }; - - MK_VIII *mk; - - static const unsigned int fault_inops[]; - - bool has_faults (unsigned int inop); - - public: - // keep in sync with IOHandler::present_status() - typedef enum - { - FAULT_ALL_MODES_INHIBIT, - FAULT_GEAR_SWITCH, - FAULT_FLAPS_SWITCH, - FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID, - FAULT_SELF_TEST_INVALID, - FAULT_GLIDESLOPE_CANCEL_INVALID, - FAULT_STEEP_APPROACH_INVALID, - FAULT_GPWS_INHIBIT, - FAULT_TA_TCF_INHIBIT, - FAULT_MODES14_INPUTS_INVALID, - FAULT_MODE5_INPUTS_INVALID, - FAULT_MODE6_INPUTS_INVALID, - FAULT_BANK_ANGLE_INPUTS_INVALID, - FAULT_TCF_INPUTS_INVALID, - N_FAULTS - } Fault; - - unsigned int faults; - - inline FaultHandler (MK_VIII *device) - : mk(device), faults(0) {} - - void boot (); - - void set_fault (Fault fault); - void unset_fault (Fault fault); - - bool has_faults () const; - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::IOHandler /////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - -public: - class IOHandler - { - public: - enum Lamp - { - LAMP_NONE, - LAMP_GLIDESLOPE, - LAMP_CAUTION, - LAMP_WARNING - }; - - struct LampConfiguration - { - bool format2; - bool flashing; - }; - - struct FaultsConfiguration - { - double max_flaps_down_airspeed; - double max_gear_down_airspeed; - }; - - struct _s_Conf - { - const LampConfiguration *lamp; - const FaultsConfiguration *faults; - bool flap_reversal; - bool steep_approach_enabled; - bool gpws_inhibit_enabled; - bool momentary_flap_override_enabled; - bool alternate_steep_approach; - bool use_internal_gps; - bool localizer_enabled; - int altitude_source; - bool use_attitude_indicator; - } conf; - - struct _s_input_feeders - { - struct _s_discretes - { - bool landing_gear; - bool landing_flaps; - bool glideslope_inhibit; - bool decision_height; - bool autopilot_engaged; - } discretes; - - struct _s_arinc429 - { - bool uncorrected_barometric_altitude; - bool barometric_altitude_rate; - bool radio_altitude; - bool glideslope_deviation; - bool roll_angle; - bool localizer_deviation; - bool computed_airspeed; - bool decision_height; - } arinc429; - } input_feeders; - - struct _s_inputs - { - struct _s_discretes - { - bool landing_gear; // appendix E 6.6.2, 3.15.1.4 - bool landing_flaps; // appendix E 6.6.4, 3.15.1.2 - bool momentary_flap_override; // appendix E 6.6.6, 3.15.1.6 - bool self_test; // appendix E 6.6.7, 3.15.1.10 - bool glideslope_inhibit; // appendix E 6.6.11, 3.15.1.1 - bool glideslope_cancel; // appendix E 6.6.13, 3.15.1.5 - bool decision_height_100; - bool decision_height; // appendix E 6.6.14, 3.10.2 - bool mode6_low_volume; // appendix E 6.6.15, 3.15.1.7 - bool audio_inhibit; // appendix E 6.6.16, 3.15.1.3 - bool ta_tcf_inhibit; // appendix E 6.6.20, 3.15.1.9 - bool autopilot_engaged; // appendix E 6.6.21, 3.15.1.8 - bool steep_approach; // appendix E 6.6.25, 3.15.1.11 - bool gpws_inhibit; // appendix E 6.6.27, 3.15.1.12 - } discretes; - - struct _s_arinc429 - { - Parameter uncorrected_barometric_altitude; // appendix E 6.2.1 - Parameter barometric_altitude_rate; // appendix E 6.2.2 - Parameter gps_altitude; // appendix E 6.2.4 - Parameter gps_latitude; // appendix E 6.2.7 - Parameter gps_longitude; // appendix E 6.2.8 - Parameter gps_vertical_figure_of_merit; // appendix E 6.2.13 - Parameter radio_altitude; // appendix E 6.2.29 - Parameter glideslope_deviation; // appendix E 6.2.30 - Parameter roll_angle; // appendix E 6.2.31 - Parameter localizer_deviation; // appendix E 6.2.33 - Parameter computed_airspeed; // appendix E 6.2.39 - Parameter decision_height; // appendix E 6.2.41 - } arinc429; - } inputs; - - struct Outputs - { - struct _s_discretes - { - bool gpws_warning; // appendix E 7.4.1, 3.15.2.5 - bool gpws_alert; // appendix E 7.4.1, 3.15.2.6 - bool audio_on; // appendix E 7.4.2, 3.15.2.10 - bool gpws_inop; // appendix E 7.4.3, 3.15.2.3 - bool tad_inop; // appendix E 7.4.3, 3.15.2.4 - bool flap_override; // appendix E 7.4.5, 3.15.2.8 - bool glideslope_cancel; // appendix E 7.4.6, 3.15.2.7 - bool steep_approach; // appendix E 7.4.12, 3.15.2.9 - } discretes; - - struct _s_arinc429 - { - int egpws_alert_discrete_1; // appendix E 7.1.1.1 - int egpwc_logic_discretes; // appendix E 7.1.1.2 - int mode6_callouts_discrete_1; // appendix E 7.1.1.3 - int mode6_callouts_discrete_2; // appendix E 7.1.1.4 - int egpws_alert_discrete_2; // appendix E 7.1.1.5 - int egpwc_alert_discrete_3; // appendix E 7.1.1.6 - } arinc429; - }; - - Outputs outputs; - - struct _s_data - { - Parameter barometric_altitude_rate; - Parameter decision_height; - Parameter geometric_altitude; - Parameter glideslope_deviation_dots; - Parameter gps_altitude; - Parameter gps_latitude; - Parameter gps_longitude; - Parameter gps_vertical_figure_of_merit; - Parameter localizer_deviation_dots; - Parameter radio_altitude; - Parameter roll_angle; - Parameter terrain_clearance; - } data; - - IOHandler (MK_VIII *device); - - void boot (); - void post_boot (); - void power_off (); - - void enter_ground (); - void enter_takeoff (); - - void update_inputs (); - void update_input_faults (); - void update_alternate_discrete_input (bool *ptr); - void update_internal_latches (); - - void update_egpws_alert_discrete_1 (); - void update_egpwc_logic_discretes (); - void update_mode6_callouts_discrete_1 (); - void update_mode6_callouts_discrete_2 (); - void update_egpws_alert_discrete_2 (); - void update_egpwc_alert_discrete_3 (); - void update_outputs (); - void reposition (); - - void update_lamps (); - void set_lamp (Lamp lamp); - - bool gpws_inhibit () const; - bool real_flaps_down () const; - bool flaps_down () const; - bool flap_override () const; - bool steep_approach () const; - bool momentary_steep_approach_enabled () const; - - void bind (SGPropertyNode *node); - - MK_VIII *mk; - - private: - - /////////////////////////////////////////////////////////////////////////// - // MK_VIII::IOHandler::TerrainClearanceFilter ///////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - class TerrainClearanceFilter - { - typedef deque< Sample > samples_type; - samples_type samples; - double value; - double last_update; + T _value; public: - inline TerrainClearanceFilter () - : value(0.0), last_update(-1.0) {} + bool ncd; - double update (double agl); - void reset (); + inline Parameter () + : _value(0), ncd(true) {} + + inline T get () const { assert(! ncd); return _value; } + inline T *get_pointer () { return &_value; } + inline void set (T value) { ncd = false; _value = value; } + inline void unset () { ncd = true; } + + inline void set (const Parameter *parameter) + { + if (parameter->ncd) + unset(); + else + set(parameter->get()); + } + + inline void set (const Parameter *parameter, double factor) + { + if (parameter->ncd) + unset(); + else + set(parameter->get() * factor); + } }; - /////////////////////////////////////////////////////////////////////////// - // MK_VIII::IOHandler (continued) ///////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::Sample ////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// - TerrainClearanceFilter terrain_clearance_filter; - - Lamp _lamp; - Timer lamp_timer; - - Timer audio_inhibit_fault_timer; - Timer landing_gear_fault_timer; - Timer flaps_down_fault_timer; - Timer momentary_flap_override_fault_timer; - Timer self_test_fault_timer; - Timer glideslope_cancel_fault_timer; - Timer steep_approach_fault_timer; - Timer gpws_inhibit_fault_timer; - Timer ta_tcf_inhibit_fault_timer; - - bool last_landing_gear; - bool last_real_flaps_down; - - typedef deque< Sample< Parameter > > altitude_samples_type; - altitude_samples_type altitude_samples; - - struct + template + class Sample { - bool glideslope_cancel; - } power_saved; + public: + double timestamp; + T value; - void update_terrain_clearance (); - void reset_terrain_clearance (); - - void handle_input_fault (bool test, FaultHandler::Fault fault); - void handle_input_fault (bool test, - Timer *timer, - double max_duration, - FaultHandler::Fault fault); - - void tie_input (SGPropertyNode *node, - const char *name, - bool *input, - bool *feed = NULL); - void tie_input (SGPropertyNode *node, - const char *name, - Parameter *input, - bool *feed = NULL); - void tie_output (SGPropertyNode *node, - const char *name, - bool *output); - void tie_output (SGPropertyNode *node, - const char *name, - int *output); - - public: - - bool get_discrete_input (bool *ptr) const; - void set_discrete_input (bool *ptr, bool value); - - void present_status (); - void present_status_section (const char *name); - void present_status_item (const char *name, const char *value = NULL); - void present_status_subitem (const char *name); - - bool get_present_status () const; - void set_present_status (bool value); - - bool *get_lamp_output (Lamp lamp); - }; - - class VoicePlayer : public FGVoicePlayer - { - public: - VoicePlayer (MK_VIII *device) : - FGVoicePlayer(&device->properties_handler, "mk-viii") - {} - - ~VoicePlayer() {} - void init (); - - struct - { - Voice *application_data_base_failed; - Voice *bank_angle; - Voice *bank_angle_bank_angle; - Voice *bank_angle_bank_angle_3; - Voice *bank_angle_inop; - Voice *bank_angle_pause_bank_angle; - Voice *bank_angle_pause_bank_angle_3; - Voice *callouts_inop; - Voice *configuration_type_invalid; - Voice *dont_sink; - Voice *dont_sink_pause_dont_sink; - Voice *five_hundred_above; - Voice *glideslope; - Voice *glideslope_inop; - Voice *gpws_inop; - Voice *hard_glideslope; - Voice *minimums; - Voice *minimums_100; - Voice *minimums_minimums; - Voice *retard; - Voice *pull_up; - Voice *sink_rate; - Voice *sink_rate_pause_sink_rate; - Voice *soft_glideslope; - Voice *terrain; - Voice *terrain_pause_terrain; - Voice *too_low_flaps; - Voice *too_low_gear; - Voice *too_low_terrain; - Voice *altitude_callouts[n_altitude_callouts]; - } voices; - - }; - -private: - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::SelfTestHandler ///////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class SelfTestHandler - { - MK_VIII *mk; - - typedef enum - { - CANCEL_NONE, - CANCEL_SHORT, - CANCEL_LONG - } Cancel; - - enum - { - ACTION_SLEEP = 1 << 0, - ACTION_VOICE = 1 << 1, - ACTION_DISCRETE_ON_OFF = 1 << 2, - ACTION_DONE = 1 << 3 + inline Sample (T _value) + : timestamp(globals->get_sim_time_sec()), value(_value) {} }; - typedef struct + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::Timer /////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class Timer { - unsigned int flags; - double sleep_duration; - bool *discrete; - } Action; + double start_time; - Cancel cancel; - Action action; - int current; - bool button_pressed; - double button_press_timestamp; - IOHandler::Outputs saved_outputs; - double sleep_start; + public: + bool running; - bool _was_here (int position); + inline Timer () + : start_time(0.0), running(false) {} - Action sleep (double duration); - Action play (VoicePlayer::Voice *voice); - Action discrete_on (bool *discrete, double duration); - Action discrete_on_off (bool *discrete, double duration); - Action discrete_on_off (bool *discrete, VoicePlayer::Voice *voice); - Action done (); - - Action run (); - - void start (); - void stop (); - void shutdown (); - - public: - typedef enum - { - STATE_NONE, - STATE_START, - STATE_RUNNING - } State; - - State state; - - inline SelfTestHandler (MK_VIII *device) - : mk(device), button_pressed(false), state(STATE_NONE) {} - - inline void power_off () { stop(); } - inline void set_inop () { stop(); } - void handle_button_event (bool value); - bool update (); - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::AlertHandler //////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class AlertHandler - { - MK_VIII *mk; - - unsigned int old_alerts; - unsigned int voice_alerts; - unsigned int repeated_alerts; - VoicePlayer::Voice *altitude_callout_voice; - - void reset (); - inline bool has_alerts (unsigned int test) const { return (alerts & test) != 0; } - inline bool has_old_alerts (unsigned int test) const { return (old_alerts & test) != 0; } - inline bool must_play_voice (unsigned int test) const { return ! has_old_alerts(test) || (repeated_alerts & test) != 0; } - bool select_voice_alerts (unsigned int test); - - public: - enum - { - ALERT_MODE1_PULL_UP = 1 << 0, - ALERT_MODE1_SINK_RATE = 1 << 1, - - ALERT_MODE2A_PREFACE = 1 << 2, - ALERT_MODE2B_PREFACE = 1 << 3, - ALERT_MODE2A = 1 << 4, - ALERT_MODE2B = 1 << 5, - ALERT_MODE2B_LANDING_MODE = 1 << 6, - ALERT_MODE2A_ALTITUDE_GAIN = 1 << 7, - ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING = 1 << 8, - - ALERT_MODE3 = 1 << 9, - - ALERT_MODE4_TOO_LOW_FLAPS = 1 << 10, - ALERT_MODE4_TOO_LOW_GEAR = 1 << 11, - ALERT_MODE4AB_TOO_LOW_TERRAIN = 1 << 12, - ALERT_MODE4C_TOO_LOW_TERRAIN = 1 << 13, - - ALERT_MODE5_SOFT = 1 << 14, - ALERT_MODE5_HARD = 1 << 15, - - ALERT_MODE6_MINIMUMS = 1 << 16, - - ALERT_MODE6_ALTITUDE_CALLOUT = 1 << 17, - ALERT_MODE6_LOW_BANK_ANGLE_1 = 1 << 18, - ALERT_MODE6_HIGH_BANK_ANGLE_1 = 1 << 19, - ALERT_MODE6_LOW_BANK_ANGLE_2 = 1 << 20, - ALERT_MODE6_HIGH_BANK_ANGLE_2 = 1 << 21, - ALERT_MODE6_LOW_BANK_ANGLE_3 = 1 << 22, - ALERT_MODE6_HIGH_BANK_ANGLE_3 = 1 << 23, - - ALERT_TCF_TOO_LOW_TERRAIN = 1 << 24, - - ALERT_MODE6_MINIMUMS_100 = 1 << 28, - ALERT_MODE6_RETARD = 1 << 29, + inline void start () { running = true; start_time = globals->get_sim_time_sec(); } + inline void stop () { running = false; } + inline double elapsed () const { assert(running); return globals->get_sim_time_sec() - start_time; } + inline double start_or_elapsed () + { + if (running) + return elapsed(); + else + { + start(); + return 0; + } + } }; - enum + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::PropertiesHandler /////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class PropertiesHandler : public FGVoicePlayer::PropertiesHandler { - ALERT_FLAG_REPEAT = 1 << 0 + MK_VIII *mk; + + public: + struct + { + SGPropertyNode_ptr ai_caged; + SGPropertyNode_ptr ai_roll; + SGPropertyNode_ptr ai_serviceable; + SGPropertyNode_ptr altimeter_altitude; + SGPropertyNode_ptr altimeter_serviceable; + SGPropertyNode_ptr altitude; + SGPropertyNode_ptr altitude_agl; + SGPropertyNode_ptr altitude_gear_agl; + SGPropertyNode_ptr altitude_radar_agl; + SGPropertyNode_ptr orientation_roll; + SGPropertyNode_ptr asi_serviceable; + SGPropertyNode_ptr asi_speed; + SGPropertyNode_ptr autopilot_heading_lock; + SGPropertyNode_ptr flaps; + SGPropertyNode_ptr gear_down; + SGPropertyNode_ptr throttle; + SGPropertyNode_ptr latitude; + SGPropertyNode_ptr longitude; + SGPropertyNode_ptr nav0_cdi_serviceable; + SGPropertyNode_ptr nav0_gs_distance; + SGPropertyNode_ptr nav0_gs_needle_deflection; + SGPropertyNode_ptr nav0_gs_serviceable; + SGPropertyNode_ptr nav0_has_gs; + SGPropertyNode_ptr nav0_heading_needle_deflection; + SGPropertyNode_ptr nav0_in_range; + SGPropertyNode_ptr nav0_nav_loc; + SGPropertyNode_ptr nav0_serviceable; + SGPropertyNode_ptr power; + SGPropertyNode_ptr replay_state; + SGPropertyNode_ptr vs; + } external_properties; + + inline PropertiesHandler (MK_VIII *device) + : FGVoicePlayer::PropertiesHandler(), mk(device) {} + + PropertiesHandler() : FGVoicePlayer::PropertiesHandler(), mk(NULL) {} + + void init (); }; - unsigned int alerts; + public: + PropertiesHandler properties_handler; - inline AlertHandler (MK_VIII *device) - : mk(device) {} + private: + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::PowerHandler //////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// - void boot (); - void reposition (); - void update (); + class PowerHandler + { + MK_VIII *mk; - void set_alerts (unsigned int _alerts, - unsigned int flags = 0, - VoicePlayer::Voice *_altitude_callout_voice = NULL); - void unset_alerts (unsigned int _alerts); + bool serviceable; + bool powered; - inline void repeat_alert (unsigned int alert) { set_alerts(alert, ALERT_FLAG_REPEAT); } - inline void set_altitude_callout_alert (VoicePlayer::Voice *voice) { set_alerts(ALERT_MODE6_ALTITUDE_CALLOUT, 0, voice); } - }; + Timer power_loss_timer; + Timer abnormal_timer; + Timer low_surge_timer; + Timer high_surge_timer; + Timer very_high_surge_timer; - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::StateHandler //////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// + bool handle_abnormal_voltage (bool abnormal, + Timer *timer, + double max_duration); + + void power_on (); + void power_off (); + + public: + inline PowerHandler (MK_VIII *device) + : mk(device), serviceable(false), powered(false) {} + + void bind (SGPropertyNode *node); + void update (); + }; + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::SystemHandler /////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class SystemHandler + { + MK_VIII *mk; + + double boot_delay; + Timer boot_timer; + + int last_replay_state; + Timer reposition_timer; + + public: + typedef enum + { + STATE_OFF, + STATE_BOOTING, + STATE_ON, + STATE_REPOSITION + } State; + + State state; + + inline SystemHandler (MK_VIII *device) + : mk(device), boot_delay(0.0), last_replay_state(0), state(STATE_OFF) {} + + void power_on (); + void power_off (); + void update (); + }; + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::ConfigurationModule ///////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class ConfigurationModule + { + public: + // keep in sync with IOHandler::present_status() + typedef enum + { + CATEGORY_AIRCRAFT_MODE_TYPE_SELECT, + CATEGORY_AIR_DATA_INPUT_SELECT, + CATEGORY_POSITION_INPUT_SELECT, + CATEGORY_ALTITUDE_CALLOUTS, + CATEGORY_AUDIO_MENU_SELECT, + CATEGORY_TERRAIN_DISPLAY_SELECT, + CATEGORY_OPTIONS_SELECT_GROUP_1, + CATEGORY_RADIO_ALTITUDE_INPUT_SELECT, + CATEGORY_NAVIGATION_INPUT_SELECT, + CATEGORY_ATTITUDE_INPUT_SELECT, + CATEGORY_HEADING_INPUT_SELECT, + CATEGORY_WINDSHEAR_INPUT_SELECT, + CATEGORY_INPUT_OUTPUT_DISCRETE_TYPE_SELECT, + CATEGORY_AUDIO_OUTPUT_LEVEL, + CATEGORY_UNDEFINED_INPUT_SELECT_1, + CATEGORY_UNDEFINED_INPUT_SELECT_2, + CATEGORY_UNDEFINED_INPUT_SELECT_3, + N_CATEGORIES + } Category; + + typedef enum + { + STATE_OK, + STATE_INVALID_DATABASE, + STATE_INVALID_AIRCRAFT_TYPE + } State; + + State state; + + int effective_categories[N_CATEGORIES]; + + ConfigurationModule (MK_VIII *device); + + void boot (); + void bind (SGPropertyNode *node); + + private: + MK_VIII *mk; + + int categories[N_CATEGORIES]; + + bool read_aircraft_mode_type_select (int value); + bool read_air_data_input_select (int value); + bool read_position_input_select (int value); + bool read_altitude_callouts (int value); + bool read_audio_menu_select (int value); + bool read_terrain_display_select (int value); + bool read_options_select_group_1 (int value); + bool read_radio_altitude_input_select (int value); + bool read_navigation_input_select (int value); + bool read_attitude_input_select (int value); + bool read_heading_input_select (int value); + bool read_windshear_input_select (int value); + bool read_input_output_discrete_type_select (int value); + bool read_audio_output_level (int value); + bool read_undefined_input_select (int value); + + static bool m6_t2_is_bank_angle (Parameter *agl, + double abs_roll_deg, + bool ap_engaged); + static bool m6_t4_is_bank_angle (Parameter *agl, + double abs_roll_deg, + bool ap_engaged); + }; + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::FaultHandler //////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class FaultHandler + { + enum + { + INOP_GPWS = 1 << 0, + INOP_TAD = 1 << 1 + }; + + MK_VIII *mk; + + static const unsigned int fault_inops[]; + + bool has_faults (unsigned int inop); + + public: + // keep in sync with IOHandler::present_status() + + typedef enum + { + FAULT_ALL_MODES_INHIBIT, + FAULT_GEAR_SWITCH, + FAULT_FLAPS_SWITCH, + FAULT_MOMENTARY_FLAP_OVERRIDE_INVALID, + FAULT_SELF_TEST_INVALID, + FAULT_GLIDESLOPE_CANCEL_INVALID, + FAULT_STEEP_APPROACH_INVALID, + FAULT_GPWS_INHIBIT, + FAULT_TA_TCF_INHIBIT, + FAULT_MODES14_INPUTS_INVALID, + FAULT_MODE5_INPUTS_INVALID, + FAULT_MODE6_INPUTS_INVALID, + FAULT_BANK_ANGLE_INPUTS_INVALID, + FAULT_TCF_INPUTS_INVALID, + N_FAULTS + } Fault; + + unsigned int faults; + + inline FaultHandler(MK_VIII *device) : + mk(device), faults(0) { + } + + void boot(); + + void set_fault(Fault fault); + void unset_fault(Fault fault); + + bool has_faults() const; + }; + + public: + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::IOHandler /////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + class IOHandler + { + public: + enum Lamp + { + LAMP_NONE, + LAMP_GLIDESLOPE, + LAMP_CAUTION, + LAMP_WARNING + }; + + struct LampConfiguration + { + bool format2; + bool flashing; + }; + + struct FaultsConfiguration + { + double max_flaps_down_airspeed; + double max_gear_down_airspeed; + }; + + struct _s_Conf + { + const LampConfiguration *lamp; + const FaultsConfiguration *faults; + bool flap_reversal; + bool steep_approach_enabled; + bool gpws_inhibit_enabled; + bool momentary_flap_override_enabled; + bool alternate_steep_approach; + bool use_internal_gps; + bool localizer_enabled; + int altitude_source; + bool use_attitude_indicator; + } conf; + + struct _s_input_feeders + { + struct _s_discretes + { + bool landing_gear; + bool landing_flaps; + bool glideslope_inhibit; + bool decision_height; + bool autopilot_engaged; + } discretes; + + struct _s_arinc429 + { + bool uncorrected_barometric_altitude; + bool barometric_altitude_rate; + bool radio_altitude; + bool glideslope_deviation; + bool roll_angle; + bool localizer_deviation; + bool computed_airspeed; + bool decision_height; + } arinc429; + } input_feeders; + + struct _s_inputs + { + struct _s_discretes + { + bool landing_gear; // appendix E 6.6.2, 3.15.1.4 + bool landing_flaps; // appendix E 6.6.4, 3.15.1.2 + bool momentary_flap_override; // appendix E 6.6.6, 3.15.1.6 + bool self_test; // appendix E 6.6.7, 3.15.1.10 + bool glideslope_inhibit; // appendix E 6.6.11, 3.15.1.1 + bool glideslope_cancel; // appendix E 6.6.13, 3.15.1.5 + bool decision_height_100; + bool decision_height; // appendix E 6.6.14, 3.10.2 + bool mode6_low_volume; // appendix E 6.6.15, 3.15.1.7 + bool audio_inhibit; // appendix E 6.6.16, 3.15.1.3 + bool ta_tcf_inhibit; // appendix E 6.6.20, 3.15.1.9 + bool autopilot_engaged; // appendix E 6.6.21, 3.15.1.8 + bool steep_approach; // appendix E 6.6.25, 3.15.1.11 + bool gpws_inhibit; // appendix E 6.6.27, 3.15.1.12 + } discretes; + + struct _s_arinc429 + { + Parameter uncorrected_barometric_altitude; // appendix E 6.2.1 + Parameter barometric_altitude_rate; // appendix E 6.2.2 + Parameter gps_altitude; // appendix E 6.2.4 + Parameter gps_latitude; // appendix E 6.2.7 + Parameter gps_longitude; // appendix E 6.2.8 + Parameter gps_vertical_figure_of_merit; // appendix E 6.2.13 + Parameter radio_altitude; // appendix E 6.2.29 + Parameter glideslope_deviation; // appendix E 6.2.30 + Parameter roll_angle; // appendix E 6.2.31 + Parameter localizer_deviation; // appendix E 6.2.33 + Parameter computed_airspeed; // appendix E 6.2.39 + Parameter decision_height; // appendix E 6.2.41 + } arinc429; + } inputs; + + struct Outputs + { + struct _s_discretes + { + bool gpws_warning; // appendix E 7.4.1, 3.15.2.5 + bool gpws_alert; // appendix E 7.4.1, 3.15.2.6 + bool audio_on; // appendix E 7.4.2, 3.15.2.10 + bool gpws_inop; // appendix E 7.4.3, 3.15.2.3 + bool tad_inop; // appendix E 7.4.3, 3.15.2.4 + bool flap_override; // appendix E 7.4.5, 3.15.2.8 + bool glideslope_cancel; // appendix E 7.4.6, 3.15.2.7 + bool steep_approach; // appendix E 7.4.12, 3.15.2.9 + } discretes; + + struct _s_arinc429 + { + int egpws_alert_discrete_1; // appendix E 7.1.1.1 + int egpwc_logic_discretes; // appendix E 7.1.1.2 + int mode6_callouts_discrete_1; // appendix E 7.1.1.3 + int mode6_callouts_discrete_2; // appendix E 7.1.1.4 + int egpws_alert_discrete_2; // appendix E 7.1.1.5 + int egpwc_alert_discrete_3; // appendix E 7.1.1.6 + } arinc429; + }; + + Outputs outputs; + + struct _s_data + { + Parameter barometric_altitude_rate; + Parameter decision_height; + Parameter geometric_altitude; + Parameter glideslope_deviation_dots; + Parameter gps_altitude; + Parameter gps_latitude; + Parameter gps_longitude; + Parameter gps_vertical_figure_of_merit; + Parameter localizer_deviation_dots; + Parameter radio_altitude; + Parameter roll_angle; + Parameter terrain_clearance; + } data; + + IOHandler (MK_VIII *device); + + void boot (); + void post_boot (); + void power_off (); + + void enter_ground (); + void enter_takeoff (); + + void update_inputs (); + void update_input_faults (); + void update_alternate_discrete_input (bool *ptr); + void update_internal_latches (); + + void update_egpws_alert_discrete_1 (); + void update_egpwc_logic_discretes (); + void update_mode6_callouts_discrete_1 (); + void update_mode6_callouts_discrete_2 (); + void update_egpws_alert_discrete_2 (); + void update_egpwc_alert_discrete_3 (); + void update_outputs (); + void reposition (); + + void update_lamps (); + void set_lamp (Lamp lamp); + + bool gpws_inhibit () const; + bool real_flaps_down () const; + bool flaps_down () const; + bool flap_override () const; + bool steep_approach () const; + bool momentary_steep_approach_enabled () const; + + void bind (SGPropertyNode *node); + + MK_VIII *mk; + + private: + + /////////////////////////////////////////////////////////////////////////// + // MK_VIII::IOHandler::TerrainClearanceFilter ///////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + class TerrainClearanceFilter + { + typedef deque< Sample > samples_type; + samples_type samples; + double value; + double last_update; + + public: + inline TerrainClearanceFilter () + : value(0.0), last_update(-1.0) {} + + double update (double agl); + void reset (); + }; + + /////////////////////////////////////////////////////////////////////////// + // MK_VIII::IOHandler (continued) ///////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + TerrainClearanceFilter terrain_clearance_filter; + + Lamp _lamp; + Timer lamp_timer; + + Timer audio_inhibit_fault_timer; + Timer landing_gear_fault_timer; + Timer flaps_down_fault_timer; + Timer momentary_flap_override_fault_timer; + Timer self_test_fault_timer; + Timer glideslope_cancel_fault_timer; + Timer steep_approach_fault_timer; + Timer gpws_inhibit_fault_timer; + Timer ta_tcf_inhibit_fault_timer; + + bool last_landing_gear; + bool last_real_flaps_down; + + typedef deque< Sample< Parameter > > altitude_samples_type; + altitude_samples_type altitude_samples; + + struct + { + bool glideslope_cancel; + } power_saved; + + void update_terrain_clearance (); + void reset_terrain_clearance (); + + void handle_input_fault (bool test, FaultHandler::Fault fault); + void handle_input_fault (bool test, + Timer *timer, + double max_duration, + FaultHandler::Fault fault); + + void tie_input (SGPropertyNode *node, + const char *name, + bool *input, + bool *feed = NULL); + void tie_input (SGPropertyNode *node, + const char *name, + Parameter *input, + bool *feed = NULL); + void tie_output (SGPropertyNode *node, + const char *name, + bool *output); + void tie_output (SGPropertyNode *node, + const char *name, + int *output); + + public: + + bool get_discrete_input (bool *ptr) const; + void set_discrete_input (bool *ptr, bool value); + + void present_status (); + void present_status_section (const char *name); + void present_status_item (const char *name, const char *value = NULL); + void present_status_subitem (const char *name); + + bool get_present_status () const; + void set_present_status (bool value); + + bool *get_lamp_output (Lamp lamp); + }; + + class VoicePlayer : public FGVoicePlayer + { + public: + VoicePlayer (MK_VIII *device) : + FGVoicePlayer(&device->properties_handler, "mk-viii") + {} + + ~VoicePlayer() {} + void init (); + + struct + { + Voice *application_data_base_failed; + Voice *bank_angle; + Voice *bank_angle_bank_angle; + Voice *bank_angle_bank_angle_3; + Voice *bank_angle_inop; + Voice *bank_angle_pause_bank_angle; + Voice *bank_angle_pause_bank_angle_3; + Voice *callouts_inop; + Voice *configuration_type_invalid; + Voice *dont_sink; + Voice *dont_sink_pause_dont_sink; + Voice *five_hundred_above; + Voice *glideslope; + Voice *glideslope_inop; + Voice *gpws_inop; + Voice *hard_glideslope; + Voice *minimums; + Voice *minimums_100; + Voice *minimums_minimums; + Voice *retard; + Voice *pull_up; + Voice *sink_rate; + Voice *sink_rate_pause_sink_rate; + Voice *soft_glideslope; + Voice *terrain; + Voice *terrain_pause_terrain; + Voice *too_low_flaps; + Voice *too_low_gear; + Voice *too_low_terrain; + Voice *altitude_callouts[n_altitude_callouts]; + } voices; + + }; + + private: + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::SelfTestHandler ///////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class SelfTestHandler + { + MK_VIII *mk; + + typedef enum + { + CANCEL_NONE, + CANCEL_SHORT, + CANCEL_LONG + } Cancel; + + enum + { + ACTION_SLEEP = 1 << 0, + ACTION_VOICE = 1 << 1, + ACTION_DISCRETE_ON_OFF = 1 << 2, + ACTION_DONE = 1 << 3 + }; + + typedef struct + { + unsigned int flags; + double sleep_duration; + bool *discrete; + } Action; + + Cancel cancel; + Action action; + int current; + bool button_pressed; + double button_press_timestamp; + IOHandler::Outputs saved_outputs; + double sleep_start; + + bool _was_here (int position); + + Action sleep (double duration); + Action play (VoicePlayer::Voice *voice); + Action discrete_on (bool *discrete, double duration); + Action discrete_on_off (bool *discrete, double duration); + Action discrete_on_off (bool *discrete, VoicePlayer::Voice *voice); + Action done (); + + Action run (); + + void start (); + void stop (); + void shutdown (); + + public: + typedef enum + { + STATE_NONE, + STATE_START, + STATE_RUNNING + } State; + + State state; + + inline SelfTestHandler (MK_VIII *device) + : mk(device), button_pressed(false), state(STATE_NONE) {} + + inline void power_off () { stop(); } + inline void set_inop () { stop(); } + void handle_button_event (bool value); + bool update (); + }; + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::AlertHandler //////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class AlertHandler + { + MK_VIII *mk; + + unsigned int old_alerts; + unsigned int voice_alerts; + unsigned int repeated_alerts; + VoicePlayer::Voice *altitude_callout_voice; + + void reset (); + inline bool has_alerts (unsigned int test) const { return (alerts & test) != 0; } + inline bool has_old_alerts (unsigned int test) const { return (old_alerts & test) != 0; } + inline bool must_play_voice (unsigned int test) const { return ! has_old_alerts(test) || (repeated_alerts & test) != 0; } + bool select_voice_alerts (unsigned int test); + + public: + enum + { + ALERT_MODE1_PULL_UP = 1 << 0, + ALERT_MODE1_SINK_RATE = 1 << 1, + + ALERT_MODE2A_PREFACE = 1 << 2, + ALERT_MODE2B_PREFACE = 1 << 3, + ALERT_MODE2A = 1 << 4, + ALERT_MODE2B = 1 << 5, + ALERT_MODE2B_LANDING_MODE = 1 << 6, + ALERT_MODE2A_ALTITUDE_GAIN = 1 << 7, + ALERT_MODE2A_ALTITUDE_GAIN_TERRAIN_CLOSING = 1 << 8, + + ALERT_MODE3 = 1 << 9, + + ALERT_MODE4_TOO_LOW_FLAPS = 1 << 10, + ALERT_MODE4_TOO_LOW_GEAR = 1 << 11, + ALERT_MODE4AB_TOO_LOW_TERRAIN = 1 << 12, + ALERT_MODE4C_TOO_LOW_TERRAIN = 1 << 13, + + ALERT_MODE5_SOFT = 1 << 14, + ALERT_MODE5_HARD = 1 << 15, + + ALERT_MODE6_MINIMUMS = 1 << 16, + + ALERT_MODE6_ALTITUDE_CALLOUT = 1 << 17, + ALERT_MODE6_LOW_BANK_ANGLE_1 = 1 << 18, + ALERT_MODE6_HIGH_BANK_ANGLE_1 = 1 << 19, + ALERT_MODE6_LOW_BANK_ANGLE_2 = 1 << 20, + ALERT_MODE6_HIGH_BANK_ANGLE_2 = 1 << 21, + ALERT_MODE6_LOW_BANK_ANGLE_3 = 1 << 22, + ALERT_MODE6_HIGH_BANK_ANGLE_3 = 1 << 23, + + ALERT_TCF_TOO_LOW_TERRAIN = 1 << 24, + + ALERT_MODE6_MINIMUMS_100 = 1 << 28, + ALERT_MODE6_RETARD = 1 << 29, + }; + + enum + { + ALERT_FLAG_REPEAT = 1 << 0 + }; + + unsigned int alerts; + + inline AlertHandler (MK_VIII *device) + : mk(device) {} + + void boot (); + void reposition (); + void update (); + + void set_alerts (unsigned int _alerts, + unsigned int flags = 0, + VoicePlayer::Voice *_altitude_callout_voice = NULL); + void unset_alerts (unsigned int _alerts); + + inline void repeat_alert (unsigned int alert) { set_alerts(alert, ALERT_FLAG_REPEAT); } + inline void set_altitude_callout_alert (VoicePlayer::Voice *voice) { set_alerts(ALERT_MODE6_ALTITUDE_CALLOUT, 0, voice); } + }; + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::StateHandler //////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// class StateHandler { @@ -900,7 +902,7 @@ private: Timer pull_up_timer; Timer sink_rate_timer; - double sink_rate_tti; // time-to-impact in minutes + double sink_rate_tti; // time-to-impact in minutes double get_pull_up_bias (); bool is_pull_up (); @@ -915,12 +917,12 @@ private: public: typedef struct { - bool flap_override_bias; - int min_agl; - double (*pull_up_min_agl1) (double vs); - int pull_up_max_agl1; - double (*pull_up_min_agl2) (double vs); - int pull_up_max_agl2; + bool flap_override_bias; + int min_agl; + double (*pull_up_min_agl1) (double vs); + int pull_up_max_agl1; + double (*pull_up_min_agl2) (double vs); + int pull_up_max_agl2; } EnvelopesConfiguration; struct @@ -947,434 +949,435 @@ private: class ClosureRateFilter { - ///////////////////////////////////////////////////////////////////////// - // MK_VIII::Mode2Handler::ClosureRateFilter::PassFilter ///////////////// - ///////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + // MK_VIII::Mode2Handler::ClosureRateFilter::PassFilter ///////////////// + ///////////////////////////////////////////////////////////////////////// - class PassFilter - { - double a0; - double a1; - double b1; + class PassFilter + { + double a0; + double a1; + double b1; - double last_input; - double last_output; + double last_input; + double last_output; - public: - inline PassFilter (double _a0, double _a1, double _b1) - : a0(_a0), a1(_a1), b1(_b1), last_input(0.0), last_output(0.0) {} + public: + inline PassFilter (double _a0, double _a1, double _b1) + : a0(_a0), a1(_a1), b1(_b1), last_input(0.0), last_output(0.0) {} - inline double filter (double input) - { - last_output = a0 * input + a1 * last_input + b1 * last_output; - last_input = input; + inline double filter (double input) + { + last_output = a0 * input + a1 * last_input + b1 * last_output; + last_input = input; - return last_output; - } + return last_output; + } - inline void reset () - { - last_input = 0; - last_output = 0; - } - }; + inline void reset () + { + last_input = 0; + last_output = 0; + } + }; - ///////////////////////////////////////////////////////////////////////// - // MK_VIII::Mode2Handler::ClosureRateFilter (continued) ///////////////// - ///////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + // MK_VIII::Mode2Handler::ClosureRateFilter (continued) ///////////////// + ///////////////////////////////////////////////////////////////////////// - MK_VIII *mk; + MK_VIII *mk; - Timer timer; - Parameter last_ra; // last radio altitude - Parameter last_ba; // last barometric altitude - PassFilter ra_filter; // radio altitude rate filter - PassFilter ba_filter; // barometric altitude rate filter + Timer timer; + Parameter last_ra; // last radio altitude + Parameter last_ba; // last barometric altitude + PassFilter ra_filter; // radio altitude rate filter + PassFilter ba_filter; // barometric altitude rate filter - double limit_radio_altitude_rate (double r); + double limit_radio_altitude_rate (double r); public: - Parameter output; + Parameter output; - inline ClosureRateFilter (MK_VIII *device) - : mk(device), - ra_filter(0.05, 0, 0.95), // low-pass filter - ba_filter(0.93, -0.93, 0.86) {} // high-pass-filter + inline ClosureRateFilter (MK_VIII *device) + : mk(device), + ra_filter(0.05, 0, 0.95), // low-pass filter + ba_filter(0.93, -0.93, 0.86) {} // high-pass-filter - void init (); - void update (); + void init (); + void update (); }; - /////////////////////////////////////////////////////////////////////////// - // MK_VIII::Mode2Handler (continued) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + // MK_VIII::Mode2Handler (continued) ////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// - MK_VIII *mk; + MK_VIII *mk; - ClosureRateFilter closure_rate_filter; + ClosureRateFilter closure_rate_filter; - Timer takeoff_timer; - Timer pull_up_timer; + Timer takeoff_timer; + Timer pull_up_timer; - double a_start_time; - Timer a_altitude_gain_timer; - double a_altitude_gain_alt; + double a_start_time; + Timer a_altitude_gain_timer; + double a_altitude_gain_alt; - void check_pull_up (unsigned int preface_alert, unsigned int alert); + void check_pull_up (unsigned int preface_alert, unsigned int alert); - bool b_conditions (); + bool b_conditions (); - bool is_a (); - bool is_b (); + bool is_a (); + bool is_b (); - void update_a (); - void update_b (); + void update_a (); + void update_b (); - public: - typedef struct + public: + typedef struct + { + int airspeed1; + int airspeed2; + } Configuration; + + const Configuration *conf; + + inline Mode2Handler (MK_VIII *device) + : mk(device), closure_rate_filter(device) {} + + void boot (); + void power_off (); + void leave_ground (); + void enter_takeoff (); + void update (); + }; + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::Mode3Handler //////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class Mode3Handler { - int airspeed1; - int airspeed2; - } Configuration; + MK_VIII *mk; - const Configuration *conf; + bool armed; + bool has_descent_alt; + double descent_alt; + double bias; - inline Mode2Handler (MK_VIII *device) - : mk(device), closure_rate_filter(device) {} + double max_alt_loss (double _bias); + double get_bias (double initial_bias, double alt_loss); + bool is (double *alt_loss); - void boot (); - void power_off (); - void leave_ground (); - void enter_takeoff (); - void update (); - }; + public: + typedef struct + { + int min_agl; + int (*max_agl) (bool flap_override); + double (*max_alt_loss) (bool flap_override, double agl); + } Configuration; - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::Mode3Handler //////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// + const Configuration *conf; - class Mode3Handler - { - MK_VIII *mk; + inline Mode3Handler (MK_VIII *device) + : mk(device), armed(false), has_descent_alt(false) {} - bool armed; - bool has_descent_alt; - double descent_alt; - double bias; + void enter_takeoff (); + void update (); + }; - double max_alt_loss (double _bias); - double get_bias (double initial_bias, double alt_loss); - bool is (double *alt_loss); + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::Mode4Handler //////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// - public: - typedef struct + class Mode4Handler { - int min_agl; - int (*max_agl) (bool flap_override); - double (*max_alt_loss) (bool flap_override, double agl); - } Configuration; + public: + typedef struct + { + int airspeed1; + int airspeed2; + int min_agl1; + double (*min_agl2) (double airspeed); + int min_agl3; + } EnvelopesConfiguration; - const Configuration *conf; + typedef struct + { + const EnvelopesConfiguration *ac; + const EnvelopesConfiguration *b; + } ModesConfiguration; - inline Mode3Handler (MK_VIII *device) - : mk(device), armed(false), has_descent_alt(false) {} + struct + { + VoicePlayer::Voice *voice_too_low_gear; + const ModesConfiguration *modes; + } conf; - void enter_takeoff (); - void update (); - }; + inline Mode4Handler (MK_VIII *device) + : mk(device),ab_bias(0.0),ab_expanded_bias(0.0),c_bias(0.0) {} - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::Mode4Handler //////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// + double get_upper_agl (const EnvelopesConfiguration *c); + void update (); - class Mode4Handler - { - public: - typedef struct + private: + MK_VIII *mk; + + double ab_bias; + double ab_expanded_bias; + double c_bias; + + const EnvelopesConfiguration *get_ab_envelope (); + double get_bias (double initial_bias, double min_agl); + void handle_alert (unsigned int alert, double min_agl, double *bias); + + void update_ab (); + void update_ab_expanded (); + void update_c (); + }; + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::Mode5Handler //////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class Mode5Handler { - int airspeed1; - int airspeed2; - int min_agl1; - double (*min_agl2) (double airspeed); - int min_agl3; - } EnvelopesConfiguration; + MK_VIII *mk; - typedef struct + Timer hard_timer; + Timer soft_timer; + + double soft_bias; + + bool is_hard (); + bool is_soft (double bias); + + double get_soft_bias (double initial_bias); + + void update_hard (bool is); + void update_soft (bool is); + + public: + inline Mode5Handler (MK_VIII *device) + : mk(device), soft_bias(0.0) {} + + void update (); + }; + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::Mode6Handler //////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + class Mode6Handler { - const EnvelopesConfiguration *ac; - const EnvelopesConfiguration *b; - } ModesConfiguration; + public: + // keep in sync with altitude_callout_definitions[] + typedef enum + { + ALTITUDE_CALLOUT_2500, + ALTITUDE_CALLOUT_1000, + ALTITUDE_CALLOUT_500, + ALTITUDE_CALLOUT_400, + ALTITUDE_CALLOUT_300, + ALTITUDE_CALLOUT_200, + ALTITUDE_CALLOUT_100, + ALTITUDE_CALLOUT_50, + ALTITUDE_CALLOUT_40, + ALTITUDE_CALLOUT_30, + ALTITUDE_CALLOUT_20, + ALTITUDE_CALLOUT_10 + } AltitudeCallout; - struct - { - VoicePlayer::Voice *voice_too_low_gear; - const ModesConfiguration *modes; - } conf; + typedef bool (*BankAnglePredicate) (Parameter *agl, + double abs_roll_deg, + bool ap_engaged); - inline Mode4Handler (MK_VIII *device) - : mk(device),ab_bias(0.0),ab_expanded_bias(0.0),c_bias(0.0) {} + struct + { + bool retard_enabled; + bool minimums_above_100_enabled; + bool minimums_enabled; + bool smart_500_enabled; + VoicePlayer::Voice *above_field_voice; - double get_upper_agl (const EnvelopesConfiguration *c); - void update (); + unsigned int altitude_callouts_enabled; + bool bank_angle_enabled; + BankAnglePredicate is_bank_angle; + } conf; - private: - MK_VIII *mk; + static const int altitude_callout_definitions[]; - double ab_bias; - double ab_expanded_bias; - double c_bias; + inline Mode6Handler (MK_VIII *device) + : mk(device) {} - const EnvelopesConfiguration *get_ab_envelope (); - double get_bias (double initial_bias, double min_agl); - void handle_alert (unsigned int alert, double min_agl, double *bias); + void boot (); + void power_off (); + void enter_takeoff (); + void leave_takeoff (); + void set_volume (float volume); + bool altitude_callouts_enabled (); + void update (); - void update_ab (); - void update_ab_expanded (); - void update_c (); - }; + private: + MK_VIII *mk; - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::Mode5Handler //////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// + bool last_decision_height; + bool last_decision_height_100; + Parameter last_radio_altitude; + Parameter last_altitude_above_field; - class Mode5Handler - { - MK_VIII *mk; + bool altitude_callouts_issued[n_altitude_callouts]; + bool minimums_issued; + bool minimums_above_100_issued; + bool above_field_issued; + bool throttle_retarded; - Timer hard_timer; - Timer soft_timer; + Timer runway_timer; + Parameter has_runway; - double soft_bias; + struct + { + double elevation; // elevation in feet + } runway; - bool is_hard (); - bool is_soft (double bias); + void reset_minimums (); + void reset_altitude_callouts (); + bool is_playing_altitude_callout (); + bool is_near_minimums (double callout); + bool is_outside_band (double elevation, double callout); + bool inhibit_smart_500 (); - double get_soft_bias (double initial_bias); + void update_minimums (); + void update_altitude_callouts (); - void update_hard (bool is); - void update_soft (bool is); + bool test_runway (const FGRunway *_runway); + bool test_airport (const FGAirport *airport); + void update_runway (); - public: - inline Mode5Handler (MK_VIII *device) - : mk(device), soft_bias(0.0) {} - - void update (); - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::Mode6Handler //////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - class Mode6Handler - { - public: - // keep in sync with altitude_callout_definitions[] - typedef enum - { - ALTITUDE_CALLOUT_2500, - ALTITUDE_CALLOUT_1000, - ALTITUDE_CALLOUT_500, - ALTITUDE_CALLOUT_400, - ALTITUDE_CALLOUT_300, - ALTITUDE_CALLOUT_200, - ALTITUDE_CALLOUT_100, - ALTITUDE_CALLOUT_50, - ALTITUDE_CALLOUT_40, - ALTITUDE_CALLOUT_30, - ALTITUDE_CALLOUT_20, - ALTITUDE_CALLOUT_10 - } AltitudeCallout; - - typedef bool (*BankAnglePredicate) (Parameter *agl, - double abs_roll_deg, - bool ap_engaged); - - struct - { - bool retard_enabled; - bool minimums_above_100_enabled; - bool minimums_enabled; - bool smart_500_enabled; - VoicePlayer::Voice *above_field_voice; - - unsigned int altitude_callouts_enabled; - bool bank_angle_enabled; - BankAnglePredicate is_bank_angle; - } conf; - - static const int altitude_callout_definitions[]; - - inline Mode6Handler (MK_VIII *device) - : mk(device) {} - - void boot (); - void power_off (); - void enter_takeoff (); - void leave_takeoff (); - void set_volume (float volume); - bool altitude_callouts_enabled (); - void update (); - - private: - MK_VIII *mk; - - bool last_decision_height; - bool last_decision_height_100; - Parameter last_radio_altitude; - Parameter last_altitude_above_field; - - bool altitude_callouts_issued[n_altitude_callouts]; - bool minimums_issued; - bool minimums_above_100_issued; - bool above_field_issued; - bool throttle_retarded; - - Timer runway_timer; - Parameter has_runway; - - struct - { - double elevation; // elevation in feet - } runway; - - void reset_minimums (); - void reset_altitude_callouts (); - bool is_playing_altitude_callout (); - bool is_near_minimums (double callout); - bool is_outside_band (double elevation, double callout); - bool inhibit_smart_500 (); - - void update_minimums (); - void update_altitude_callouts (); - - bool test_runway (const FGRunway *_runway); - bool test_airport (const FGAirport *airport); - void update_runway (); - - void get_altitude_above_field (Parameter *parameter); - void update_above_field_callout (); - - bool is_bank_angle (double abs_roll_angle, double bias); - bool is_high_bank_angle (); - unsigned int get_bank_angle_alerts (); - void update_bank_angle (); + void get_altitude_above_field (Parameter *parameter); + void update_above_field_callout (); - class AirportFilter : public FGAirport::AirportFilter - { - public: - AirportFilter(Mode6Handler *s) - : self(s) {} - - virtual bool passAirport(FGAirport *a) const; - - virtual FGPositioned::Type maxType() const { - return FGPositioned::AIRPORT; - } - - private: - Mode6Handler* self; + bool is_bank_angle (double abs_roll_angle, double bias); + bool is_high_bank_angle (); + unsigned int get_bank_angle_alerts (); + void update_bank_angle (); + + class AirportFilter : public FGAirport::AirportFilter + { + public: + AirportFilter(Mode6Handler *s) + : self(s) {} + + virtual bool passAirport(FGAirport *a) const; + + virtual FGPositioned::Type maxType() const { + return FGPositioned::AIRPORT; + } + + private: + Mode6Handler* self; + }; }; - }; - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII::TCFHandler ////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII::TCFHandler ////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// - class TCFHandler - { - typedef struct + class TCFHandler { - SGGeod position; // position of threshold - double heading; // runway heading - } RunwayEdge; + typedef struct + { + SGGeod position; // position of threshold + double heading; // runway heading + } RunwayEdge; - MK_VIII *mk; + MK_VIII *mk; - static const double k; + static const double k; - Timer runway_timer; - bool has_runway; + Timer runway_timer; + bool has_runway; - struct - { - SGGeod center; // center point - double elevation; // elevation in feet - double half_length; // runway half length, in nautical miles - double half_width_m; // runway half width, in meters - RunwayEdge edge; // runway threshold - SGVec3d bias_points[2]; // vertices of the bias area - } runway; + struct + { + SGGeod center; // center point + double elevation; // elevation in feet + double half_length; // runway half length, in nautical miles + double half_width_m; // runway half width, in meters + RunwayEdge edge; // runway threshold + SGVec3d bias_points[2]; // vertices of the bias area + } runway; - double bias; - double *reference; - double initial_value; + double bias; + double *reference; + double initial_value; - void update_runway (); + void update_runway (); - bool is_inside_edge_triangle (RunwayEdge *edge); - bool is_inside_bias_area (); + bool is_inside_edge_triangle (RunwayEdge *edge); + bool is_inside_bias_area (); - bool is_tcf (); - bool is_rfcf (); + bool is_tcf (); + bool is_rfcf (); - class AirportFilter : public FGAirport::AirportFilter - { - public: - AirportFilter(MK_VIII *device) + class AirportFilter : public FGAirport::AirportFilter + { + public: + AirportFilter(MK_VIII *device) + : mk(device) {} + + virtual bool passAirport(FGAirport *a) const; + private: + MK_VIII* mk; + }; + + public: + struct + { + bool enabled; + } conf; + + inline TCFHandler (MK_VIII *device) : mk(device) {} - - virtual bool passAirport(FGAirport *a) const; - private: - MK_VIII* mk; + + void update (); }; - public: + + ///////////////////////////////////////////////////////////////////////////// + // MK_VIII (continued) ////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + std::string name; + int num; + + PowerHandler power_handler; + SystemHandler system_handler; + ConfigurationModule configuration_module; + FaultHandler fault_handler; + IOHandler io_handler; + VoicePlayer voice_player; + SelfTestHandler self_test_handler; + AlertHandler alert_handler; + StateHandler state_handler; + Mode1Handler mode1_handler; + Mode2Handler mode2_handler; + Mode3Handler mode3_handler; + Mode4Handler mode4_handler; + Mode5Handler mode5_handler; + Mode6Handler mode6_handler; + TCFHandler tcf_handler; + struct { - bool enabled; + int runway_database; } conf; - inline TCFHandler (MK_VIII *device) - : mk(device) {} - - void update (); - }; - - ///////////////////////////////////////////////////////////////////////////// - // MK_VIII (continued) ////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////// - - std::string name; - int num; - - PowerHandler power_handler; - SystemHandler system_handler; - ConfigurationModule configuration_module; - FaultHandler fault_handler; - IOHandler io_handler; - VoicePlayer voice_player; - SelfTestHandler self_test_handler; - AlertHandler alert_handler; - StateHandler state_handler; - Mode1Handler mode1_handler; - Mode2Handler mode2_handler; - Mode3Handler mode3_handler; - Mode4Handler mode4_handler; - Mode5Handler mode5_handler; - Mode6Handler mode6_handler; - TCFHandler tcf_handler; - - struct - { - int runway_database; - } conf; - public: - MK_VIII (SGPropertyNode *node); + MK_VIII (SGPropertyNode *node); - virtual void init (); - virtual void bind (); - virtual void unbind (); - virtual void update (double dt); + virtual void init (); + virtual void bind (); + virtual void unbind (); + virtual void update (double dt); }; #ifdef _MSC_VER