diff --git a/src/Instrumentation/mk_viii.cxx b/src/Instrumentation/mk_viii.cxx index b293c83a5..7be9ec68d 100644 --- a/src/Instrumentation/mk_viii.cxx +++ b/src/Instrumentation/mk_viii.cxx @@ -170,6 +170,7 @@ MK_VIII::PropertiesHandler::init () 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); @@ -567,16 +568,18 @@ MK_VIII::ConfigurationModule::read_altitude_callouts (int value) { enum { - MINIMUMS = -1, - SMART_500 = -2, - FIELD_500 = -3, - FIELD_500_ABOVE = -4 + 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[13]; + int callouts[16]; } values[] = { { 0, { MINIMUMS, SMART_500, 200, 100, 50, 40, 30, 20, 10, 0 } }, { 1, { MINIMUMS, SMART_500, 200, 0 } }, @@ -595,22 +598,35 @@ MK_VIII::ConfigurationModule::read_altitude_callouts (int value) { 14, { MINIMUMS, 100, 0 } }, { 15, { MINIMUMS, 200, 100, 0 } }, { 100, { FIELD_500, 0 } }, - { 101, { FIELD_500_ABOVE, 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 } }, }; - unsigned i; - + 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 (i = 0; i < n_elements(values); i++) + 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: mk->mode6_handler.conf.minimums_enabled = true; break; @@ -1319,6 +1335,10 @@ MK_VIII::IOHandler::update_inputs () 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(); @@ -1646,6 +1666,7 @@ MK_VIII::IOHandler::update_mode6_callouts_discrete_2 () { 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) } @@ -2135,7 +2156,9 @@ MK_VIII::VoicePlayer::init () make_voice(&voices.glideslope_inop, "glideslope-inop"); make_voice(&voices.gpws_inop, "gpws-inop"); make_voice(&voices.hard_glideslope, "glideslope", "glideslope", 3.0); + make_voice(&voices.retard, "retard"); make_voice(&voices.minimums, "minimums"); + make_voice(&voices.minimums_100, "100-above"); make_voice(&voices.minimums_minimums, "minimums", "minimums"); make_voice(&voices.pull_up, "pull-up"); make_voice(&voices.sink_rate, "sink-rate"); @@ -2355,6 +2378,11 @@ MK_VIII::SelfTestHandler::run () 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) @@ -2367,10 +2395,10 @@ MK_VIII::SelfTestHandler::run () } for (unsigned i = 0; i < n_altitude_callouts; i++) if (! was_here_offset(i)) - { + { if (mk->mode6_handler.conf.altitude_callouts_enabled & (1<<i)) return play(mk_altitude_voice(i)); - } + } if (! was_here()) { @@ -2641,6 +2669,16 @@ MK_VIII::AlertHandler::update () if (! has_old_alerts(ALERT_MODE6_MINIMUMS)) mk->voice_player.play(mk_voice(minimums_minimums)); } + 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)); + } + 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); + } 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)) @@ -3807,12 +3845,13 @@ MK_VIII::Mode5Handler::update () // keep sorted in descending order const int MK_VIII::Mode6Handler::altitude_callout_definitions[] = - { 1000, 500, 400, 300, 200, 100, 50, 40, 30, 20, 10 }; + { 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; } void @@ -3820,6 +3859,7 @@ MK_VIII::Mode6Handler::reset_altitude_callouts () { for (unsigned i = 0; i < n_altitude_callouts; i++) altitude_callouts_issued[i] = false; + throttle_retarded = false; } bool @@ -3967,28 +4007,47 @@ MK_VIII::Mode6Handler::update_minimums () && conf.minimums_enabled && ! minimums_issued && mk_dinput(landing_gear) - && mk_dinput(decision_height) && ! last_decision_height) - { - minimums_issued = true; + { + 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_set_alerts(mk_alert(MODE6_MINIMUMS)); - } + 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); + + 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); } void @@ -3997,8 +4056,23 @@ MK_VIII::Mode6Handler::update_altitude_callouts () if (! mk->io_handler.gpws_inhibit() && is_playing_altitude_callout()) goto end; - if (! mk->io_handler.gpws_inhibit() - && ! mk->state_handler.ground // [1] + if (! mk->io_handler.gpws_inhibit()) + { + if (mk->mode6_handler.conf.retard_enabled && + (!throttle_retarded)&& + (mk_data(radio_altitude).get() < 25)) + { + 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<<i)) @@ -4023,6 +4097,7 @@ MK_VIII::Mode6Handler::update_altitude_callouts () goto end; } } + } mk_unset_alerts(mk_alert(MODE6_ALTITUDE_CALLOUT)); diff --git a/src/Instrumentation/mk_viii.hxx b/src/Instrumentation/mk_viii.hxx index a67ea474a..4c807e1af 100644 --- a/src/Instrumentation/mk_viii.hxx +++ b/src/Instrumentation/mk_viii.hxx @@ -55,7 +55,7 @@ class SGSampleGroup; class MK_VIII : public SGSubsystem { // keep in sync with Mode6Handler::altitude_callout_definitions[] - static const unsigned n_altitude_callouts = 11; + static const unsigned n_altitude_callouts = 12; ///////////////////////////////////////////////////////////////////////////// // MK_VIII::Parameter /////////////////////////////////////////////////////// @@ -164,6 +164,7 @@ class MK_VIII : public SGSubsystem 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; @@ -460,6 +461,7 @@ public: 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 @@ -686,7 +688,9 @@ public: 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; @@ -818,6 +822,7 @@ private: 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, @@ -826,7 +831,10 @@ private: ALERT_MODE6_LOW_BANK_ANGLE_3 = 1 << 22, ALERT_MODE6_HIGH_BANK_ANGLE_3 = 1 << 23, - ALERT_TCF_TOO_LOW_TERRAIN = 1 << 24 + ALERT_TCF_TOO_LOW_TERRAIN = 1 << 24, + + ALERT_MODE6_MINIMUMS_100 = 1 << 28, + ALERT_MODE6_RETARD = 1 << 29, }; enum @@ -1163,6 +1171,7 @@ private: // keep in sync with altitude_callout_definitions[] typedef enum { + ALTITUDE_CALLOUT_2500, ALTITUDE_CALLOUT_1000, ALTITUDE_CALLOUT_500, ALTITUDE_CALLOUT_400, @@ -1209,13 +1218,16 @@ private: private: MK_VIII *mk; - bool last_decision_height; - Parameter<double> last_radio_altitude; - Parameter<double> last_altitude_above_field; + bool last_decision_height; + bool last_decision_height_100; + Parameter<double> last_radio_altitude; + Parameter<double> 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<bool> has_runway;