libcyberradio 22.01.24
RadioHandler.cpp
1/***************************************************************************
2 * \file RadioHandler.cpp
3 * \brief Defines the radio handler interface for the NDR551.
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/NDR551/RadioHandler.h"
12#include "LibCyberRadio/Driver/NDR551/DataPort.h"
13#include "LibCyberRadio/Driver/NDR551/NbddcComponent.h"
14#include "LibCyberRadio/Driver/NDR551/TunerComponent.h"
15#include "LibCyberRadio/Driver/NDR551/VitaIfSpec.h"
16#include "LibCyberRadio/Driver/NDR551/WbddcComponent.h"
17//#include "LibCyberRadio/Driver/NDR551/WbddcGroupComponent.h"
18//#include "LibCyberRadio/Driver/NDR551/NbddcGroupComponent.h"
19#include "LibCyberRadio/Common/Pythonesque.h"
20#include <json/json.h>
21#include <sstream>
22#include <cstdio>
23
24
25namespace LibCyberRadio
26{
27
28 namespace Driver
29 {
30
31 namespace NDR551
32 {
33
34 RadioHandler::RadioHandler(bool debug) :
35 ::LibCyberRadio::Driver::RadioHandler(
36 /* const std::string& name */ "NDR551",
37 /* int numTuner */ 4,
38 /* int tunerIndexBase */ 0,
39 /* int numWbddc */ 8,
40 /* int wbddcIndexBase */ 0,
41 /* int numNbddc */ 64,
42 /* int nbddcIndexBase */ 0,
43 /* int numTunerBoards */ 1,
44 /* int maxTunerBw */ 18000,
45 /* int numTransmitters */ 0,
46 /* int transmitterIndexBase */ 0,
47 /* int numDuc */ 0,
48 /* int ducIndexBase */ 0,
49 /* int numWbddcGroups */ 4,
50 /* int wbddcGroupIndexBase */ 1,
51 /* int numNbddcGroups */ 8,
52 /* int nbddcGroupIndexBase */ 1,
53 /* int numDdcGroups */ 0,
54 /* int ddcGroupIndexBase */ 1,
55 /* int numDataPorts */ 4,
56 /* int dataPortIndexBase */ 0,
57 /* int numSimpleIpSetups */ 0,
58 /* double adcRate */ 128.036,
59 /* VitaIfSpec ifSpec */ NDR551::VitaIfSpec(),
60 /* bool debug */ debug)
61 {
62 this->initConfigurationDict();
63 _connModesSupported.push_back("udp");
64 _defaultDeviceInfo = 19091;
65 _transport.setJson(true);
66 if(this->isConnected()){
67 this->queryConfiguration();
68 }
69
70 // Allocate tuner components
71 for (int tuner = _tunerIndexBase;
72 tuner < (_tunerIndexBase + _numTuner); tuner++)
73 {
74
75 _tuners[tuner] = new NDR551::TunerComponent(
76 /* int index */ tuner,
77 /* RadioHandler* parent */ this,
78 /* bool debug */ _debug,
79 /* double frequency */ 800e6,
80 /* double attenuation */ 0.0,
81 /* int filter */ 0);
82 }
83 // Allocate WBDDC components
84 for (int wbddc = _wbddcIndexBase;
85 wbddc < (_wbddcIndexBase + _numWbddc); wbddc++)
86 {
87 _wbddcs[wbddc] = new NDR551::WbddcComponent(
88 /* int index */ wbddc,
89 /* RadioHandler* parent */ this,
90 /* bool debug */ _debug,
91 /* int dataPort */ wbddc % 4,
92 /* int rateIndex */ 40,
93 /* int udpDestination */ 0,
94 /* int vitaEnable */ 0,
95 /* int streamId */ 0);
96 // The Radio comes up at 0...
97 // set a sane number
98 _wbddcs[wbddc]->setRateIndex(40);
99 }
100
101 // Allocate NBDDC components
102 for (int nbddc = _nbddcIndexBase;
103 nbddc < (_nbddcIndexBase + _numNbddc); nbddc++)
104 {
105 _nbddcs[nbddc] = new NDR551::NbddcComponent(
106 /* int index */ nbddc,
107 /* RadioHandler* parent */ this,
108 /* bool debug */ _debug,
109 /* int dataPort */ (int)((nbddc & 0x10) >> 4),
110 /* int rateIndex */ 0,
111 /* int udpDestination */ 0,
112 /* int vitaEnable */ 0,
113 /* int streamId */ 0,
114 /* double frequency */ 0.0,
115 /* int source */ (int)((nbddc & 0x10) >> 4));
116 }
117#if 0
118 // Allocate WBDDC group components
119 for (int group = _wbddcGroupIndexBase;
120 group < (_wbddcGroupIndexBase + _numWbddcGroups); group++)
121 {
122 _wbddcGroups[group] = new NDR551::WbddcGroupComponent(
123 /* int index */ group,
124 /* RadioHandler* parent */ this,
125 /* bool debug */ _debug);
126 }
127 // Allocate NBDDC group components
128 for (int group = _nbddcGroupIndexBase;
129 group < (_nbddcGroupIndexBase + _numNbddcGroups); group++)
130 {
131 _nbddcGroups[group] = new NDR551::NbddcGroupComponent(
132 /* int index */ group,
133 /* RadioHandler* parent */ this,
134 /* bool debug */ _debug);
135 }
136#endif
137 // Allocate data ports
138 for (int dataPort = _dataPortIndexBase;
139 dataPort < (_dataPortIndexBase + _numDataPorts); dataPort++)
140 {
141 _dataPorts[dataPort] = new NDR551::DataPort(
142 /* int index */ dataPort,
143 /* RadioHandler* parent */ this,
144 /* bool debug */ _debug,
145 /* const std::string& sourceIP */ "0.0.0.0");
146 }
147 }
148
152
153 RadioHandler::RadioHandler(const RadioHandler &other) :
155 {
156 }
157
159 {
160 ::LibCyberRadio::Driver::RadioHandler::operator=(other);
161 // Block self-assignment
162 if (this != &other)
163 {
164 }
165 return *this;
166 }
167
168 // Default implementation is the NDR308 pattern
170 {
171 //this->debug("[RadioHandler::initConfigurationDict] Called\n");
172 _config.clear();
173 _config["referenceMode"] = _referenceMode;
174 //this->debug("[RadioHandler::initConfigurationDict] Returning\n");
175 }
176
178 {
179 this->debug("[NDR551::RadioHandler::queryConfiguration] Called\n");
180 // Purge the banner sent over when a connection is made.
181 //BasicStringList rsp = _transport.receive(_defaultTimeout);
182 // Call the base-class queryConfiguration() to retrieve identity info
183 // and query configuration for all components
184 Json::Value root(Json::objectValue);
185 root["msg"] = this->getMessageId();
186 root["cmd"] = "qstatus";
187 Json::Value params(Json::objectValue);
188 root["params"] = params;
189 Json::FastWriter fastWriter;
190 std::string output = fastWriter.write(root);
192 if ( _config.hasKey("referenceMode") )
193 {
194 this->executeReferenceModeQuery(_referenceMode);
195 }
196 this->debug("[NDR551::RadioHandler::queryConfiguration] Returning\n");
197
198 for ( TunerComponentDict::iterator it = _tuners.begin();
199 it != _tuners.end(); it++)
200 {
201 it->second->queryConfiguration();
202 }
203 for ( WbddcComponentDict::iterator it = _wbddcs.begin();
204 it != _wbddcs.end(); it++)
205 {
206 it->second->queryConfiguration();
207 }
208 for ( DataPortDict::iterator it = _dataPorts.begin();
209 it != _dataPorts.end(); it++)
210 {
211 it->second->queryConfiguration();
212 }
213 }
214
215 bool RadioHandler::queryVersionInfo()
216 {
217 this->debug("[NDR551::RadioHandler::queryVersionInfo] Called\n");
218 // First, call the base-class version
219 bool ret = true;
220 Json::Value root(Json::objectValue);
221 root["msg"] = this->getMessageId();
222 root["cmd"] = "qstatus";
223 Json::Value params(Json::objectValue);
224 root["params"] = params;
225 Json::FastWriter fastWriter;
226 std::string output = fastWriter.write(root);
228 // Next, use the hardware version info string to determine
229 // -- unit revision
230 // -- number of tuner boards
231 // -- max tuner bandwidth
232 if ( ret )
233 {
234 // Set number of installed tuner boards to zero
235 _numTunerBoards = 0;
236 // Progress state tracker: 0=Unit, 1=Digital Board, 2+=Tuner Boards
237 int stateTracker = -1;
238 // Split the hardware version info string into separate lines
239 BasicStringList vec = Pythonesque::Split(_versionInfo["hardwareVersion"], "\n");
240 // Iterate over the list
241 for (BasicStringList::iterator it = vec.begin(); it != vec.end(); it++)
242 {
243 // First, determine if the current line indicates a change in progress state
244 if ( it->find("Unit") == 0 )
245 stateTracker = 0;
246 else if ( it->find("Digital Board") == 0 )
247 stateTracker = 1;
248 else if ( it->find("Tuner Quad") == 0 )
249 stateTracker = 2;
250 // Then use the current line to determine other quantities
251 switch( stateTracker )
252 {
253 case 0:
254 if ( it->find(" Revision: ") != std::string::npos )
255 _versionInfo["unitRevision"] = Pythonesque::Replace(*it, " Revision: ", "");
256 break;
257 case 1:
258 break;
259 case 2:
260 if ( ( it->find("Tuner Quad") == 0) && ( it->find("Not Installed") != std::string::npos) )
261 _numTunerBoards++;
262 else if ( it->find("Bandwidth: ") == 0 )
263 {
264 std::string tmp = Pythonesque::Replace(*it, "Bandwidth: ", "");
265 std::istringstream iss(tmp);
266 // Handle the corner case where the radio doesn't report its
267 // maximum tuner bandwidth properly (returning 0 for BW).
268 int value;
269 iss >> value;
270 if ( value != 0 )
271 _maxTunerBw = value;
272 }
273 break;
274 default:
275 break;
276 }
277
278 }
279 }
280 // Calculate number of tuners/WBDDCs from tuner boards
281 _numTuner = std::min(_numTuner, _numTunerBoards * 4);
282 _numWbddc = _numTuner;
283 this->debug("[NDR551::RadioHandler::queryVersionInfo] Number of tuner boards=%d\n", _numTunerBoards);
284 this->debug("[NDR551::RadioHandler::queryVersionInfo] Number of tuners=%d\n", _numTuner);
285 // Deallocate any tuners and DDCs that don't have a tuner board
286 this->debug("[NDR551::RadioHandler::queryVersionInfo] Deallocating nonexistent tuners/WBDDCs\n");
287 TunerComponentDict::iterator it = _tuners.begin();
288 for (; it != _tuners.end(); )
289 {
290 if ( it->first >= (_tunerIndexBase + _numTuner) )
291 {
292 this->debug("[NDR551::RadioHandler::queryVersionInfo] -- Deallocating tuner=%d\n", it->first);
293 delete it->second;
294 _tuners.erase(it++);
295 }
296 else
297 {
298 this->debug("[NDR551::RadioHandler::queryVersionInfo] -- OK tuner=%d\n", it->first);
299 it++;
300 }
301 }
302 WbddcComponentDict::iterator it2 = _wbddcs.begin();
303 for (; it2 != _wbddcs.end(); )
304 {
305 if ( it2->first >= (_wbddcIndexBase + _numWbddc) )
306 {
307 this->debug("[NDR551::RadioHandler::queryVersionInfo] -- Deallocating WBDDC=%d\n", it2->first);
308 delete it2->second;
309 _wbddcs.erase(it2++);
310 }
311 else
312 {
313 this->debug("[NDR551::RadioHandler::queryVersionInfo] -- OK WBDDC=%d\n", it2->first);
314 it2++;
315 }
316 }
317 // Determine frequency range from max bandwidth
318 this->debug("[NDR551::RadioHandler::queryVersionInfo] Max tuner bandwidth=%d MHz\n", _maxTunerBw);
319 for (it = _tuners.begin(); it != _tuners.end(); it++)
320 {
321 it->second->setFrequencyRangeMax(_maxTunerBw * 1e6);
322 }
323 // Debug dump
324 if (ret)
325 {
326 for (BasicStringStringDict::iterator it = _versionInfo.begin(); it != _versionInfo.end(); it++)
327 {
328 this->debug("[NDR551::RadioHandler::queryVersionInfo] %s = \"%s\"\n", it->first.c_str(), it->second.c_str());
329 }
330 }
331 this->debug("[NDR551::RadioHandler::queryVersionInfo] Returning %s\n", debugBool(ret));
332 return ret;
333 }
334
335 // NOTE: The default implementation is the NDR551 implementation,
336 // but this just makes it explicit in the code.
337 bool RadioHandler::executeQueryIDN(std::string& model,
338 std::string& serialNumber)
339 {
340 return ::LibCyberRadio::Driver::RadioHandler::executeQueryIDN(model, serialNumber);
341 }
342
343 // NOTE: The default implementation is the NDR551 implementation,
344 // but this just makes it explicit in the code.
345 bool RadioHandler::executeQueryVER(std::string& softwareVersion,
346 std::string& firmwareVersion,
347 std::string& referenceVersion,
348 std::string& firmwareDate)
349 {
350
351 return ::LibCyberRadio::Driver::RadioHandler::executeQueryVER(softwareVersion,
352 firmwareVersion,
353 referenceVersion,
354 firmwareDate);
355 }
356
357 // NOTE: The default implementation is the NDR551 implementation,
358 // but this just makes it explicit in the code.
359 bool RadioHandler::executeQueryHREV(std::string& hardwareInfo)
360 {
361 return ::LibCyberRadio::Driver::RadioHandler::executeQueryHREV(hardwareInfo);
362 }
363
365 {
366 auto time = std::chrono::system_clock::now();
367 auto now_sec = std::chrono::time_point_cast<std::chrono::seconds>(time);
368 auto epoch = now_sec.time_since_epoch();
369 auto v = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
370 return (uint32_t)v.count();
371 }
372 bool RadioHandler::executeReferenceModeQuery(int& refMode)
373 {
374 this->debug("[NDR551::RadioHandler::queryVersionInfo] Called\n");
375 // First, call the base-class version
376 bool ret = true;
377 Json::Value root(Json::objectValue);
378 root["msg"] = this->getMessageId();
379 root["cmd"] = "qref";
380 Json::Value params(Json::objectValue);
381 root["params"] = params;
382 Json::FastWriter fastWriter;
383 std::string output = fastWriter.write(root);
385 Json::Reader reader;
386 Json::Value returnVal;
387 std::string t = rsp.at(0);
388 printf("%s\n",t.c_str());
389 bool parsingSuccessful = reader.parse( t.c_str(), returnVal ); //parse process
390 refMode = boost::lexical_cast<int>(returnVal["cfg10m"].asInt());
391 return ret;
392 }
393
394 bool RadioHandler::executeReferenceModeCommand(int& refMode)
395 {
396 this->debug("[NDR551::RadioHandler::queryVersionInfo] Called\n");
397 // First, call the base-class version
398 bool ret = true;
399 Json::Value root(Json::objectValue);
400 root["msg"] = this->getMessageId();
401 root["cmd"] = "ref";
402 Json::Value params(Json::objectValue);
403 root["params"] = params;
404 Json::FastWriter fastWriter;
405 std::string output = fastWriter.write(root);
406 return ret;
407 }
408
409 } /* namespace NDR551 */
410
411 } /* namespace Driver */
412
413} /* namespace LibCyberRadio */
virtual const char * debugBool(bool x)
Gets a debug output string for a Boolean value.
virtual int debug(const char *format,...)
Outputs debug information.
Radio handler class for the NDR551.
uint32_t getMessageId(void)
Returns a Time for the msg parameter.
virtual void queryConfiguration()
Tells the radio to query its hardware configuration in order to create its configuration dictionary (...
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
virtual ~RadioHandler()
Destroys a RadioHandler object.
VITA interface specification for the NDR308.
Definition VitaIfSpec.h:38
Generic radio handler class.
virtual RadioHandler & operator=(const RadioHandler &other)
Assignment operator for RadioHandler objects.
virtual BasicStringList sendCommand(const std::string &cmdString, double timeout=-1)
Sends a command to the radio.
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 NDR551 radios.
Definition DataPort.h:36
Provides programming elements for driving CRS NDR-class radios.
Defines functionality for LibCyberRadio applications.
Definition App.h:24
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
Definition BasicList.h:25