SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
plutosdroutput.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include <QDebug>
19 #include <QNetworkReply>
20 #include <QBuffer>
21 
22 #include "SWGDeviceSettings.h"
23 #include "SWGDeviceState.h"
24 #include "SWGDeviceReport.h"
26 
27 #include "dsp/dspcommands.h"
28 #include "dsp/dspengine.h"
29 #include "device/deviceapi.h"
32 
33 #include "plutosdroutput.h"
34 #include "plutosdroutputthread.h"
35 
36 #define PLUTOSDR_BLOCKSIZE_SAMPLES (16*1024) //complex samples per buffer (must be multiple of 64)
37 
40 
42  m_deviceAPI(deviceAPI),
43  m_deviceDescription("PlutoSDROutput"),
44  m_settings(),
45  m_running(false),
46  m_plutoTxBuffer(0),
47  m_plutoSDROutputThread(0)
48 {
49  m_deviceAPI->setNbSinkStreams(1);
50  m_deviceSampleRates.m_addaConnvRate = 0;
51  m_deviceSampleRates.m_bbRateHz = 0;
52  m_deviceSampleRates.m_firRate = 0;
53  m_deviceSampleRates.m_hb1Rate = 0;
54  m_deviceSampleRates.m_hb2Rate = 0;
55  m_deviceSampleRates.m_hb3Rate = 0;
56 
57  suspendBuddies();
58  openDevice();
59  resumeBuddies();
60 
61  m_networkManager = new QNetworkAccessManager();
62  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
63 }
64 
66 {
67  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
68  delete m_networkManager;
69 
71  closeDevice();
72  resumeBuddies();
73 }
74 
76 {
77  delete this;
78 }
79 
81 {
83 }
84 
86 {
88  return false;
89  }
90 
91  if (m_running) stop();
92 
93  // start / stop streaming is done in the thread.
94 
96  qDebug("PlutoSDROutput::start: thread created");
97 
99 
102 
104  m_running = true;
105 
106  return true;
107 }
108 
110 {
111  if (m_plutoSDROutputThread != 0)
112  {
114  delete m_plutoSDROutputThread;
116  }
117 
119  m_running = false;
120 }
121 
122 QByteArray PlutoSDROutput::serialize() const
123 {
124  return m_settings.serialize();
125 }
126 
127 bool PlutoSDROutput::deserialize(const QByteArray& data)
128 {
129  bool success = true;
130 
131  if (!m_settings.deserialize(data))
132  {
134  success = false;
135  }
136 
138  m_inputMessageQueue.push(message);
139 
140  if (m_guiMessageQueue)
141  {
143  m_guiMessageQueue->push(messageToGUI);
144  }
145 
146  return success;
147 }
148 
150 {
151  return m_deviceDescription;
152 }
154 {
156 }
157 
159 {
161 }
162 
163 void PlutoSDROutput::setCenterFrequency(qint64 centerFrequency)
164 {
166  settings.m_centerFrequency = centerFrequency;
167 
168  MsgConfigurePlutoSDR* message = MsgConfigurePlutoSDR::create(settings, false);
169  m_inputMessageQueue.push(message);
170 
171  if (m_guiMessageQueue)
172  {
173  MsgConfigurePlutoSDR* messageToGUI = MsgConfigurePlutoSDR::create(settings, false);
174  m_guiMessageQueue->push(messageToGUI);
175  }
176 }
177 
179 {
180  if (MsgConfigurePlutoSDR::match(message))
181  {
182  MsgConfigurePlutoSDR& conf = (MsgConfigurePlutoSDR&) message;
183  qDebug() << "PlutoSDROutput::handleMessage: MsgConfigurePlutoSDR";
184 
185  if (!applySettings(conf.getSettings(), conf.getForce()))
186  {
187  qDebug("PlutoSDROutput::handleMessage config error");
188  }
189 
190  return true;
191  }
192  else if (DevicePlutoSDRShared::MsgCrossReportToBuddy::match(message)) // message from buddy
193  {
199  PlutoSDROutputSettings newSettings = m_settings;
200  newSettings.m_lpfFIREnable = conf.isLpfFirEnable();
201  applySettings(newSettings);
202 
203  return true;
204  }
205  else if (MsgStartStop::match(message))
206  {
207  MsgStartStop& cmd = (MsgStartStop&) message;
208  qDebug() << "PlutoSDROutput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
209 
210  if (cmd.getStartStop())
211  {
213  {
215  }
216  }
217  else
218  {
220  }
221 
224  }
225 
226  return true;
227  }
228  else
229  {
230  return false;
231  }
232 }
233 
235 {
237 
238  // look for Rx buddy and get reference to common parameters
239  if (m_deviceAPI->getSourceBuddies().size() > 0) // then sink
240  {
241  qDebug("PlutoSDROutput::openDevice: look at Rx buddy");
242 
243  DeviceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0];
244  DevicePlutoSDRShared* buddySharedPtr = (DevicePlutoSDRShared*) sourceBuddy->getBuddySharedPtr();
245  m_deviceShared.m_deviceParams = buddySharedPtr->m_deviceParams;
246 
248  {
249  qCritical("PlutoSDROutput::openDevice: cannot get device parameters from Rx buddy");
250  return false; // the device params should have been created by the buddy
251  }
252  else
253  {
254  qDebug("PlutoSDROutput::openDevice: getting device parameters from Rx buddy");
255  }
256  }
257  // There is no buddy then create the first PlutoSDR common parameters
258  // open the device this will also populate common fields
259  else
260  {
261  qDebug("PlutoSDROutput::openDevice: open device here");
262 
264  char serial[256];
265  strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
267  }
268 
269  m_deviceAPI->setBuddySharedPtr(&m_deviceShared); // propagate common parameters to API
270 
271  // acquire the channel
273  plutoBox->openTx();
274  m_plutoTxBuffer = plutoBox->createTxBuffer(PLUTOSDR_BLOCKSIZE_SAMPLES, false); // PlutoSDR buffer size is counted in number of (I,Q) samples
275 
276  return true;
277 }
278 
280 {
281  if (m_deviceShared.m_deviceParams->getBox() == 0) { // was never open
282  return;
283  }
284 
285  if (m_deviceAPI->getSourceBuddies().size() == 0)
286  {
290  }
291 }
292 
294 {
295  // suspend Rx buddy's thread
296 
297  for (unsigned int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++)
298  {
300  DevicePlutoSDRShared *buddyShared = (DevicePlutoSDRShared *) buddy->getBuddySharedPtr();
301 
302  if (buddyShared->m_thread) {
303  buddyShared->m_thread->stopWork();
304  }
305  }
306 }
307 
309 {
310  // resume Rx buddy's thread
311 
312  for (unsigned int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++)
313  {
315  DevicePlutoSDRShared *buddyShared = (DevicePlutoSDRShared *) buddy->getBuddySharedPtr();
316 
317  if (buddyShared->m_thread) {
318  buddyShared->m_thread->startWork();
319  }
320  }
321 }
322 
323 bool PlutoSDROutput::applySettings(const PlutoSDROutputSettings& settings, bool force)
324 {
325  bool forwardChangeOwnDSP = false;
326  bool forwardChangeOtherDSP = false;
327  bool ownThreadWasRunning = false;
328  bool suspendAllOtherThreads = false; // All others means Rx in fact
330  QLocale loc;
331  QList<QString> reverseAPIKeys;
332 
333  qDebug().noquote() << "PlutoSDROutput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz"
334  << " m_devSampleRate: " << loc.toString(m_settings.m_devSampleRate) << "S/s"
335  << " m_LOppmTenths: " << m_settings.m_LOppmTenths
336  << " m_lpfFIREnable: " << m_settings.m_lpfFIREnable
337  << " m_lpfFIRBW: " << loc.toString(m_settings.m_lpfFIRBW)
338  << " m_lpfFIRlog2Interp: " << m_settings.m_lpfFIRlog2Interp
339  << " m_lpfFIRGain: " << m_settings.m_lpfFIRGain
340  << " m_log2Interp: " << loc.toString(1<<m_settings.m_log2Interp)
341  << " m_lpfBW: " << loc.toString(m_settings.m_lpfBW)
342  << " m_att: " << m_settings.m_att
343  << " m_antennaPath: " << (int) m_settings.m_antennaPath
344  << " m_transverterMode: " << m_settings.m_transverterMode
345  << " m_transverterDeltaFrequency: " << m_settings.m_transverterDeltaFrequency
346  << " force: " << force;
347 
348  if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) {
349  reverseAPIKeys.append("devSampleRate");
350  }
351  if ((m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force) {
352  reverseAPIKeys.append("lpfFIREnable");
353  }
354  if ((m_settings.m_lpfFIRlog2Interp != settings.m_lpfFIRlog2Interp) || force) {
355  reverseAPIKeys.append("lpfFIRlog2Interp");
356  }
357  if ((m_settings.m_lpfFIRBW != settings.m_lpfFIRBW) || force) {
358  reverseAPIKeys.append("lpfFIRBW");
359  }
360  if ((m_settings.m_lpfFIRGain != settings.m_lpfFIRGain) || force) {
361  reverseAPIKeys.append("lpfFIRGain");
362  }
363  if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) {
364  reverseAPIKeys.append("LOppmTenths");
365  }
366 
367  // determine if buddies threads or own thread need to be suspended
368 
369  // changes affecting all buddies can occur if
370  // - device to host sample rate is changed
371  // - FIR filter is enabled or disabled
372  // - FIR filter is changed
373  // - LO correction is changed
374  if ((m_settings.m_devSampleRate != settings.m_devSampleRate) ||
375  (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) ||
377  (settings.m_lpfFIRBW != m_settings.m_lpfFIRBW) ||
378  (settings.m_lpfFIRGain != m_settings.m_lpfFIRGain) ||
379  (m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force)
380  {
381  suspendAllOtherThreads = true;
382  }
383 
384  if (suspendAllOtherThreads)
385  {
386  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
387  std::vector<DeviceAPI*>::const_iterator itSink = sourceBuddies.begin();
388 
389  for (; itSink != sourceBuddies.end(); ++itSink)
390  {
391  DevicePlutoSDRShared *buddySharedPtr = (DevicePlutoSDRShared *) (*itSink)->getBuddySharedPtr();
392 
393  if (buddySharedPtr->m_thread) {
394  buddySharedPtr->m_thread->stopWork();
395  buddySharedPtr->m_threadWasRunning = true;
396  }
397  else
398  {
399  buddySharedPtr->m_threadWasRunning = false;
400  }
401  }
402  }
403 
405  {
407  ownThreadWasRunning = true;
408  }
409 
410  // apply settings
411 
412  // Change affecting device sample rate chain and other buddies
413  if ((m_settings.m_devSampleRate != settings.m_devSampleRate) ||
414  (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) ||
416  (settings.m_lpfFIRBW != m_settings.m_lpfFIRBW) ||
417  (settings.m_lpfFIRGain != m_settings.m_lpfFIRGain) || force)
418  {
419  plutoBox->setFIR(settings.m_devSampleRate, settings.m_lpfFIRlog2Interp, DevicePlutoSDRBox::USE_TX, settings.m_lpfFIRBW, settings.m_lpfFIRGain);
420  plutoBox->setFIREnable(settings.m_lpfFIREnable); // eventually enable/disable FIR
421  plutoBox->setSampleRate(settings.m_devSampleRate); // and set end point sample rate
422 
423  plutoBox->getTxSampleRates(m_deviceSampleRates); // pick up possible new rates
424  qDebug() << "PlutoSDRInput::applySettings: BBPLL(Hz): " << m_deviceSampleRates.m_bbRateHz
425  << " DAC: " << m_deviceSampleRates.m_addaConnvRate
426  << " <-HB3- " << m_deviceSampleRates.m_hb3Rate
427  << " <-HB2- " << m_deviceSampleRates.m_hb2Rate
428  << " <-HB1- " << m_deviceSampleRates.m_hb1Rate
429  << " <-FIR- " << m_deviceSampleRates.m_firRate;
430 
431  forwardChangeOtherDSP = true;
432  forwardChangeOwnDSP = (m_settings.m_devSampleRate != settings.m_devSampleRate) || force;
433  }
434 
435  if ((m_settings.m_log2Interp != settings.m_log2Interp) || force)
436  {
437  reverseAPIKeys.append("log2Interp");
439 
440  if (m_plutoSDROutputThread != 0)
441  {
443  qDebug() << "PlutoSDROutput::applySettings: set soft interpolation in thread to " << (1<<settings.m_log2Interp);
444  }
445 
446  forwardChangeOwnDSP = true;
447  }
448 
449  if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force)
450  {
451  plutoBox->setLOPPMTenths(settings.m_LOppmTenths);
452  forwardChangeOtherDSP = true;
453  }
454 
455  std::vector<std::string> params;
456  bool paramsToSet = false;
457 
458  if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) {
459  reverseAPIKeys.append("centerFrequency");
460  }
461  if ((m_settings.m_transverterMode != settings.m_transverterMode) || force) {
462  reverseAPIKeys.append("transverterMode");
463  }
465  reverseAPIKeys.append("transverterDeltaFrequency");
466  }
467 
468  if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency)
471 
472  {
473  qint64 deviceCenterFrequency = settings.m_centerFrequency;
474  deviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0;
475  deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency;
476 
477 
478  params.push_back(QString(tr("out_altvoltage1_TX_LO_frequency=%1").arg(deviceCenterFrequency)).toStdString());
479  paramsToSet = true;
480  forwardChangeOwnDSP = true;
481 
482  qDebug() << "PlutoSDROutput::applySettings: center freq: " << settings.m_centerFrequency << " Hz"
483  << " device center freq: " << deviceCenterFrequency << " Hz";
484 
485  }
486 
487  if ((m_settings.m_lpfBW != settings.m_lpfBW) || force)
488  {
489  reverseAPIKeys.append("lpfBW");
490  params.push_back(QString(tr("out_voltage_rf_bandwidth=%1").arg(settings.m_lpfBW)).toStdString());
491  paramsToSet = true;
492  }
493 
494  if ((m_settings.m_antennaPath != settings.m_antennaPath) || force)
495  {
496  reverseAPIKeys.append("antennaPath");
497  QString rfPortStr;
499  params.push_back(QString(tr("out_voltage0_rf_port_select=%1").arg(rfPortStr)).toStdString());
500  paramsToSet = true;
501  }
502 
503  if ((m_settings.m_att != settings.m_att) || force)
504  {
505  reverseAPIKeys.append("att");
506  float attF = settings.m_att * 0.25f;
507  params.push_back(QString(tr("out_voltage0_hardwaregain=%1").arg(attF)).toStdString());
508  paramsToSet = true;
509  }
510 
511  if (paramsToSet)
512  {
513  plutoBox->set_params(DevicePlutoSDRBox::DEVICE_PHY, params);
514  }
515 
516  if (settings.m_useReverseAPI)
517  {
518  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
522  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
523  }
524 
525  m_settings = settings;
526 
527  if (suspendAllOtherThreads)
528  {
529  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
530  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
531 
532  for (; itSource != sourceBuddies.end(); ++itSource)
533  {
534  DevicePlutoSDRShared *buddySharedPtr = (DevicePlutoSDRShared *) (*itSource)->getBuddySharedPtr();
535 
536  if (buddySharedPtr->m_threadWasRunning) {
537  buddySharedPtr->m_thread->startWork();
538  }
539  }
540  }
541 
542  if (ownThreadWasRunning) {
544  }
545 
546  // TODO: forward changes to other (Rx) DSP
547  if (forwardChangeOtherDSP)
548  {
549  qDebug("PlutoSDROutput::applySettings: forwardChangeOtherDSP");
550 
551  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
552  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
553 
554  for (; itSource != sourceBuddies.end(); ++itSource)
555  {
557  settings.m_devSampleRate,
558  settings.m_lpfFIREnable,
559  settings.m_lpfFIRlog2Interp,
560  settings.m_lpfFIRBW,
561  settings.m_LOppmTenths);
562 
563  if ((*itSource)->getSamplingDeviceGUIMessageQueue())
564  {
566  (*itSource)->getSamplingDeviceGUIMessageQueue()->push(msgToGUI);
567  }
568 
569  (*itSource)->getSamplingDeviceInputMessageQueue()->push(msg);
570  }
571  }
572 
573  if (forwardChangeOwnDSP)
574  {
575  qDebug("PlutoSDROutput::applySettings: forward change to self");
576 
577  int sampleRate = m_settings.m_devSampleRate/(1<<m_settings.m_log2Interp);
580  }
581 
582  return true;
583 }
584 
585 void PlutoSDROutput::getRSSI(std::string& rssiStr)
586 {
588 
589  if (!plutoBox->getTxRSSI(rssiStr, 0)) {
590  rssiStr = "xxx dB";
591  }
592 }
593 
594 void PlutoSDROutput::getLORange(qint64& minLimit, qint64& maxLimit)
595 {
596  uint64_t min, max;
598 
599  plutoBox->getTxLORange(min, max);
600  minLimit = min;
601  maxLimit = max;
602 }
603 
604 void PlutoSDROutput::getbbLPRange(quint32& minLimit, quint32& maxLimit)
605 {
606  uint32_t min, max;
608 
609  plutoBox->getbbLPTxRange(min, max);
610  minLimit = min;
611  maxLimit = max;
612 }
613 
615 {
617  return plutoBox->fetchTemp();
618 }
619 
621 {
623  return plutoBox->getTemp();
624 }
625 
627  SWGSDRangel::SWGDeviceState& response,
628  QString& errorMessage)
629 {
630  (void) errorMessage;
632  return 200;
633 }
634 
636  bool run,
637  SWGSDRangel::SWGDeviceState& response,
638  QString& errorMessage)
639 {
640  (void) errorMessage;
642  MsgStartStop *message = MsgStartStop::create(run);
643  m_inputMessageQueue.push(message);
644 
645  if (m_guiMessageQueue)
646  {
647  MsgStartStop *messagetoGui = MsgStartStop::create(run);
648  m_guiMessageQueue->push(messagetoGui);
649  }
650 
651  return 200;
652 }
653 
656  QString& errorMessage)
657 {
658  (void) errorMessage;
660  response.getPlutoSdrOutputSettings()->init();
662  return 200;
663 }
664 
666  bool force,
667  const QStringList& deviceSettingsKeys,
668  SWGSDRangel::SWGDeviceSettings& response, // query + response
669  QString& errorMessage)
670 {
671  (void) errorMessage;
673 
674  if (deviceSettingsKeys.contains("centerFrequency")) {
676  }
677  if (deviceSettingsKeys.contains("devSampleRate")) {
679  }
680  if (deviceSettingsKeys.contains("LOppmTenths")) {
681  settings.m_LOppmTenths = response.getPlutoSdrOutputSettings()->getLOppmTenths();
682  }
683  if (deviceSettingsKeys.contains("lpfFIREnable")) {
684  settings.m_lpfFIREnable = response.getPlutoSdrOutputSettings()->getLpfFirEnable() != 0;
685  }
686  if (deviceSettingsKeys.contains("lpfFIRBW")) {
687  settings.m_lpfFIRBW = response.getPlutoSdrOutputSettings()->getLpfFirbw();
688  }
689  if (deviceSettingsKeys.contains("lpfFIRlog2Interp")) {
691  }
692  if (deviceSettingsKeys.contains("lpfFIRGain")) {
693  settings.m_lpfFIRGain = response.getPlutoSdrOutputSettings()->getLpfFirGain();
694  }
695  if (deviceSettingsKeys.contains("log2Interp")) {
696  settings.m_log2Interp = response.getPlutoSdrOutputSettings()->getLog2Interp();
697  }
698  if (deviceSettingsKeys.contains("lpfBW")) {
699  settings.m_lpfBW = response.getPlutoSdrOutputSettings()->getLpfBw();
700  }
701  if (deviceSettingsKeys.contains("att")) {
702  settings.m_att = response.getPlutoSdrOutputSettings()->getAtt();
703  }
704  if (deviceSettingsKeys.contains("antennaPath")) {
705  int antennaPath = response.getPlutoSdrOutputSettings()->getAntennaPath();
706  antennaPath = antennaPath < 0 ? 0 : antennaPath >= PlutoSDROutputSettings::RFPATH_END ? PlutoSDROutputSettings::RFPATH_END-1 : antennaPath;
707  settings.m_antennaPath = (PlutoSDROutputSettings::RFPath) antennaPath;
708  }
709  if (deviceSettingsKeys.contains("transverterDeltaFrequency")) {
711  }
712  if (deviceSettingsKeys.contains("transverterMode")) {
713  settings.m_transverterMode = response.getPlutoSdrOutputSettings()->getTransverterMode() != 0;
714  }
715  if (deviceSettingsKeys.contains("useReverseAPI")) {
716  settings.m_useReverseAPI = response.getPlutoSdrOutputSettings()->getUseReverseApi() != 0;
717  }
718  if (deviceSettingsKeys.contains("reverseAPIAddress")) {
720  }
721  if (deviceSettingsKeys.contains("reverseAPIPort")) {
723  }
724  if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
726  }
727 
728  MsgConfigurePlutoSDR *msg = MsgConfigurePlutoSDR::create(settings, force);
730 
731  if (m_guiMessageQueue) // forward to GUI if any
732  {
733  MsgConfigurePlutoSDR *msgToGUI = MsgConfigurePlutoSDR::create(settings, force);
734  m_guiMessageQueue->push(msgToGUI);
735  }
736 
737  webapiFormatDeviceSettings(response, settings);
738  return 200;
739 }
740 
743  QString& errorMessage)
744 {
745  (void) errorMessage;
747  response.getPlutoSdrOutputReport()->init();
748  webapiFormatDeviceReport(response);
749  return 200;
750 }
751 
753 {
757  response.getPlutoSdrOutputSettings()->setLpfFirEnable(settings.m_lpfFIREnable ? 1 : 0);
758  response.getPlutoSdrOutputSettings()->setLpfFirbw(settings.m_lpfFIRBW);
762  response.getPlutoSdrOutputSettings()->setLpfBw(settings.m_lpfBW);
763  response.getPlutoSdrOutputSettings()->setAtt(settings.m_att);
764  response.getPlutoSdrOutputSettings()->setAntennaPath((int) settings.m_antennaPath);
766  response.getPlutoSdrOutputSettings()->setTransverterMode(settings.m_transverterMode ? 1 : 0);
767  response.getPlutoSdrOutputSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
768 
771  } else {
772  response.getPlutoSdrOutputSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
773  }
774 
777 }
778 
780 {
782  std::string rssiStr;
783  getRSSI(rssiStr);
784  response.getPlutoSdrOutputReport()->setRssi(new QString(rssiStr.c_str()));
787 }
788 
789 void PlutoSDROutput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const PlutoSDROutputSettings& settings, bool force)
790 {
792  swgDeviceSettings->setDirection(1); // single Tx
793  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
794  swgDeviceSettings->setDeviceHwType(new QString("PlutoSDR"));
796  SWGSDRangel::SWGPlutoSdrOutputSettings *swgPlutoSdrOutputSettings = swgDeviceSettings->getPlutoSdrOutputSettings();
797 
798  // transfer data that has been modified. When force is on transfer all data except reverse API data
799 
800  if (deviceSettingsKeys.contains("centerFrequency") || force) {
801  swgPlutoSdrOutputSettings->setCenterFrequency(settings.m_centerFrequency);
802  }
803  if (deviceSettingsKeys.contains("devSampleRate") || force) {
804  swgPlutoSdrOutputSettings->setDevSampleRate(settings.m_devSampleRate);
805  }
806  if (deviceSettingsKeys.contains("LOppmTenths") || force) {
807  swgPlutoSdrOutputSettings->setLOppmTenths(settings.m_LOppmTenths);
808  }
809  if (deviceSettingsKeys.contains("lpfFIREnable") || force) {
810  swgPlutoSdrOutputSettings->setLpfFirEnable(settings.m_lpfFIREnable ? 1 : 0);
811  }
812  if (deviceSettingsKeys.contains("lpfFIRBW") || force) {
813  swgPlutoSdrOutputSettings->setLpfFirbw(settings.m_lpfFIRBW);
814  }
815  if (deviceSettingsKeys.contains("lpfFIRlog2Interp") || force) {
816  swgPlutoSdrOutputSettings->setLpfFiRlog2Interp(settings.m_lpfFIRlog2Interp);
817  }
818  if (deviceSettingsKeys.contains("lpfFIRGain") || force) {
819  swgPlutoSdrOutputSettings->setLpfFirGain(settings.m_lpfFIRGain);
820  }
821  if (deviceSettingsKeys.contains("log2Interp") || force) {
822  swgPlutoSdrOutputSettings->setLog2Interp(settings.m_log2Interp);
823  }
824  if (deviceSettingsKeys.contains("lpfBW") || force) {
825  swgPlutoSdrOutputSettings->setLpfBw(settings.m_lpfBW);
826  }
827  if (deviceSettingsKeys.contains("att") || force) {
828  swgPlutoSdrOutputSettings->setAtt(settings.m_att);
829  }
830  if (deviceSettingsKeys.contains("antennaPath") || force) {
831  swgPlutoSdrOutputSettings->setAntennaPath((int) settings.m_antennaPath);
832  }
833  if (deviceSettingsKeys.contains("transverterDeltaFrequency") || force) {
834  swgPlutoSdrOutputSettings->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency);
835  }
836  if (deviceSettingsKeys.contains("transverterMode") || force) {
837  swgPlutoSdrOutputSettings->setTransverterMode(settings.m_transverterMode ? 1 : 0);
838  }
839 
840  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings")
841  .arg(settings.m_reverseAPIAddress)
842  .arg(settings.m_reverseAPIPort)
843  .arg(settings.m_reverseAPIDeviceIndex);
844  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
845  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
846 
847  QBuffer *buffer=new QBuffer();
848  buffer->open((QBuffer::ReadWrite));
849  buffer->write(swgDeviceSettings->asJson().toUtf8());
850  buffer->seek(0);
851 
852  // Always use PATCH to avoid passing reverse API settings
853  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
854 
855  delete swgDeviceSettings;
856 }
857 
859 {
861  swgDeviceSettings->setDirection(1); // single Tx
862  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
863  swgDeviceSettings->setDeviceHwType(new QString("PlutoSDR"));
864 
865  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
869  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
870  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
871 
872  QBuffer *buffer=new QBuffer();
873  buffer->open((QBuffer::ReadWrite));
874  buffer->write(swgDeviceSettings->asJson().toUtf8());
875  buffer->seek(0);
876 
877  if (start) {
878  m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer);
879  } else {
880  m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer);
881  }
882 
883  delete swgDeviceSettings;
884 }
885 
886 void PlutoSDROutput::networkManagerFinished(QNetworkReply *reply)
887 {
888  QNetworkReply::NetworkError replyError = reply->error();
889 
890  if (replyError)
891  {
892  qWarning() << "PlutoSDROutput::networkManagerFinished:"
893  << " error(" << (int) replyError
894  << "): " << replyError
895  << ": " << reply->errorString();
896  return;
897  }
898 
899  QString answer = reply->readAll();
900  answer.chop(1); // remove last \n
901  qDebug("PlutoSDROutput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
902 }
qint32 m_LOppmTenths
XO correction.
void webapiReverseSendStartStop(bool start)
bool startDeviceEngine()
Start the device engine corresponding to the stream type.
Definition: deviceapi.cpp:253
virtual int webapiSettingsPutPatch(bool force, const QStringList &deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
void setSampleRate(uint32_t sampleRate)
struct iio_buffer * m_plutoTxBuffer
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void stopDeviceEngine()
Stop the device engine corresponding to the stream type.
Definition: deviceapi.cpp:266
void setPlutoSdrOutputSettings(SWGPlutoSdrOutputSettings *pluto_sdr_output_settings)
bool m_threadWasRunning
flag to know if thread needs to be resumed after suspend
void setReverseApiAddress(QString *reverse_api_address)
virtual QString asJson() override
MessageQueue * getDeviceEngineInputMessageQueue()
Device engine message queue.
Definition: deviceapi.cpp:316
ThreadInterface * m_thread
holds the thread address if started else 0
bool initDeviceEngine()
Init the device engine corresponding to the stream type.
Definition: deviceapi.cpp:240
SWGPlutoSdrOutputSettings * getPlutoSdrOutputSettings()
qint32 m_att
"hardware" attenuation in dB fourths
bool getTxRSSI(std::string &rssiStr, unsigned int chan)
void setLpfFiRlog2Interp(qint32 lpf_fi_rlog2_interp)
virtual const QString & getDeviceDescription() const
virtual void init()
initializations to be done when all collaborating objects are created and possibly connected ...
void setOriginatorIndex(qint32 originator_index)
DevicePlutoSDRParams * m_deviceParams
unique hardware device parameters
bool open(const std::string &serial)
uint32_t m_hb3Rate
Rate of the HB3/(DEC3 or INT3) filter (Rx: out, Tx: in) - this is the HB2 working sample rate...
static MsgCrossReportToBuddy * create(uint64_t devSampleRate, bool lpfFIREnable, uint32_t lpfFIRlog2Interp, uint32_t lpfFIRBW, int32_t loPPMTenths)
unsigned int uint32_t
Definition: rtptypes_win.h:46
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
virtual quint64 getCenterFrequency() const
Center frequency exposed by the sink.
MessageQueue m_inputMessageQueue
Input queue to the sink.
void setFIREnable(bool enable)
void getRSSI(std::string &rssiStr)
int getDeviceSetIndex() const
Definition: deviceapi.h:131
SWGPlutoSdrOutputReport * getPlutoSdrOutputReport()
void * getBuddySharedPtr() const
Definition: deviceapi.h:161
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
quint32 m_lpfBW
analog lowpass filter bandwidth (Hz)
bool deserialize(const QByteArray &data)
void setLOPPMTenths(int ppmTenths)
PlutoSDROutputThread * m_plutoSDROutputThread
void setPlutoSdrOutputReport(SWGPlutoSdrOutputReport *pluto_sdr_output_report)
DevicePlutoSDRBox::SampleRates m_deviceSampleRates
void setFIR(uint32_t sampleRate, uint32_t intdec, DeviceUse use, uint32_t bw, int gain)
static MsgConfigurePlutoSDR * create(const PlutoSDROutputSettings &settings, bool force)
bool m_lpfFIREnable
enable digital lowpass FIR filter
void setBuddySharedPtr(void *ptr)
Definition: deviceapi.h:162
QNetworkRequest m_networkRequest
virtual bool deserialize(const QByteArray &data)
int32_t i
Definition: decimators.h:244
void webapiReverseSendSettings(QList< QString > &deviceSettingsKeys, const PlutoSDROutputSettings &settings, bool force)
static bool match(const Message *message)
Definition: message.cpp:45
static void translateRFPath(RFPath path, QString &s)
void networkManagerFinished(QNetworkReply *reply)
const PlutoSDROutputSettings & getSettings() const
virtual int webapiRunGet(SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
bool getTxSampleRates(SampleRates &sampleRates)
DevicePlutoSDRShared m_deviceShared
void getTxLORange(uint64_t &minLimit, uint64_t &maxLimit)
virtual int webapiSettingsGet(SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
struct iio_buffer * createTxBuffer(unsigned int size, bool cyclic)
uint32_t m_firRate
Rate of FIR filter (Rx: out, Tx: in) - this is the host/device communication sample rate...
quint32 m_lpfFIRlog2Interp
digital lowpass FIR filter log2 of interpolation factor (0..2)
virtual void stop()
DevicePlutoSDRBox * getBox()
void getDeviceEngineStateStr(QString &state)
Definition: deviceapi.cpp:389
bool applySettings(const PlutoSDROutputSettings &settings, bool force=false)
uint32_t m_hb2Rate
Rate of the HB2 filter (Rx: out, Tx: in) - this is the HB1 working sample rate.
void resize(uint32_t size)
const QString & getSamplingDeviceSerial() const
Definition: deviceapi.h:121
virtual int webapiRun(bool run, SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
virtual QByteArray serialize() const
void setTransverterDeltaFrequency(qint64 transverter_delta_frequency)
quint64 m_devSampleRate
Host interface sample rate.
QNetworkAccessManager * m_networkManager
uint32_t m_hb1Rate
Rate of the HB1 filter (Rx: out, Tx: in) - this is the FIR working sample rate.
void getbbLPRange(quint32 &minLimit, quint32 &maxLimit)
SampleSourceFifo m_sampleSourceFifo
virtual bool start()
const std::vector< DeviceAPI * > & getSourceBuddies() const
Definition: deviceapi.h:165
uint32_t m_bbRateHz
Baseband PLL rate (Hz) - used internally.
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings &response, const PlutoSDROutputSettings &settings)
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport &response)
float getTemp() const
DeviceAPI * m_deviceAPI
static MsgStartStop * create(bool startStop)
void getLORange(qint64 &minLimit, qint64 &maxLimit)
QString m_deviceDescription
#define PLUTOSDR_BLOCKSIZE_SAMPLES
void setDirection(qint32 direction)
uint32_t m_addaConnvRate
A/D or D/A converter rat - this is the HB3 working sample rate.
uint32_t getDACSampleRate() const
virtual void setCenterFrequency(qint64 centerFrequency)
int m_lpfFIRGain
digital lowpass FIR filter gain (dB)
virtual int getSampleRate() const
Sample rate exposed by the sink.
quint32 m_lpfFIRBW
digital lowpass FIR filter bandwidth (Hz)
void getbbLPTxRange(uint32_t &minLimit, uint32_t &maxLimit)
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
PlutoSDROutputSettings m_settings
virtual void destroy()
T max(const T &x, const T &y)
Definition: framework.h:446
virtual int webapiReportGet(SWGSDRangel::SWGDeviceReport &response, QString &errorMessage)
void setDeviceHwType(QString *device_hw_type)
void setLog2Interpolation(unsigned int log2_interp)
void set_params(DeviceType devType, const std::vector< std::string > &params)
virtual bool handleMessage(const Message &message)
T min(const T &x, const T &y)
Definition: framework.h:440
unsigned __int64 uint64_t
Definition: rtptypes_win.h:48