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.
limesdrinput.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 <cstddef>
19 #include <string.h>
20 
21 #include <QMutexLocker>
22 #include <QDebug>
23 #include <QNetworkReply>
24 #include <QBuffer>
25 
26 #include "lime/LimeSuite.h"
27 
28 #include "SWGDeviceSettings.h"
30 #include "SWGDeviceState.h"
31 #include "SWGDeviceReport.h"
32 #include "SWGLimeSdrInputReport.h"
33 
34 #include "device/deviceapi.h"
35 #include "dsp/dspcommands.h"
36 #include "dsp/filerecord.h"
37 #include "dsp/dspengine.h"
38 #include "limesdrinput.h"
39 #include "limesdrinputthread.h"
42 #include "limesdr/devicelimesdr.h"
43 
50 
52  m_deviceAPI(deviceAPI),
53  m_settings(),
54  m_limeSDRInputThread(0),
55  m_deviceDescription("LimeSDRInput"),
56  m_running(false),
57  m_channelAcquired(false)
58 {
59  m_streamId.handle = 0;
60  suspendRxBuddies();
61  suspendTxBuddies();
62  openDevice();
63  resumeTxBuddies();
64  resumeRxBuddies();
65 
66  m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
67  m_deviceAPI->setNbSourceStreams(1);
68  m_deviceAPI->addAncillarySink(m_fileSink);
69 
70  m_networkManager = new QNetworkAccessManager();
71  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
72 }
73 
75 {
76  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
77  delete m_networkManager;
78 
79  if (m_running) {
80  stop();
81  }
82 
84  delete m_fileSink;
87  closeDevice();
90 }
91 
93 {
94  delete this;
95 }
96 
98 {
99  if (!m_sampleFifo.setSize(96000 * 4))
100  {
101  qCritical("LimeSDRInput::openDevice: could not allocate SampleFifo");
102  return false;
103  }
104  else
105  {
106  qDebug("LimeSDRInput::openDevice: allocated SampleFifo");
107  }
108 
109  int requestedChannel = m_deviceAPI->getDeviceItemIndex();
110 
111  // look for Rx buddies and get reference to common parameters
112  // if there is a channel left take the first available
113  if (m_deviceAPI->getSourceBuddies().size() > 0) // look source sibling first
114  {
115  qDebug("LimeSDRInput::openDevice: look in Rx buddies");
116 
117  DeviceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0];
118  //m_deviceShared = *((DeviceLimeSDRShared *) sourceBuddy->getBuddySharedPtr()); // copy shared data
119  DeviceLimeSDRShared *deviceLimeSDRShared = (DeviceLimeSDRShared*) sourceBuddy->getBuddySharedPtr();
120 
121  if (deviceLimeSDRShared == 0)
122  {
123  qCritical("LimeSDRInput::openDevice: the source buddy shared pointer is null");
124  return false;
125  }
126 
127  m_deviceShared.m_deviceParams = deviceLimeSDRShared->m_deviceParams;
128 
129  DeviceLimeSDRParams *deviceParams = m_deviceShared.m_deviceParams; // get device parameters
130 
131  if (deviceParams == 0)
132  {
133  qCritical("LimeSDRInput::openDevice: cannot get device parameters from Rx buddy");
134  return false; // the device params should have been created by the buddy
135  }
136  else
137  {
138  qDebug("LimeSDRInput::openDevice: getting device parameters from Rx buddy");
139  }
140 
141  if (m_deviceAPI->getSourceBuddies().size() == deviceParams->m_nbRxChannels)
142  {
143  qCritical("LimeSDRInput::openDevice: no more Rx channels available in device");
144  return false; // no more Rx channels available in device
145  }
146  else
147  {
148  qDebug("LimeSDRInput::openDevice: at least one more Rx channel is available in device");
149  }
150 
151  // check if the requested channel is busy and abort if so (should not happen if device management is working correctly)
152 
153  for (unsigned int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++)
154  {
156  DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr();
157 
158  if (buddyShared->m_channel == requestedChannel)
159  {
160  qCritical("LimeSDRInput::openDevice: cannot open busy channel %u", requestedChannel);
161  return false;
162  }
163  }
164 
165  m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
166  }
167  // look for Tx buddies and get reference to common parameters
168  // take the first Rx channel
169  else if (m_deviceAPI->getSinkBuddies().size() > 0) // then sink
170  {
171  qDebug("LimeSDRInput::openDevice: look in Tx buddies");
172 
173  DeviceAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0];
174  //m_deviceShared = *((DeviceLimeSDRShared *) sinkBuddy->getBuddySharedPtr()); // copy parameters
175  DeviceLimeSDRShared *deviceLimeSDRShared = (DeviceLimeSDRShared*) sinkBuddy->getBuddySharedPtr();
176 
177  if (deviceLimeSDRShared == 0)
178  {
179  qCritical("LimeSDRInput::openDevice: the sink buddy shared pointer is null");
180  return false;
181  }
182 
183  m_deviceShared.m_deviceParams = deviceLimeSDRShared->m_deviceParams;
184 
186  {
187  qCritical("LimeSDRInput::openDevice: cannot get device parameters from Tx buddy");
188  return false; // the device params should have been created by the buddy
189  }
190  else
191  {
192  qDebug("LimeSDRInput::openDevice: getting device parameters from Tx buddy");
193  }
194 
195  m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
196  }
197  // There are no buddies then create the first LimeSDR common parameters
198  // open the device this will also populate common fields
199  // take the first Rx channel
200  else
201  {
202  qDebug("LimeSDRInput::openDevice: open device here");
203 
205  char serial[256];
206  strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
208  m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
209  }
210 
211  m_deviceAPI->setBuddySharedPtr(&m_deviceShared); // propagate common parameters to API
212 
213  return true;
214 }
215 
217 {
218  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
219  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
220 
221  qDebug("LimeSDRInput::suspendRxBuddies (%lu)", sourceBuddies.size());
222 
223  for (; itSource != sourceBuddies.end(); ++itSource)
224  {
225  DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr();
226 
227  if (buddySharedPtr->m_thread && buddySharedPtr->m_thread->isRunning())
228  {
229  buddySharedPtr->m_thread->stopWork();
230  buddySharedPtr->m_threadWasRunning = true;
231  }
232  else
233  {
234  buddySharedPtr->m_threadWasRunning = false;
235  }
236  }
237 }
238 
240 {
241  const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
242  std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
243 
244  qDebug("LimeSDRInput::suspendTxBuddies (%lu)", sinkBuddies.size());
245 
246  for (; itSink != sinkBuddies.end(); ++itSink)
247  {
248  DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr();
249 
250  if ((buddySharedPtr->m_thread) && buddySharedPtr->m_thread->isRunning())
251  {
252  buddySharedPtr->m_thread->stopWork();
253  buddySharedPtr->m_threadWasRunning = true;
254  }
255  else
256  {
257  buddySharedPtr->m_threadWasRunning = false;
258  }
259  }
260 }
261 
263 {
264  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
265  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
266 
267  qDebug("LimeSDRInput::resumeRxBuddies (%lu)", sourceBuddies.size());
268 
269  for (; itSource != sourceBuddies.end(); ++itSource)
270  {
271  DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr();
272 
273  if (buddySharedPtr->m_threadWasRunning) {
274  buddySharedPtr->m_thread->startWork();
275  }
276  }
277 }
278 
280 {
281  const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
282  std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
283 
284  qDebug("LimeSDRInput::resumeTxBuddies (%lu)", sinkBuddies.size());
285 
286  for (; itSink != sinkBuddies.end(); ++itSink)
287  {
288  DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr();
289 
290  if (buddySharedPtr->m_threadWasRunning) {
291  buddySharedPtr->m_thread->startWork();
292  }
293  }
294 }
295 
297 {
298  if (m_deviceShared.m_deviceParams->getDevice() == 0) { // was never open
299  return;
300  }
301 
302  if (m_running) { stop(); }
303 
305 
306  // No buddies so effectively close the device
307 
308  if ((m_deviceAPI->getSinkBuddies().size() == 0) && (m_deviceAPI->getSourceBuddies().size() == 0))
309  {
313  }
314 }
315 
317 {
320 
321  // acquire the channel
322 
323  if (LMS_EnableChannel(m_deviceShared.m_deviceParams->getDevice(), LMS_CH_RX, m_deviceShared.m_channel, true) != 0)
324  {
325  qCritical("LimeSDRInput::acquireChannel: cannot enable Rx channel %d", m_deviceShared.m_channel);
326  return false;
327  }
328  else
329  {
330  qDebug("LimeSDRInput::acquireChannel: Rx channel %d enabled", m_deviceShared.m_channel);
331  }
332 
333  // set up the stream
334 
335  m_streamId.channel = m_deviceShared.m_channel; // channel number
336  m_streamId.fifoSize = 1024 * 1024; // fifo size in samples (SR / 10 take ~5MS/s)
337  m_streamId.throughputVsLatency = 0.5; // optimize for min latency
338  m_streamId.isTx = false; // RX channel
339  m_streamId.dataFmt = lms_stream_t::LMS_FMT_I12; // 12-bit integers
340 
341  if (LMS_SetupStream(m_deviceShared.m_deviceParams->getDevice(), &m_streamId) != 0)
342  {
343  qCritical("LimeSDRInput::acquireChannel: cannot setup the stream on Rx channel %d", m_deviceShared.m_channel);
344  resumeTxBuddies();
345  resumeRxBuddies();
346  return false;
347  }
348  else
349  {
350  qDebug("LimeSDRInput::acquireChannel: stream set up on Rx channel %d", m_deviceShared.m_channel);
351  }
352 
353  resumeTxBuddies();
354  resumeRxBuddies();
355 
356  m_channelAcquired = true;
357 
358  return true;
359 }
360 
362 {
365 
366  // destroy the stream
367  if (LMS_DestroyStream(m_deviceShared.m_deviceParams->getDevice(), &m_streamId) != 0)
368  {
369  qWarning("LimeSDRInput::releaseChannel: cannot destroy the stream on Rx channel %d", m_deviceShared.m_channel);
370  }
371  else
372  {
373  qDebug("LimeSDRInput::releaseChannel: stream destroyed on Rx channel %d", m_deviceShared.m_channel);
374  }
375 
376  m_streamId.handle = 0;
377 
378  // release the channel
379 
380  if (LMS_EnableChannel(m_deviceShared.m_deviceParams->getDevice(), LMS_CH_RX, m_deviceShared.m_channel, false) != 0)
381  {
382  qWarning("LimeSDRInput::releaseChannel: cannot disable Rx channel %d", m_deviceShared.m_channel);
383  }
384  else
385  {
386  qDebug("LimeSDRInput::releaseChannel: Rx channel %d disabled", m_deviceShared.m_channel);
387  }
388 
389  resumeTxBuddies();
390  resumeRxBuddies();
391 
392  // The channel will be effectively released to be reused in another device set only at close time
393 
394  m_channelAcquired = false;
395 }
396 
398 {
399  applySettings(m_settings, true, false);
400 }
401 
403 {
405  return false;
406  }
407 
408  if (m_running) { stop(); }
409 
410  if (!acquireChannel())
411  {
412  return false;
413  }
414 
415  // start / stop streaming is done in the thread.
416 
418  qDebug("LimeSDRInput::start: thread created");
419 
420  applySettings(m_settings, true);
421 
423 
425 
427  m_running = true;
428 
429  return true;
430 }
431 
433 {
434  qDebug("LimeSDRInput::stop");
435 
436  if (m_limeSDRInputThread != 0)
437  {
439  delete m_limeSDRInputThread;
441  }
442 
444  m_running = false;
445 
446  releaseChannel();
447 }
448 
449 QByteArray LimeSDRInput::serialize() const
450 {
451  return m_settings.serialize();
452 }
453 
454 bool LimeSDRInput::deserialize(const QByteArray& data)
455 {
456  bool success = true;
457 
458  if (!m_settings.deserialize(data))
459  {
461  success = false;
462  }
463 
465  m_inputMessageQueue.push(message);
466 
467  if (m_guiMessageQueue)
468  {
470  m_guiMessageQueue->push(messageToGUI);
471  }
472 
473  return success;
474 }
475 
477 {
478  return m_deviceDescription;
479 }
480 
482 {
483  int rate = m_settings.m_devSampleRate;
484  return (rate / (1<<m_settings.m_log2SoftDecim));
485 }
486 
488 {
490 }
491 
492 void LimeSDRInput::setCenterFrequency(qint64 centerFrequency)
493 {
494  LimeSDRInputSettings settings = m_settings;
495  settings.m_centerFrequency = centerFrequency - (m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0);
496 
497  MsgConfigureLimeSDR* message = MsgConfigureLimeSDR::create(settings, false);
498  m_inputMessageQueue.push(message);
499 
500  if (m_guiMessageQueue)
501  {
502  MsgConfigureLimeSDR* messageToGUI = MsgConfigureLimeSDR::create(settings, false);
503  m_guiMessageQueue->push(messageToGUI);
504  }
505 }
506 
508 {
509  return m_deviceShared.m_channel;
510 }
511 
512 void LimeSDRInput::getLORange(float& minF, float& maxF) const
513 {
514  lms_range_t range = m_deviceShared.m_deviceParams->m_loRangeRx;
515  minF = range.min;
516  maxF = range.max;
517  qDebug("LimeSDRInput::getLORange: min: %f max: %f", range.min, range.max);
518 }
519 
520 void LimeSDRInput::getSRRange(float& minF, float& maxF) const
521 {
522  lms_range_t range = m_deviceShared.m_deviceParams->m_srRangeRx;
523  minF = range.min;
524  maxF = range.max;
525  qDebug("LimeSDRInput::getSRRange: min: %f max: %f", range.min, range.max);
526 }
527 
528 void LimeSDRInput::getLPRange(float& minF, float& maxF) const
529 {
530  lms_range_t range = m_deviceShared.m_deviceParams->m_lpfRangeRx;
531  minF = range.min;
532  maxF = range.max;
533  qDebug("LimeSDRInput::getLPRange: min: %f max: %f", range.min, range.max);
534 }
535 
537 {
539 }
540 
542 {
545  } else {
547  }
548 }
549 
551 {
552  if (MsgConfigureLimeSDR::match(message))
553  {
554  MsgConfigureLimeSDR& conf = (MsgConfigureLimeSDR&) message;
555  qDebug() << "LimeSDRInput::handleMessage: MsgConfigureLimeSDR";
556 
557  if (!applySettings(conf.getSettings(), conf.getForce()))
558  {
559  qDebug("LimeSDRInput::handleMessage config error");
560  }
561 
562  return true;
563  }
565  {
567 
568  if (report.getRxElseTx())
569  {
573  }
574  else if (m_running)
575  {
576  double host_Hz;
577  double rf_Hz;
578 
579  if (LMS_GetSampleRate(m_deviceShared.m_deviceParams->getDevice(),
580  LMS_CH_RX,
582  &host_Hz,
583  &rf_Hz) < 0)
584  {
585  qDebug("LimeSDRInput::handleMessage: MsgReportBuddyChange: LMS_GetSampleRate() failed");
586  }
587  else
588  {
589  m_settings.m_devSampleRate = roundf(host_Hz);
590  int hard = roundf(rf_Hz) / m_settings.m_devSampleRate;
591  m_settings.m_log2HardDecim = log2(hard);
592 
593  qDebug() << "LimeSDRInput::handleMessage: MsgReportBuddyChange:"
594  << " host_Hz: " << host_Hz
595  << " rf_Hz: " << rf_Hz
596  << " m_devSampleRate: " << m_settings.m_devSampleRate
597  << " log2Hard: " << hard
598  << " m_log2HardDecim: " << m_settings.m_log2HardDecim;
599 // int adcdac_rate = report.getDevSampleRate() * (1<<report.getLog2HardDecimInterp());
600 // m_settings.m_devSampleRate = adcdac_rate / (1<<m_settings.m_log2HardDecim); // new device to host sample rate
601  }
602  }
603 
604  if (m_settings.m_ncoEnable) // need to reset NCO after sample rate change
605  {
606  applySettings(m_settings, false, true);
607  }
608 
609  int ncoShift = m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0;
610 
613  m_settings.m_centerFrequency + ncoShift);
615 
616  if (getMessageQueueToGUI())
617  {
620  getMessageQueueToGUI()->push(reportToGUI);
621  }
622 
623  return true;
624  }
626  {
628 
629  m_settings.m_extClock = report.getExtClock();
631 
632  if (getMessageQueueToGUI())
633  {
636  getMessageQueueToGUI()->push(reportToGUI);
637  }
638 
639  return true;
640  }
642  {
644 
645  m_settings.m_gpioDir = report.getGPIODir();
646  m_settings.m_gpioPins = report.getGPIOPins();
647 
648  // no GUI for the moment only REST API
649 
650  return true;
651  }
652  else if (MsgGetStreamInfo::match(message))
653  {
654 // qDebug() << "LimeSDRInput::handleMessage: MsgGetStreamInfo";
655  lms_stream_status_t status;
656 
657  if (m_streamId.handle && (LMS_GetStreamStatus(&m_streamId, &status) == 0))
658  {
660  {
662  true, // Success
663  status.active,
664  status.fifoFilledCount,
665  status.fifoSize,
666  status.underrun,
667  status.overrun,
668  status.droppedPackets,
669  status.linkRate,
670  status.timestamp);
672  }
673  }
674  else
675  {
677  {
679  false, // Success
680  false, // status.active,
681  0, // status.fifoFilledCount,
682  16384, // status.fifoSize,
683  0, // status.underrun,
684  0, // status.overrun,
685  0, // status.droppedPackets,
686  0, // status.linkRate,
687  0); // status.timestamp);
689  }
690  }
691 
692  return true;
693  }
694  else if (MsgGetDeviceInfo::match(message))
695  {
696  double temp = 0.0;
697  uint8_t gpioPins = 0;
698 
699  if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp) != 0)) {
700  qDebug("LimeSDRInput::handleMessage: MsgGetDeviceInfo: cannot get temperature");
701  }
702 
705  {
706  if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1) != 0)) {
707  qDebug("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get GPIO pins values");
708  }
709  }
710 
711  // send to oneself
713  {
716  }
717 
718  // send to source buddies
719  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
720  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
721 
722  for (; itSource != sourceBuddies.end(); ++itSource)
723  {
724  if ((*itSource)->getSamplingDeviceGUIMessageQueue())
725  {
727  (*itSource)->getSamplingDeviceGUIMessageQueue()->push(report);
728  }
729  }
730 
731  // send to sink buddies
732  const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
733  std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
734 
735  for (; itSink != sinkBuddies.end(); ++itSink)
736  {
737  if ((*itSink)->getSamplingDeviceGUIMessageQueue())
738  {
740  (*itSink)->getSamplingDeviceGUIMessageQueue()->push(report);
741  }
742  }
743 
744  return true;
745  }
746  else if (MsgFileRecord::match(message))
747  {
748  MsgFileRecord& conf = (MsgFileRecord&) message;
749  qDebug() << "LimeSDRInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
750 
751  if (conf.getStartStop())
752  {
753  if (m_settings.m_fileRecordName.size() != 0) {
755  } else {
757  }
758 
760  }
761  else
762  {
764  }
765 
766  return true;
767  }
768  else if (MsgStartStop::match(message))
769  {
770  MsgStartStop& cmd = (MsgStartStop&) message;
771  qDebug() << "LimeSDRInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
772 
773  if (cmd.getStartStop())
774  {
776  {
778  }
779  }
780  else
781  {
783  }
784 
787  }
788 
789  return true;
790  }
791  else
792  {
793  return false;
794  }
795 }
796 
797 bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool force, bool forceNCOFrequency)
798 {
799  bool forwardChangeOwnDSP = false;
800  bool forwardChangeRxDSP = false;
801  bool forwardChangeAllDSP = false;
802  bool forwardClockSource = false;
803  bool forwardGPIOChange = false;
804  bool ownThreadWasRunning = false;
805  bool doCalibration = false;
806  bool doLPCalibration = false;
807  bool setAntennaAuto = false;
808  double clockGenFreq = 0.0;
809  QList<QString> reverseAPIKeys;
810 
811 // QMutexLocker mutexLocker(&m_mutex);
812 
813  qint64 deviceCenterFrequency = settings.m_centerFrequency;
814  deviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0;
815  deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency;
816 
817  if (LMS_GetClockFreq(m_deviceShared.m_deviceParams->getDevice(), LMS_CLOCK_CGEN, &clockGenFreq) != 0)
818  {
819  qCritical("LimeSDRInput::applySettings: could not get clock gen frequency");
820  }
821  else
822  {
823  qDebug() << "LimeSDRInput::applySettings: clock gen frequency: " << clockGenFreq;
824  }
825 
826  // apply settings
827 
828  if ((m_settings.m_dcBlock != settings.m_dcBlock) || force)
829  {
830  reverseAPIKeys.append("dcBlock");
832  }
833 
834  if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
835  {
836  reverseAPIKeys.append("iqCorrection");
838  }
839 
840  if ((m_settings.m_gainMode != settings.m_gainMode) || force)
841  {
842  reverseAPIKeys.append("gainMode");
843 
845  {
847  {
848  if (LMS_SetGaindB(m_deviceShared.m_deviceParams->getDevice(),
849  LMS_CH_RX,
851  settings.m_gain) < 0)
852  {
853  qDebug("LimeSDRInput::applySettings: LMS_SetGaindB() failed");
854  }
855  else
856  {
857  doCalibration = true;
858  qDebug() << "LimeSDRInput::applySettings: Gain (auto) set to " << settings.m_gain;
859  }
860  }
861  }
862  else
863  {
865  {
868  settings.m_lnaGain))
869  {
870  doCalibration = true;
871  qDebug() << "LimeSDRInput::applySettings: LNA gain (manual) set to " << settings.m_lnaGain;
872  }
873  else
874  {
875  qDebug("LimeSDRInput::applySettings: DeviceLimeSDR::SetRFELNA_dB() failed");
876  }
877 
880  settings.m_tiaGain))
881  {
882  doCalibration = true;
883  qDebug() << "LimeSDRInput::applySettings: TIA gain (manual) set to " << settings.m_tiaGain;
884  }
885  else
886  {
887  qDebug("LimeSDRInput::applySettings: DeviceLimeSDR::SetRFETIA_dB() failed");
888  }
889 
892  settings.m_pgaGain))
893  {
894  doCalibration = true;
895  qDebug() << "LimeSDRInput::applySettings: PGA gain (manual) set to " << settings.m_pgaGain;
896  }
897  else
898  {
899  qDebug("LimeSDRInput::applySettings: DeviceLimeSDR::SetRBBPGA_dB() failed");
900  }
901  }
902  }
903  }
904 
906  {
907  reverseAPIKeys.append("gain");
908 
910  {
911  if (LMS_SetGaindB(m_deviceShared.m_deviceParams->getDevice(),
912  LMS_CH_RX,
914  settings.m_gain) < 0)
915  {
916  qDebug("LimeSDRInput::applySettings: LMS_SetGaindB() failed");
917  }
918  else
919  {
920  doCalibration = true;
921  qDebug() << "LimeSDRInput::applySettings: Gain (auto) set to " << settings.m_gain;
922  }
923  }
924  }
925 
927  {
928  reverseAPIKeys.append("lnaGain");
929 
931  {
934  settings.m_lnaGain))
935  {
936  doCalibration = true;
937  qDebug() << "LimeSDRInput::applySettings: LNA gain (manual) set to " << settings.m_lnaGain;
938  }
939  else
940  {
941  qDebug("LimeSDRInput::applySettings: DeviceLimeSDR::SetRFELNA_dB() failed");
942  }
943  }
944  }
945 
947  {
948  reverseAPIKeys.append("tiaGain");
949 
951  {
954  settings.m_tiaGain))
955  {
956  doCalibration = true;
957  qDebug() << "LimeSDRInput::applySettings: TIA gain (manual) set to " << settings.m_tiaGain;
958  }
959  else
960  {
961  qDebug("LimeSDRInput::applySettings: DeviceLimeSDR::SetRFETIA_dB() failed");
962  }
963  }
964  }
965 
967  {
968  reverseAPIKeys.append("pgaGain");
969 
971  {
974  settings.m_pgaGain))
975  {
976  doCalibration = true;
977  qDebug() << "LimeSDRInput::applySettings: PGA gain (manual) set to " << settings.m_pgaGain;
978  }
979  else
980  {
981  qDebug("LimeSDRInput::applySettings: DeviceLimeSDR::SetRBBPGA_dB() failed");
982  }
983  }
984  }
985 
986  if ((m_settings.m_devSampleRate != settings.m_devSampleRate)
987  || (m_settings.m_log2HardDecim != settings.m_log2HardDecim) || force)
988  {
989  reverseAPIKeys.append("devSampleRate");
990  reverseAPIKeys.append("log2HardDecim");
991  forwardChangeAllDSP = true; //m_settings.m_devSampleRate != settings.m_devSampleRate;
992 
994  {
995  if (LMS_SetSampleRateDir(m_deviceShared.m_deviceParams->getDevice(),
996  LMS_CH_RX,
997  settings.m_devSampleRate,
998  1<<settings.m_log2HardDecim) < 0)
999  {
1000  qCritical("LimeSDRInput::applySettings: could not set sample rate to %d with oversampling of %d",
1001  settings.m_devSampleRate,
1002  1<<settings.m_log2HardDecim);
1003  }
1004  else
1005  {
1008  //doCalibration = true;
1009  forceNCOFrequency = true;
1010  qDebug("LimeSDRInput::applySettings: set sample rate set to %d with oversampling of %d",
1011  settings.m_devSampleRate,
1012  1<<settings.m_log2HardDecim);
1013  }
1014  }
1015  }
1016 
1017  if ((m_settings.m_lpfBW != settings.m_lpfBW) || force)
1018  {
1019  reverseAPIKeys.append("lpfBW");
1020 
1022  {
1023  doLPCalibration = true;
1024  }
1025  }
1026 
1027  if ((m_settings.m_lpfFIRBW != settings.m_lpfFIRBW) ||
1028  (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force)
1029  {
1030  reverseAPIKeys.append("lpfFIRBW");
1031  reverseAPIKeys.append("lpfFIREnable");
1032 
1034  {
1035  if (LMS_SetGFIRLPF(m_deviceShared.m_deviceParams->getDevice(),
1036  LMS_CH_RX,
1038  settings.m_lpfFIREnable,
1039  settings.m_lpfFIRBW) < 0)
1040  {
1041  qCritical("LimeSDRInput::applySettings: could %s and set LPF FIR to %f Hz",
1042  settings.m_lpfFIREnable ? "enable" : "disable",
1043  settings.m_lpfFIRBW);
1044  }
1045  else
1046  {
1047  //doCalibration = true;
1048  qDebug("LimeSDRInput::applySettings: %sd and set LPF FIR to %f Hz",
1049  settings.m_lpfFIREnable ? "enable" : "disable",
1050  settings.m_lpfFIRBW);
1051  }
1052  }
1053  }
1054 
1055  if ((m_settings.m_ncoFrequency != settings.m_ncoFrequency) ||
1056  (m_settings.m_ncoEnable != settings.m_ncoEnable) || force || forceNCOFrequency)
1057  {
1058  reverseAPIKeys.append("ncoFrequency");
1059  reverseAPIKeys.append("ncoEnable");
1060  forwardChangeOwnDSP = true;
1061 
1063  {
1065  LMS_CH_RX,
1067  settings.m_ncoEnable,
1068  settings.m_ncoFrequency))
1069  {
1070  //doCalibration = true;
1071  m_deviceShared.m_ncoFrequency = settings.m_ncoEnable ? settings.m_ncoFrequency : 0; // for buddies
1072  qDebug("LimeSDRInput::applySettings: %sd and set NCO to %d Hz",
1073  settings.m_ncoEnable ? "enable" : "disable",
1074  settings.m_ncoFrequency);
1075  }
1076  else
1077  {
1078  qCritical("LimeSDRInput::applySettings: could not %s and set NCO to %d Hz",
1079  settings.m_ncoEnable ? "enable" : "disable",
1080  settings.m_ncoFrequency);
1081  }
1082  }
1083  }
1084 
1085  if ((m_settings.m_log2SoftDecim != settings.m_log2SoftDecim) || force)
1086  {
1087  reverseAPIKeys.append("log2SoftDecim");
1088  forwardChangeOwnDSP = true;
1089  m_deviceShared.m_log2Soft = settings.m_log2SoftDecim; // for buddies
1090 
1091  if (m_limeSDRInputThread != 0)
1092  {
1094  qDebug() << "LimeSDRInput::applySettings: set soft decimation to " << (1<<settings.m_log2SoftDecim);
1095  }
1096  }
1097 
1098  if ((m_settings.m_antennaPath != settings.m_antennaPath) || force)
1099  {
1100  reverseAPIKeys.append("antennaPath");
1101 
1103  {
1106  settings.m_antennaPath))
1107  {
1108  doCalibration = true;
1109  //setAntennaAuto = (settings.m_antennaPath == 0);
1110  qDebug("LimeSDRInput::applySettings: set antenna path to %d on channel %d",
1111  (int) settings.m_antennaPath,
1113  }
1114  else
1115  {
1116  qCritical("LimeSDRInput::applySettings: could not set antenna path to %d",
1117  (int) settings.m_antennaPath);
1118  }
1119  }
1120  }
1121 
1125  || setAntennaAuto || force)
1126  {
1127  reverseAPIKeys.append("centerFrequency");
1128  reverseAPIKeys.append("transverterMode");
1129  reverseAPIKeys.append("transverterDeltaFrequency");
1130  forwardChangeRxDSP = true;
1131 
1133  {
1134  if (LMS_SetClockFreq(m_deviceShared.m_deviceParams->getDevice(), LMS_CLOCK_SXR, deviceCenterFrequency) < 0)
1135  {
1136  qCritical("LimeSDRInput::applySettings: could not set frequency to %lld", deviceCenterFrequency);
1137  }
1138  else
1139  {
1140  doCalibration = true;
1141  m_deviceShared.m_centerFrequency = deviceCenterFrequency; // for buddies
1142  qDebug("LimeSDRInput::applySettings: frequency set to %lld", deviceCenterFrequency);
1143  }
1144  }
1145  }
1146 
1147  if ((m_settings.m_extClock != settings.m_extClock) ||
1148  (settings.m_extClock && (m_settings.m_extClockFreq != settings.m_extClockFreq)) || force)
1149  {
1150  reverseAPIKeys.append("extClock");
1151  reverseAPIKeys.append("extClockFreq");
1152 
1154  settings.m_extClock,
1155  settings.m_extClockFreq))
1156  {
1157  forwardClockSource = true;
1158  doCalibration = true;
1159  qDebug("LimeSDRInput::applySettings: clock set to %s (Ext: %d Hz)",
1160  settings.m_extClock ? "external" : "internal",
1161  settings.m_extClockFreq);
1162  }
1163  else
1164  {
1165  qCritical("LimeSDRInput::applySettings: could not set clock to %s (Ext: %d Hz)",
1166  settings.m_extClock ? "external" : "internal",
1167  settings.m_extClockFreq);
1168  }
1169  }
1170 
1173  {
1174  if ((m_settings.m_gpioDir != settings.m_gpioDir) || force)
1175  {
1176  reverseAPIKeys.append("gpioDir");
1177 
1178  if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) != 0)
1179  {
1180  qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir);
1181  }
1182  else
1183  {
1184  forwardGPIOChange = true;
1185  qDebug("LimeSDROutput::applySettings: GPIO directions set to %u", settings.m_gpioDir);
1186  }
1187  }
1188 
1189  if ((m_settings.m_gpioPins != settings.m_gpioPins) || force)
1190  {
1191  reverseAPIKeys.append("gpioPins");
1192 
1193  if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) != 0)
1194  {
1195  qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins);
1196  }
1197  else
1198  {
1199  forwardGPIOChange = true;
1200  qDebug("LimeSDROutput::applySettings: GPIO pins set to %u", settings.m_gpioPins);
1201  }
1202  }
1203  }
1204 
1205  if (settings.m_useReverseAPI)
1206  {
1207  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
1211  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
1212  }
1213 
1214  m_settings = settings;
1215  double clockGenFreqAfter;
1216 
1217  if (LMS_GetClockFreq(m_deviceShared.m_deviceParams->getDevice(), LMS_CLOCK_CGEN, &clockGenFreqAfter) != 0)
1218  {
1219  qCritical("LimeSDRInput::applySettings: could not get clock gen frequency");
1220  }
1221  else
1222  {
1223  qDebug() << "LimeSDRInput::applySettings: clock gen frequency after: " << clockGenFreqAfter;
1224  doCalibration = doCalibration || (clockGenFreqAfter != clockGenFreq);
1225  }
1226 
1227  if (doCalibration || doLPCalibration)
1228  {
1230  {
1232  ownThreadWasRunning = true;
1233  }
1234 
1235  suspendRxBuddies();
1236  suspendTxBuddies();
1237 
1238  if (doCalibration)
1239  {
1240  if (LMS_Calibrate(m_deviceShared.m_deviceParams->getDevice(),
1241  LMS_CH_RX,
1244  0) < 0)
1245  {
1246  qCritical("LimeSDRInput::applySettings: calibration failed on Rx channel %d", m_deviceShared.m_channel);
1247  }
1248  else
1249  {
1250  qDebug("LimeSDRInput::applySettings: calibration successful on Rx channel %d", m_deviceShared.m_channel);
1251  }
1252  }
1253 
1254  if (doLPCalibration)
1255  {
1256  if (LMS_SetLPFBW(m_deviceShared.m_deviceParams->getDevice(),
1257  LMS_CH_RX,
1259  m_settings.m_lpfBW) < 0)
1260  {
1261  qCritical("LimeSDRInput::applySettings: could not set LPF to %f Hz", m_settings.m_lpfBW);
1262  }
1263  else
1264  {
1265  qDebug("LimeSDRInput::applySettings: LPF set to %f Hz", m_settings.m_lpfBW);
1266  }
1267  }
1268 
1269  resumeTxBuddies();
1270  resumeRxBuddies();
1271 
1272  if (ownThreadWasRunning) {
1274  }
1275  }
1276 
1277  // forward changes to buddies or oneself
1278 
1279  if (forwardChangeAllDSP)
1280  {
1281  qDebug("LimeSDRInput::applySettings: forward change to all buddies");
1282 
1283  int ncoShift = m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0;
1284 
1285  // send to self first
1288  m_settings.m_centerFrequency + ncoShift);
1290 
1291  // send to source buddies
1292  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
1293  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
1294 
1295  for (; itSource != sourceBuddies.end(); ++itSource)
1296  {
1299  (*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
1300  }
1301 
1302  // send to sink buddies
1303  const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
1304  std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
1305 
1306  for (; itSink != sinkBuddies.end(); ++itSink)
1307  {
1310  (*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
1311  }
1312  }
1313  else if (forwardChangeRxDSP)
1314  {
1315  qDebug("LimeSDRInput::applySettings: forward change to Rx buddies");
1316 
1317  int sampleRate = m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftDecim);
1318  int ncoShift = m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0;
1319 
1320  // send to self first
1321  DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, m_settings.m_centerFrequency + ncoShift);
1323 
1324  // send to source buddies
1325  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
1326  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
1327 
1328  for (; itSource != sourceBuddies.end(); ++itSource)
1329  {
1332  (*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
1333  }
1334  }
1335  else if (forwardChangeOwnDSP)
1336  {
1337  qDebug("LimeSDRInput::applySettings: forward change to self only");
1338 
1339  int sampleRate = m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftDecim);
1340  int ncoShift = m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0;
1341  DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, m_settings.m_centerFrequency + ncoShift);
1342  m_fileSink->handleMessage(*notif); // forward to file sink
1344  }
1345 
1346  if (forwardClockSource)
1347  {
1348  // send to source buddies
1349  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
1350  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
1351 
1352  for (; itSource != sourceBuddies.end(); ++itSource)
1353  {
1356  (*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
1357  }
1358 
1359  // send to sink buddies
1360  const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
1361  std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
1362 
1363  for (; itSink != sinkBuddies.end(); ++itSink)
1364  {
1367  (*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
1368  }
1369  }
1370 
1371  if (forwardGPIOChange)
1372  {
1373  // send to source buddies
1374  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
1375  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
1376 
1377  for (; itSource != sourceBuddies.end(); ++itSource)
1378  {
1381  (*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
1382  }
1383 
1384  // send to sink buddies
1385  const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
1386  std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
1387 
1388  for (; itSink != sinkBuddies.end(); ++itSink)
1389  {
1392  (*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
1393  }
1394  }
1395 
1396  QLocale loc;
1397 
1398  qDebug().noquote() << "LimeSDRInput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz"
1399  << " m_transverterMode: " << m_settings.m_transverterMode
1400  << " m_transverterDeltaFrequency: " << m_settings.m_transverterDeltaFrequency
1401  << " deviceCenterFrequency: " << deviceCenterFrequency
1402  << " device stream sample rate: " << loc.toString(m_settings.m_devSampleRate) << "S/s"
1403  << " sample rate with soft decimation: " << loc.toString( m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftDecim)) << "S/s"
1404  << " ADC sample rate with hard decimation: " << loc.toString(m_settings.m_devSampleRate*(1<<m_settings.m_log2HardDecim)) << "S/s"
1405  << " m_log2HardDecim: " << m_settings.m_log2HardDecim
1406  << " m_log2SoftDecim: " << m_settings.m_log2SoftDecim
1407  << " m_gain: " << m_settings.m_gain
1408  << " m_lpfBW: " << loc.toString(static_cast<int>(m_settings.m_lpfBW))
1409  << " m_lpfFIRBW: " << loc.toString(static_cast<int>(m_settings.m_lpfFIRBW))
1410  << " m_lpfFIREnable: " << m_settings.m_lpfFIREnable
1411  << " m_ncoEnable: " << m_settings.m_ncoEnable
1412  << " m_ncoFrequency: " << loc.toString(m_settings.m_ncoFrequency)
1413  << " m_antennaPath: " << m_settings.m_antennaPath
1414  << " m_extClock: " << m_settings.m_extClock
1415  << " m_extClockFreq: " << loc.toString(m_settings.m_extClockFreq)
1416  << " m_gpioDir: " << m_settings.m_gpioDir
1417  << " m_gpioPins: " << m_settings.m_gpioPins
1418  << " force: " << force
1419  << " forceNCOFrequency: " << forceNCOFrequency
1420  << " doCalibration: " << doCalibration
1421  << " doLPCalibration: " << doLPCalibration;
1422 
1423  return true;
1424 }
1425 
1428  QString& errorMessage)
1429 {
1430  (void) errorMessage;
1432  response.getLimeSdrInputSettings()->init();
1434  return 200;
1435 }
1436 
1438  bool force,
1439  const QStringList& deviceSettingsKeys,
1440  SWGSDRangel::SWGDeviceSettings& response, // query + response
1441  QString& errorMessage)
1442 {
1443  (void) errorMessage;
1444  LimeSDRInputSettings settings = m_settings;
1445 
1446  if (deviceSettingsKeys.contains("antennaPath")) {
1448  }
1449  if (deviceSettingsKeys.contains("centerFrequency")) {
1451  }
1452  if (deviceSettingsKeys.contains("dcBlock")) {
1453  settings.m_dcBlock = response.getLimeSdrInputSettings()->getDcBlock() != 0;
1454  }
1455  if (deviceSettingsKeys.contains("devSampleRate")) {
1456  settings.m_devSampleRate = response.getLimeSdrInputSettings()->getDevSampleRate();
1457  }
1458  if (deviceSettingsKeys.contains("extClock")) {
1459  settings.m_extClock = response.getLimeSdrInputSettings()->getExtClock() != 0;
1460  }
1461  if (deviceSettingsKeys.contains("extClockFreq")) {
1462  settings.m_extClockFreq = response.getLimeSdrInputSettings()->getExtClockFreq();
1463  }
1464  if (deviceSettingsKeys.contains("gain")) {
1465  settings.m_gain = response.getLimeSdrInputSettings()->getGain();
1466  }
1467  if (deviceSettingsKeys.contains("gainMode")) {
1469  }
1470  if (deviceSettingsKeys.contains("iqCorrection")) {
1471  settings.m_iqCorrection = response.getLimeSdrInputSettings()->getIqCorrection() != 0;
1472  }
1473  if (deviceSettingsKeys.contains("lnaGain")) {
1474  settings.m_lnaGain = response.getLimeSdrInputSettings()->getLnaGain();
1475  }
1476  if (deviceSettingsKeys.contains("log2HardDecim")) {
1477  settings.m_log2HardDecim = response.getLimeSdrInputSettings()->getLog2HardDecim();
1478  }
1479  if (deviceSettingsKeys.contains("log2SoftDecim")) {
1480  settings.m_log2SoftDecim = response.getLimeSdrInputSettings()->getLog2SoftDecim();
1481  }
1482  if (deviceSettingsKeys.contains("lpfBW")) {
1483  settings.m_lpfBW = response.getLimeSdrInputSettings()->getLpfBw();
1484  }
1485  if (deviceSettingsKeys.contains("lpfFIREnable")) {
1486  settings.m_lpfFIREnable = response.getLimeSdrInputSettings()->getLpfFirEnable() != 0;
1487  }
1488  if (deviceSettingsKeys.contains("lpfFIRBW")) {
1489  settings.m_lpfFIRBW = response.getLimeSdrInputSettings()->getLpfFirbw();
1490  }
1491  if (deviceSettingsKeys.contains("ncoEnable")) {
1492  settings.m_ncoEnable = response.getLimeSdrInputSettings()->getNcoEnable() != 0;
1493  }
1494  if (deviceSettingsKeys.contains("ncoFrequency")) {
1495  settings.m_ncoFrequency = response.getLimeSdrInputSettings()->getNcoFrequency();
1496  }
1497  if (deviceSettingsKeys.contains("pgaGain")) {
1498  settings.m_pgaGain = response.getLimeSdrInputSettings()->getPgaGain();
1499  }
1500  if (deviceSettingsKeys.contains("tiaGain")) {
1501  settings.m_tiaGain = response.getLimeSdrInputSettings()->getTiaGain();
1502  }
1503  if (deviceSettingsKeys.contains("transverterDeltaFrequency")) {
1505  }
1506  if (deviceSettingsKeys.contains("transverterMode")) {
1507  settings.m_transverterMode = response.getLimeSdrInputSettings()->getTransverterMode() != 0;
1508  }
1509  if (deviceSettingsKeys.contains("fileRecordName")) {
1511  }
1512  if (deviceSettingsKeys.contains("gpioDir")) {
1513  settings.m_gpioDir = response.getLimeSdrInputSettings()->getGpioDir() & 0xFF;
1514  }
1515  if (deviceSettingsKeys.contains("gpioPins")) {
1516  settings.m_gpioPins = response.getLimeSdrInputSettings()->getGpioPins() & 0xFF;
1517  }
1518  if (deviceSettingsKeys.contains("useReverseAPI")) {
1519  settings.m_useReverseAPI = response.getLimeSdrInputSettings()->getUseReverseApi() != 0;
1520  }
1521  if (deviceSettingsKeys.contains("reverseAPIAddress")) {
1523  }
1524  if (deviceSettingsKeys.contains("reverseAPIPort")) {
1526  }
1527  if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
1529  }
1530 
1531  MsgConfigureLimeSDR *msg = MsgConfigureLimeSDR::create(settings, force);
1533 
1534  if (m_guiMessageQueue) // forward to GUI if any
1535  {
1536  MsgConfigureLimeSDR *msgToGUI = MsgConfigureLimeSDR::create(settings, force);
1537  m_guiMessageQueue->push(msgToGUI);
1538  }
1539 
1540  webapiFormatDeviceSettings(response, settings);
1541  return 200;
1542 }
1543 
1545 {
1546  response.getLimeSdrInputSettings()->setAntennaPath((int) settings.m_antennaPath);
1548  response.getLimeSdrInputSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
1550  response.getLimeSdrInputSettings()->setExtClock(settings.m_extClock ? 1 : 0);
1552  response.getLimeSdrInputSettings()->setGain(settings.m_gain);
1553  response.getLimeSdrInputSettings()->setGainMode((int) settings.m_gainMode);
1554  response.getLimeSdrInputSettings()->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
1555  response.getLimeSdrInputSettings()->setLnaGain(settings.m_lnaGain);
1558  response.getLimeSdrInputSettings()->setLpfBw(settings.m_lpfBW);
1559  response.getLimeSdrInputSettings()->setLpfFirEnable(settings.m_lpfFIREnable ? 1 : 0);
1560  response.getLimeSdrInputSettings()->setLpfFirbw(settings.m_lpfFIRBW);
1561  response.getLimeSdrInputSettings()->setNcoEnable(settings.m_ncoEnable ? 1 : 0);
1563  response.getLimeSdrInputSettings()->setPgaGain(settings.m_pgaGain);
1564  response.getLimeSdrInputSettings()->setTiaGain(settings.m_tiaGain);
1566  response.getLimeSdrInputSettings()->setTransverterMode(settings.m_transverterMode ? 1 : 0);
1567 
1568  if (response.getLimeSdrInputSettings()->getFileRecordName()) {
1570  } else {
1571  response.getLimeSdrInputSettings()->setFileRecordName(new QString(settings.m_fileRecordName));
1572  }
1573 
1574  response.getLimeSdrInputSettings()->setGpioDir(settings.m_gpioDir);
1575  response.getLimeSdrInputSettings()->setGpioPins(settings.m_gpioPins);
1576  response.getLimeSdrInputSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
1577 
1578  if (response.getLimeSdrInputSettings()->getReverseApiAddress()) {
1580  } else {
1581  response.getLimeSdrInputSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
1582  }
1583 
1586 }
1587 
1589  SWGSDRangel::SWGDeviceReport& response,
1590  QString& errorMessage)
1591 {
1592  (void) errorMessage;
1594  response.getLimeSdrInputReport()->init();
1595  webapiFormatDeviceReport(response);
1596  return 200;
1597 }
1598 
1600  SWGSDRangel::SWGDeviceState& response,
1601  QString& errorMessage)
1602 {
1603  (void) errorMessage;
1605  return 200;
1606 }
1607 
1609  bool run,
1610  SWGSDRangel::SWGDeviceState& response,
1611  QString& errorMessage)
1612 {
1613  (void) errorMessage;
1615  MsgStartStop *message = MsgStartStop::create(run);
1616  m_inputMessageQueue.push(message);
1617 
1618  if (m_guiMessageQueue) // forward to GUI if any
1619  {
1620  MsgStartStop *msgToGUI = MsgStartStop::create(run);
1621  m_guiMessageQueue->push(msgToGUI);
1622  }
1623 
1624  return 200;
1625 }
1626 
1628 {
1629  bool success = false;
1630  double temp = 0.0;
1631  uint8_t gpioDir = 0;
1632  uint8_t gpioPins = 0;
1633  lms_stream_status_t status;
1634  status.active = false;
1635  status.fifoFilledCount = 0;
1636  status.fifoSize = 1;
1637  status.underrun = 0;
1638  status.overrun = 0;
1639  status.droppedPackets = 0;
1640  status.linkRate = 0.0;
1641  status.timestamp = 0;
1642 
1643  success = (m_streamId.handle && (LMS_GetStreamStatus(&m_streamId, &status) == 0));
1644 
1645  response.getLimeSdrInputReport()->setSuccess(success ? 1 : 0);
1646  response.getLimeSdrInputReport()->setStreamActive(status.active ? 1 : 0);
1647  response.getLimeSdrInputReport()->setFifoSize(status.fifoSize);
1648  response.getLimeSdrInputReport()->setFifoFill(status.fifoFilledCount);
1649  response.getLimeSdrInputReport()->setUnderrunCount(status.underrun);
1650  response.getLimeSdrInputReport()->setOverrunCount(status.overrun);
1651  response.getLimeSdrInputReport()->setDroppedPacketsCount(status.droppedPackets);
1652  response.getLimeSdrInputReport()->setLinkRate(status.linkRate);
1653  response.getLimeSdrInputReport()->setHwTimestamp(status.timestamp);
1654 
1656  {
1657  LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp);
1658  LMS_GPIODirRead(m_deviceShared.m_deviceParams->getDevice(), &gpioDir, 1);
1659  LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1);
1660  }
1661 
1662  response.getLimeSdrInputReport()->setTemperature(temp);
1663  response.getLimeSdrInputReport()->setGpioDir(gpioDir);
1664  response.getLimeSdrInputReport()->setGpioPins(gpioPins);
1665 }
1666 
1667 void LimeSDRInput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const LimeSDRInputSettings& settings, bool force)
1668 {
1670  swgDeviceSettings->setDirection(0); // single Rx
1671  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
1672  swgDeviceSettings->setDeviceHwType(new QString("LimeSDR"));
1674  SWGSDRangel::SWGLimeSdrInputSettings *swgLimeSdrInputSettings = swgDeviceSettings->getLimeSdrInputSettings();
1675 
1676  // transfer data that has been modified. When force is on transfer all data except reverse API data
1677 
1678  if (deviceSettingsKeys.contains("antennaPath") || force) {
1679  swgLimeSdrInputSettings->setAntennaPath((int) settings.m_antennaPath);
1680  }
1681  if (deviceSettingsKeys.contains("centerFrequency") || force) {
1682  swgLimeSdrInputSettings->setCenterFrequency(settings.m_centerFrequency);
1683  }
1684  if (deviceSettingsKeys.contains("dcBlock") || force) {
1685  swgLimeSdrInputSettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
1686  }
1687  if (deviceSettingsKeys.contains("devSampleRate") || force) {
1688  swgLimeSdrInputSettings->setDevSampleRate(settings.m_devSampleRate);
1689  }
1690  if (deviceSettingsKeys.contains("extClock") || force) {
1691  swgLimeSdrInputSettings->setExtClock(settings.m_extClock ? 1 : 0);
1692  }
1693  if (deviceSettingsKeys.contains("extClockFreq") || force) {
1694  swgLimeSdrInputSettings->setExtClockFreq(settings.m_extClockFreq);
1695  }
1696  if (deviceSettingsKeys.contains("gain") || force) {
1697  swgLimeSdrInputSettings->setGain(settings.m_gain);
1698  }
1699  if (deviceSettingsKeys.contains("gainMode") || force) {
1700  swgLimeSdrInputSettings->setGainMode((int) settings.m_gainMode);
1701  }
1702  if (deviceSettingsKeys.contains("iqCorrection") || force) {
1703  swgLimeSdrInputSettings->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
1704  }
1705  if (deviceSettingsKeys.contains("lnaGain") || force) {
1706  swgLimeSdrInputSettings->setLnaGain(settings.m_lnaGain);
1707  }
1708  if (deviceSettingsKeys.contains("log2HardDecim") || force) {
1709  swgLimeSdrInputSettings->setLog2HardDecim(settings.m_log2HardDecim);
1710  }
1711  if (deviceSettingsKeys.contains("log2SoftDecim") || force) {
1712  swgLimeSdrInputSettings->setLog2SoftDecim(settings.m_log2SoftDecim);
1713  }
1714  if (deviceSettingsKeys.contains("lpfBW") || force) {
1715  swgLimeSdrInputSettings->setLpfBw(settings.m_lpfBW);
1716  }
1717  if (deviceSettingsKeys.contains("lpfFIREnable") || force) {
1718  swgLimeSdrInputSettings->setLpfFirEnable(settings.m_lpfFIREnable ? 1 : 0);
1719  }
1720  if (deviceSettingsKeys.contains("lpfFIRBW") || force) {
1721  swgLimeSdrInputSettings->setLpfFirbw(settings.m_lpfFIRBW);
1722  }
1723  if (deviceSettingsKeys.contains("ncoEnable") || force) {
1724  swgLimeSdrInputSettings->setNcoEnable(settings.m_ncoEnable ? 1 : 0);
1725  }
1726  if (deviceSettingsKeys.contains("ncoFrequency") || force) {
1727  swgLimeSdrInputSettings->setNcoFrequency(settings.m_ncoFrequency);
1728  }
1729  if (deviceSettingsKeys.contains("pgaGain") || force) {
1730  swgLimeSdrInputSettings->setPgaGain(settings.m_pgaGain);
1731  }
1732  if (deviceSettingsKeys.contains("tiaGain") || force) {
1733  swgLimeSdrInputSettings->setTiaGain(settings.m_tiaGain);
1734  }
1735  if (deviceSettingsKeys.contains("transverterDeltaFrequency") || force) {
1736  swgLimeSdrInputSettings->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency);
1737  }
1738  if (deviceSettingsKeys.contains("transverterMode") || force) {
1739  swgLimeSdrInputSettings->setTransverterMode(settings.m_transverterMode ? 1 : 0);
1740  }
1741  if (deviceSettingsKeys.contains("fileRecordName") || force) {
1742  swgLimeSdrInputSettings->setFileRecordName(new QString(settings.m_fileRecordName));
1743  }
1744  if (deviceSettingsKeys.contains("gpioDir") || force) {
1745  swgLimeSdrInputSettings->setGpioDir(settings.m_gpioDir & 0xFF);
1746  }
1747  if (deviceSettingsKeys.contains("gpioPins") || force) {
1748  swgLimeSdrInputSettings->setGpioPins(settings.m_gpioPins & 0xFF);
1749  }
1750 
1751  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings")
1752  .arg(settings.m_reverseAPIAddress)
1753  .arg(settings.m_reverseAPIPort)
1754  .arg(settings.m_reverseAPIDeviceIndex);
1755  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
1756  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
1757 
1758  QBuffer *buffer=new QBuffer();
1759  buffer->open((QBuffer::ReadWrite));
1760  buffer->write(swgDeviceSettings->asJson().toUtf8());
1761  buffer->seek(0);
1762 
1763  // Always use PATCH to avoid passing reverse API settings
1764  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
1765 
1766  delete swgDeviceSettings;
1767 }
1768 
1770 {
1772  swgDeviceSettings->setDirection(0); // single Rx
1773  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
1774  swgDeviceSettings->setDeviceHwType(new QString("LimeSDR"));
1775 
1776  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
1780  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
1781  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
1782 
1783  QBuffer *buffer=new QBuffer();
1784  buffer->open((QBuffer::ReadWrite));
1785  buffer->write(swgDeviceSettings->asJson().toUtf8());
1786  buffer->seek(0);
1787 
1788  if (start) {
1789  m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer);
1790  } else {
1791  m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer);
1792  }
1793 
1794  delete swgDeviceSettings;
1795 }
1796 
1797 void LimeSDRInput::networkManagerFinished(QNetworkReply *reply)
1798 {
1799  QNetworkReply::NetworkError replyError = reply->error();
1800 
1801  if (replyError)
1802  {
1803  qWarning() << "LimeSDRInput::networkManagerFinished:"
1804  << " error(" << (int) replyError
1805  << "): " << replyError
1806  << ": " << reply->errorString();
1807  return;
1808  }
1809 
1810  QString answer = reply->readAll();
1811  answer.chop(1); // remove last \n
1812  qDebug("LimeSDRInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
1813 }
static bool SetRFELNA_dB(lms_device_t *device, std::size_t chan, int value)
void setReverseApiAddress(QString *reverse_api_address)
bool startDeviceEngine()
Start the device engine corresponding to the stream type.
Definition: deviceapi.cpp:253
void setDevSampleRate(qint32 dev_sample_rate)
static MsgConfigureLimeSDR * create(const LimeSDRInputSettings &settings, bool force)
Definition: limesdrinput.h:48
void suspendRxBuddies()
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport &response)
int m_channel
logical device channel number (-1 if none)
int m_log2OvSRRx
log2 of Rx oversampling (0..5)
uint32_t getHWLog2Decim() const
void push(Message *message, bool emitSignal=true)
Push message onto queue.
uint8_t m_gpioDir
GPIO pin direction LSB first; 0 input, 1 output.
void stopDeviceEngine()
Stop the device engine corresponding to the stream type.
Definition: deviceapi.cpp:266
void setFileName(const QString &filename)
Definition: filerecord.cpp:59
virtual int webapiReportGet(SWGSDRangel::SWGDeviceReport &response, QString &errorMessage)
uint getDeviceUID() const
Return the current device engine unique ID.
Definition: deviceapi.cpp:303
void setLimeSdrInputSettings(SWGLimeSdrInputSettings *lime_sdr_input_settings)
bool openDevice()
DeviceLimeSDRParams::LimeType getLimeType() const
lms_range_t m_lpfRangeRx
Low pass filter range information (Rx side)
static MsgReportBuddyChange * create(int devSampleRate, int log2HardDecimInterp, uint64_t centerFrequency, bool rxElseTx)
virtual void setCenterFrequency(qint64 centerFrequency)
const std::vector< DeviceAPI * > & getSinkBuddies() const
Definition: deviceapi.h:166
void startRecording()
Definition: filerecord.cpp:105
uint32_t m_tiaGain
Manual TIA gain.
MessageQueue m_inputMessageQueue
Input queue to the source.
void setDroppedPacketsCount(qint32 dropped_packets_count)
virtual QString asJson() override
MessageQueue * getDeviceEngineInputMessageQueue()
Device engine message queue.
Definition: deviceapi.cpp:316
void resumeRxBuddies()
static bool SetRBBPGA_dB(lms_device_t *device, std::size_t chan, float value)
void webapiReverseSendSettings(QList< QString > &deviceSettingsKeys, const LimeSDRInputSettings &settings, bool force)
lms_device_t * getDevice()
bool m_lpfFIREnable
Enable LMS digital lowpass FIR filters.
virtual int webapiRun(bool run, SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
bool applySettings(const LimeSDRInputSettings &settings, bool force=false, bool forceNCOFrequency=false)
static MsgReportStreamInfo * create(bool success, bool active, uint32_t fifoFilledCount, uint32_t fifoSize, uint32_t underrun, uint32_t overrun, uint32_t droppedPackets, float linkRate, uint64_t timestamp)
Definition: limesdrinput.h:108
uint32_t getDeviceItemIndex() const
Definition: deviceapi.h:129
static MsgStartStop * create(bool startStop)
Definition: limesdrinput.h:194
virtual int webapiSettingsPutPatch(bool force, const QStringList &deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
bool m_extClock
True if external clock source.
LimeSDRInputThread * m_limeSDRInputThread
Definition: limesdrinput.h:261
lms_range_t m_srRangeRx
ADC sample rate range.
uint32_t m_nbRxChannels
number of Rx channels (normally 2, we&#39;ll see if we really use it...)
QByteArray serialize() const
bool initDeviceEngine()
Init the device engine corresponding to the stream type.
Definition: deviceapi.cpp:240
uint32_t m_lnaGain
Manual LAN gain.
int m_ncoFrequency
Actual NCO frequency (the resulting frequency with mixing is displayed)
static bool SetRFETIA_dB(lms_device_t *device, std::size_t chan, int value)
bool deserialize(const QByteArray &data)
void setCenterFrequency(qint64 center_frequency)
void setOriginatorIndex(qint32 originator_index)
uint32_t m_gain
Optimally distributed gain (dB)
void setUseReverseApi(qint32 use_reverse_api)
SampleSinkFifo m_sampleFifo
FileRecord * m_fileSink
File sink to record device I/Q output.
Definition: limesdrinput.h:267
bool setSize(int size)
MessageQueue * getMessageQueueToGUI()
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 bool handleMessage(const Message &message)
Processing of a message. Returns true if message has actually been processed.
Definition: filerecord.cpp:128
SWGLimeSdrInputReport * getLimeSdrInputReport()
void networkManagerFinished(QNetworkReply *reply)
int getDeviceSetIndex() const
Definition: deviceapi.h:131
float m_lpfFIRBW
LMS digital lowpass FIR filters bandwidth (Hz)
virtual bool start()
void setTransverterDeltaFrequency(qint64 transverter_delta_frequency)
virtual void startWork()
void * getBuddySharedPtr() const
Definition: deviceapi.h:161
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
bool m_threadWasRunning
flag to know if thread needs to be resumed after suspend
unsigned char uint8_t
Definition: rtptypes_win.h:42
void genUniqueFileName(uint deviceUID, int istream=-1)
Definition: filerecord.cpp:67
void getLORange(float &minF, float &maxF) const
bool m_channelAcquired
Definition: limesdrinput.h:265
void setLog2Decimation(unsigned int log2_decim)
const LimeSDRInputSettings & getSettings() const
Definition: limesdrinput.h:45
virtual bool deserialize(const QByteArray &data)
virtual int webapiSettingsGet(SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
void setBuddySharedPtr(void *ptr)
Definition: deviceapi.h:162
virtual bool isRunning()
void stopRecording()
Definition: filerecord.cpp:117
int32_t i
Definition: decimators.h:244
void setUnderrunCount(qint32 underrun_count)
virtual void destroy()
void setLog2SoftDecim(qint32 log2_soft_decim)
static bool match(const Message *message)
Definition: message.cpp:45
QString m_deviceDescription
Definition: limesdrinput.h:262
void setFileRecordName(QString *file_record_name)
std::size_t getChannelIndex()
lms_stream_t m_streamId
Definition: limesdrinput.h:266
void removeAncillarySink(BasebandSampleSink *sink, unsigned int index=0)
Removes it.
Definition: deviceapi.cpp:100
virtual int getSampleRate() const
Sample rate exposed by the source.
bool m_ncoEnable
Enable TSP NCO and mixing.
virtual int webapiRunGet(SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
static bool setNCOFrequency(lms_device_t *device, bool dir_tx, std::size_t chan, bool enable, float frequency)
bool acquireChannel()
QNetworkRequest m_networkRequest
Definition: limesdrinput.h:269
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
uint32_t m_pgaGain
Manual PGA gain.
virtual QByteArray serialize() const
float m_sampleRate
ADC/DAC sample rate.
virtual bool handleMessage(const Message &message)
float m_lpfBW
LMS amalog lowpass filter bandwidth (Hz)
void setLog2HardDecim(qint32 log2_hard_decim)
void setTransverterMode(qint32 transverter_mode)
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings &response, const LimeSDRInputSettings &settings)
void getDeviceEngineStateStr(QString &state)
Definition: deviceapi.cpp:389
const QString & getSamplingDeviceSerial() const
Definition: deviceapi.h:121
QNetworkAccessManager * m_networkManager
Definition: limesdrinput.h:268
virtual const QString & getDeviceDescription() const
virtual void stop()
LimeType m_type
Hardware type.
virtual void init()
initializations to be done when all collaborating objects are created and possibly connected ...
GainMode m_gainMode
Gain mode: auto or manual.
uint8_t m_gpioPins
GPIO pins to write; LSB first.
void getLPRange(float &minF, float &maxF) const
void webapiReverseSendStartStop(bool start)
const std::vector< DeviceAPI * > & getSourceBuddies() const
Definition: deviceapi.h:165
static bool setClockSource(lms_device_t *device, bool extClock, uint32_t extClockFrequency)
DeviceLimeSDRShared m_deviceShared
Definition: limesdrinput.h:264
void resumeTxBuddies()
DeviceAPI * m_deviceAPI
Definition: limesdrinput.h:258
LimeSDRInputSettings m_settings
Definition: limesdrinput.h:260
void setOverrunCount(qint32 overrun_count)
void closeDevice()
DeviceLimeSDRParams * m_deviceParams
unique hardware device parameters
void suspendTxBuddies()
virtual quint64 getCenterFrequency() const
Center frequency exposed by the source.
void releaseChannel()
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
uint32_t m_extClockFreq
Frequency (Hz) of external clock source.
bool open(lms_info_str_t deviceStr)
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection, int streamIndex=0)
Configure current device engine DSP corrections (Rx)
Definition: deviceapi.cpp:355
virtual ~LimeSDRInput()
ThreadInterface * m_thread
holds the thread address if started else 0
SWGLimeSdrInputSettings * getLimeSdrInputSettings()
void setDirection(qint32 direction)
void getSRRange(float &minF, float &maxF) const
lms_range_t m_loRangeRx
LO range for Rx.
void setReverseApiPort(qint32 reverse_api_port)
static bool setRxAntennaPath(lms_device_t *device, std::size_t chan, int path)
void setStreamActive(qint32 stream_active)
void setDeviceHwType(QString *device_hw_type)
void setLimeSdrInputReport(SWGLimeSdrInputReport *lime_sdr_input_report)
MessageQueue * getSamplingDeviceGUIMessageQueue()
Sampling device (ex: single Tx) GUI input message queue.
Definition: deviceapi.cpp:342
static MsgReportClockSourceChange * create(bool extClock, uint32_t m_extClockFreq)
static MsgReportDeviceInfo * create(float temperature, uint8_t gpioPins)