libcyberradio  22.01.24
TunerComponent.cpp
1 /***************************************************************************
2  * \file TunerComponent.cpp
3  * \brief Defines the basic tuner interface for an NDR-class radio.
4  * \author DA
5  * \author NH
6  * \author MN
7  * \copyright (c) 2017 CyberRadio Solutions, Inc. All rights reserved.
8  *
9  ***************************************************************************/
10 
11 #include "LibCyberRadio/Driver/TunerComponent.h"
12 #include "LibCyberRadio/Driver/RadioHandler.h"
13 #include "LibCyberRadio/Common/Pythonesque.h"
14 #include <boost/lexical_cast.hpp>
15 #include <sstream>
16 #include <iomanip>
17 
18 
19 namespace LibCyberRadio
20 {
21  namespace Driver
22  {
23 
25  const std::string& name,
26  int index,
27  RadioHandler* parent,
28  bool debug,
29  double freqRangeMin,
30  double freqRangeMax,
31  double freqRes,
32  double freqUnits,
33  double attRangeMin,
34  double attRangeMax,
35  double attRes,
36  bool agc,
37  double frequency,
38  double attenuation,
39  int filter) :
40  RadioComponent(name, index, parent, debug),
41  _freqRangeMin(freqRangeMin),
42  _freqRangeMax(freqRangeMax),
43  _freqRes(freqRes),
44  _freqUnits(freqUnits),
45  _attRangeMin(attRangeMin),
46  _attRangeMax(attRangeMax),
47  _attRes(attRes),
48  _agc(agc),
49  _frequency(frequency),
50  _attenuation(attenuation),
51  _filter(filter),
52  _timingAdj(0)
53  {
54  // Call init function
56  }
57 
59  {
60  }
61 
63  RadioComponent(other),
64  _freqRangeMin(other._freqRangeMin),
65  _freqRangeMax(other._freqRangeMax),
66  _freqRes(other._freqRes),
67  _freqUnits(other._freqUnits),
68  _attRangeMin(other._attRangeMin),
69  _attRangeMax(other._attRangeMax),
70  _attRes(other._attRes),
71  _agc(other._agc),
72  _frequency(other._frequency),
73  _attenuation(other._attenuation),
74  _filter(other._filter),
75  _timingAdj(other._timingAdj)
76  {
77  }
78 
80  {
82  if ( this != &other )
83  {
84  _freqRangeMin = other._freqRangeMin;
85  _freqRangeMax = other._freqRangeMax;
86  _freqRes = other._freqRes;
87  _freqUnits = other._freqUnits;
88  _attRangeMin = other._attRangeMin;
89  _attRangeMax = other._attRangeMax;
90  _attRes = other._attRes;
91  _agc = other._agc;
92  _frequency = other._frequency;
93  _attenuation = other._attenuation;
94  _filter = other._filter;
95  _timingAdj = other._timingAdj;
96  }
97  return *this;
98  }
99 
100  bool TunerComponent::enable(bool enabled)
101  {
102  bool adjEnabled = enabled;
103  bool ret = false;
104  if ( _config.hasKey("enable") )
105  {
106  ret = executeEnableCommand(_index, adjEnabled);
107  if ( ret )
108  {
109  // If the hardware call succeeds, call the base class version
110  RadioComponent::enable(adjEnabled);
111  }
112  }
113  return ret;
114  }
115 
117  {
118  this->debug("[TunerComponent::setConfiguration] Called\n");
119  // Call the base-class version to modify the configuration dictionary
120  // (this including any enabling/disabling)
121  bool ret = RadioComponent::setConfiguration(cfg);
122  // Use the keys provided in the *incoming* dictionary to determine
123  // what needs to be changed via hardware calls.
124  double adjFrequency = _frequency;
125  double adjAttenuation = _attenuation;
126  int adjFilter = _filter;
127  int adjAdj = _timingAdj;
128  bool freqCmdNeedsExecuting = false;
129  bool attCmdNeedsExecuting = false;
130  bool filCmdNeedsExecuting = false;
131  bool adjCmdNeedsExecuting = false;
132  if ( cfg.hasKey("frequency") && _config.hasKey("frequency") )
133  {
134  adjFrequency = getConfigurationValueAsDbl("frequency");
135  freqCmdNeedsExecuting = true;
136  }
137  if ( cfg.hasKey("attenuation") && _config.hasKey("attenuation") )
138  {
139  adjAttenuation = getConfigurationValueAsDbl("attenuation");
140  attCmdNeedsExecuting = true;
141  }
142  if ( cfg.hasKey("filter") && _config.hasKey("filter") )
143  {
144  adjFilter = getConfigurationValueAsInt("filter");
145  filCmdNeedsExecuting = true;
146  }
147  if ( cfg.hasKey("timingAdj") && _config.hasKey("timingAdj") )
148  {
149  adjAdj = getConfigurationValueAsInt("timingAdj");
150  adjCmdNeedsExecuting = true;
151  }
152  if ( freqCmdNeedsExecuting )
153  {
154  ret &= executeFreqCommand(_index, adjFrequency);
155  }
156  if ( attCmdNeedsExecuting )
157  {
158  ret &= executeAttenCommand(_index, adjAttenuation);
159  }
160  if ( filCmdNeedsExecuting )
161  {
162  ret &= executeFilterCommand(_index, adjFilter);
163  }
164  if ( adjCmdNeedsExecuting )
165  {
166  ret &= executeTimingAdjustmentCommand(_index, adjAdj);
167  }
168  this->debug("[TunerComponent::setConfiguration] Returning %s\n", debugBool(ret));
169  return ret;
170  }
171 
173  {
174  this->debug("[TunerComponent::queryConfiguration] Called\n");
175  if ( _config.hasKey("enable") )
176  {
177  executeEnableQuery(_index, _enabled);
178  }
179  if ( _config.hasKey("frequency") )
180  {
181  executeFreqQuery(_index, _frequency);
182  }
183  if ( _config.hasKey("attenuation") )
184  {
185  executeAttenQuery(_index, _attenuation);
186  }
187  if ( _config.hasKey("filter") )
188  {
189  executeFilterQuery(_index, _filter);
190  }
191  if ( _config.hasKey("timingAdj") )
192  {
193  executeTimingAdjustmentQuery(_index, _timingAdj);
194  }
196  this->debug("[TunerComponent::queryConfiguration] Returning\n");
197  }
198 
200  {
201  return _frequency;
202  }
203 
205  {
206  double adjFreq = freq;
207  bool ret = false;
208  if ( _config.hasKey("frequency") )
209  {
210  ret = executeFreqCommand(_index, adjFreq);
211  if ( ret )
212  {
213  _frequency = adjFreq;
215  }
216  }
217  return ret;
218  }
219 
221  {
222  return _attenuation;
223  }
224 
226  {
227  double adjAtten = atten;
228  bool ret = false;
229  if ( _config.hasKey("attenuation") )
230  {
231  ret = executeAttenCommand(_index, adjAtten);
232  if ( ret )
233  {
234  _attenuation = adjAtten;
236  }
237  }
238  return ret;
239  }
240 
242  {
243  return _filter;
244  }
245 
246  bool TunerComponent::setFilter(int filter)
247  {
248  int adjFilter = filter;
249  bool ret = false;
250  if ( _config.hasKey("filter") )
251  {
252  ret = executeFilterCommand(_index, adjFilter);
253  if ( ret )
254  {
255  _filter = adjFilter;
257  }
258  }
259  return ret;
260  }
261 
263  {
264  return _timingAdj;
265  }
266 
268  {
269  int adjAdj = timingAdj;
270  bool ret = false;
271  if ( _config.hasKey("timingAdj") )
272  {
273  ret = executeTimingAdjustmentCommand(_index, adjAdj);
274  if ( ret )
275  {
276  _timingAdj = adjAdj;
278  }
279  }
280  return ret;
281  }
282 
284  {
285  BasicDoubleList ret;
286  ret.push_back(_freqRangeMin);
287  ret.push_back(_freqRangeMax);
288  return ret;
289  }
290 
292  {
293  return _freqRes;
294  }
295 
297  {
298  return _freqUnits;
299  }
300 
302  {
303  BasicDoubleList ret;
304  ret.push_back(_attRangeMin);
305  ret.push_back(_attRangeMax);
306  return ret;
307  }
308 
310  {
311  return _attRes;
312  }
313 
315  {
316  return _agc;
317  }
318 
320  {
321  _freqRangeMax = freq;
322  return true;
323  }
324 
326  {
327  //this->debug("[TunerComponent::initConfigurationDict] Called\n");
328  _config.clear();
329  _config["enable"] = "";
330  _config["frequency"] = "";
331  _config["attenuation"] = "";
332  _config["filter"] = "";
333  _config["timingAdj"] = "";
334  //this->debug("[TunerComponent::initConfigurationDict] Returning\n");
335  }
336 
338  {
339  this->debug("[TunerComponent::updateConfigurationDict] Called\n");
341  bool res;
342  if ( _config.hasKey("frequency") )
343  {
344  res = setConfigurationValueToDbl("frequency", _frequency);
345  }
346  if ( _config.hasKey("attenuation") )
347  {
348  res = setConfigurationValueToDbl("attenuation", _attenuation);
349  }
350  if ( _config.hasKey("filter") )
351  {
352  res = setConfigurationValueToInt("filter", _filter);
353  }
354  if ( _config.hasKey("timingAdj") )
355  {
356  res = setConfigurationValueToInt("timingAdj", _timingAdj);
357  }
358  //this->debug("[TunerComponent::updateConfigurationDict] Current configuration\n");
359  //this->dumpConfiguration();
360  this->debug("[TunerComponent::updateConfigurationDict] Returning\n");
361  }
362 
363  bool TunerComponent::executeEnableQuery(int index, bool& enabled)
364  {
365  bool ret = false;
366  if ( (_parent != NULL) && (_parent->isConnected()) )
367  {
368  std::ostringstream oss;
369  oss << "TPWR? " << index << "\n";
370  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
371  if ( _parent->getLastCommandErrorInfo() == "" )
372  {
374  Pythonesque::Replace(rsp.front(), "TPWR ", ""),
375  ", ");
376  // vec[0] = Index
377  // vec[1] = Powered state (0=off, 1=on)
378  enabled = (boost::lexical_cast<int>(vec[1]) == 1);
379  ret = true;
380  }
381  }
382  return ret;
383 
384  }
385 
386  // Frequency query uses the NDR308 implementation as the base
387  bool TunerComponent::executeFreqQuery(int index, double& freq)
388  {
389  bool ret = false;
390  if ( (_parent != NULL) && (_parent->isConnected()) )
391  {
392  std::ostringstream oss;
393  oss << "FRQ? " << index << "\n";
394  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
395  if ( _parent->getLastCommandErrorInfo() == "" )
396  {
398  Pythonesque::Replace(rsp.front(), "FRQ ", ""),
399  ", ");
400  // vec[0] = Index
401  // vec[1] = Frequency (MHz)
402  freq = boost::lexical_cast<int>(vec[1]) * _freqUnits;
403  ret = true;
404  }
405  }
406  return ret;
407  }
408 
409  // Attenuation query uses the NDR308 implementation as the base
410  bool TunerComponent::executeAttenQuery(int index, double& atten)
411  {
412  bool ret = false;
413  if ( (_parent != NULL) && (_parent->isConnected()) )
414  {
415  std::ostringstream oss;
416  oss << "ATT? " << index << "\n";
417  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
418  if ( _parent->getLastCommandErrorInfo() == "" )
419  {
421  Pythonesque::Replace(rsp.front(), "ATT ", ""),
422  ", ");
423  // vec[0] = Index
424  // vec[1] = Atten (dB)
425  atten = boost::lexical_cast<double>(vec[1]);
426  ret = true;
427  }
428  }
429  return ret;
430  }
431 
432  // Filter query uses the NDR308 implementation as the base
433  bool TunerComponent::executeFilterQuery(int index, int& filter)
434  {
435  bool ret = false;
436  if ( (_parent != NULL) && (_parent->isConnected()) )
437  {
438  std::ostringstream oss;
439  oss << "FIF? " << index << "\n";
440  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
441  if ( _parent->getLastCommandErrorInfo() == "" )
442  {
444  Pythonesque::Replace(rsp.front(), "FIF ", ""),
445  ", ");
446  // vec[0] = Index
447  // vec[1] = Filter index
448  filter = boost::lexical_cast<int>(vec[1]);
449  ret = true;
450  }
451  }
452  return ret;
453  }
454 
455  bool TunerComponent::executeTimingAdjustmentQuery(int index, int& timingAdj)
456  {
457  bool ret = false;
458  if ( (_parent != NULL) && (_parent->isConnected()) )
459  {
460  std::ostringstream oss;
461  oss << "TADJ? " << index << "\n";
462  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
463  if ( _parent->getLastCommandErrorInfo() == "" )
464  {
466  Pythonesque::Replace(rsp.front(), "TADJ ", ""),
467  ", ");
468  // vec[0] = Index
469  // vec[1] = Timing adjustment
470  timingAdj = boost::lexical_cast<int>(vec[1]);
471  ret = true;
472  }
473  }
474  return ret;
475  }
476 
477  bool TunerComponent::executeEnableCommand(int index, bool& enabled)
478  {
479  bool ret = false;
480  if ( (_parent != NULL) && (_parent->isConnected()) )
481  {
482  std::ostringstream oss;
483  oss << "TPWR " << index
484  << ", " << (enabled ? 1 : 0)
485  << "\n";
486  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
487  if ( _parent->getLastCommandErrorInfo() == "" )
488  {
489  ret = true;
490  }
491  }
492  return ret;
493  }
494 
495  // Frequency command uses the NDR308 implementation as the base
496  bool TunerComponent::executeFreqCommand(int index, double& freq)
497  {
498  bool ret = false;
499  if ( (_parent != NULL) && (_parent->isConnected()) )
500  {
501  std::ostringstream oss;
502  oss << "FRQ " << index
503  << ", " << boost::lexical_cast<int>(freq / _freqUnits)
504  << "\n";
505  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
506  if ( _parent->getLastCommandErrorInfo() == "" )
507  {
508  freq = (int)(freq / _freqUnits) * _freqUnits;
509  ret = true;
510  }
511  }
512  return ret;
513  }
514 
515  // Attenuation command uses the NDR308 implementation as the base
516  bool TunerComponent::executeAttenCommand(int index, double& atten)
517  {
518  bool ret = false;
519  if ( (_parent != NULL) && (_parent->isConnected()) )
520  {
521  std::ostringstream oss;
522  oss << "ATT " << index
523  << ", " << atten
524  << "\n";
525  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
526  if ( _parent->getLastCommandErrorInfo() == "" )
527  {
528  atten = (double)((int)atten);
529  ret = true;
530  }
531  }
532  return ret;
533  }
534 
535  // Filter command uses the NDR308 implementation as the base
536  bool TunerComponent::executeFilterCommand(int index, int& filter)
537  {
538  bool ret = false;
539  if ( (_parent != NULL) && (_parent->isConnected()) )
540  {
541  std::ostringstream oss;
542  oss << "FIF " << index
543  << ", " << filter
544  << "\n";
545  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
546  if ( _parent->getLastCommandErrorInfo() == "" )
547  {
548  ret = true;
549  }
550  }
551  return ret;
552  }
553 
554  bool TunerComponent::executeTimingAdjustmentCommand(int index, int& timingAdj)
555  {
556  bool ret = false;
557  if ( (_parent != NULL) && (_parent->isConnected()) )
558  {
559  std::ostringstream oss;
560  oss << "TADJ " << index
561  << ", " << timingAdj
562  << "\n";
563  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
564  if ( _parent->getLastCommandErrorInfo() == "" )
565  {
566  ret = true;
567  }
568  }
569  return ret;
570  }
571 
572  } // namespace Driver
573 
574 } // namespace LibCyberRadio
575 
virtual bool setTimingAdjustment(int timingAdj)
Sets the timing adjustment setting.
virtual bool executeFreqQuery(int index, double &freq)
Executes the tuner frequency query command.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
virtual TunerComponent & operator=(const TunerComponent &other)
Assignment operator for TunerComponent objects.
virtual bool executeTimingAdjustmentCommand(int index, int &timingAdj)
Executes the tuner timing adjustment command.
virtual bool executeAttenCommand(int index, double &atten)
Executes the tuner attenuation set command.
virtual double getAttenuationRes() const
Gets the attenuation resolution.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
virtual double getFrequencyUnit() const
Gets the tuned frequency units.
virtual bool setConfigurationValueToDbl(const std::string &key, const double value)
Sets a named configuration value to a double value.
virtual bool setFrequencyRangeMax(double freq)
Sets the maximum end of the tunable frequency range.
Base hardware component class.
virtual bool executeFilterCommand(int index, int &filter)
Executes the tuner filter set command.
virtual bool hasKey(const std::string &key) const
Determines if the dictionary has the given key.
virtual void queryConfiguration()
Tells the component to query its hardware configuration in order to create its configuration dictiona...
virtual bool executeEnableQuery(int index, bool &enabled)
Executes the tuner enabled query command.
virtual bool executeTimingAdjustmentQuery(int index, int &timingAdj)
Executes the tuner timing adjustment query.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this component.
BASIC_LIST_CONTAINER< double > BasicDoubleList
Type representing a list of doubles.
Definition: BasicList.h:29
virtual int getConfigurationValueAsInt(const std::string &key) const
Gets a named configuration value as an integer value.
TunerComponent(const std::string &name="TUNER", int index=1, RadioHandler *parent=NULL, bool debug=false, double freqRangeMin=20e6, double freqRangeMax=6000e6, double freqRes=1e6, double freqUnits=1e6, double attRangeMin=0.0, double attRangeMax=30.0, double attRes=1.0, bool agc=false, double frequency=800e6, double attenuation=0.0, int filter=0)
Constructs a TunerComponent object.
virtual BasicDoubleList getFrequencyRange() const
Gets the tunable frequency range.
virtual bool setFilter(int filter)
Sets the filter setting.
virtual double getAttenuation() const
Gets the attenuation.
virtual bool isConnected() const
Gets whether or not the handler is connected.
virtual RadioComponent & operator=(const RadioComponent &other)
Assignment operator for RadioComponent objects.
static std::string Replace(const std::string &str, const std::string &oldstr, const std::string &newstr, int count=INT_MAX)
Replaces occurrences of one substring with another within the given string.
Definition: Pythonesque.cpp:62
virtual double getFrequency() const
Gets the tuned frequency.
virtual bool enable(bool enabled=true)
Enables this component.
virtual bool setAttenuation(double atten)
Sets the attenuation.
static BasicStringList Split(const std::string &str, const std::string &sep, int maxsplit=INT_MAX)
Splits the given string into a list of string tokens.
Definition: Pythonesque.cpp:77
virtual bool enable(bool enabled=true)
Enables this component.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this component.
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
Generic radio handler class.
Definition: RadioHandler.h:54
virtual int debug(const char *format,...)
Outputs debug information.
Definition: Debuggable.cpp:95
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
Definition: BasicList.h:25
virtual bool executeFilterQuery(int index, int &filter)
Executes the tuner filter query command.
virtual bool isAgcSupported() const
Gets whether or not the tuner supports AGC.
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
virtual bool setFrequency(double freq)
Sets the tuned frequency.
A configuration dictionary.
Definition: Configurable.h:51
virtual std::string getLastCommandErrorInfo() const
Gets the error message from the last command attempted.
virtual const char * debugBool(bool x)
Gets a debug output string for a Boolean value.
Definition: Debuggable.cpp:126
Base tuner component class.
virtual int getTimingAdjustment() const
Gets the timing adjustment setting.
virtual bool executeEnableCommand(int index, bool &enabled)
Executes the tuner enable command.
virtual BasicStringList sendCommand(const std::string &cmdString, double timeout=-1)
Sends a command to the radio.
virtual double getConfigurationValueAsDbl(const std::string &key) const
Gets a named configuration value as a double value.
virtual bool executeAttenQuery(int index, double &atten)
Executes the tuner attenuation query command.
virtual ~TunerComponent()
Destroys a TunerComponent object.
virtual bool executeFreqCommand(int index, double &freq)
Executes the tuner frequency set command.
virtual double getFrequencyRes() const
Gets the tuned frequency resolution.
virtual int getFilter() const
Gets the filter setting.
virtual bool setConfigurationValueToInt(const std::string &key, const int value)
Sets a named configuration value to an integer value.
virtual BasicDoubleList getAttenuationRange() const
Gets the attenuation range.