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
19namespace 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
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
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
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 const char * debugBool(bool x)
Gets a debug output string for a Boolean value.
virtual int debug(const char *format,...)
Outputs debug information.
virtual int getConfigurationValueAsInt(const std::string &key) const
Gets a named configuration value as an integer value.
virtual double getConfigurationValueAsDbl(const std::string &key) const
Gets a named configuration value as a double value.
virtual bool setConfigurationValueToInt(const std::string &key, const int value)
Sets a named configuration value to an integer value.
virtual bool setConfigurationValueToDbl(const std::string &key, const double value)
Sets a named configuration value to a double value.
A configuration dictionary.
virtual bool hasKey(const std::string &key) const
Determines if the dictionary has the given key.
virtual bool enable(bool enabled=true)
Enables this component.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this component.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
virtual RadioComponent & operator=(const RadioComponent &other)
Assignment operator for RadioComponent objects.
RadioComponent(const std::string &name="<unknown>", int index=0, RadioHandler *parent=NULL, bool debug=false)
Constructs a RadioComponent object.
Generic radio handler class.
virtual bool enable(bool enabled=true)
Enables this component.
virtual int getTimingAdjustment() const
Gets the timing adjustment setting.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this component.
virtual int getFilter() const
Gets the filter setting.
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 double getAttenuation() const
Gets the attenuation.
virtual bool setAttenuation(double atten)
Sets the attenuation.
virtual bool executeEnableCommand(int index, bool &enabled)
Executes the tuner enable command.
virtual BasicDoubleList getFrequencyRange() const
Gets the tunable frequency range.
virtual bool setFrequency(double freq)
Sets the tuned frequency.
virtual bool executeAttenCommand(int index, double &atten)
Executes the tuner attenuation set command.
virtual bool isAgcSupported() const
Gets whether or not the tuner supports AGC.
virtual double getFrequency() const
Gets the tuned frequency.
virtual bool executeFreqCommand(int index, double &freq)
Executes the tuner frequency set command.
virtual bool executeTimingAdjustmentCommand(int index, int &timingAdj)
Executes the tuner timing adjustment command.
virtual BasicDoubleList getAttenuationRange() const
Gets the attenuation range.
virtual TunerComponent & operator=(const TunerComponent &other)
Assignment operator for TunerComponent objects.
virtual void queryConfiguration()
Tells the component to query its hardware configuration in order to create its configuration dictiona...
virtual bool setTimingAdjustment(int timingAdj)
Sets the timing adjustment setting.
virtual bool executeFreqQuery(int index, double &freq)
Executes the tuner frequency query command.
virtual bool executeFilterQuery(int index, int &filter)
Executes the tuner filter query command.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
virtual double getAttenuationRes() const
Gets the attenuation resolution.
virtual bool setFrequencyRangeMax(double freq)
Sets the maximum end of the tunable frequency range.
virtual bool setFilter(int filter)
Sets the filter setting.
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
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 double getFrequencyUnit() const
Gets the tuned frequency units.
virtual ~TunerComponent()
Destroys a TunerComponent object.
virtual bool executeFilterCommand(int index, int &filter)
Executes the tuner filter set command.
virtual bool executeAttenQuery(int index, double &atten)
Executes the tuner attenuation query command.
virtual double getFrequencyRes() const
Gets the tuned frequency resolution.
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.
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.
Provides programming elements for driving CRS NDR-class radios.
Defines functionality for LibCyberRadio applications.
Definition App.h:24
BASIC_LIST_CONTAINER< double > BasicDoubleList
Type representing a list of doubles.
Definition BasicList.h:29
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
Definition BasicList.h:25