]> git.mxchange.org Git - flightgear.git/commitdiff
Add 8.33 kHz support to the commradio
authorTorsten Dreyer <torsten@t3r.de>
Wed, 27 May 2015 11:23:45 +0000 (13:23 +0200)
committerTorsten Dreyer <torsten@t3r.de>
Thu, 28 May 2015 10:04:23 +0000 (12:04 +0200)
Usage:
Add
  <comm-radio>
    <name>comm</name>
    <number>0</number>
    <eight-point-three type="bool">true</eight-point-three>
  </comm-radio>
to the instrumentation.xml

If eight-point-three is disabled nor not present, previous functionality is unchanged

If eight-point-three is enabled,
set
/instrumentation/comm[x]/frequencies/[selected|standby]-mhz
to the desired 8.33 channel (118.000..136.990) or
/instrumentation/comm[x]/frequencies/[selected|standby]-channel
to the desired channel-number (0..3039).

Valid channels are:
xxx.000
xxx.005
xxx.010
xxx.015
xxx.025
xxx.030
xxx.035
xxx.040
xxx.050
xxx.055
xxx.060
xxx.065
xxx.075
xxx.080
xxx.085
xxx.090
where 118.0 <= xxx <= 136.990

src/Instrumentation/commradio.cxx
src/Instrumentation/frequencyformatter.hxx

index 9c8265a6ea22e88f8168d09b03b80d2c9e127f8d..3fdd62956c7414e64b9845e6ebb6f50887e9314d 100644 (file)
@@ -341,6 +341,119 @@ void MetarBridge::valueChanged(SGPropertyNode * node)
   }
 }
 
+/* ------------- 8.3kHz Channel implementation ---------------------- */
+
+class EightPointThreeFrequencyFormatter :
+               public FrequencyFormatterBase,
+               public SGPropertyChangeListener {
+public:
+       EightPointThreeFrequencyFormatter( SGPropertyNode_ptr root,
+                       const char * channel,
+                       const char * fmt,
+                       const char * width,
+                       const char * frq,
+                       const char * cnum ) :
+               _channel( root, channel ),
+               _frequency( root, frq ),
+               _channelSpacing( root, width ),
+               _formattedChannel( root, fmt ),
+               _channelNum( root, cnum )
+       {
+               // ensure properties exist.
+               _channel.node(true);
+               _frequency.node(true);
+               _channelSpacing.node(true);
+               _channelNum.node(true);
+               _formattedChannel.node(true);
+
+               _channel.node()->addChangeListener( this, true );
+               _channelNum.node()->addChangeListener( this, true );
+       }
+
+       virtual ~EightPointThreeFrequencyFormatter()
+       {
+                 _channel.node()->removeChangeListener( this );
+                 _channelNum.node()->removeChangeListener( this );
+       }
+
+private:
+       EightPointThreeFrequencyFormatter( const EightPointThreeFrequencyFormatter & );
+       EightPointThreeFrequencyFormatter & operator = ( const EightPointThreeFrequencyFormatter & );
+
+       void valueChanged (SGPropertyNode * prop) {
+               if( prop == _channel.node() )
+                       setFrequency(prop->getDoubleValue());
+               else if( prop == _channelNum.node() )
+                       setChannel(prop->getIntValue());
+       }
+
+       void setChannel( int channel ) {
+               channel %= 3040;
+               if( channel < 0 ) channel += 3040;
+               double f = 118.000 + 0.025*(channel/4) + 0.005*(channel%4);
+               if( f != _channel )     _channel = f;
+       }
+
+       void setFrequency( double channel ) {
+               // format as fixed decimal "nnn.nnn"
+               std::ostringstream buf;
+               buf << std::fixed
+                   << std::setw(6)
+                   << std::setfill('0')
+                   << std::setprecision(3)
+                   << _channel;
+               _formattedChannel = buf.str();
+
+               // sanitize range and round to nearest kHz.
+               unsigned c = static_cast<int>(SGMiscd::round(SGMiscd::clip( channel, 118.0, 136.99 ) * 1000));
+
+               if ( (c % 25)  == 0 ) {
+                       // legacy 25kHz channels continue to be just that.
+                       _channelSpacing = 25.0;
+                       _frequency = c / 1000.0;
+
+                       int channelNum = (c-118000)/25*4;
+                       if( channelNum != _channelNum ) _channelNum = channelNum;
+
+                       if( _frequency != channel ) {
+                               _channel = _frequency; //triggers recursion
+                       }
+               } else {
+                       _channelSpacing = 8.33;
+
+                       // 25kHz base frequency: xxx.000, xxx.025, xxx.050, xxx.075
+                       unsigned base25 = (c/25) * 25;
+
+                       // add n*8.33 to the 25kHz frequency
+                       unsigned subChannel = SGMisc<unsigned>::clip((c - base25)/5-1, 0, 2 );
+
+                       _frequency = (base25 + 8.33 * subChannel)/1000.0;
+
+                       int channelNum = (base25-118000)/25*4 + subChannel+1;
+                       if( channelNum != _channelNum ) _channelNum = channelNum;
+
+                       // set to correct channel on bogous input
+                       double sanitizedChannel = (base25 + 5*(subChannel+1))/1000.0;
+                       if( sanitizedChannel != channel ) {
+                               _channel = sanitizedChannel; // triggers recursion
+                       }
+               }
+       }
+
+       double getFrequency() const {
+               return _channel;
+       }
+
+
+    PropertyObject<double> _channel;
+    PropertyObject<double> _frequency;
+    PropertyObject<double> _channelSpacing;
+    PropertyObject<string> _formattedChannel;
+    PropertyObject<int>   _channelNum;
+
+};
+
+
 /* ------------- The CommRadio implementation ---------------------- */
 
 class CommRadioImpl: public CommRadio, OutputProperties {
@@ -365,8 +478,8 @@ private:
   #if defined(ENABLE_FLITE)
   AtisSpeaker _atisSpeaker;
   #endif
-  FrequencyFormatter _useFrequencyFormatter;
-  FrequencyFormatter _stbyFrequencyFormatter;
+  SGSharedPtr<FrequencyFormatterBase> _useFrequencyFormatter;
+  SGSharedPtr<FrequencyFormatterBase> _stbyFrequencyFormatter;
   const SignalQualityComputerRef _signalQualityComputer;
 
   double _stationTTL;
@@ -383,6 +496,7 @@ private:
   PropertyObject<string> _atis;
   PropertyObject<bool> _addNoise;
   PropertyObject<double> _cutoffSignalQuality;
+
 };
 
 CommRadioImpl::CommRadioImpl(SGPropertyNode_ptr node)
@@ -390,12 +504,6 @@ CommRadioImpl::CommRadioImpl(SGPropertyNode_ptr node)
         fgGetNode("/instrumentation", true)->getNode(node->getStringValue("name", "comm"), node->getIntValue("number", 0), true)),
         _num(node->getIntValue("number", 0)),
         _metarBridge(new MetarBridge()),
-        _useFrequencyFormatter(_rootNode->getNode("frequencies/selected-mhz", true),
-            _rootNode->getNode("frequencies/selected-mhz-fmt", true), 0.025, 118.0, 137.0),
-
-        _stbyFrequencyFormatter(_rootNode->getNode("frequencies/standby-mhz", true),
-            _rootNode->getNode("frequencies/standby-mhz-fmt", true), 0.025, 118.0, 137.0),
-
         _signalQualityComputer(new SimpleDistanceSquareSignalQualityComputer()),
 
         _stationTTL(0.0),
@@ -410,6 +518,36 @@ CommRadioImpl::CommRadioImpl(SGPropertyNode_ptr node)
         _addNoise(_rootNode->getNode("add-noise", true)),
         _cutoffSignalQuality(_rootNode->getNode("cutoff-signal-quality", true))
 {
+  if( node->getBoolValue("eight-point-three", false ) ) {
+         _useFrequencyFormatter = new EightPointThreeFrequencyFormatter(
+                 _rootNode->getNode("frequencies", true),
+                 "selected-mhz",
+                 "selected-mhz-fmt",
+                 "selected-channel-width-khz",
+                 "selected-real-frequency-mhz",
+                 "selected-channel"
+                 );
+         _stbyFrequencyFormatter = new EightPointThreeFrequencyFormatter(
+                 _rootNode->getNode("frequencies", true),
+                 "standby-mhz",
+                 "standby-mhz-fmt",
+                 "standby-channel-width-khz",
+                 "standby-real-frequency-mhz",
+                 "standby-channel"
+                 );
+  } else {
+      _useFrequencyFormatter = new FrequencyFormatter(
+         _rootNode->getNode("frequencies/selected-mhz", true),
+          _rootNode->getNode("frequencies/selected-mhz-fmt", true),
+                 0.025, 118.0, 137.0);
+
+      _stbyFrequencyFormatter = new FrequencyFormatter(
+         _rootNode->getNode("frequencies/standby-mhz", true),
+          _rootNode->getNode("frequencies/standby-mhz-fmt", true),
+                 0.025, 118.0, 137.0);
+
+
+  }
 }
 
 CommRadioImpl::~CommRadioImpl()
@@ -520,8 +658,8 @@ void CommRadioImpl::update(double dt)
     return;
   }
 
-  if (_frequency != _useFrequencyFormatter.getFrequency()) {
-    _frequency = _useFrequencyFormatter.getFrequency();
+  if (_frequency != _useFrequencyFormatter->getFrequency()) {
+    _frequency = _useFrequencyFormatter->getFrequency();
     _stationTTL = 0.0;
   }
 
index f36c785049d0499de9ea7b3359f3a5823a2e783c..684e413fdc5a178adfee32f9bad953b96d66019b 100644 (file)
@@ -2,8 +2,17 @@
 #define __FREQUENCY_FORMATTER_HXX
 
 /* ------------- A NAV/COMM Frequency formatter ---------------------- */
+class FrequencyFormatterBase : public SGReferenced {
+public:
+         virtual ~FrequencyFormatterBase()
+         {
+         }
+
+         virtual double getFrequency() const = 0;
+
+};
 
-class FrequencyFormatter : public SGPropertyChangeListener {
+class FrequencyFormatter : public FrequencyFormatterBase, public SGPropertyChangeListener {
 public:
   FrequencyFormatter( SGPropertyNode_ptr freqNode, SGPropertyNode_ptr fmtFreqNode, double channelSpacing, double min, double max ) :
     _freqNode( freqNode ),
@@ -12,10 +21,9 @@ public:
     _min(min),
     _max(max)
   {
-    _freqNode->addChangeListener( this );
-    valueChanged(_freqNode);
+    _freqNode->addChangeListener( this, true );
   }
-  ~FrequencyFormatter()
+  virtual ~FrequencyFormatter()
   {
     _freqNode->removeChangeListener( this );
   }
@@ -32,7 +40,7 @@ public:
     _fmtFreqNode->setStringValue( buf.str() );
   }
 
-  double getFrequency() const 
+  virtual double getFrequency() const
   {
     double d = SGMiscd::roundToInt(_freqNode->getDoubleValue() / _channelSpacing) * _channelSpacing;
     // strip last digit, do not round