Some more refactoring of the radios
- wrap the ident-generating code into a class - move dme-in-range property into dme.cxx - move dme-ident generation into dme.cxx - support ident-button and volume for dme idents - use globals.get_aircraft_position instead of properties - some minor cleanup
This commit is contained in:
parent
2de3872d66
commit
43109feb0c
14 changed files with 323 additions and 262 deletions
|
@ -3197,6 +3197,14 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="Lib_Sound"
|
Name="Lib_Sound"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\Sound\audioident.cxx"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\Sound\audioident.hxx"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\Sound\beacon.cxx"
|
RelativePath="..\..\..\src\Sound\beacon.cxx"
|
||||||
>
|
>
|
||||||
|
|
|
@ -252,7 +252,7 @@ ADF::search (double frequency_khz, double longitude_rad,
|
||||||
}
|
}
|
||||||
|
|
||||||
SGSoundSample *sound;
|
SGSoundSample *sound;
|
||||||
sound = FGMorse::instance()->make_ident( ident, LO_FREQUENCY );
|
sound = FGMorse::instance()->make_ident( ident, FGMorse::LO_FREQUENCY );
|
||||||
sound->set_volume(_last_volume = 0);
|
sound->set_volume(_last_volume = 0);
|
||||||
_sgr->add( sound, _adf_ident );
|
_sgr->add( sound, _adf_ident );
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,16 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/sg_inlines.h>
|
||||||
#include <simgear/math/sg_geodesy.hxx>
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
#include <simgear/math/sg_random.h>
|
#include <simgear/math/sg_random.h>
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include <Navaids/navlist.hxx>
|
#include <Navaids/navlist.hxx>
|
||||||
|
#include <Sound/audioident.hxx>
|
||||||
|
|
||||||
#include "dme.hxx"
|
#include "dme.hxx"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjust the range.
|
* Adjust the range.
|
||||||
*
|
*
|
||||||
|
@ -44,17 +45,16 @@ DME::DME ( SGPropertyNode *node )
|
||||||
: _last_distance_nm(0),
|
: _last_distance_nm(0),
|
||||||
_last_frequency_mhz(-1),
|
_last_frequency_mhz(-1),
|
||||||
_time_before_search_sec(0),
|
_time_before_search_sec(0),
|
||||||
_transmitter_valid(false),
|
_navrecord(NULL),
|
||||||
_transmitter_elevation_ft(0),
|
|
||||||
_transmitter_range_nm(0),
|
|
||||||
_transmitter_bias(0.0),
|
|
||||||
_name(node->getStringValue("name", "dme")),
|
_name(node->getStringValue("name", "dme")),
|
||||||
_num(node->getIntValue("number", 0))
|
_num(node->getIntValue("number", 0)),
|
||||||
|
_audioIdent(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
DME::~DME ()
|
DME::~DME ()
|
||||||
{
|
{
|
||||||
|
delete _audioIdent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -65,9 +65,6 @@ DME::init ()
|
||||||
|
|
||||||
SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true );
|
SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true );
|
||||||
|
|
||||||
_longitude_node = fgGetNode("/position/longitude-deg", true);
|
|
||||||
_latitude_node = fgGetNode("/position/latitude-deg", true);
|
|
||||||
_altitude_node = fgGetNode("/position/altitude-ft", true);
|
|
||||||
_serviceable_node = node->getChild("serviceable", 0, true);
|
_serviceable_node = node->getChild("serviceable", 0, true);
|
||||||
_electrical_node = fgGetNode("/systems/electrical/outputs/dme", true);
|
_electrical_node = fgGetNode("/systems/electrical/outputs/dme", true);
|
||||||
SGPropertyNode *fnode = node->getChild("frequencies", 0, true);
|
SGPropertyNode *fnode = node->getChild("frequencies", 0, true);
|
||||||
|
@ -77,11 +74,28 @@ DME::init ()
|
||||||
_distance_node = node->getChild("indicated-distance-nm", 0, true);
|
_distance_node = node->getChild("indicated-distance-nm", 0, true);
|
||||||
_speed_node = node->getChild("indicated-ground-speed-kt", 0, true);
|
_speed_node = node->getChild("indicated-ground-speed-kt", 0, true);
|
||||||
_time_node = node->getChild("indicated-time-min", 0, true);
|
_time_node = node->getChild("indicated-time-min", 0, true);
|
||||||
|
|
||||||
|
double d = node->getDoubleValue( "volume", 1.0 );
|
||||||
|
_volume_node = node->getChild("volume", 0, true);
|
||||||
|
_volume_node->setDoubleValue( d );
|
||||||
|
|
||||||
|
bool b = node->getBoolValue( "ident", false );
|
||||||
|
_ident_btn_node = node->getChild("ident", 0, true);
|
||||||
|
_ident_btn_node->setBoolValue( b );
|
||||||
|
|
||||||
|
std::ostringstream temp;
|
||||||
|
temp << _name << "-ident-" << _num;
|
||||||
|
if( NULL == _audioIdent )
|
||||||
|
_audioIdent = new DMEAudioIdent( temp.str() );
|
||||||
|
_audioIdent->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DME::update (double delta_time_sec)
|
DME::update (double delta_time_sec)
|
||||||
{
|
{
|
||||||
|
if( delta_time_sec < SGLimitsd::min() )
|
||||||
|
return; //paused
|
||||||
|
|
||||||
// Figure out the source
|
// Figure out the source
|
||||||
const char * source = _source_node->getStringValue();
|
const char * source = _source_node->getStringValue();
|
||||||
if (source[0] == '\0') {
|
if (source[0] == '\0') {
|
||||||
|
@ -100,48 +114,50 @@ DME::update (double delta_time_sec)
|
||||||
_frequency_node->setDoubleValue(frequency_mhz);
|
_frequency_node->setDoubleValue(frequency_mhz);
|
||||||
|
|
||||||
// Get the aircraft position
|
// Get the aircraft position
|
||||||
double longitude_rad =
|
|
||||||
_longitude_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
|
|
||||||
double latitude_rad =
|
|
||||||
_latitude_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
|
|
||||||
double altitude_m =
|
|
||||||
_altitude_node->getDoubleValue() * SG_FEET_TO_METER;
|
|
||||||
|
|
||||||
// On timeout, scan again
|
// On timeout, scan again
|
||||||
_time_before_search_sec -= delta_time_sec;
|
_time_before_search_sec -= delta_time_sec;
|
||||||
if (_time_before_search_sec < 0)
|
if (_time_before_search_sec < 0) {
|
||||||
search(frequency_mhz, longitude_rad,
|
_time_before_search_sec = 1.0;
|
||||||
latitude_rad, altitude_m);
|
|
||||||
|
_navrecord = globals->get_dmelist()->findByFreq( frequency_mhz,
|
||||||
|
globals->get_aircraft_position());
|
||||||
|
}
|
||||||
|
|
||||||
// If it's off, don't bother.
|
// If it's off, don't bother.
|
||||||
if (!_serviceable_node->getBoolValue() ||
|
if (!_serviceable_node->getBoolValue() ||
|
||||||
!_electrical_node->getBoolValue() ||
|
!_electrical_node->getBoolValue() ||
|
||||||
!_transmitter_valid) {
|
NULL == _navrecord ) {
|
||||||
_last_distance_nm = 0;
|
_last_distance_nm = 0;
|
||||||
_in_range_node->setBoolValue(false);
|
_in_range_node->setBoolValue(false);
|
||||||
_distance_node->setDoubleValue(0);
|
_distance_node->setDoubleValue(0);
|
||||||
_speed_node->setDoubleValue(0);
|
_speed_node->setDoubleValue(0);
|
||||||
_time_node->setDoubleValue(0);
|
_time_node->setDoubleValue(0);
|
||||||
|
_audioIdent->setIdent("", 0.0 );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the distance to the transmitter
|
// Calculate the distance to the transmitter
|
||||||
SGGeod geod = SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m);
|
SGVec3d location = SGVec3d::fromGeod(globals->get_aircraft_position());
|
||||||
SGVec3d location = SGVec3d::fromGeod(geod);
|
|
||||||
|
|
||||||
double distance_nm = dist(_transmitter, location) * SG_METER_TO_NM;
|
double distance_nm = dist(_navrecord->cart(), location) * SG_METER_TO_NM;
|
||||||
|
|
||||||
double range_nm = adjust_range(_transmitter_elevation_ft,
|
double range_nm = adjust_range(_navrecord->get_elev_ft(),
|
||||||
altitude_m * SG_METER_TO_FEET,
|
globals->get_aircraft_position().getElevationFt(),
|
||||||
_transmitter_range_nm);
|
_navrecord->get_range());
|
||||||
|
|
||||||
if (distance_nm <= range_nm) {
|
if (distance_nm <= range_nm) {
|
||||||
|
double volume = _volume_node->getDoubleValue();
|
||||||
|
if( false == _ident_btn_node->getBoolValue() )
|
||||||
|
volume = 0.0;
|
||||||
|
|
||||||
|
_audioIdent->setIdent(_navrecord->ident(), volume );
|
||||||
|
|
||||||
double speed_kt = (fabs(distance_nm - _last_distance_nm) *
|
double speed_kt = (fabs(distance_nm - _last_distance_nm) *
|
||||||
((1 / delta_time_sec) * 3600.0));
|
((1 / delta_time_sec) * 3600.0));
|
||||||
_last_distance_nm = distance_nm;
|
_last_distance_nm = distance_nm;
|
||||||
|
|
||||||
_in_range_node->setBoolValue(true);
|
_in_range_node->setBoolValue(true);
|
||||||
double tmp_dist = distance_nm - _transmitter_bias;
|
double tmp_dist = distance_nm - _navrecord->get_multiuse();
|
||||||
if ( tmp_dist < 0.0 ) {
|
if ( tmp_dist < 0.0 ) {
|
||||||
tmp_dist = 0.0;
|
tmp_dist = 0.0;
|
||||||
}
|
}
|
||||||
|
@ -156,29 +172,10 @@ DME::update (double delta_time_sec)
|
||||||
_distance_node->setDoubleValue(0);
|
_distance_node->setDoubleValue(0);
|
||||||
_speed_node->setDoubleValue(0);
|
_speed_node->setDoubleValue(0);
|
||||||
_time_node->setDoubleValue(0);
|
_time_node->setDoubleValue(0);
|
||||||
|
_audioIdent->setIdent("", 0.0 );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
_audioIdent->update( delta_time_sec );
|
||||||
DME::search (double frequency_mhz, double longitude_rad,
|
|
||||||
double latitude_rad, double altitude_m)
|
|
||||||
{
|
|
||||||
// reset search time
|
|
||||||
_time_before_search_sec = 1.0;
|
|
||||||
|
|
||||||
// try the ILS list first
|
|
||||||
|
|
||||||
FGNavRecord *dme = globals->get_dmelist()->findByFreq( frequency_mhz,
|
|
||||||
SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m));
|
|
||||||
|
|
||||||
_transmitter_valid = (dme != NULL);
|
|
||||||
|
|
||||||
if ( _transmitter_valid ) {
|
|
||||||
_transmitter = dme->cart();
|
|
||||||
_transmitter_elevation_ft = dme->get_elev_ft();
|
|
||||||
_transmitter_range_nm = dme->get_range();
|
|
||||||
_transmitter_bias = dme->get_multiuse();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of dme.cxx
|
// end of dme.cxx
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model a DME radio.
|
* Model a DME radio.
|
||||||
*
|
*
|
||||||
|
@ -44,12 +43,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void search (double frequency, double longitude_rad,
|
|
||||||
double latitude_rad, double altitude_m);
|
|
||||||
|
|
||||||
SGPropertyNode_ptr _longitude_node;
|
|
||||||
SGPropertyNode_ptr _latitude_node;
|
|
||||||
SGPropertyNode_ptr _altitude_node;
|
|
||||||
SGPropertyNode_ptr _serviceable_node;
|
SGPropertyNode_ptr _serviceable_node;
|
||||||
SGPropertyNode_ptr _electrical_node;
|
SGPropertyNode_ptr _electrical_node;
|
||||||
SGPropertyNode_ptr _source_node;
|
SGPropertyNode_ptr _source_node;
|
||||||
|
@ -59,20 +52,19 @@ private:
|
||||||
SGPropertyNode_ptr _distance_node;
|
SGPropertyNode_ptr _distance_node;
|
||||||
SGPropertyNode_ptr _speed_node;
|
SGPropertyNode_ptr _speed_node;
|
||||||
SGPropertyNode_ptr _time_node;
|
SGPropertyNode_ptr _time_node;
|
||||||
|
SGPropertyNode_ptr _ident_btn_node;
|
||||||
|
SGPropertyNode_ptr _volume_node;
|
||||||
|
|
||||||
double _last_distance_nm;
|
double _last_distance_nm;
|
||||||
double _last_frequency_mhz;
|
double _last_frequency_mhz;
|
||||||
double _time_before_search_sec;
|
double _time_before_search_sec;
|
||||||
|
|
||||||
bool _transmitter_valid;
|
FGNavRecord * _navrecord;
|
||||||
SGVec3d _transmitter;
|
|
||||||
double _transmitter_elevation_ft;
|
|
||||||
double _transmitter_range_nm;
|
|
||||||
double _transmitter_bias;
|
|
||||||
|
|
||||||
string _name;
|
string _name;
|
||||||
int _num;
|
int _num;
|
||||||
|
|
||||||
|
class AudioIdent * _audioIdent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
//
|
//
|
||||||
// $Id$
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
@ -71,9 +70,6 @@ static double kludgeRange ( double stationElev, double aircraftElev,
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
FGKR_87::FGKR_87( SGPropertyNode *node ) :
|
FGKR_87::FGKR_87( SGPropertyNode *node ) :
|
||||||
lon_node(fgGetNode("/position/longitude-deg", true)),
|
|
||||||
lat_node(fgGetNode("/position/latitude-deg", true)),
|
|
||||||
alt_node(fgGetNode("/position/altitude-ft", true)),
|
|
||||||
bus_power(fgGetNode("/systems/electrical/outputs/adf", true)),
|
bus_power(fgGetNode("/systems/electrical/outputs/adf", true)),
|
||||||
serviceable(fgGetNode("/instrumentation/adf/serviceable", true)),
|
serviceable(fgGetNode("/instrumentation/adf/serviceable", true)),
|
||||||
need_update(true),
|
need_update(true),
|
||||||
|
@ -249,9 +245,7 @@ void FGKR_87::unbind () {
|
||||||
|
|
||||||
// Update the various nav values based on position and valid tuned in navs
|
// Update the various nav values based on position and valid tuned in navs
|
||||||
void FGKR_87::update( double dt_sec ) {
|
void FGKR_87::update( double dt_sec ) {
|
||||||
SGGeod acft = SGGeod::fromDegFt(lon_node->getDoubleValue(),
|
SGGeod acft = globals->get_aircraft_position();
|
||||||
lat_node->getDoubleValue(),
|
|
||||||
alt_node->getDoubleValue());
|
|
||||||
|
|
||||||
need_update = false;
|
need_update = false;
|
||||||
|
|
||||||
|
@ -497,8 +491,7 @@ void FGKR_87::update( double dt_sec ) {
|
||||||
|
|
||||||
// Update current nav/adf radio stations based on current postition
|
// Update current nav/adf radio stations based on current postition
|
||||||
void FGKR_87::search() {
|
void FGKR_87::search() {
|
||||||
SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
|
SGGeod pos = globals->get_aircraft_position();
|
||||||
lat_node->getDoubleValue(), alt_node->getDoubleValue());
|
|
||||||
|
|
||||||
// FIXME: the panel should handle this
|
// FIXME: the panel should handle this
|
||||||
static string last_ident = "";
|
static string last_ident = "";
|
||||||
|
@ -534,7 +527,7 @@ void FGKR_87::search() {
|
||||||
_sgr->remove( "adf-ident" );
|
_sgr->remove( "adf-ident" );
|
||||||
}
|
}
|
||||||
SGSoundSample *sound;
|
SGSoundSample *sound;
|
||||||
sound = FGMorse::instance()->make_ident( trans_ident, LO_FREQUENCY );
|
sound = FGMorse::instance()->make_ident( trans_ident, FGMorse::LO_FREQUENCY );
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
_sgr->add( sound, "adf-ident" );
|
_sgr->add( sound, "adf-ident" );
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,6 @@ class SGSampleGroup;
|
||||||
|
|
||||||
class FGKR_87 : public SGSubsystem
|
class FGKR_87 : public SGSubsystem
|
||||||
{
|
{
|
||||||
SGPropertyNode_ptr lon_node;
|
|
||||||
SGPropertyNode_ptr lat_node;
|
|
||||||
SGPropertyNode_ptr alt_node;
|
|
||||||
SGPropertyNode_ptr bus_power;
|
SGPropertyNode_ptr bus_power;
|
||||||
SGPropertyNode_ptr serviceable;
|
SGPropertyNode_ptr serviceable;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
//
|
//
|
||||||
// $Id$
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
|
@ -40,12 +38,10 @@
|
||||||
#include <simgear/misc/strutils.hxx>
|
#include <simgear/misc/strutils.hxx>
|
||||||
|
|
||||||
#include <Navaids/navrecord.hxx>
|
#include <Navaids/navrecord.hxx>
|
||||||
|
#include <Sound/audioident.hxx>
|
||||||
#include <Airports/runways.hxx>
|
#include <Airports/runways.hxx>
|
||||||
#include <Navaids/navlist.hxx>
|
#include <Navaids/navlist.hxx>
|
||||||
#include <Main/util.hxx>
|
#include <Main/util.hxx>
|
||||||
#include <Sound/morse.hxx>
|
|
||||||
|
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
@ -105,9 +101,6 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
||||||
term_tbl(NULL),
|
term_tbl(NULL),
|
||||||
low_tbl(NULL),
|
low_tbl(NULL),
|
||||||
high_tbl(NULL),
|
high_tbl(NULL),
|
||||||
lon_node(fgGetNode("/position/longitude-deg", true)),
|
|
||||||
lat_node(fgGetNode("/position/latitude-deg", true)),
|
|
||||||
alt_node(fgGetNode("/position/altitude-ft", true)),
|
|
||||||
_operable(false),
|
_operable(false),
|
||||||
play_count(0),
|
play_count(0),
|
||||||
last_time(0),
|
last_time(0),
|
||||||
|
@ -126,14 +119,13 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
||||||
_gsCart(SGVec3d::zeros()),
|
_gsCart(SGVec3d::zeros()),
|
||||||
_gsAxis(SGVec3d::zeros()),
|
_gsAxis(SGVec3d::zeros()),
|
||||||
_gsVertical(SGVec3d::zeros()),
|
_gsVertical(SGVec3d::zeros()),
|
||||||
_dmeInRange(false),
|
|
||||||
_toFlag(false),
|
_toFlag(false),
|
||||||
_fromFlag(false),
|
_fromFlag(false),
|
||||||
_cdiDeflection(0.0),
|
_cdiDeflection(0.0),
|
||||||
_cdiCrossTrackErrorM(0.0),
|
_cdiCrossTrackErrorM(0.0),
|
||||||
_gsNeedleDeflection(0.0),
|
_gsNeedleDeflection(0.0),
|
||||||
_gsNeedleDeflectionNorm(0.0),
|
_gsNeedleDeflectionNorm(0.0),
|
||||||
_sgr(NULL)
|
_audioIdent(NULL)
|
||||||
{
|
{
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
SGPath term = path;
|
SGPath term = path;
|
||||||
|
@ -166,16 +158,14 @@ FGNavRadio::~FGNavRadio()
|
||||||
delete term_tbl;
|
delete term_tbl;
|
||||||
delete low_tbl;
|
delete low_tbl;
|
||||||
delete high_tbl;
|
delete high_tbl;
|
||||||
|
|
||||||
|
delete _audioIdent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGNavRadio::init ()
|
FGNavRadio::init ()
|
||||||
{
|
{
|
||||||
SGSoundMgr *smgr = globals->get_soundmgr();
|
|
||||||
_sgr = smgr->find("avionics", true);
|
|
||||||
_sgr->tie_to_listener();
|
|
||||||
|
|
||||||
SGPropertyNode* node = _radio_node.get();
|
SGPropertyNode* node = _radio_node.get();
|
||||||
bus_power_node =
|
bus_power_node =
|
||||||
fgGetNode(("/systems/electrical/outputs/" + _name).c_str(), true);
|
fgGetNode(("/systems/electrical/outputs/" + _name).c_str(), true);
|
||||||
|
@ -196,7 +186,6 @@ FGNavRadio::init ()
|
||||||
cdi_serviceable_node = createServiceableProp(node, "cdi");
|
cdi_serviceable_node = createServiceableProp(node, "cdi");
|
||||||
gs_serviceable_node = createServiceableProp(node, "gs");
|
gs_serviceable_node = createServiceableProp(node, "gs");
|
||||||
tofrom_serviceable_node = createServiceableProp(node, "to-from");
|
tofrom_serviceable_node = createServiceableProp(node, "to-from");
|
||||||
dme_serviceable_node = createServiceableProp(node, "dme");
|
|
||||||
|
|
||||||
falseCoursesEnabledNode =
|
falseCoursesEnabledNode =
|
||||||
fgGetNode("/sim/realism/false-radio-courses-enabled");
|
fgGetNode("/sim/realism/false-radio-courses-enabled");
|
||||||
|
@ -266,27 +255,28 @@ FGNavRadio::init ()
|
||||||
_magvarNode = fgGetNode("/environment/magnetic-variation-deg", true);
|
_magvarNode = fgGetNode("/environment/magnetic-variation-deg", true);
|
||||||
|
|
||||||
std::ostringstream temp;
|
std::ostringstream temp;
|
||||||
temp << _name << "nav-ident" << _num;
|
temp << _name << "-ident-" << _num;
|
||||||
nav_fx_name = temp.str();
|
if( NULL == _audioIdent )
|
||||||
temp << _name << "dme-ident" << _num;
|
_audioIdent = new VORAudioIdent( temp.str() );
|
||||||
dme_fx_name = temp.str();
|
_audioIdent->init();
|
||||||
|
|
||||||
|
// dme-in-range is deprecated,
|
||||||
|
// temporarily create dme-in-range alias for instrumentation/dme[0]/in-range
|
||||||
|
// remove after flightgear 2.6.0
|
||||||
|
node->getNode( "dme-in-range", true )->alias( fgGetNode("/instrumentation/dme[0]/in-range", true ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FGNavRadio::bind ()
|
FGNavRadio::bind ()
|
||||||
{
|
{
|
||||||
tie("dme-in-range", SGRawValuePointer<bool>(&_dmeInRange));
|
_radio_node->tie( "operable", SGRawValueMethods<FGNavRadio,bool>( *this, &FGNavRadio::isOperable ) );
|
||||||
tie("operable", SGRawValueMethods<FGNavRadio, bool>(*this, &FGNavRadio::isOperable, NULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGNavRadio::unbind ()
|
FGNavRadio::unbind ()
|
||||||
{
|
{
|
||||||
for (unsigned int t=0; t<_tiedNodes.size(); ++t) {
|
_radio_node->untie("operable");
|
||||||
_tiedNodes[t]->untie();
|
|
||||||
}
|
|
||||||
_tiedNodes.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -386,7 +376,7 @@ FGNavRadio::update(double dt)
|
||||||
clearOutputs();
|
clearOutputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAudio();
|
updateAudio( dt );
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGNavRadio::clearOutputs()
|
void FGNavRadio::clearOutputs()
|
||||||
|
@ -412,17 +402,13 @@ void FGNavRadio::clearOutputs()
|
||||||
is_valid_node->setBoolValue(false);
|
is_valid_node->setBoolValue(false);
|
||||||
nav_id_node->setStringValue("");
|
nav_id_node->setStringValue("");
|
||||||
|
|
||||||
_dmeInRange = false;
|
|
||||||
_operable = false;
|
_operable = false;
|
||||||
_navaid = NULL;
|
_navaid = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGNavRadio::updateReceiver(double dt)
|
void FGNavRadio::updateReceiver(double dt)
|
||||||
{
|
{
|
||||||
SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
|
SGVec3d aircraft = SGVec3d::fromGeod(globals->get_aircraft_position());
|
||||||
lat_node->getDoubleValue(),
|
|
||||||
alt_node->getDoubleValue());
|
|
||||||
SGVec3d aircraft = SGVec3d::fromGeod(pos);
|
|
||||||
double loc_dist = 0;
|
double loc_dist = 0;
|
||||||
|
|
||||||
// Do a nav station search only once a second to reduce
|
// Do a nav station search only once a second to reduce
|
||||||
|
@ -438,11 +424,10 @@ void FGNavRadio::updateReceiver(double dt)
|
||||||
loc_dist = dist(aircraft, _navaid->cart());
|
loc_dist = dist(aircraft, _navaid->cart());
|
||||||
loc_dist_node->setDoubleValue( loc_dist );
|
loc_dist_node->setDoubleValue( loc_dist );
|
||||||
}
|
}
|
||||||
updateDME(aircraft);
|
|
||||||
|
|
||||||
if (nav_slaved_to_gps_node->getBoolValue()) {
|
if (nav_slaved_to_gps_node->getBoolValue()) {
|
||||||
// when slaved to GPS: only allow stuff above: tune NAV station
|
// when slaved to GPS: only allow stuff above: tune NAV station
|
||||||
// upate DME. All other data driven by GPS only.
|
// All other data driven by GPS only.
|
||||||
updateGPSSlaved();
|
updateGPSSlaved();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -468,7 +453,7 @@ void FGNavRadio::updateReceiver(double dt)
|
||||||
// compute forward and reverse wgs84 headings to localizer
|
// compute forward and reverse wgs84 headings to localizer
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
double hdg;
|
double hdg;
|
||||||
SGGeodesy::inverse(pos, _navaid->geod(), hdg, az2, s);
|
SGGeodesy::inverse(globals->get_aircraft_position(), _navaid->geod(), hdg, az2, s);
|
||||||
heading_node->setDoubleValue(hdg);
|
heading_node->setDoubleValue(hdg);
|
||||||
double radial = az2 - twist;
|
double radial = az2 - twist;
|
||||||
double recip = radial + 180.0;
|
double recip = radial + 180.0;
|
||||||
|
@ -497,11 +482,11 @@ void FGNavRadio::updateReceiver(double dt)
|
||||||
double offset = radial - target_radial;
|
double offset = radial - target_radial;
|
||||||
SG_NORMALIZE_RANGE(offset, -180.0, 180.0);
|
SG_NORMALIZE_RANGE(offset, -180.0, 180.0);
|
||||||
effective_range
|
effective_range
|
||||||
= adjustILSRange( nav_elev, pos.getElevationM(), offset,
|
= adjustILSRange( nav_elev, globals->get_aircraft_position().getElevationM(), offset,
|
||||||
loc_dist * SG_METER_TO_NM );
|
loc_dist * SG_METER_TO_NM );
|
||||||
} else {
|
} else {
|
||||||
effective_range
|
effective_range
|
||||||
= adjustNavRange( nav_elev, pos.getElevationM(), _navaid->get_range() );
|
= adjustNavRange( nav_elev, globals->get_aircraft_position().getElevationM(), _navaid->get_range() );
|
||||||
}
|
}
|
||||||
|
|
||||||
double effective_range_m = effective_range * SG_NM_TO_METER;
|
double effective_range_m = effective_range * SG_NM_TO_METER;
|
||||||
|
@ -679,17 +664,6 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig
|
||||||
->setDoubleValue( gs_rate_of_climb_node->getDoubleValue() * 60 );
|
->setDoubleValue( gs_rate_of_climb_node->getDoubleValue() * 60 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGNavRadio::updateDME(const SGVec3d& aircraft)
|
|
||||||
{
|
|
||||||
if (!_dme || !dme_serviceable_node->getBoolValue()) {
|
|
||||||
_dmeInRange = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double dme_distance = dist(aircraft, _dme->cart());
|
|
||||||
_dmeInRange = (dme_distance < _dme->get_range() * SG_NM_TO_METER);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FGNavRadio::valueChanged (SGPropertyNode* prop)
|
void FGNavRadio::valueChanged (SGPropertyNode* prop)
|
||||||
{
|
{
|
||||||
if (prop == gps_course_node) {
|
if (prop == gps_course_node) {
|
||||||
|
@ -849,9 +823,10 @@ void FGNavRadio::updateCDI(double dt)
|
||||||
last_xtrack_error = _cdiCrossTrackErrorM;
|
last_xtrack_error = _cdiCrossTrackErrorM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGNavRadio::updateAudio()
|
void FGNavRadio::updateAudio( double dt )
|
||||||
{
|
{
|
||||||
if (!_navaid || !inrange_node->getBoolValue() || !nav_serviceable_node->getBoolValue()) {
|
if (!_navaid || !inrange_node->getBoolValue() || !nav_serviceable_node->getBoolValue()) {
|
||||||
|
_audioIdent->setIdent("", 0.0 );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,57 +836,13 @@ void FGNavRadio::updateAudio()
|
||||||
|| !(bus_power_node->getDoubleValue() > 1.0)
|
|| !(bus_power_node->getDoubleValue() > 1.0)
|
||||||
|| !ident_btn_node->getBoolValue()
|
|| !ident_btn_node->getBoolValue()
|
||||||
|| !audio_btn_node->getBoolValue() ) {
|
|| !audio_btn_node->getBoolValue() ) {
|
||||||
_sgr->stop( nav_fx_name );
|
_audioIdent->setIdent("", 0.0 );
|
||||||
_sgr->stop( dme_fx_name );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGSoundSample *sound = _sgr->find( nav_fx_name );
|
_audioIdent->setIdent( _navaid->get_trans_ident(), vol_btn_node->getFloatValue() );
|
||||||
double vol = vol_btn_node->getFloatValue();
|
|
||||||
SG_CLAMP_RANGE(vol, 0.0, 1.0);
|
|
||||||
|
|
||||||
if ( sound != NULL ) {
|
_audioIdent->update( dt );
|
||||||
sound->set_volume( vol );
|
|
||||||
} else {
|
|
||||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-vor-ident sound" );
|
|
||||||
}
|
|
||||||
|
|
||||||
sound = _sgr->find( dme_fx_name );
|
|
||||||
if ( sound != NULL ) {
|
|
||||||
sound->set_volume( vol );
|
|
||||||
} else {
|
|
||||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-dme-ident sound" );
|
|
||||||
}
|
|
||||||
|
|
||||||
const int NUM_IDENT_SLOTS = 5;
|
|
||||||
const time_t SLOT_LENGTH = 5; // seconds
|
|
||||||
|
|
||||||
// There are N slots numbered 0 through (NUM_IDENT_SLOTS-1) inclusive.
|
|
||||||
// Each slot is 5 seconds long.
|
|
||||||
// Slots 0 is for DME
|
|
||||||
// the rest are for azimuth.
|
|
||||||
time_t now = globals->get_time_params()->get_cur_time();
|
|
||||||
if ((now >= last_time) && (now < last_time + SLOT_LENGTH)) {
|
|
||||||
return; // wait longer
|
|
||||||
}
|
|
||||||
|
|
||||||
last_time = now;
|
|
||||||
play_count++;
|
|
||||||
play_count %= NUM_IDENT_SLOTS;
|
|
||||||
|
|
||||||
// Previous ident is out of time; if still playing, cut it off:
|
|
||||||
_sgr->stop( nav_fx_name );
|
|
||||||
_sgr->stop( dme_fx_name );
|
|
||||||
if (play_count == 0) { // the DME slot
|
|
||||||
if (_dmeInRange && dme_serviceable_node->getBoolValue()) {
|
|
||||||
// play DME ident
|
|
||||||
if (vol > 0.05) _sgr->play_once( dme_fx_name );
|
|
||||||
}
|
|
||||||
} else { // NAV slot
|
|
||||||
if (inrange_node->getBoolValue() && nav_serviceable_node->getBoolValue()) {
|
|
||||||
if (vol > 0.05) _sgr->play_once(nav_fx_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FGNavRecord* FGNavRadio::findPrimaryNavaid(const SGGeod& aPos, double aFreqMHz)
|
FGNavRecord* FGNavRadio::findPrimaryNavaid(const SGGeod& aPos, double aFreqMHz)
|
||||||
|
@ -928,11 +859,9 @@ FGNavRecord* FGNavRadio::findPrimaryNavaid(const SGGeod& aPos, double aFreqMHz)
|
||||||
void FGNavRadio::search()
|
void FGNavRadio::search()
|
||||||
{
|
{
|
||||||
_time_before_search_sec = 1.0;
|
_time_before_search_sec = 1.0;
|
||||||
SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
|
|
||||||
lat_node->getDoubleValue(), alt_node->getDoubleValue());
|
|
||||||
double freq = freq_node->getDoubleValue();
|
double freq = freq_node->getDoubleValue();
|
||||||
|
|
||||||
FGNavRecord* nav = findPrimaryNavaid(pos, freq);
|
FGNavRecord* nav = findPrimaryNavaid(globals->get_aircraft_position(), freq);
|
||||||
if (nav == _navaid) {
|
if (nav == _navaid) {
|
||||||
return; // found the same as last search, we're done
|
return; // found the same as last search, we're done
|
||||||
}
|
}
|
||||||
|
@ -940,16 +869,10 @@ void FGNavRadio::search()
|
||||||
_navaid = nav;
|
_navaid = nav;
|
||||||
string identBuffer(4, ' ');
|
string identBuffer(4, ' ');
|
||||||
if (nav) {
|
if (nav) {
|
||||||
// use ILS signals as DME, otherwise search by frequency
|
|
||||||
if (nav->type()==FGPositioned::ILS)
|
|
||||||
_dme = nav;
|
|
||||||
else
|
|
||||||
_dme = globals->get_dmelist()->findByFreq(freq, pos);
|
|
||||||
|
|
||||||
nav_id_node->setStringValue(nav->get_ident());
|
nav_id_node->setStringValue(nav->get_ident());
|
||||||
identBuffer = simgear::strutils::rpad( nav->ident(), 4, ' ' );
|
identBuffer = simgear::strutils::rpad( nav->ident(), 4, ' ' );
|
||||||
|
|
||||||
effective_range = adjustNavRange(nav->get_elev_ft(), pos.getElevationM(), nav->get_range());
|
effective_range = adjustNavRange(nav->get_elev_ft(), globals->get_aircraft_position().getElevationM(), nav->get_range());
|
||||||
loc_node->setBoolValue(nav->type() != FGPositioned::VOR);
|
loc_node->setBoolValue(nav->type() != FGPositioned::VOR);
|
||||||
twist = nav->get_multiuse();
|
twist = nav->get_multiuse();
|
||||||
|
|
||||||
|
@ -958,7 +881,7 @@ void FGNavRadio::search()
|
||||||
_gs = NULL;
|
_gs = NULL;
|
||||||
has_gs_node->setBoolValue(false);
|
has_gs_node->setBoolValue(false);
|
||||||
} else { // ILS or LOC
|
} else { // ILS or LOC
|
||||||
_gs = globals->get_gslist()->findByFreq(freq, pos);
|
_gs = globals->get_gslist()->findByFreq(freq, globals->get_aircraft_position());
|
||||||
has_gs_node->setBoolValue(_gs != NULL);
|
has_gs_node->setBoolValue(_gs != NULL);
|
||||||
_localizerWidth = nav->localizerWidth();
|
_localizerWidth = nav->localizerWidth();
|
||||||
twist = 0.0;
|
twist = 0.0;
|
||||||
|
@ -986,16 +909,12 @@ void FGNavRadio::search()
|
||||||
} // of have glideslope
|
} // of have glideslope
|
||||||
} // of found LOC or ILS
|
} // of found LOC or ILS
|
||||||
|
|
||||||
audioNavidChanged();
|
|
||||||
} else { // found nothing
|
} else { // found nothing
|
||||||
_gs = NULL;
|
_gs = NULL;
|
||||||
_dme = NULL;
|
|
||||||
nav_id_node->setStringValue("");
|
nav_id_node->setStringValue("");
|
||||||
loc_node->setBoolValue(false);
|
loc_node->setBoolValue(false);
|
||||||
has_gs_node->setBoolValue(false);
|
has_gs_node->setBoolValue(false);
|
||||||
|
_audioIdent->setIdent("", 0.0 );
|
||||||
_sgr->remove( nav_fx_name );
|
|
||||||
_sgr->remove( dme_fx_name );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is_valid_node->setBoolValue(nav != NULL);
|
is_valid_node->setBoolValue(nav != NULL);
|
||||||
|
@ -1004,33 +923,3 @@ void FGNavRadio::search()
|
||||||
id_c3_node->setIntValue( (int)identBuffer[2] );
|
id_c3_node->setIntValue( (int)identBuffer[2] );
|
||||||
id_c4_node->setIntValue( (int)identBuffer[3] );
|
id_c4_node->setIntValue( (int)identBuffer[3] );
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGNavRadio::audioNavidChanged()
|
|
||||||
{
|
|
||||||
if (_sgr->exists(nav_fx_name)) {
|
|
||||||
_sgr->remove(nav_fx_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
string trans_ident(_navaid->get_trans_ident());
|
|
||||||
SGSoundSample* sound = FGMorse::instance()->make_ident(trans_ident, LO_FREQUENCY);
|
|
||||||
sound->set_volume( 0.3 );
|
|
||||||
if (!_sgr->add( sound, nav_fx_name )) {
|
|
||||||
SG_LOG(SG_COCKPIT, SG_WARN, "Failed to add v1-vor-ident sound");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( _sgr->exists( dme_fx_name ) ) {
|
|
||||||
_sgr->remove( dme_fx_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
sound = FGMorse::instance()->make_ident( trans_ident, HI_FREQUENCY );
|
|
||||||
sound->set_volume( 0.3 );
|
|
||||||
_sgr->add( sound, dme_fx_name );
|
|
||||||
|
|
||||||
int offset = (int)(sg_random() * 30.0);
|
|
||||||
play_count = offset / 4;
|
|
||||||
last_time = globals->get_time_params()->get_cur_time() - offset;
|
|
||||||
} catch (sg_io_exception& e) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -45,9 +45,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
SGInterpTable *high_tbl;
|
SGInterpTable *high_tbl;
|
||||||
|
|
||||||
SGPropertyNode_ptr _radio_node;
|
SGPropertyNode_ptr _radio_node;
|
||||||
SGPropertyNode_ptr lon_node;
|
|
||||||
SGPropertyNode_ptr lat_node;
|
|
||||||
SGPropertyNode_ptr alt_node;
|
|
||||||
SGPropertyNode_ptr bus_power_node;
|
SGPropertyNode_ptr bus_power_node;
|
||||||
|
|
||||||
// property inputs
|
// property inputs
|
||||||
|
@ -65,7 +62,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
SGPropertyNode_ptr cdi_serviceable_node;
|
SGPropertyNode_ptr cdi_serviceable_node;
|
||||||
SGPropertyNode_ptr gs_serviceable_node;
|
SGPropertyNode_ptr gs_serviceable_node;
|
||||||
SGPropertyNode_ptr tofrom_serviceable_node;
|
SGPropertyNode_ptr tofrom_serviceable_node;
|
||||||
SGPropertyNode_ptr dme_serviceable_node;
|
|
||||||
|
|
||||||
// property outputs
|
// property outputs
|
||||||
SGPropertyNode_ptr fmt_freq_node; // formated frequency
|
SGPropertyNode_ptr fmt_freq_node; // formated frequency
|
||||||
|
@ -131,9 +127,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
FGNavRecordPtr _navaid;
|
FGNavRecordPtr _navaid;
|
||||||
FGNavRecordPtr _gs;
|
FGNavRecordPtr _gs;
|
||||||
|
|
||||||
string nav_fx_name;
|
|
||||||
string dme_fx_name;
|
|
||||||
|
|
||||||
double target_radial;
|
double target_radial;
|
||||||
double effective_range;
|
double effective_range;
|
||||||
double target_gs;
|
double target_gs;
|
||||||
|
@ -152,9 +145,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
|
|
||||||
SGVec3d _gsCart, _gsAxis, _gsVertical, _gsBaseline;
|
SGVec3d _gsCart, _gsAxis, _gsVertical, _gsBaseline;
|
||||||
|
|
||||||
FGNavRecordPtr _dme;
|
|
||||||
bool _dmeInRange;
|
|
||||||
|
|
||||||
// CDI properties
|
// CDI properties
|
||||||
bool _toFlag, _fromFlag;
|
bool _toFlag, _fromFlag;
|
||||||
double _cdiDeflection;
|
double _cdiDeflection;
|
||||||
|
@ -163,8 +153,7 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
double _gsNeedleDeflectionNorm;
|
double _gsNeedleDeflectionNorm;
|
||||||
double _gsDirect;
|
double _gsDirect;
|
||||||
|
|
||||||
SGSharedPtr<SGSampleGroup> _sgr;
|
class AudioIdent * _audioIdent;
|
||||||
std::vector<SGPropertyNode_ptr> _tiedNodes;
|
|
||||||
|
|
||||||
bool updateWithPower(double aDt);
|
bool updateWithPower(double aDt);
|
||||||
|
|
||||||
|
@ -176,11 +165,9 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
double adjustILSRange( double stationElev, double aircraftElev,
|
double adjustILSRange( double stationElev, double aircraftElev,
|
||||||
double offsetDegrees, double distance );
|
double offsetDegrees, double distance );
|
||||||
|
|
||||||
void updateAudio();
|
void updateAudio( double dt );
|
||||||
void audioNavidChanged();
|
|
||||||
|
|
||||||
void updateReceiver(double dt);
|
void updateReceiver(double dt);
|
||||||
void updateDME(const SGVec3d& aircraft);
|
|
||||||
void updateGlideSlope(double dt, const SGVec3d& aircraft, double signal_quality_norm);
|
void updateGlideSlope(double dt, const SGVec3d& aircraft, double signal_quality_norm);
|
||||||
void updateGPSSlaved();
|
void updateGPSSlaved();
|
||||||
void updateCDI(double dt);
|
void updateCDI(double dt);
|
||||||
|
@ -193,17 +180,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
bool isOperable() const
|
bool isOperable() const
|
||||||
{ return _operable; }
|
{ return _operable; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Tied-properties helper, record nodes which are tied for easy un-tie-ing
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
void tie(const char* aRelPath, const SGRawValue<T>& aRawValue)
|
|
||||||
{
|
|
||||||
SGPropertyNode_ptr nd = _radio_node->getNode(aRelPath, true);
|
|
||||||
_tiedNodes.push_back(nd);
|
|
||||||
nd->tie(aRawValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// implement SGPropertyChangeListener
|
// implement SGPropertyChangeListener
|
||||||
virtual void valueChanged (SGPropertyNode * prop);
|
virtual void valueChanged (SGPropertyNode * prop);
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
include(FlightGearComponent)
|
include(FlightGearComponent)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
audioident.cxx
|
||||||
soundgenerator.cxx
|
soundgenerator.cxx
|
||||||
beacon.cxx
|
beacon.cxx
|
||||||
fg_fx.cxx
|
fg_fx.cxx
|
||||||
|
@ -11,6 +12,7 @@ set(SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
|
audioident.hxx
|
||||||
soundgenerator.hxx
|
soundgenerator.hxx
|
||||||
beacon.hxx
|
beacon.hxx
|
||||||
fg_fx.hxx
|
fg_fx.hxx
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
noinst_LIBRARIES = libSound.a
|
noinst_LIBRARIES = libSound.a
|
||||||
|
|
||||||
libSound_a_SOURCES = \
|
libSound_a_SOURCES = \
|
||||||
|
audioident.cxx audioident.hxx \
|
||||||
soundgenerator.cxx soundgenerator.hxx \
|
soundgenerator.cxx soundgenerator.hxx \
|
||||||
beacon.cxx beacon.hxx \
|
beacon.cxx beacon.hxx \
|
||||||
fg_fx.cxx fg_fx.hxx \
|
fg_fx.cxx fg_fx.hxx \
|
||||||
|
|
141
src/Sound/audioident.cxx
Normal file
141
src/Sound/audioident.cxx
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
// audioident.cxx -- audible station identifiers
|
||||||
|
//
|
||||||
|
// Written by Torsten Dreyer, September 2011
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "audioident.hxx"
|
||||||
|
#include <simgear/sg_inlines.h>
|
||||||
|
|
||||||
|
#include <Main/globals.hxx>
|
||||||
|
#include <Sound/Morse.hxx>
|
||||||
|
|
||||||
|
AudioIdent::AudioIdent( const std::string & fx_name, const double interval_secs, const int frequency_hz ) :
|
||||||
|
_fx_name(fx_name),
|
||||||
|
_frequency(frequency_hz),
|
||||||
|
_timer(0.0),
|
||||||
|
_interval(interval_secs),
|
||||||
|
_running(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioIdent::init()
|
||||||
|
{
|
||||||
|
_timer = 0.0;
|
||||||
|
_ident = "";
|
||||||
|
_running = false;
|
||||||
|
_sgr = globals->get_soundmgr()->find("avionics", true);
|
||||||
|
_sgr->tie_to_listener();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioIdent::stop()
|
||||||
|
{
|
||||||
|
if( _sgr->exists( _fx_name ) )
|
||||||
|
_sgr->stop( _fx_name );
|
||||||
|
_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioIdent::start()
|
||||||
|
{
|
||||||
|
_timer = _interval;
|
||||||
|
_sgr->play_once(_fx_name);
|
||||||
|
_running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioIdent::setVolumeNorm( double volumeNorm )
|
||||||
|
{
|
||||||
|
SG_CLAMP_RANGE(volumeNorm, 0.0, 1.0);
|
||||||
|
|
||||||
|
SGSoundSample *sound = _sgr->find( _fx_name );
|
||||||
|
|
||||||
|
if ( sound != NULL ) {
|
||||||
|
sound->set_volume( volumeNorm );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioIdent::setIdent( const std::string & ident, double volumeNorm )
|
||||||
|
{
|
||||||
|
if( _ident == ident ) {
|
||||||
|
if( false == _ident.empty() )
|
||||||
|
setVolumeNorm( volumeNorm );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
stop();
|
||||||
|
|
||||||
|
if ( _sgr->exists( _fx_name ) )
|
||||||
|
_sgr->remove( _fx_name );
|
||||||
|
|
||||||
|
if( false == ident.empty() ) {
|
||||||
|
|
||||||
|
SGSoundSample* sound = FGMorse::instance()->make_ident(ident, _frequency );
|
||||||
|
sound->set_volume( volumeNorm );
|
||||||
|
if (!_sgr->add( sound, _fx_name )) {
|
||||||
|
SG_LOG(SG_SOUND, SG_WARN, "Failed to add sound '" << _fx_name << "' for ident '" << ident << "'" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
_ident = ident;
|
||||||
|
|
||||||
|
} catch (sg_io_exception& e) {
|
||||||
|
SG_LOG(SG_SOUND, SG_ALERT, e.getFormattedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioIdent::update( double dt )
|
||||||
|
{
|
||||||
|
// single-shot
|
||||||
|
if( false == _running || _interval < SGLimitsd::min() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
_timer -= dt;
|
||||||
|
|
||||||
|
if( _timer < SGLimitsd::min() ) {
|
||||||
|
_timer = _interval;
|
||||||
|
stop();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: shall transmit at least 6 wpm (ICAO Annex 10 - 3.5.3.6.3)
|
||||||
|
DMEAudioIdent::DMEAudioIdent( const std::string & fx_name )
|
||||||
|
: AudioIdent( fx_name, 40, FGMorse::HI_FREQUENCY )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//FIXME: for co-located VOR/DME or ILS/DME, assign four time-slots
|
||||||
|
// 3xVOR/ILS ident, 1xDME ident
|
||||||
|
|
||||||
|
// FIXME: shall transmit at approx. 7 wpm (ICAO Annex 10 - 3.3.6.5.1)
|
||||||
|
VORAudioIdent::VORAudioIdent( const std::string & fx_name )
|
||||||
|
: AudioIdent( fx_name, 10, FGMorse::LO_FREQUENCY )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: LOCAudioIdent at approx 7wpm (ICAO Annex 10 - 3.1.3.9.4)
|
||||||
|
// not less than six times per minute at approx equal intervals
|
||||||
|
// frequency 1020+/-50Hz (3.1.3.9.2)
|
||||||
|
|
||||||
|
// FIXME: NDBAudioIdent at approx 7 wpm (ICAO ANNEX 10 - 3.4.5.1)
|
||||||
|
// at least once every 10s (3.4.5.2.1)
|
||||||
|
// frequency 1020+/-50Hz or 400+/-25Hz (3.4.5.4)
|
65
src/Sound/audioident.hxx
Normal file
65
src/Sound/audioident.hxx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// audioident.hxx -- audible station identifiers
|
||||||
|
//
|
||||||
|
// Written by Torsten Dreyer, September 2011
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _FGAUDIOIDENT_HXX
|
||||||
|
#define _FGAUDIOIDENT_HXX
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
|
|
||||||
|
class AudioIdent {
|
||||||
|
public:
|
||||||
|
AudioIdent( const std::string & fx_name, const double interval_secs, const int frequency );
|
||||||
|
void init();
|
||||||
|
void setVolumeNorm( double volumeNorm );
|
||||||
|
void setIdent( const std::string & ident, double volumeNorm );
|
||||||
|
|
||||||
|
void update( double dt );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void stop();
|
||||||
|
void start();
|
||||||
|
|
||||||
|
SGSharedPtr<SGSampleGroup> _sgr;
|
||||||
|
std::string _fx_name;
|
||||||
|
const int _frequency;
|
||||||
|
std::string _ident;
|
||||||
|
double _timer;
|
||||||
|
double _interval;
|
||||||
|
bool _running;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DMEAudioIdent : public AudioIdent {
|
||||||
|
public:
|
||||||
|
DMEAudioIdent( const std::string & fx_name );
|
||||||
|
};
|
||||||
|
|
||||||
|
class VORAudioIdent : public AudioIdent {
|
||||||
|
public:
|
||||||
|
VORAudioIdent( const std::string & fx_name );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _FGAUDIOIDENT_HXX
|
|
@ -26,6 +26,12 @@
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
static const char DI = '1';
|
||||||
|
static const char DIT = '1';
|
||||||
|
static const char DA = '2';
|
||||||
|
static const char DAH = '2';
|
||||||
|
static const char END = '0';
|
||||||
|
|
||||||
static const char alphabet[26][4] = {
|
static const char alphabet[26][4] = {
|
||||||
{ DI, DAH, END, END }, /* A */
|
{ DI, DAH, END, END }, /* A */
|
||||||
{ DA, DI, DI, DIT }, /* B */
|
{ DA, DI, DI, DIT }, /* B */
|
||||||
|
|
|
@ -75,23 +75,6 @@
|
||||||
// Hz for the VOR ident.
|
// Hz for the VOR ident.
|
||||||
|
|
||||||
|
|
||||||
static const char DI = '1';
|
|
||||||
static const char DIT = '1';
|
|
||||||
static const char DA = '2';
|
|
||||||
static const char DAH = '2';
|
|
||||||
static const char END = '0';
|
|
||||||
|
|
||||||
static const int BYTES_PER_SECOND = 22050;
|
|
||||||
// static const int BEAT_LENGTH = 240; // milleseconds (5 wpm)
|
|
||||||
static const int BEAT_LENGTH = 92; // milleseconds (13 wpm)
|
|
||||||
static const int TRANSITION_BYTES = (int)(0.005 * BYTES_PER_SECOND);
|
|
||||||
static const int COUNT_SIZE = BYTES_PER_SECOND * BEAT_LENGTH / 1000;
|
|
||||||
static const int DIT_SIZE = 2 * COUNT_SIZE; // 2 counts
|
|
||||||
static const int DAH_SIZE = 4 * COUNT_SIZE; // 4 counts
|
|
||||||
static const int SPACE_SIZE = 3 * COUNT_SIZE; // 3 counts
|
|
||||||
static const int LO_FREQUENCY = 1020; // AIM 1-1-7 (f) specified in Hz
|
|
||||||
static const int HI_FREQUENCY = 1350; // AIM 1-1-7 (f) specified in Hz
|
|
||||||
|
|
||||||
// manages everything we need to know for an individual sound sample
|
// manages everything we need to know for an individual sound sample
|
||||||
class FGMorse : public FGSoundGenerator {
|
class FGMorse : public FGSoundGenerator {
|
||||||
|
|
||||||
|
@ -113,6 +96,17 @@ private:
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static const int BYTES_PER_SECOND = 22050;
|
||||||
|
// static const int BEAT_LENGTH = 240; // milleseconds (5 wpm)
|
||||||
|
static const int BEAT_LENGTH = 92; // milleseconds (13 wpm)
|
||||||
|
static const int TRANSITION_BYTES = (int)(0.005 * BYTES_PER_SECOND);
|
||||||
|
static const int COUNT_SIZE = BYTES_PER_SECOND * BEAT_LENGTH / 1000;
|
||||||
|
static const int DIT_SIZE = 2 * COUNT_SIZE; // 2 counts
|
||||||
|
static const int DAH_SIZE = 4 * COUNT_SIZE; // 4 counts
|
||||||
|
static const int SPACE_SIZE = 3 * COUNT_SIZE; // 3 counts
|
||||||
|
static const int LO_FREQUENCY = 1020; // AIM 1-1-7 (f) specified in Hz
|
||||||
|
static const int HI_FREQUENCY = 1350; // AIM 1-1-7 (f) specified in Hz
|
||||||
|
|
||||||
|
|
||||||
FGMorse();
|
FGMorse();
|
||||||
~FGMorse();
|
~FGMorse();
|
||||||
|
|
Loading…
Add table
Reference in a new issue