X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInstrumentation%2Fmk_viii.cxx;h=eb40aee4d3b906a9f8d82b84436ceef99f821006;hb=1eb8ae1fbf43359eec09b99885a9280f529c86fb;hp=a3073136a713076b46d5c5befa365d1759f1ac39;hpb=b770e22a482dd950ea3c89226762a6284af3be1c;p=flightgear.git diff --git a/src/Instrumentation/mk_viii.cxx b/src/Instrumentation/mk_viii.cxx old mode 100755 new mode 100644 index a3073136a..eb40aee4d --- 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,15 +70,20 @@ #include #include #include +#include #include using std::string; #include -#include -#ifndef _MSC_VER +#include + +#if defined( HAVE_VERSION_H ) && HAVE_VERSION_H # include +#else +# include #endif + #include
#include
#include "instrument_mgr.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; @@ -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; } @@ -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) { @@ -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)); } @@ -2097,257 +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); -} - -void -MK_VIII::VoicePlayer::Speaker::update_configuration () -{ - map< string, SGSharedPtr >::iterator iter; - for (iter = player->samples.begin(); iter != player->samples.end(); iter++) - { - SGSoundSample *sample = (*iter).second; - - sample->set_pitch(pitch); - } - - 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 (float _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(); - samples.clear(); -} - void MK_VIII::VoicePlayer::init () { -#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay" - - SGSoundMgr *smgr = globals->get_soundmgr(); - _sgr = smgr->find("avionics", true); - _sgr->tie_to_listener(); - - 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->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; - - SGSoundSample *sample = _sgr->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); - } - - _sgr->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 (float _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(); } /////////////////////////////////////////////////////////////////////////////// @@ -2624,6 +2455,8 @@ MK_VIII::SelfTestHandler::stop () button_pressed = false; state = STATE_NONE; + // reset self-test handler position + current=0; } } @@ -2848,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)) @@ -2931,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 @@ -2955,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; } /////////////////////////////////////////////////////////////////////////////// @@ -3570,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; } @@ -3704,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; } @@ -3764,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 @@ -3789,6 +3640,7 @@ MK_VIII::Mode4Handler::update_ab_expanded () } mk_unset_alerts(mk_alert(MODE4AB_TOO_LOW_TERRAIN)); + ab_expanded_bias=0.0; } void @@ -3805,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 @@ -3845,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; @@ -3883,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; @@ -4490,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(); @@ -4783,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) { @@ -4866,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