X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInstrumentation%2Fmk_viii.cxx;h=9b0ee2b480428d5d32f0c16010907d18e914071d;hb=d15d2ad2703e0572e3b9a24d238d6089be1ec6b9;hp=3bbdc4235d73c902f64e4300a0b5a7a3b27dff67;hpb=c9e8112a816ebb423442d87dae92b7eb978e317f;p=flightgear.git diff --git a/src/Instrumentation/mk_viii.cxx b/src/Instrumentation/mk_viii.cxx old mode 100755 new mode 100644 index 3bbdc4235..9b0ee2b48 --- a/src/Instrumentation/mk_viii.cxx +++ b/src/Instrumentation/mk_viii.cxx @@ -16,7 +16,7 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. // /////////////////////////////////////////////////////////////////////////////// // @@ -70,17 +70,22 @@ #include #include #include +#include #include using std::string; -#include "Airports/runways.hxx" -#include "Airports/simple.hxx" -#ifndef _MSC_VER -# include "Include/version.h" +#include +#include + +#if defined( HAVE_VERSION_H ) && HAVE_VERSION_H +# include +#else +# include #endif -#include "Main/fg_props.hxx" -#include "Main/globals.hxx" + +#include
+#include
#include "instrument_mgr.hxx" #include "mk_viii.hxx" @@ -182,6 +187,9 @@ MK_VIII::PropertiesHandler::init () 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); @@ -203,17 +211,6 @@ MK_VIII::PropertiesHandler::init () mk_node(vs) = fgGetNode("/velocities/vertical-speed-fps", true); } -void -MK_VIII::PropertiesHandler::unbind () -{ - vector::iterator iter; - - for (iter = tied_properties.begin(); iter != tied_properties.end(); iter++) - (*iter)->untie(); - - tied_properties.clear(); -} - /////////////////////////////////////////////////////////////////////////////// // PowerHandler /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -360,6 +357,7 @@ MK_VIII::SystemHandler::update () if (replay_state != last_replay_state) { mk->alert_handler.reposition(); + mk->io_handler.reposition(); last_replay_state = replay_state; state = STATE_REPOSITION; @@ -549,7 +547,7 @@ MK_VIII::ConfigurationModule::read_aircraft_mode_type_select (int value) { 255, &m1_t1, &m2_t1, &m3_t1, &m4_t1, m6_t2, &f_fast, 2000 } }; - for (int i = 0; i < n_elements(aircraft_types); i++) + 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; @@ -625,7 +623,7 @@ MK_VIII::ConfigurationModule::read_altitude_callouts (int value) { 101, { FIELD_500_ABOVE, 0 } } }; - int i; + unsigned i; mk->mode6_handler.conf.minimums_enabled = false; mk->mode6_handler.conf.smart_500_enabled = false; @@ -656,7 +654,7 @@ MK_VIII::ConfigurationModule::read_altitude_callouts (int value) break; default: - for (int k = 0; k < n_altitude_callouts; k++) + 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[k] = true; break; @@ -712,7 +710,7 @@ MK_VIII::ConfigurationModule::read_options_select_group_1 (int value) bool MK_VIII::ConfigurationModule::read_radio_altitude_input_select (int value) { - // unimplemented + mk->io_handler.conf.altitude_source = value; return (value >= 0 && value <= 4) || (value >= 251 && value <= 255); } @@ -732,7 +730,10 @@ MK_VIII::ConfigurationModule::read_navigation_input_select (int value) bool MK_VIII::ConfigurationModule::read_attitude_input_select (int value) { - // unimplemented + 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; } @@ -773,7 +774,7 @@ MK_VIII::ConfigurationModule::read_input_output_discrete_type_select (int value) { 255, { false, false }, true, false, true } }; - for (int i = 0; i < n_elements(io_types); i++) + 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; @@ -801,7 +802,7 @@ MK_VIII::ConfigurationModule::read_audio_output_level (int value) { 4, -24 } }; - for (int i = 0; i < n_elements(values); i++) + 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)); @@ -979,6 +980,11 @@ MK_VIII::IOHandler::TerrainClearanceFilter::update (double agl) // [PILOT] page 20 specifies that the terrain clearance is equal to // 75% of the radio altitude, averaged over the previous 15 seconds. + // 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; // remove samples older than 15 seconds @@ -992,8 +998,10 @@ MK_VIII::IOHandler::TerrainClearanceFilter::update (double agl) double new_value = 0; if (samples.size() > 0) { + // 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 += (*iter).value; new_value /= samples.size(); } new_value *= 0.75; @@ -1009,6 +1017,7 @@ MK_VIII::IOHandler::TerrainClearanceFilter::reset () { samples.clear(); value = 0; + last_update = -1.0; } MK_VIII::IOHandler::IOHandler (MK_VIII *device) @@ -1049,6 +1058,7 @@ MK_VIII::IOHandler::boot () mk_doutput(glideslope_cancel) = power_saved.glideslope_cancel; altitude_samples.clear(); + reset_terrain_clearance(); } void @@ -1144,9 +1154,21 @@ MK_VIII::IOHandler::update_inputs () 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. - double agl = mk_node(altitude_agl)->getDoubleValue(); mk_ainput(radio_altitude).set(SG_MAX2(0.0, agl)); } if (mk_ainput_feed(glideslope_deviation)) @@ -1164,11 +1186,20 @@ MK_VIII::IOHandler::update_inputs () } 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(); } + else + { + // use simulator source + mk_ainput(roll_angle).set(mk_node(orientation_roll)->getDoubleValue()); + } + } if (mk_ainput_feed(localizer_deviation)) { if (mk_node(nav0_serviceable)->getBoolValue() @@ -1335,6 +1366,12 @@ MK_VIII::IOHandler::reset_terrain_clearance () update_terrain_clearance(); } +void +MK_VIII::IOHandler::reposition () +{ + reset_terrain_clearance(); +} + void MK_VIII::IOHandler::handle_input_fault (bool test, FaultHandler::Fault fault) { @@ -1550,7 +1587,7 @@ MK_VIII::IOHandler::update_egpws_alert_discrete_1 () { 19, mk_voice(minimums_minimums) } }; - for (int i = 0; i < n_elements(voices); i++) + 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; @@ -1584,7 +1621,7 @@ MK_VIII::IOHandler::update_egpwc_logic_discretes () { 25, mk_alert(MODE5_SOFT) | mk_alert(MODE5_HARD) } }; - for (int i = 0; i < n_elements(logic); i++) + 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; } @@ -1610,7 +1647,7 @@ MK_VIII::IOHandler::update_mode6_callouts_discrete_1 () { 25, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_300) } }; - for (int i = 0; i < n_elements(voices); i++) + 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; @@ -1639,7 +1676,7 @@ MK_VIII::IOHandler::update_mode6_callouts_discrete_2 () { 23, mk_voice(five_hundred_above) } }; - for (int i = 0; i < n_elements(voices); i++) + 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; @@ -1811,7 +1848,8 @@ MK_VIII::IOHandler::tie_input (SGPropertyNode *node, bool *input, bool *feed) { - mk->properties_handler.tie(node, (string("inputs/discretes/") + name).c_str(), RawValueMethodsData(*this, input, &MK_VIII::IOHandler::get_discrete_input, &MK_VIII::IOHandler::set_discrete_input)); + 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)); } @@ -2049,7 +2087,7 @@ MK_VIII::IOHandler::present_status () "TCF INPUTS INVALID" }; - for (int i = 0; i < n_elements(fault_names); i++) + for (size_t i = 0; i < n_elements(fault_names); i++) if (mk->fault_handler.faults[i]) present_status_subitem(fault_names[i]); } @@ -2075,7 +2113,7 @@ MK_VIII::IOHandler::present_status () "VOLUME SELECT" }; - for (int i = 0; i < n_elements(category_names); i++) + for (size_t i = 0; i < n_elements(category_names); i++) { std::ostringstream value; value << "= " << mk->configuration_module.effective_categories[i]; @@ -2097,285 +2135,50 @@ MK_VIII::IOHandler::set_present_status (bool value) /////////////////////////////////////////////////////////////////////////////// -// VoicePlayer //////////////////////////////////////////////////////////////// +// MK_VIII::VoicePlayer /////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -void -MK_VIII::VoicePlayer::Speaker::bind (SGPropertyNode *node) -{ - // uses xmlsound property names - tie(node, "volume", &volume); - tie(node, "pitch", &pitch); - tie(node, "position/x", &position[0]); - tie(node, "position/y", &position[1]); - tie(node, "position/z", &position[2]); - tie(node, "orientation/x", &orientation[0]); - tie(node, "orientation/y", &orientation[1]); - tie(node, "orientation/z", &orientation[2]); - tie(node, "orientation/inner-cone", &inner_cone); - tie(node, "orientation/outer-cone", &outer_cone); - tie(node, "reference-dist", &reference_dist); - tie(node, "max-dist", &max_dist); -} - -void -MK_VIII::VoicePlayer::Speaker::update_configuration () -{ - map::iterator iter; - for (iter = player->samples.begin(); iter != player->samples.end(); iter++) - { - SGSoundSample *sample = (*iter).second; - - sample->set_pitch(pitch); - sample->set_offset_pos(position); - sample->set_orientation(orientation, - inner_cone, - outer_cone, - outer_gain); - sample->set_reference_dist(reference_dist); - sample->set_max_dist(max_dist); - } - - if (player->voice) - player->voice->volume_changed(); -} - -MK_VIII::VoicePlayer::Voice::~Voice () -{ - for (iter = elements.begin(); iter != elements.end(); iter++) - delete *iter; // we owned the element - elements.clear(); -} - -void -MK_VIII::VoicePlayer::Voice::play () -{ - iter = elements.begin(); - element = *iter; - - element->play(get_volume()); -} - -void -MK_VIII::VoicePlayer::Voice::stop (bool now) -{ - if (element) - { - if (now || element->silence) - { - element->stop(); - element = NULL; - } - else - iter = elements.end() - 1; // stop after the current element finishes - } -} - -void -MK_VIII::VoicePlayer::Voice::set_volume (double _volume) -{ - volume = _volume; - volume_changed(); -} - -void -MK_VIII::VoicePlayer::Voice::volume_changed () -{ - if (element) - element->set_volume(get_volume()); -} - -void -MK_VIII::VoicePlayer::Voice::update () -{ - if (element) - { - if (! element->is_playing()) - { - if (++iter == elements.end()) - element = NULL; - else - { - element = *iter; - element->play(get_volume()); - } - } - } -} - -MK_VIII::VoicePlayer::~VoicePlayer () -{ - vector::iterator iter1; - for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++) - delete *iter1; - _voices.clear(); - -/* sound mgr already destroyed - samples already deleted - map::iterator iter2; - for (iter2 = samples.begin(); iter2 != samples.end(); iter2++) - { - bool status = globals->get_soundmgr()->remove((*iter2).first); - assert(status); - } -*/ - samples.clear(); -} - void MK_VIII::VoicePlayer::init () { -#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay" - - make_voice(&voices.application_data_base_failed, "application-data-base-failed"); - make_voice(&voices.bank_angle, "bank-angle"); - make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle"); - make_voice(&voices.bank_angle_bank_angle_3, "bank-angle", "bank-angle", 3.0); - make_voice(&voices.bank_angle_inop, "bank-angle-inop"); - make_voice(&voices.bank_angle_pause_bank_angle, "bank-angle", STDPAUSE, "bank-angle"); - make_voice(&voices.bank_angle_pause_bank_angle_3, "bank-angle", STDPAUSE, "bank-angle", 3.0); - make_voice(&voices.callouts_inop, "callouts-inop"); - make_voice(&voices.configuration_type_invalid, "configuration-type-invalid"); - make_voice(&voices.dont_sink, "dont-sink"); - make_voice(&voices.dont_sink_pause_dont_sink, "dont-sink", STDPAUSE, "dont-sink"); - make_voice(&voices.five_hundred_above, "500-above"); - make_voice(&voices.glideslope, "glideslope"); - 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.minimums, "minimums"); - make_voice(&voices.minimums_minimums, "minimums", "minimums"); - make_voice(&voices.pull_up, "pull-up"); - make_voice(&voices.sink_rate, "sink-rate"); - make_voice(&voices.sink_rate_pause_sink_rate, "sink-rate", STDPAUSE, "sink-rate"); - make_voice(&voices.soft_glideslope, new Voice::SampleElement(get_sample("glideslope"), modify_amplitude(1.0, -6))); - make_voice(&voices.terrain, "terrain"); - make_voice(&voices.terrain_pause_terrain, "terrain", STDPAUSE, "terrain"); - make_voice(&voices.too_low_flaps, "too-low-flaps"); - make_voice(&voices.too_low_gear, "too-low-gear"); - make_voice(&voices.too_low_terrain, "too-low-terrain"); - - for (int i = 0; i < n_altitude_callouts; i++) - { - std::ostringstream name; - name << "altitude-" << mk->mode6_handler.altitude_callout_definitions[i]; - make_voice(&voices.altitude_callouts[i], name.str().c_str()); - } - - speaker.update_configuration(); -} - -SGSoundSample * -MK_VIII::VoicePlayer::get_sample (const char *name) -{ - std::ostringstream refname; - refname << mk->name << "[" << mk->num << "]" << "/" << name; - - SGSoundMgr *soundmgr = globals->get_soundmgr(); - if (soundmgr->is_working() == false) - { - return NULL; - } - - SGSoundSample *sample = soundmgr->find(refname.str()); - if (! sample) - { - SGPath sample_path(globals->get_fg_root()); - sample_path.append("Sounds/mk-viii"); - - string filename = string(name) + ".wav"; - try - { - sample = new SGSoundSample(sample_path.c_str(), filename.c_str()); - } - catch (const sg_exception &e) - { - SG_LOG(SG_INSTR, SG_ALERT, "Error loading MK VIII sound sample \"" + filename + "\": " + e.getFormattedMessage()); - exit(1); - } - - soundmgr->add(sample, refname.str()); - samples[refname.str()] = sample; - } - - return sample; -} - -void -MK_VIII::VoicePlayer::play (Voice *_voice, unsigned int flags) -{ - if (test_bits(flags, PLAY_NOW) || ! voice || voice->element->silence) - { - if (voice) - voice->stop(true); - - voice = _voice; - looped = test_bits(flags, PLAY_LOOPED); - - next_voice = NULL; - next_looped = false; - - voice->play(); - } - else - { - next_voice = _voice; - next_looped = test_bits(flags, PLAY_LOOPED); - } -} - -void -MK_VIII::VoicePlayer::stop (unsigned int flags) -{ - if (voice) - { - voice->stop(test_bits(flags, STOP_NOW)); - if (voice->element) - looped = false; - else - voice = NULL; - next_voice = NULL; - } -} - -void -MK_VIII::VoicePlayer::set_volume (double _volume) -{ - volume = _volume; - if (voice) - voice->volume_changed(); -} - -void -MK_VIII::VoicePlayer::update () -{ - if (voice) - { - voice->update(); - - if (next_voice) - { - if (! voice->element || voice->element->silence) - { - voice = next_voice; - looped = next_looped; - - next_voice = NULL; - next_looped = false; - - voice->play(); - } - } - else - { - if (! voice->element) - { - if (looped) - voice->play(); - else - voice = NULL; - } - } - } + FGVoicePlayer::init(); + +#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay" + make_voice(&voices.application_data_base_failed, "application-data-base-failed"); + make_voice(&voices.bank_angle, "bank-angle"); + make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle"); + make_voice(&voices.bank_angle_bank_angle_3, "bank-angle", "bank-angle", 3.0); + make_voice(&voices.bank_angle_inop, "bank-angle-inop"); + make_voice(&voices.bank_angle_pause_bank_angle, "bank-angle", STDPAUSE, "bank-angle"); + make_voice(&voices.bank_angle_pause_bank_angle_3, "bank-angle", STDPAUSE, "bank-angle", 3.0); + make_voice(&voices.callouts_inop, "callouts-inop"); + make_voice(&voices.configuration_type_invalid, "configuration-type-invalid"); + make_voice(&voices.dont_sink, "dont-sink"); + make_voice(&voices.dont_sink_pause_dont_sink, "dont-sink", STDPAUSE, "dont-sink"); + make_voice(&voices.five_hundred_above, "500-above"); + make_voice(&voices.glideslope, "glideslope"); + 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.minimums, "minimums"); + make_voice(&voices.minimums_minimums, "minimums", "minimums"); + make_voice(&voices.pull_up, "pull-up"); + make_voice(&voices.sink_rate, "sink-rate"); + make_voice(&voices.sink_rate_pause_sink_rate, "sink-rate", STDPAUSE, "sink-rate"); + make_voice(&voices.soft_glideslope, new Voice::SampleElement(get_sample("glideslope"), modify_amplitude(1.0, -6))); + make_voice(&voices.terrain, "terrain"); + make_voice(&voices.terrain_pause_terrain, "terrain", STDPAUSE, "terrain"); + make_voice(&voices.too_low_flaps, "too-low-flaps"); + make_voice(&voices.too_low_gear, "too-low-gear"); + make_voice(&voices.too_low_terrain, "too-low-terrain"); + + for (unsigned i = 0; i < n_altitude_callouts; i++) + { + std::ostringstream name; + name << "altitude-" << MK_VIII::Mode6Handler::altitude_callout_definitions[i]; + make_voice(&voices.altitude_callouts[i], name.str().c_str()); + } + speaker.update_configuration(); } /////////////////////////////////////////////////////////////////////////////// @@ -2587,7 +2390,7 @@ MK_VIII::SelfTestHandler::run () if (mk->mode6_handler.conf.above_field_voice) return play(mk->mode6_handler.conf.above_field_voice); } - for (int i = 0; i < n_altitude_callouts; i++) + for (unsigned i = 0; i < n_altitude_callouts; i++) if (! was_here_offset(i)) { if (mk->mode6_handler.conf.altitude_callouts_enabled[i]) @@ -2652,6 +2455,8 @@ MK_VIII::SelfTestHandler::stop () button_pressed = false; state = STATE_NONE; + // reset self-test handler position + current=0; } } @@ -2876,6 +2681,7 @@ MK_VIII::AlertHandler::update () { 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)) @@ -2959,11 +2765,11 @@ MK_VIII::AlertHandler::update () mk->voice_player.play(mk_voice(bank_angle_pause_bank_angle)); } - // set new state - - old_alerts = alerts; + // remember all alerts voiced so far... + old_alerts |= voice_alerts; + // ... forget those no longer active + old_alerts &= alerts; repeated_alerts = 0; - altitude_callout_voice = NULL; } void @@ -2983,6 +2789,8 @@ MK_VIII::AlertHandler::unset_alerts (unsigned int _alerts) { alerts &= ~_alerts; repeated_alerts &= ~_alerts; + if (_alerts & ALERT_MODE6_ALTITUDE_CALLOUT) + altitude_callout_voice = NULL; } /////////////////////////////////////////////////////////////////////////////// @@ -3598,9 +3406,16 @@ MK_VIII::Mode3Handler::max_alt_loss (double _bias) double MK_VIII::Mode3Handler::get_bias (double initial_bias, double alt_loss) { - if (mk_data(radio_altitude).get() > 0) - while (alt_loss > max_alt_loss(initial_bias)) + // 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; } @@ -3732,8 +3547,15 @@ MK_VIII::Mode4Handler::get_ab_envelope () double MK_VIII::Mode4Handler::get_bias (double initial_bias, double min_agl) { - while (mk_data(radio_altitude).get() < min_agl - min_agl * initial_bias) - 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; } @@ -3792,6 +3614,7 @@ MK_VIII::Mode4Handler::update_ab () } mk_unset_alerts(mk_alert(MODE4_TOO_LOW_FLAPS) | mk_alert(MODE4_TOO_LOW_GEAR)); + ab_bias=0.0; } void @@ -3817,6 +3640,7 @@ MK_VIII::Mode4Handler::update_ab_expanded () } mk_unset_alerts(mk_alert(MODE4AB_TOO_LOW_TERRAIN)); + ab_expanded_bias=0.0; } void @@ -3833,7 +3657,10 @@ MK_VIII::Mode4Handler::update_c () && 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 @@ -3873,6 +3700,7 @@ MK_VIII::Mode5Handler::is_hard () bool MK_VIII::Mode5Handler::is_soft (double bias) { + // do not repeat glide-slope alerts below 30ft agl if (mk_data(radio_altitude).get() > 30) { double bias_dots = 1.3 * bias; @@ -3911,7 +3739,10 @@ MK_VIII::Mode5Handler::is_soft (double bias) double MK_VIII::Mode5Handler::get_soft_bias (double initial_bias) { - while (is_soft(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; return initial_bias; @@ -4011,14 +3842,14 @@ MK_VIII::Mode6Handler::reset_minimums () void MK_VIII::Mode6Handler::reset_altitude_callouts () { - for (int i = 0; i < n_altitude_callouts; i++) + for (unsigned i = 0; i < n_altitude_callouts; i++) altitude_callouts_issued[i] = false; } bool MK_VIII::Mode6Handler::is_playing_altitude_callout () { - for (int i = 0; i < n_altitude_callouts; i++) + 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; @@ -4092,7 +3923,7 @@ MK_VIII::Mode6Handler::boot () last_radio_altitude.set(&mk_data(radio_altitude)); // [SPEC] 6.4.2 - for (int i = 0; i < n_altitude_callouts; i++) + 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]; @@ -4130,11 +3961,11 @@ MK_VIII::Mode6Handler::leave_takeoff () } void -MK_VIII::Mode6Handler::set_volume (double volume) +MK_VIII::Mode6Handler::set_volume (float volume) { mk_voice(minimums_minimums)->set_volume(volume); mk_voice(five_hundred_above)->set_volume(volume); - for (int i = 0; i < n_altitude_callouts; i++) + for (unsigned i = 0; i < n_altitude_callouts; i++) mk_altitude_voice(i)->set_volume(volume); } @@ -4144,7 +3975,7 @@ MK_VIII::Mode6Handler::altitude_callouts_enabled () if (conf.minimums_enabled || conf.smart_500_enabled || conf.above_field_voice) return true; - for (int i = 0; i < n_altitude_callouts; i++) + for (unsigned i = 0; i < n_altitude_callouts; i++) if (conf.altitude_callouts_enabled[i]) return true; @@ -4197,7 +4028,7 @@ MK_VIII::Mode6Handler::update_altitude_callouts () if (! mk->io_handler.gpws_inhibit() && ! mk->state_handler.ground // [1] && ! mk_data(radio_altitude).ncd) - for (int i = 0; i < n_altitude_callouts && mk_data(radio_altitude).get() <= altitude_callout_definitions[i]; i++) + for (unsigned i = 0; i < n_altitude_callouts && mk_data(radio_altitude).get() <= altitude_callout_definitions[i]; i++) if ((conf.altitude_callouts_enabled[i] || (altitude_callout_definitions[i] == 500 && conf.smart_500_enabled)) @@ -4206,7 +4037,7 @@ MK_VIII::Mode6Handler::update_altitude_callouts () || last_radio_altitude.get() > altitude_callout_definitions[i])) { // lock out all callouts superior or equal to this one - for (int j = 0; j <= i; j++) + for (unsigned j = 0; j <= i; j++) altitude_callouts_issued[j] = true; altitude_callouts_issued[i] = true; @@ -4518,10 +4349,12 @@ MK_VIII::TCFHandler::update_runway () if (!apt) return; - has_runway = true; - FGRunway* _runway = select_runway(apt); + if (!_runway) return; + + has_runway = true; + runway.center.latitude = _runway->latitude(); runway.center.longitude = _runway->longitude(); @@ -4587,7 +4420,7 @@ MK_VIII::TCFHandler::get_bias_area_edges (Position *edge, Position *bias_edge2) { double half_bias_width_m = k * SG_NM_TO_METER + half_width_m; - double tmp_latitude, tmp_longitude, az; + double tmp_latitude = 0.0, tmp_longitude = 0.0, az = 0.0; geo_direct_wgs_84(0, edge->latitude, @@ -4811,8 +4644,15 @@ MK_VIII::TCFHandler::update () if (mk_test_alert(TCF_TOO_LOW_TERRAIN)) { double new_bias = bias; - while (*reference < initial_value - initial_value * new_bias) - new_bias += 0.2; + // 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) { @@ -4840,10 +4680,9 @@ MK_VIII::TCFHandler::update () /////////////////////////////////////////////////////////////////////////////// MK_VIII::MK_VIII (SGPropertyNode *node) - : name("mk-viii"), + : properties_handler(this), + name("mk-viii"), num(0), - - properties_handler(this), power_handler(this), system_handler(this), configuration_module(this), @@ -4895,7 +4734,7 @@ MK_VIII::bind () configuration_module.bind(node); power_handler.bind(node); io_handler.bind(node); - voice_player.bind(node); + voice_player.bind(node, "Sounds/mk-viii/"); } void