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.
hackrfinput.cpp
Go to the documentation of this file.
1 // Copyright (C) 2015 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 <string.h>
19 #include <errno.h>
20 
21 #include <QDebug>
22 #include <QNetworkReply>
23 #include <QBuffer>
24 
25 #include "SWGDeviceSettings.h"
26 #include "SWGDeviceState.h"
27 
28 #include "util/simpleserializer.h"
29 #include "dsp/dspcommands.h"
30 #include "dsp/dspengine.h"
31 #include "dsp/filerecord.h"
32 #include "device/deviceapi.h"
35 
36 #include "hackrfinput.h"
37 #include "hackrfinputthread.h"
38 
43 
45  m_deviceAPI(deviceAPI),
46  m_settings(),
47  m_dev(0),
48  m_hackRFThread(0),
49  m_deviceDescription("HackRF"),
50  m_running(false)
51 {
52  openDevice();
53 
54  m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
55  m_deviceAPI->setNbSourceStreams(1);
56  m_deviceAPI->addAncillarySink(m_fileSink);
57 
58  m_deviceAPI->setBuddySharedPtr(&m_sharedParams);
59 
60  m_networkManager = new QNetworkAccessManager();
61  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
62 }
63 
65 {
66  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
67  delete m_networkManager;
68 
69  if (m_running) {
70  stop();
71  }
72 
74  delete m_fileSink;
75  closeDevice();
77 }
78 
80 {
81  delete this;
82 }
83 
85 {
86  if (m_dev != 0)
87  {
88  closeDevice();
89  }
90 
91  if (!m_sampleFifo.setSize(1<<19))
92  {
93  qCritical("HackRFInput::start: could not allocate SampleFifo");
94  return false;
95  }
96 
97  if (m_deviceAPI->getSinkBuddies().size() > 0)
98  {
99  DeviceAPI *buddy = m_deviceAPI->getSinkBuddies()[0];
100  DeviceHackRFParams *buddySharedParams = (DeviceHackRFParams *) buddy->getBuddySharedPtr();
101 
102  if (buddySharedParams == 0)
103  {
104  qCritical("HackRFInput::openDevice: could not get shared parameters from buddy");
105  return false;
106  }
107 
108  if (buddySharedParams->m_dev == 0) // device is not opened by buddy
109  {
110  qCritical("HackRFInput::openDevice: could not get HackRF handle from buddy");
111  return false;
112  }
113 
114  m_sharedParams = *(buddySharedParams); // copy parameters from buddy
115  m_dev = m_sharedParams.m_dev; // get HackRF handle
116  }
117  else
118  {
120  {
121  qCritical("HackRFInput::openDevice: could not open HackRF %s", qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
122  return false;
123  }
124 
126  }
127 
128  return true;
129 }
130 
132 {
133  applySettings(m_settings, true);
134 }
135 
137 {
138 // QMutexLocker mutexLocker(&m_mutex);
139  if (!m_dev) {
140  return false;
141  }
142 
143  if (m_running) {
144  stop();
145  }
146 
148 
149 // mutexLocker.unlock();
150 
151  applySettings(m_settings, true);
152 
156 
158 
159  qDebug("HackRFInput::startInput: started");
160  m_running = true;
161 
162  return true;
163 }
164 
166 {
167  if (m_deviceAPI->getSinkBuddies().size() == 0)
168  {
169  qDebug("HackRFInput::closeDevice: closing device since Tx side is not open");
170 
171  if(m_dev != 0) // close BladeRF
172  {
173  hackrf_close(m_dev);
174  //hackrf_exit(); // TODO: this may not work if several HackRF Devices are running concurrently. It should be handled globally in the application
175  }
176  }
177 
178  m_sharedParams.m_dev = 0;
179  m_dev = 0;
180 }
181 
183 {
184  qDebug("HackRFInput::stop");
185 // QMutexLocker mutexLocker(&m_mutex);
186 
187  if (m_hackRFThread != 0)
188  {
190  delete m_hackRFThread;
191  m_hackRFThread = 0;
192  }
193 
194  m_running = false;
195 }
196 
197 QByteArray HackRFInput::serialize() const
198 {
199  return m_settings.serialize();
200 }
201 
202 bool HackRFInput::deserialize(const QByteArray& data)
203 {
204  bool success = true;
205 
206  if (!m_settings.deserialize(data))
207  {
209  success = false;
210  }
211 
213  m_inputMessageQueue.push(message);
214 
215  if (m_guiMessageQueue)
216  {
218  m_guiMessageQueue->push(messageToGUI);
219  }
220 
221  return success;
222 }
223 
224 const QString& HackRFInput::getDeviceDescription() const
225 {
226  return m_deviceDescription;
227 }
228 
230 {
232 }
233 
235 {
237 }
238 
239 void HackRFInput::setCenterFrequency(qint64 centerFrequency)
240 {
241  HackRFInputSettings settings = m_settings;
242  settings.m_centerFrequency = centerFrequency;
243 
244  MsgConfigureHackRF* message = MsgConfigureHackRF::create(settings, false);
245  m_inputMessageQueue.push(message);
246 
247  if (m_guiMessageQueue)
248  {
249  MsgConfigureHackRF* messageToGUI = MsgConfigureHackRF::create(settings, false);
250  m_guiMessageQueue->push(messageToGUI);
251  }
252 }
253 
255 {
256  if (MsgConfigureHackRF::match(message))
257  {
258  MsgConfigureHackRF& conf = (MsgConfigureHackRF&) message;
259  qDebug() << "HackRFInput::handleMessage: MsgConfigureHackRF";
260 
261  bool success = applySettings(conf.getSettings(), conf.getForce());
262 
263  if (!success)
264  {
265  qDebug("HackRFInput::handleMessage: config error");
266  }
267 
268  return true;
269  }
270  else if (MsgFileRecord::match(message))
271  {
272  MsgFileRecord& conf = (MsgFileRecord&) message;
273  qDebug() << "HackRFInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
274 
275  if (conf.getStartStop())
276  {
277  if (m_settings.m_fileRecordName.size() != 0) {
279  } else {
281  }
282 
284  }
285  else
286  {
288  }
289 
290  return true;
291  }
292  else if (MsgStartStop::match(message))
293  {
294  MsgStartStop& cmd = (MsgStartStop&) message;
295  qDebug() << "HackRFInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
296 
297  if (cmd.getStartStop())
298  {
300  {
302  }
303  }
304  else
305  {
307  }
308 
311  }
312 
313  return true;
314  }
316  {
318  qint64 centerFrequency = DeviceSampleSource::calculateCenterFrequency(
319  freqMsg.getFrequency(),
320  0,
325  qDebug("HackRFInput::handleMessage: MsgSynchronizeFrequency: centerFrequency: %lld Hz", centerFrequency);
326  HackRFInputSettings settings = m_settings;
327  settings.m_centerFrequency = centerFrequency;
328 
329  if (m_guiMessageQueue)
330  {
331  MsgConfigureHackRF* messageToGUI = MsgConfigureHackRF::create(settings, false);
332  m_guiMessageQueue->push(messageToGUI);
333  }
334 
336  int sampleRate = m_settings.m_devSampleRate/(1<<m_settings.m_log2Decim);
338  m_fileSink->handleMessage(*notif); // forward to file sink
340 
341  return true;
342  }
343  else
344  {
345  return false;
346  }
347 }
348 
349 void HackRFInput::setDeviceCenterFrequency(quint64 freq_hz, qint32 LOppmTenths)
350 {
351  if (!m_dev) {
352  return;
353  }
354 
355  qint64 df = ((qint64)freq_hz * LOppmTenths) / 10000000LL;
356  hackrf_error rc = (hackrf_error) hackrf_set_freq(m_dev, static_cast<uint64_t>(freq_hz + df));
357 
358  if (rc != HACKRF_SUCCESS) {
359  qWarning("HackRFInput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz + df);
360  } else {
361  qDebug("HackRFInput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz + df);
362  }
363 }
364 
365 bool HackRFInput::applySettings(const HackRFInputSettings& settings, bool force)
366 {
367 // QMutexLocker mutexLocker(&m_mutex);
368 
369  bool forwardChange = false;
370  hackrf_error rc;
371  QList<QString> reverseAPIKeys;
372 
373  qDebug() << "HackRFInput::applySettings";
374 
375  if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) {
376  reverseAPIKeys.append("dcBlock");
377  }
378  if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) {
379  reverseAPIKeys.append("iqCorrection");
380  }
381 
382  if ((m_settings.m_dcBlock != settings.m_dcBlock) ||
383  (m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
384  {
386  }
387 
388  if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force)
389  {
390  reverseAPIKeys.append("devSampleRate");
391  forwardChange = true;
392 
393  if (m_dev != 0)
394  {
395  rc = (hackrf_error) hackrf_set_sample_rate_manual(m_dev, settings.m_devSampleRate, 1);
396 
397  if (rc != HACKRF_SUCCESS)
398  {
399  qCritical("HackRFInput::applySettings: could not set sample rate TO %llu S/s: %s", settings.m_devSampleRate, hackrf_error_name(rc));
400  }
401  else
402  {
403  if (m_hackRFThread != 0)
404  {
405  qDebug("HackRFInput::applySettings: sample rate set to %llu S/s", settings.m_devSampleRate);
407  }
408  }
409  }
410  }
411 
412  if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
413  {
414  reverseAPIKeys.append("log2Decim");
415  forwardChange = true;
416 
417  if (m_hackRFThread != 0)
418  {
420  qDebug() << "HackRFInput: set decimation to " << (1<<settings.m_log2Decim);
421  }
422  }
423 
424  if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency)) {
425  reverseAPIKeys.append("centerFrequency");
426  }
427 
428  if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) {
429  reverseAPIKeys.append("LOppmTenths");
430  }
431  if ((m_settings.m_fcPos != settings.m_fcPos) || force) {
432  reverseAPIKeys.append("fcPos");
433  }
434 
435  if ((m_settings.m_centerFrequency != settings.m_centerFrequency) ||
437  (m_settings.m_LOppmTenths != settings.m_LOppmTenths) ||
438  (m_settings.m_log2Decim != settings.m_log2Decim) ||
439  (m_settings.m_fcPos != settings.m_fcPos) || force)
440  {
441  qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency(
442  settings.m_centerFrequency,
443  0,
444  settings.m_log2Decim,
446  settings.m_devSampleRate,
447  DeviceSampleSource::FrequencyShiftScheme::FSHIFT_TXSYNC,
448  false);
449  setDeviceCenterFrequency(deviceCenterFrequency, settings.m_LOppmTenths);
450 
451  if (m_deviceAPI->getSinkBuddies().size() > 0) // forward to buddy if necessary
452  {
453  DeviceAPI *buddy = m_deviceAPI->getSinkBuddies()[0];
455  buddy->getSamplingDeviceInputMessageQueue()->push(freqMsg);
456  }
457 
458  forwardChange = true;
459  }
460 
461  if ((m_settings.m_fcPos != settings.m_fcPos) || force)
462  {
463  if (m_hackRFThread != 0)
464  {
465  m_hackRFThread->setFcPos((int) settings.m_fcPos);
466  qDebug() << "HackRFInput: set fc pos (enum) to " << (int) settings.m_fcPos;
467  }
468  }
469 
470  if ((m_settings.m_lnaGain != settings.m_lnaGain) || force)
471  {
472  reverseAPIKeys.append("lnaGain");
473 
474  if (m_dev != 0)
475  {
476  rc = (hackrf_error) hackrf_set_lna_gain(m_dev, settings.m_lnaGain);
477 
478  if (rc != HACKRF_SUCCESS) {
479  qDebug("HackRFInput::applySettings: airspy_set_lna_gain failed: %s", hackrf_error_name(rc));
480  } else {
481  qDebug() << "HackRFInput:applySettings: LNA gain set to " << settings.m_lnaGain;
482  }
483  }
484  }
485 
486  if ((m_settings.m_vgaGain != settings.m_vgaGain) || force)
487  {
488  reverseAPIKeys.append("vgaGain");
489 
490  if (m_dev != 0)
491  {
492  rc = (hackrf_error) hackrf_set_vga_gain(m_dev, settings.m_vgaGain);
493 
494  if (rc != HACKRF_SUCCESS) {
495  qDebug("HackRFInput::applySettings: hackrf_set_vga_gain failed: %s", hackrf_error_name(rc));
496  } else {
497  qDebug() << "HackRFInput:applySettings: VGA gain set to " << settings.m_vgaGain;
498  }
499  }
500  }
501 
502  if ((m_settings.m_bandwidth != settings.m_bandwidth) || force)
503  {
504  reverseAPIKeys.append("bandwidth");
505 
506  if (m_dev != 0)
507  {
508  uint32_t bw_index = hackrf_compute_baseband_filter_bw_round_down_lt(settings.m_bandwidth + 1); // +1 so the round down to lower than yields desired bandwidth
509  rc = (hackrf_error) hackrf_set_baseband_filter_bandwidth(m_dev, bw_index);
510 
511  if (rc != HACKRF_SUCCESS) {
512  qDebug("HackRFInput::applySettings: hackrf_set_baseband_filter_bandwidth failed: %s", hackrf_error_name(rc));
513  } else {
514  qDebug() << "HackRFInput:applySettings: Baseband BW filter set to " << settings.m_bandwidth << " Hz";
515  }
516  }
517  }
518 
519  if ((m_settings.m_biasT != settings.m_biasT) || force)
520  {
521  reverseAPIKeys.append("biasT");
522 
523  if (m_dev != 0)
524  {
525  rc = (hackrf_error) hackrf_set_antenna_enable(m_dev, (settings.m_biasT ? 1 : 0));
526 
527  if (rc != HACKRF_SUCCESS) {
528  qDebug("HackRFInput::applySettings: hackrf_set_antenna_enable failed: %s", hackrf_error_name(rc));
529  } else {
530  qDebug() << "HackRFInput:applySettings: bias tee set to " << settings.m_biasT;
531  }
532  }
533  }
534 
535  if ((m_settings.m_lnaExt != settings.m_lnaExt) || force)
536  {
537  reverseAPIKeys.append("lnaExt");
538 
539  if (m_dev != 0)
540  {
541  rc = (hackrf_error) hackrf_set_amp_enable(m_dev, (settings.m_lnaExt ? 1 : 0));
542 
543  if (rc != HACKRF_SUCCESS) {
544  qDebug("HackRFInput::applySettings: hackrf_set_amp_enable failed: %s", hackrf_error_name(rc));
545  } else {
546  qDebug() << "HackRFInput:applySettings: extra LNA set to " << settings.m_lnaExt;
547  }
548  }
549  }
550 
551  if (forwardChange)
552  {
553  int sampleRate = settings.m_devSampleRate/(1<<settings.m_log2Decim);
554  DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_centerFrequency);
555  m_fileSink->handleMessage(*notif); // forward to file sink
557  }
558 
559  if (settings.m_useReverseAPI)
560  {
561  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
565  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
566  }
567 
568  m_settings = settings;
569 
570  qDebug() << "HackRFInput::applySettings: "
571  << " m_centerFrequency: " << m_settings.m_centerFrequency << " Hz"
572  << " m_LOppmTenths: " << m_settings.m_LOppmTenths
573  << " m_bandwidth: " << m_settings.m_bandwidth
574  << " m_lnaGain: " << m_settings.m_lnaGain
575  << " m_vgaGain: " << m_settings.m_vgaGain
576  << " m_log2Decim: " << m_settings.m_log2Decim
577  << " m_fcPos: " << m_settings.m_fcPos
578  << " m_devSampleRate: " << m_settings.m_devSampleRate
579  << " m_biasT: " << m_settings.m_biasT
580  << " m_lnaExt: " << m_settings.m_lnaExt
581  << " m_dcBlock: " << m_settings.m_dcBlock;
582 
583  return true;
584 }
585 
588  QString& errorMessage)
589 {
590  (void) errorMessage;
592  response.getHackRfInputSettings()->init();
594  return 200;
595 }
596 
598  bool force,
599  const QStringList& deviceSettingsKeys,
600  SWGSDRangel::SWGDeviceSettings& response, // query + response
601  QString& errorMessage)
602 {
603  (void) errorMessage;
604  HackRFInputSettings settings = m_settings;
605 
606  if (deviceSettingsKeys.contains("centerFrequency")) {
608  }
609  if (deviceSettingsKeys.contains("LOppmTenths")) {
610  settings.m_LOppmTenths = response.getHackRfInputSettings()->getLOppmTenths();
611  }
612  if (deviceSettingsKeys.contains("bandwidth")) {
613  settings.m_bandwidth = response.getHackRfInputSettings()->getBandwidth();
614  }
615  if (deviceSettingsKeys.contains("lnaGain")) {
616  settings.m_lnaGain = response.getHackRfInputSettings()->getLnaGain();
617  }
618  if (deviceSettingsKeys.contains("vgaGain")) {
619  settings.m_vgaGain = response.getHackRfInputSettings()->getVgaGain();
620  }
621  if (deviceSettingsKeys.contains("log2Decim")) {
622  settings.m_log2Decim = response.getHackRfInputSettings()->getLog2Decim();
623  }
624  if (deviceSettingsKeys.contains("fcPos"))
625  {
626  int fcPos = response.getHackRfInputSettings()->getFcPos();
627  fcPos = fcPos < 0 ? 0 : fcPos > 2 ? 2 : fcPos;
628  settings.m_fcPos = (HackRFInputSettings::fcPos_t) fcPos;
629  }
630  if (deviceSettingsKeys.contains("devSampleRate")) {
632  }
633  if (deviceSettingsKeys.contains("biasT")) {
634  settings.m_biasT = response.getHackRfInputSettings()->getBiasT() != 0;
635  }
636  if (deviceSettingsKeys.contains("lnaExt")) {
637  settings.m_lnaExt = response.getHackRfInputSettings()->getLnaExt() != 0;
638  }
639  if (deviceSettingsKeys.contains("dcBlock")) {
640  settings.m_dcBlock = response.getHackRfInputSettings()->getDcBlock() != 0;
641  }
642  if (deviceSettingsKeys.contains("iqCorrection")) {
643  settings.m_iqCorrection = response.getHackRfInputSettings()->getIqCorrection() != 0;
644  }
645  if (deviceSettingsKeys.contains("fileRecordName")) {
647  }
648  if (deviceSettingsKeys.contains("useReverseAPI")) {
649  settings.m_useReverseAPI = response.getHackRfInputSettings()->getUseReverseApi() != 0;
650  }
651  if (deviceSettingsKeys.contains("reverseAPIAddress")) {
653  }
654  if (deviceSettingsKeys.contains("reverseAPIPort")) {
656  }
657  if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
659  }
660 
661  MsgConfigureHackRF *msg = MsgConfigureHackRF::create(settings, force);
663 
664  if (m_guiMessageQueue) // forward to GUI if any
665  {
666  MsgConfigureHackRF *msgToGUI = MsgConfigureHackRF::create(settings, force);
667  m_guiMessageQueue->push(msgToGUI);
668  }
669 
670  webapiFormatDeviceSettings(response, settings);
671  return 200;
672 }
673 
675 {
678  response.getHackRfInputSettings()->setBandwidth(settings.m_bandwidth);
679  response.getHackRfInputSettings()->setLnaGain(settings.m_lnaGain);
680  response.getHackRfInputSettings()->setVgaGain(settings.m_vgaGain);
681  response.getHackRfInputSettings()->setLog2Decim(settings.m_log2Decim);
682  response.getHackRfInputSettings()->setFcPos(settings.m_fcPos);
684  response.getHackRfInputSettings()->setBiasT(settings.m_biasT ? 1 : 0);
685  response.getHackRfInputSettings()->setLnaExt(settings.m_lnaExt ? 1 : 0);
686  response.getHackRfInputSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
687  response.getHackRfInputSettings()->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
688 
689  if (response.getHackRfInputSettings()->getFileRecordName()) {
691  } else {
692  response.getHackRfInputSettings()->setFileRecordName(new QString(settings.m_fileRecordName));
693  }
694 
695  response.getHackRfInputSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
696 
697  if (response.getHackRfInputSettings()->getReverseApiAddress()) {
699  } else {
700  response.getHackRfInputSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
701  }
702 
705 }
706 
708  SWGSDRangel::SWGDeviceState& response,
709  QString& errorMessage)
710 {
711  (void) errorMessage;
713  return 200;
714 }
715 
717  bool run,
718  SWGSDRangel::SWGDeviceState& response,
719  QString& errorMessage)
720 {
721  (void) errorMessage;
723  MsgStartStop *message = MsgStartStop::create(run);
724  m_inputMessageQueue.push(message);
725 
726  if (m_guiMessageQueue) // forward to GUI if any
727  {
728  MsgStartStop *msgToGUI = MsgStartStop::create(run);
729  m_guiMessageQueue->push(msgToGUI);
730  }
731 
732  return 200;
733 }
734 
735 void HackRFInput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const HackRFInputSettings& settings, bool force)
736 {
738  swgDeviceSettings->setDirection(0); // single Rx
739  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
740  swgDeviceSettings->setDeviceHwType(new QString("HackRF"));
742  SWGSDRangel::SWGHackRFInputSettings *swgHackRFInputSettings = swgDeviceSettings->getHackRfInputSettings();
743 
744  // transfer data that has been modified. When force is on transfer all data except reverse API data
745 
746  if (deviceSettingsKeys.contains("centerFrequency") || force) {
747  swgHackRFInputSettings->setCenterFrequency(settings.m_centerFrequency);
748  }
749  if (deviceSettingsKeys.contains("LOppmTenths") || force) {
750  swgHackRFInputSettings->setLOppmTenths(settings.m_LOppmTenths);
751  }
752  if (deviceSettingsKeys.contains("bandwidth") || force) {
753  swgHackRFInputSettings->setBandwidth(settings.m_bandwidth);
754  }
755  if (deviceSettingsKeys.contains("lnaGain") || force) {
756  swgHackRFInputSettings->setLnaGain(settings.m_lnaGain);
757  }
758  if (deviceSettingsKeys.contains("vgaGain") || force) {
759  swgHackRFInputSettings->setVgaGain(settings.m_vgaGain);
760  }
761  if (deviceSettingsKeys.contains("log2Decim") || force) {
762  swgHackRFInputSettings->setLog2Decim(settings.m_log2Decim);
763  }
764  if (deviceSettingsKeys.contains("fcPos") || force) {
765  swgHackRFInputSettings->setFcPos((int) settings.m_fcPos);
766  }
767  if (deviceSettingsKeys.contains("devSampleRate") || force) {
768  swgHackRFInputSettings->setDevSampleRate(settings.m_devSampleRate);
769  }
770  if (deviceSettingsKeys.contains("biasT") || force) {
771  swgHackRFInputSettings->setBiasT(settings.m_biasT ? 1 : 0);
772  }
773  if (deviceSettingsKeys.contains("lnaExt") || force) {
774  swgHackRFInputSettings->setLnaExt(settings.m_lnaExt ? 1 : 0);
775  }
776  if (deviceSettingsKeys.contains("dcBlock") || force) {
777  swgHackRFInputSettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
778  }
779  if (deviceSettingsKeys.contains("iqCorrection") || force) {
780  swgHackRFInputSettings->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
781  }
782  if (deviceSettingsKeys.contains("fileRecordName") || force) {
783  swgHackRFInputSettings->setFileRecordName(new QString(settings.m_fileRecordName));
784  }
785 
786  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings")
787  .arg(settings.m_reverseAPIAddress)
788  .arg(settings.m_reverseAPIPort)
789  .arg(settings.m_reverseAPIDeviceIndex);
790  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
791  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
792 
793  QBuffer *buffer=new QBuffer();
794  buffer->open((QBuffer::ReadWrite));
795  buffer->write(swgDeviceSettings->asJson().toUtf8());
796  buffer->seek(0);
797 
798  // Always use PATCH to avoid passing reverse API settings
799  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
800 
801  delete swgDeviceSettings;
802 }
803 
805 {
807  swgDeviceSettings->setDirection(0); // single Rx
808  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
809  swgDeviceSettings->setDeviceHwType(new QString("HackRF"));
810 
811  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
815  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
816  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
817 
818  QBuffer *buffer=new QBuffer();
819  buffer->open((QBuffer::ReadWrite));
820  buffer->write(swgDeviceSettings->asJson().toUtf8());
821  buffer->seek(0);
822 
823  if (start) {
824  m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer);
825  } else {
826  m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer);
827  }
828 
829  delete swgDeviceSettings;
830 }
831 
832 void HackRFInput::networkManagerFinished(QNetworkReply *reply)
833 {
834  QNetworkReply::NetworkError replyError = reply->error();
835 
836  if (replyError)
837  {
838  qWarning() << "HackRFInput::networkManagerFinished:"
839  << " error(" << (int) replyError
840  << "): " << replyError
841  << ": " << reply->errorString();
842  return;
843  }
844 
845  QString answer = reply->readAll();
846  answer.chop(1); // remove last \n
847  qDebug("HackRFInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
848 }
bool startDeviceEngine()
Start the device engine corresponding to the stream type.
Definition: deviceapi.cpp:253
DeviceHackRFParams m_sharedParams
Definition: hackrfinput.h:166
void setLog2Decimation(unsigned int log2_decim)
const HackRFInputSettings & getSettings() const
Definition: hackrfinput.h:45
bool applySettings(const HackRFInputSettings &settings, bool force)
QByteArray serialize() const
static qint64 calculateDeviceCenterFrequency(quint64 centerFrequency, qint64 transverterDeltaFrequency, int log2Decim, fcPos_t fcPos, quint32 devSampleRate, FrequencyShiftScheme frequencyShiftScheme, bool transverterMode=false)
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 setReverseApiAddress(QString *reverse_api_address)
void setFileName(const QString &filename)
Definition: filerecord.cpp:59
uint getDeviceUID() const
Return the current device engine unique ID.
Definition: deviceapi.cpp:303
virtual quint64 getCenterFrequency() const
Center frequency exposed by the source.
void setFileRecordName(QString *file_record_name)
const std::vector< DeviceAPI * > & getSinkBuddies() const
Definition: deviceapi.h:166
void startRecording()
Definition: filerecord.cpp:105
MessageQueue m_inputMessageQueue
Input queue to the source.
virtual QString asJson() override
MessageQueue * getDeviceEngineInputMessageQueue()
Device engine message queue.
Definition: deviceapi.cpp:316
virtual int webapiRun(bool run, SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
virtual bool handleMessage(const Message &message)
virtual void destroy()
Definition: hackrfinput.cpp:79
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings &response, const HackRFInputSettings &settings)
struct hackrf_device * m_dev
Definition: hackrfinput.h:163
bool initDeviceEngine()
Init the device engine corresponding to the stream type.
Definition: deviceapi.cpp:240
HackRFInputThread * m_hackRFThread
Definition: hackrfinput.h:164
bool openDevice()
Definition: hackrfinput.cpp:84
QNetworkRequest m_networkRequest
Definition: hackrfinput.h:170
static MsgConfigureHackRF * create(const HackRFInputSettings &settings, bool force=false)
Definition: hackrfinput.h:48
DeviceAPI * m_deviceAPI
Definition: hackrfinput.h:160
void setOriginatorIndex(qint32 originator_index)
virtual void init()
initializations to be done when all collaborating objects are created and possibly connected ...
virtual QByteArray serialize() const
static hackrf_device * open_hackrf(int sequence)
SampleSinkFifo m_sampleFifo
bool setSize(int size)
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
virtual bool start()
virtual bool deserialize(const QByteArray &data)
void webapiReverseSendSettings(QList< QString > &deviceSettingsKeys, const HackRFInputSettings &settings, bool force)
void closeDevice()
int getDeviceSetIndex() const
Definition: deviceapi.h:131
void * getBuddySharedPtr() const
Definition: deviceapi.h:161
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
void genUniqueFileName(uint deviceUID, int istream=-1)
Definition: filerecord.cpp:67
virtual ~HackRFInput()
Definition: hackrfinput.cpp:64
void setBuddySharedPtr(void *ptr)
Definition: deviceapi.h:162
void stopRecording()
Definition: filerecord.cpp:117
virtual const QString & getDeviceDescription() const
MessageQueue * getSamplingDeviceInputMessageQueue()
Sampling device (ex: single Rx) input message queue.
Definition: deviceapi.cpp:329
static bool match(const Message *message)
Definition: message.cpp:45
void removeAncillarySink(BasebandSampleSink *sink, unsigned int index=0)
Removes it.
Definition: deviceapi.cpp:100
virtual int getSampleRate() const
Sample rate exposed by the source.
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
static MsgSynchronizeFrequency * create(uint64_t frequency)
virtual void stop()
virtual int webapiRunGet(SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
void setUseReverseApi(qint32 use_reverse_api)
bool m_running
Definition: hackrfinput.h:167
void getDeviceEngineStateStr(QString &state)
Definition: deviceapi.cpp:389
bool getStartStop() const
Definition: hackrfinput.h:85
const QString & getSamplingDeviceSerial() const
Definition: deviceapi.h:121
void setDeviceCenterFrequency(quint64 freq, qint32 LOppmTenths)
void setReverseApiPort(qint32 reverse_api_port)
static MsgStartStop * create(bool startStop)
Definition: hackrfinput.h:87
virtual int webapiSettingsPutPatch(bool force, const QStringList &deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
virtual void setCenterFrequency(qint64 centerFrequency)
void networkManagerFinished(QNetworkReply *reply)
virtual int webapiSettingsGet(SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
QString m_deviceDescription
Definition: hackrfinput.h:165
void setHackRfInputSettings(SWGHackRFInputSettings *hack_rf_input_settings)
FileRecord * m_fileSink
File sink to record device I/Q output.
Definition: hackrfinput.h:168
void setSamplerate(uint32_t samplerate)
SWGHackRFInputSettings * getHackRfInputSettings()
void webapiReverseSendStartStop(bool start)
void setCenterFrequency(qint64 center_frequency)
bool deserialize(const QByteArray &data)
struct hackrf_device * m_dev
device handle if the party has ownership else 0
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection, int streamIndex=0)
Configure current device engine DSP corrections (Rx)
Definition: deviceapi.cpp:355
static qint64 calculateCenterFrequency(quint64 deviceCenterFrequency, qint64 transverterDeltaFrequency, int log2Decim, fcPos_t fcPos, quint32 devSampleRate, FrequencyShiftScheme frequencyShiftScheme, bool transverterMode=false)
void setDirection(qint32 direction)
void setDevSampleRate(qint32 dev_sample_rate)
QNetworkAccessManager * m_networkManager
Definition: hackrfinput.h:169
HackRFInputSettings m_settings
Definition: hackrfinput.h:162
void setFcPos(int fcPos)
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void setDeviceHwType(QString *device_hw_type)