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.
airspyinput.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 <QList>
23 #include <QNetworkReply>
24 #include <QBuffer>
25 
26 #include "SWGDeviceSettings.h"
27 #include "SWGDeviceState.h"
28 #include "SWGDeviceReport.h"
29 #include "SWGAirspyReport.h"
30 
31 #include "airspyinput.h"
32 #include "airspyplugin.h"
33 
34 #include "device/deviceapi.h"
35 #include "dsp/filerecord.h"
36 #include "dsp/dspcommands.h"
37 #include "dsp/dspengine.h"
38 #include "airspysettings.h"
39 #include "airspythread.h"
40 
44 
45 const qint64 AirspyInput::loLowLimitFreq = 24000000L;
46 const qint64 AirspyInput::loHighLimitFreq = 1900000000L;
47 
49  m_deviceAPI(deviceAPI),
50  m_settings(),
51  m_dev(0),
52  m_airspyThread(0),
53  m_deviceDescription("Airspy"),
54  m_running(false)
55 {
56  openDevice();
57  m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
60 
61  m_networkManager = new QNetworkAccessManager();
62  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
63 }
64 
66 {
67  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
68  delete m_networkManager;
69 
70  if (m_running) {
71  stop();
72  }
73 
75  delete m_fileSink;
76  closeDevice();
77 }
78 
80 {
81  delete this;
82 }
83 
85 {
86  if (m_dev != 0)
87  {
88  closeDevice();
89  }
90 
91  airspy_error rc;
92 
93  rc = (airspy_error) airspy_init();
94 
95  if (rc != AIRSPY_SUCCESS)
96  {
97  qCritical("AirspyInput::start: failed to initiate Airspy library %s", airspy_error_name(rc));
98  }
99 
100  if (!m_sampleFifo.setSize(1<<19))
101  {
102  qCritical("AirspyInput::start: could not allocate SampleFifo");
103  return false;
104  }
105 
106  int device = m_deviceAPI->getSamplingDeviceSequence();
107 
108  if ((m_dev = open_airspy_from_sequence(device)) == 0)
109  {
110  qCritical("AirspyInput::start: could not open Airspy #%d", device);
111  return false;
112  }
113 
114 #ifdef LIBAIRSPY_DEFAULT_RATES
115  qDebug("AirspyInput::start: detault rates");
116  m_sampleRates.clear();
117  m_sampleRates.push_back(10000000);
118  m_sampleRates.push_back(2500000);
119 #else
120  uint32_t nbSampleRates;
121  uint32_t *sampleRates;
122 
123  airspy_get_samplerates(m_dev, &nbSampleRates, 0);
124 
125  sampleRates = new uint32_t[nbSampleRates];
126 
127  airspy_get_samplerates(m_dev, sampleRates, nbSampleRates);
128 
129  if (nbSampleRates == 0)
130  {
131  qCritical("AirspyInput::start: could not obtain Airspy sample rates");
132  return false;
133  }
134  else
135  {
136  qDebug("AirspyInput::start: %d sample rates", nbSampleRates);
137  }
138 
139  m_sampleRates.clear();
140 
141  for (unsigned int i=0; i<nbSampleRates; i++)
142  {
143  m_sampleRates.push_back(sampleRates[i]);
144  qDebug("AirspyInput::start: sampleRates[%d] = %u Hz", i, sampleRates[i]);
145  }
146 
147  delete[] sampleRates;
148 #endif
149 
150 // MsgReportAirspy *message = MsgReportAirspy::create(m_sampleRates);
151 // getOutputMessageQueueToGUI()->push(message);
152 
153  rc = (airspy_error) airspy_set_sample_type(m_dev, AIRSPY_SAMPLE_INT16_IQ);
154 
155  if (rc != AIRSPY_SUCCESS)
156  {
157  qCritical("AirspyInput::start: could not set sample type to INT16_IQ");
158  return false;
159  }
160 
161  return true;
162 }
163 
165 {
166  applySettings(m_settings, true);
167 }
168 
170 {
171  QMutexLocker mutexLocker(&m_mutex);
172 
173  if (!m_dev) {
174  return false;
175  }
176 
177  if (m_running) { stop(); }
178 
183 
185 
186  mutexLocker.unlock();
187 
188  applySettings(m_settings, true);
189 
190  qDebug("AirspyInput::startInput: started");
191  m_running = true;
192 
193  return true;
194 }
195 
197 {
198  if (m_dev != 0)
199  {
200  airspy_stop_rx(m_dev);
201  airspy_close(m_dev);
202  m_dev = 0;
203  }
204 
205  m_deviceDescription.clear();
206  airspy_exit();
207 }
208 
210 {
211  qDebug("AirspyInput::stop");
212  QMutexLocker mutexLocker(&m_mutex);
213 
214  if (m_airspyThread != 0)
215  {
217  delete m_airspyThread;
218  m_airspyThread = 0;
219  }
220 
221  m_running = false;
222 }
223 
224 QByteArray AirspyInput::serialize() const
225 {
226  return m_settings.serialize();
227 }
228 
229 bool AirspyInput::deserialize(const QByteArray& data)
230 {
231  bool success = true;
232 
233  if (!m_settings.deserialize(data))
234  {
236  success = false;
237  }
238 
240  m_inputMessageQueue.push(message);
241 
242  if (m_guiMessageQueue)
243  {
245  m_guiMessageQueue->push(messageToGUI);
246  }
247 
248  return success;
249 }
250 
251 const QString& AirspyInput::getDeviceDescription() const
252 {
253  return m_deviceDescription;
254 }
255 
257 {
259  return (rate / (1<<m_settings.m_log2Decim));
260 }
261 
263 {
265 }
266 
267 void AirspyInput::setCenterFrequency(qint64 centerFrequency)
268 {
269  AirspySettings settings = m_settings;
270  settings.m_centerFrequency = centerFrequency;
271 
272  MsgConfigureAirspy* message = MsgConfigureAirspy::create(settings, false);
273  m_inputMessageQueue.push(message);
274 
275  if (m_guiMessageQueue)
276  {
277  MsgConfigureAirspy* messageToGUI = MsgConfigureAirspy::create(settings, false);
278  m_guiMessageQueue->push(messageToGUI);
279  }
280 }
281 
283 {
284  if (MsgConfigureAirspy::match(message))
285  {
286  MsgConfigureAirspy& conf = (MsgConfigureAirspy&) message;
287  qDebug() << "AirspyInput::handleMessage: MsgConfigureAirspy";
288 
289  bool success = applySettings(conf.getSettings(), conf.getForce());
290 
291  if (!success)
292  {
293  qDebug("AirspyInput::handleMessage: Airspy config error");
294  }
295 
296  return true;
297  }
298  else if (MsgStartStop::match(message))
299  {
300  MsgStartStop& cmd = (MsgStartStop&) message;
301  qDebug() << "AirspyInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
302 
303  if (cmd.getStartStop())
304  {
306  {
308  }
309  }
310  else
311  {
313  }
314 
317  }
318 
319  return true;
320  }
321  else if (MsgFileRecord::match(message))
322  {
323  MsgFileRecord& conf = (MsgFileRecord&) message;
324  qDebug() << "AirspyInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
325 
326  if (conf.getStartStop())
327  {
328  if (m_settings.m_fileRecordName.size() != 0) {
330  } else {
332  }
333 
335  }
336  else
337  {
339  }
340 
341  return true;
342  }
343  else
344  {
345  return false;
346  }
347 }
348 
350 {
351  qint64 df = ((qint64)freq_hz * m_settings.m_LOppmTenths) / 10000000LL;
352  freq_hz += df;
353 
354  airspy_error rc = (airspy_error) airspy_set_freq(m_dev, static_cast<uint32_t>(freq_hz));
355 
356  if (rc != AIRSPY_SUCCESS)
357  {
358  qWarning("AirspyInput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz);
359  }
360  else
361  {
362  qDebug("AirspyInput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz);
363  }
364 }
365 
366 bool AirspyInput::applySettings(const AirspySettings& settings, bool force)
367 {
368  QMutexLocker mutexLocker(&m_mutex);
369 
370  bool forwardChange = false;
371  airspy_error rc = AIRSPY_ERROR_OTHER;
372  QList<QString> reverseAPIKeys;
373 
374  qDebug() << "AirspyInput::applySettings";
375 
376  if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) {
377  reverseAPIKeys.append("dcBlock");
378  }
379  if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) {
380  reverseAPIKeys.append("iqCorrection");
381  }
382 
383  if ((m_settings.m_dcBlock != settings.m_dcBlock) ||
384  (m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
385  {
387  }
388 
389  if ((m_settings.m_devSampleRateIndex != settings.m_devSampleRateIndex) || force)
390  {
391  reverseAPIKeys.append("devSampleRateIndex");
392  forwardChange = true;
393 
394  if (m_dev != 0)
395  {
396  rc = (airspy_error) airspy_set_samplerate(m_dev, static_cast<airspy_samplerate_t>(settings.m_devSampleRateIndex));
397 
398  if (rc != AIRSPY_SUCCESS)
399  {
400  qCritical("AirspyInput::applySettings: could not set sample rate index %u (%d S/s): %s", settings.m_devSampleRateIndex, m_sampleRates[settings.m_devSampleRateIndex], airspy_error_name(rc));
401  }
402  else if (m_airspyThread != 0)
403  {
404  qDebug("AirspyInput::applySettings: sample rate set to index: %u (%d S/s)", settings.m_devSampleRateIndex, m_sampleRates[settings.m_devSampleRateIndex]);
406  }
407  }
408  }
409 
410  if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
411  {
412  reverseAPIKeys.append("log2Decim");
413  forwardChange = true;
414 
415  if (m_airspyThread != 0)
416  {
418  qDebug() << "AirspyInput: set decimation to " << (1<<settings.m_log2Decim);
419  }
420  }
421 
422  if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) {
423  reverseAPIKeys.append("centerFrequency");
424  }
425  if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) {
426  reverseAPIKeys.append("LOppmTenths");
427  }
428  if ((m_settings.m_fcPos != settings.m_fcPos) || force) {
429  reverseAPIKeys.append("fcPos");
430  }
431  if ((m_settings.m_transverterMode != settings.m_transverterMode) || force) {
432  reverseAPIKeys.append("transverterMode");
433  }
435  reverseAPIKeys.append("transverterDeltaFrequency");
436  }
437 
439  || (m_settings.m_LOppmTenths != settings.m_LOppmTenths)
440  || (m_settings.m_fcPos != settings.m_fcPos)
441  || (m_settings.m_log2Decim != settings.m_log2Decim)
444  {
445  qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency(
446  settings.m_centerFrequency,
448  settings.m_log2Decim,
451  DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD,
452  settings.m_transverterMode);
453 
454  if (m_dev != 0) {
455  setDeviceCenterFrequency(deviceCenterFrequency);
456  }
457 
458  forwardChange = true;
459  }
460 
461  if ((m_settings.m_fcPos != settings.m_fcPos) || force)
462  {
463  if (m_airspyThread != 0)
464  {
465  m_airspyThread->setFcPos((int) settings.m_fcPos);
466  qDebug() << "AirspyInput: 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 = (airspy_error) airspy_set_lna_gain(m_dev, settings.m_lnaGain);
477 
478  if (rc != AIRSPY_SUCCESS) {
479  qDebug("AirspyInput::applySettings: airspy_set_lna_gain failed: %s", airspy_error_name(rc));
480  } else {
481  qDebug() << "AirspyInput:applySettings: LNA gain set to " << settings.m_lnaGain;
482  }
483  }
484  }
485 
486  if ((m_settings.m_lnaAGC != settings.m_lnaAGC) || force)
487  {
488  reverseAPIKeys.append("lnaAGC");
489 
490  if (m_dev != 0) {
491  rc = (airspy_error) airspy_set_lna_agc(m_dev, (settings.m_lnaAGC ? 1 : 0));
492  }
493 
494  if (rc != AIRSPY_SUCCESS) {
495  qDebug("AirspyInput::applySettings: airspy_set_lna_agc failed: %s", airspy_error_name(rc));
496  } else {
497  qDebug() << "AirspyInput:applySettings: LNA AGC set to " << settings.m_lnaAGC;
498  }
499  }
500 
501  if ((m_settings.m_mixerGain != settings.m_mixerGain) || force)
502  {
503  reverseAPIKeys.append("mixerGain");
504 
505  if (m_dev != 0)
506  {
507  rc = (airspy_error) airspy_set_mixer_gain(m_dev, settings.m_mixerGain);
508 
509  if (rc != AIRSPY_SUCCESS) {
510  qDebug("AirspyInput::applySettings: airspy_set_mixer_gain failed: %s", airspy_error_name(rc));
511  } else {
512  qDebug() << "AirspyInput:applySettings: mixer gain set to " << settings.m_mixerGain;
513  }
514  }
515  }
516 
517  if ((m_settings.m_mixerAGC != settings.m_mixerAGC) || force)
518  {
519  reverseAPIKeys.append("mixerAGC");
520 
521  if (m_dev != 0) {
522  rc = (airspy_error) airspy_set_mixer_agc(m_dev, (settings.m_mixerAGC ? 1 : 0));
523  }
524 
525  if (rc != AIRSPY_SUCCESS) {
526  qDebug("AirspyInput::applySettings: airspy_set_mixer_agc failed: %s", airspy_error_name(rc));
527  } else {
528  qDebug() << "AirspyInput:applySettings: Mixer AGC set to " << settings.m_mixerAGC;
529  }
530  }
531 
532  if ((m_settings.m_vgaGain != settings.m_vgaGain) || force)
533  {
534  reverseAPIKeys.append("vgaGain");
535 
536  if (m_dev != 0)
537  {
538  rc = (airspy_error) airspy_set_vga_gain(m_dev, settings.m_vgaGain);
539 
540  if (rc != AIRSPY_SUCCESS) {
541  qDebug("AirspyInput::applySettings: airspy_set_vga_gain failed: %s", airspy_error_name(rc));
542  } else {
543  qDebug() << "AirspyInput:applySettings: VGA gain set to " << settings.m_vgaGain;
544  }
545  }
546  }
547 
548  if ((m_settings.m_biasT != settings.m_biasT) || force)
549  {
550  reverseAPIKeys.append("biasT");
551 
552  if (m_dev != 0)
553  {
554  rc = (airspy_error) airspy_set_rf_bias(m_dev, (settings.m_biasT ? 1 : 0));
555 
556  if (rc != AIRSPY_SUCCESS) {
557  qDebug("AirspyInput::applySettings: airspy_set_rf_bias failed: %s", airspy_error_name(rc));
558  } else {
559  qDebug() << "AirspyInput:applySettings: bias tee set to " << settings.m_biasT;
560  }
561  }
562  }
563 
564  if (settings.m_useReverseAPI)
565  {
566  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
570  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
571  }
572 
573  m_settings = settings;
574 
575  if (forwardChange)
576  {
579  m_fileSink->handleMessage(*notif); // forward to file sink
581  }
582 
583  return true;
584 }
585 
586 struct airspy_device *AirspyInput::open_airspy_from_sequence(int sequence)
587 {
588  struct airspy_device *devinfo;
589  airspy_error rc = AIRSPY_ERROR_OTHER;
590 
591  for (int i = 0; i < AirspyPlugin::m_maxDevices; i++)
592  {
593  rc = (airspy_error) airspy_open(&devinfo);
594 
595  if (rc == AIRSPY_SUCCESS)
596  {
597  if (i == sequence) {
598  return devinfo;
599  } else {
600  airspy_close(devinfo);
601  }
602  }
603  else
604  {
605  break;
606  }
607  }
608 
609  return 0;
610 }
611 
613  SWGSDRangel::SWGDeviceState& response,
614  QString& errorMessage)
615 {
616  (void) errorMessage;
618  return 200;
619 }
620 
622  bool run,
623  SWGSDRangel::SWGDeviceState& response,
624  QString& errorMessage)
625 {
626  (void) errorMessage;
628  MsgStartStop *message = MsgStartStop::create(run);
629  m_inputMessageQueue.push(message);
630 
631  if (m_guiMessageQueue) // forward to GUI if any
632  {
633  MsgStartStop *msgToGUI = MsgStartStop::create(run);
634  m_guiMessageQueue->push(msgToGUI);
635  }
636 
637  return 200;
638 }
639 
642  QString& errorMessage)
643 {
644  (void) errorMessage;
646  response.getAirspySettings()->init();
648  return 200;
649 }
650 
652  bool force,
653  const QStringList& deviceSettingsKeys,
654  SWGSDRangel::SWGDeviceSettings& response, // query + response
655  QString& errorMessage)
656 {
657  (void) errorMessage;
658  AirspySettings settings = m_settings;
659 
660  if (deviceSettingsKeys.contains("centerFrequency")) {
661  settings.m_centerFrequency = response.getAirspySettings()->getCenterFrequency();
662  }
663  if (deviceSettingsKeys.contains("LOppmTenths")) {
664  settings.m_LOppmTenths = response.getAirspySettings()->getLOppmTenths();
665  }
666  if (deviceSettingsKeys.contains("devSampleRateIndex")) {
668  }
669  if (deviceSettingsKeys.contains("lnaGain")) {
670  settings.m_lnaGain = response.getAirspySettings()->getLnaGain();
671  }
672  if (deviceSettingsKeys.contains("mixerGain")) {
673  settings.m_mixerGain = response.getAirspySettings()->getMixerGain();
674  }
675  if (deviceSettingsKeys.contains("vgaGain")) {
676  settings.m_vgaGain = response.getAirspySettings()->getVgaGain();
677  }
678  if (deviceSettingsKeys.contains("lnaAGC")) {
679  settings.m_lnaAGC = response.getAirspySettings()->getLnaAgc() != 0;
680  }
681  if (deviceSettingsKeys.contains("mixerAGC")) {
682  settings.m_mixerAGC = response.getAirspySettings()->getMixerAgc() != 0;
683  }
684  if (deviceSettingsKeys.contains("log2Decim")) {
685  settings.m_log2Decim = response.getAirspySettings()->getLog2Decim();
686  }
687  if (deviceSettingsKeys.contains("fcPos")) {
688  int fcPos = response.getAirspySettings()->getFcPos();
689  fcPos = fcPos < 0 ? 0 : fcPos > 2 ? 2 : fcPos;
690  settings.m_fcPos = (AirspySettings::fcPos_t) fcPos;
691  }
692  if (deviceSettingsKeys.contains("biasT")) {
693  settings.m_biasT = response.getAirspySettings()->getBiasT() != 0;
694  }
695  if (deviceSettingsKeys.contains("dcBlock")) {
696  settings.m_dcBlock = response.getAirspySettings()->getDcBlock() != 0;
697  }
698  if (deviceSettingsKeys.contains("iqCorrection")) {
699  settings.m_iqCorrection = response.getAirspySettings()->getIqCorrection() != 0;
700  }
701  if (deviceSettingsKeys.contains("transverterDeltaFrequency")) {
703  }
704  if (deviceSettingsKeys.contains("transverterMode")) {
705  settings.m_transverterMode = response.getAirspySettings()->getTransverterMode() != 0;
706  }
707  if (deviceSettingsKeys.contains("fileRecordName")) {
708  settings.m_fileRecordName = *response.getAirspySettings()->getFileRecordName();
709  }
710  if (deviceSettingsKeys.contains("useReverseAPI")) {
711  settings.m_useReverseAPI = response.getAirspySettings()->getUseReverseApi() != 0;
712  }
713  if (deviceSettingsKeys.contains("reverseAPIAddress")) {
715  }
716  if (deviceSettingsKeys.contains("reverseAPIPort")) {
717  settings.m_reverseAPIPort = response.getAirspySettings()->getReverseApiPort();
718  }
719  if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
721  }
722 
723  MsgConfigureAirspy *msg = MsgConfigureAirspy::create(settings, force);
725 
726  if (m_guiMessageQueue) // forward to GUI if any
727  {
728  MsgConfigureAirspy *msgToGUI = MsgConfigureAirspy::create(settings, force);
729  m_guiMessageQueue->push(msgToGUI);
730  }
731 
732  webapiFormatDeviceSettings(response, settings);
733  return 200;
734 }
735 
738  QString& errorMessage)
739 {
740  (void) errorMessage;
742  response.getAirspyReport()->init();
743  webapiFormatDeviceReport(response);
744  return 200;
745 }
746 
748 {
750  response.getAirspySettings()->setLOppmTenths(settings.m_LOppmTenths);
752  response.getAirspySettings()->setLnaGain(settings.m_lnaGain);
753  response.getAirspySettings()->setMixerGain(settings.m_mixerGain);
754  response.getAirspySettings()->setVgaGain(settings.m_vgaGain);
755  response.getAirspySettings()->setLnaAgc(settings.m_lnaAGC ? 1 : 0);
756  response.getAirspySettings()->setMixerAgc(settings.m_mixerAGC ? 1 : 0);
757  response.getAirspySettings()->setLog2Decim(settings.m_log2Decim);
758  response.getAirspySettings()->setFcPos((int) settings.m_fcPos);
759  response.getAirspySettings()->setBiasT(settings.m_biasT ? 1 : 0);
760  response.getAirspySettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
761  response.getAirspySettings()->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
763  response.getAirspySettings()->setTransverterMode(settings.m_transverterMode ? 1 : 0);
764 
765  if (response.getAirspySettings()->getFileRecordName()) {
766  *response.getAirspySettings()->getFileRecordName() = settings.m_fileRecordName;
767  } else {
768  response.getAirspySettings()->setFileRecordName(new QString(settings.m_fileRecordName));
769  }
770 
771  response.getAirspySettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
772 
773  if (response.getAirspySettings()->getReverseApiAddress()) {
775  } else {
776  response.getAirspySettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
777  }
778 
781 }
782 
784 {
785  response.getAirspyReport()->setSampleRates(new QList<SWGSDRangel::SWGSampleRate*>);
786 
787  for (std::vector<uint32_t>::const_iterator it = getSampleRates().begin(); it != getSampleRates().end(); ++it)
788  {
789  response.getAirspyReport()->getSampleRates()->append(new SWGSDRangel::SWGSampleRate);
790  response.getAirspyReport()->getSampleRates()->back()->setRate(*it);
791  }
792 }
793 
794 void AirspyInput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const AirspySettings& settings, bool force)
795 {
797  swgDeviceSettings->setDirection(0); // single Rx
798  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
799  swgDeviceSettings->setDeviceHwType(new QString("Airspy"));
800  swgDeviceSettings->setAirspySettings(new SWGSDRangel::SWGAirspySettings());
801  SWGSDRangel::SWGAirspySettings *swgAirspySettings = swgDeviceSettings->getAirspySettings();
802 
803  // transfer data that has been modified. When force is on transfer all data except reverse API data
804 
805  if (deviceSettingsKeys.contains("centerFrequency") || force) {
806  swgAirspySettings->setCenterFrequency(settings.m_centerFrequency);
807  }
808  if (deviceSettingsKeys.contains("LOppmTenths") || force) {
809  swgAirspySettings->setLOppmTenths(settings.m_LOppmTenths);
810  }
811  if (deviceSettingsKeys.contains("devSampleRateIndex") || force) {
812  swgAirspySettings->setDevSampleRateIndex(settings.m_devSampleRateIndex);
813  }
814  if (deviceSettingsKeys.contains("lnaGain") || force) {
815  swgAirspySettings->setLnaGain(settings.m_lnaGain);
816  }
817  if (deviceSettingsKeys.contains("mixerGain") || force) {
818  swgAirspySettings->setMixerGain(settings.m_mixerGain);
819  }
820  if (deviceSettingsKeys.contains("vgaGain") || force) {
821  swgAirspySettings->setVgaGain(settings.m_vgaGain);
822  }
823  if (deviceSettingsKeys.contains("lnaAGC") || force) {
824  swgAirspySettings->setLnaAgc(settings.m_lnaAGC ? 1 : 0);
825  }
826  if (deviceSettingsKeys.contains("mixerAGC") || force) {
827  swgAirspySettings->setMixerAgc(settings.m_mixerAGC ? 1 : 0);
828  }
829  if (deviceSettingsKeys.contains("log2Decim") || force) {
830  swgAirspySettings->setLog2Decim(settings.m_log2Decim);
831  }
832  if (deviceSettingsKeys.contains("fcPos") || force) {
833  swgAirspySettings->setFcPos((int) settings.m_fcPos);
834  }
835  if (deviceSettingsKeys.contains("biasT") || force) {
836  swgAirspySettings->setBiasT(settings.m_biasT ? 1 : 0);
837  }
838  if (deviceSettingsKeys.contains("dcBlock") || force) {
839  swgAirspySettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
840  }
841  if (deviceSettingsKeys.contains("iqCorrection") || force) {
842  swgAirspySettings->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
843  }
844  if (deviceSettingsKeys.contains("transverterDeltaFrequency") || force) {
845  swgAirspySettings->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency);
846  }
847  if (deviceSettingsKeys.contains("transverterMode") || force) {
848  swgAirspySettings->setTransverterMode(settings.m_transverterMode ? 1 : 0);
849  }
850  if (deviceSettingsKeys.contains("fileRecordName") || force) {
851  swgAirspySettings->setFileRecordName(new QString(settings.m_fileRecordName));
852  }
853 
854  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings")
855  .arg(settings.m_reverseAPIAddress)
856  .arg(settings.m_reverseAPIPort)
857  .arg(settings.m_reverseAPIDeviceIndex);
858  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
859  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
860 
861  QBuffer *buffer=new QBuffer();
862  buffer->open((QBuffer::ReadWrite));
863  buffer->write(swgDeviceSettings->asJson().toUtf8());
864  buffer->seek(0);
865 
866  // Always use PATCH to avoid passing reverse API settings
867  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
868 
869  delete swgDeviceSettings;
870 }
871 
873 {
875  swgDeviceSettings->setDirection(0); // single Rx
876  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
877  swgDeviceSettings->setDeviceHwType(new QString("Airspy"));
878 
879  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
883  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
884  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
885 
886  QBuffer *buffer=new QBuffer();
887  buffer->open((QBuffer::ReadWrite));
888  buffer->write(swgDeviceSettings->asJson().toUtf8());
889  buffer->seek(0);
890 
891  if (start) {
892  m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer);
893  } else {
894  m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer);
895  }
896 
897  delete swgDeviceSettings;
898 }
899 
900 void AirspyInput::networkManagerFinished(QNetworkReply *reply)
901 {
902  QNetworkReply::NetworkError replyError = reply->error();
903 
904  if (replyError)
905  {
906  qWarning() << "AirspyInput::networkManagerFinished:"
907  << " error(" << (int) replyError
908  << "): " << replyError
909  << ": " << reply->errorString();
910  return;
911  }
912 
913  QString answer = reply->readAll();
914  answer.chop(1); // remove last \n
915  qDebug("AirspyInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
916 }
FileRecord * m_fileSink
File sink to record device I/Q output.
Definition: airspyinput.h:155
bool m_running
Definition: airspyinput.h:154
bool startDeviceEngine()
Start the device engine corresponding to the stream type.
Definition: deviceapi.cpp:253
quint32 m_devSampleRateIndex
SWGAirspyReport * getAirspyReport()
quint64 m_centerFrequency
QNetworkRequest m_networkRequest
Definition: airspyinput.h:157
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 setLOppmTenths(qint32 l_oppm_tenths)
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport &response)
void stopDeviceEngine()
Stop the device engine corresponding to the stream type.
Definition: deviceapi.cpp:266
void setFileName(const QString &filename)
Definition: filerecord.cpp:59
uint getDeviceUID() const
Return the current device engine unique ID.
Definition: deviceapi.cpp:303
void networkManagerFinished(QNetworkReply *reply)
QString m_deviceDescription
Definition: airspyinput.h:152
const AirspySettings & getSettings() const
Definition: airspyinput.h:42
void setNbSourceStreams(uint32_t nbSourceStreams)
Definition: deviceapi.h:168
virtual quint64 getCenterFrequency() const
Center frequency exposed by the source.
virtual bool handleMessage(const Message &message)
static const qint64 loLowLimitFreq
Definition: airspyinput.h:143
virtual bool start()
virtual int webapiSettingsPutPatch(bool force, const QStringList &deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
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 getSampleRate() const
Sample rate exposed by the source.
virtual bool deserialize(const QByteArray &data)
virtual ~AirspyInput()
Definition: airspyinput.cpp:65
virtual QByteArray serialize() const
SWGAirspySettings * getAirspySettings()
QString m_fileRecordName
bool initDeviceEngine()
Init the device engine corresponding to the stream type.
Definition: deviceapi.cpp:240
quint32 m_log2Decim
static const int m_maxDevices
Definition: airspyplugin.h:48
void setAirspyReport(SWGAirspyReport *airspy_report)
quint32 m_mixerGain
virtual void init()
initializations to be done when all collaborating objects are created and possibly connected ...
static MsgStartStop * create(bool startStop)
Definition: airspyinput.h:86
void setOriginatorIndex(qint32 originator_index)
void setMixerAgc(qint32 mixer_agc)
SampleSinkFifo m_sampleFifo
bool setSize(int size)
void setAirspySettings(SWGAirspySettings *airspy_settings)
unsigned int uint32_t
Definition: rtptypes_win.h:46
bool openDevice()
Definition: airspyinput.cpp:84
AirspyInput(DeviceAPI *deviceAPI)
Definition: airspyinput.cpp:48
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
void setTransverterDeltaFrequency(qint64 transverter_delta_frequency)
void setLog2Decim(qint32 log2_decim)
virtual int webapiRunGet(SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
int getDeviceSetIndex() const
Definition: deviceapi.h:131
void setCenterFrequency(qint64 center_frequency)
void setTransverterMode(qint32 transverter_mode)
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
void addAncillarySink(BasebandSampleSink *sink, unsigned int index=0)
Adds a sink to receive full baseband and that is not a channel (e.g. spectrum)
Definition: deviceapi.cpp:89
void genUniqueFileName(uint deviceUID, int istream=-1)
Definition: filerecord.cpp:67
std::vector< uint32_t > m_sampleRates
Definition: airspyinput.h:153
virtual int webapiReportGet(SWGSDRangel::SWGDeviceReport &response, QString &errorMessage)
const std::vector< uint32_t > & getSampleRates() const
Definition: airspyinput.h:116
void setLog2Decimation(unsigned int log2_decim)
virtual void setCenterFrequency(qint64 centerFrequency)
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings &response, const AirspySettings &settings)
void setIqCorrection(qint32 iq_correction)
void stopRecording()
Definition: filerecord.cpp:117
int32_t i
Definition: decimators.h:244
AirspySettings m_settings
Definition: airspyinput.h:149
static bool match(const Message *message)
Definition: message.cpp:45
void setReverseApiAddress(QString *reverse_api_address)
struct airspy_device * open_airspy_from_sequence(int sequence)
virtual void destroy()
Definition: airspyinput.cpp:79
void removeAncillarySink(BasebandSampleSink *sink, unsigned int index=0)
Removes it.
Definition: deviceapi.cpp:100
qint64 m_transverterDeltaFrequency
QMutex m_mutex
Definition: airspyinput.h:148
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
DeviceAPI * m_deviceAPI
Definition: airspyinput.h:147
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void setDevSampleRateIndex(qint32 dev_sample_rate_index)
static const qint64 loHighLimitFreq
Definition: airspyinput.h:144
bool getStartStop() const
Definition: airspyinput.h:84
void getDeviceEngineStateStr(QString &state)
Definition: deviceapi.cpp:389
AirspyThread * m_airspyThread
Definition: airspyinput.h:151
virtual int webapiSettingsGet(SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
void webapiReverseSendSettings(QList< QString > &deviceSettingsKeys, const AirspySettings &settings, bool force)
uint16_t m_reverseAPIPort
void setSamplerate(uint32_t samplerate)
void setFcPos(int fcPos)
void setFileRecordName(QString *file_record_name)
QNetworkAccessManager * m_networkManager
Definition: airspyinput.h:156
virtual const QString & getDeviceDescription() const
QString m_reverseAPIAddress
QByteArray serialize() const
bool applySettings(const AirspySettings &settings, bool force)
struct airspy_device * m_dev
Definition: airspyinput.h:150
bool deserialize(const QByteArray &data)
uint16_t m_reverseAPIDeviceIndex
void setUseReverseApi(qint32 use_reverse_api)
void setMixerGain(qint32 mixer_gain)
void setDeviceCenterFrequency(quint64 freq)
void closeDevice()
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection, int streamIndex=0)
Configure current device engine DSP corrections (Rx)
Definition: deviceapi.cpp:355
qint32 m_LOppmTenths
void setSampleRates(QList< SWGSampleRate *> *sample_rates)
uint32_t getSamplingDeviceSequence() const
Definition: deviceapi.h:123
void setDirection(qint32 direction)
void webapiReverseSendStartStop(bool start)
virtual int webapiRun(bool run, SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
QList< SWGSampleRate * > * getSampleRates()
static MsgConfigureAirspy * create(const AirspySettings &settings, bool force)
Definition: airspyinput.h:45
void startWork()
void setDeviceHwType(QString *device_hw_type)
void setReverseApiPort(qint32 reverse_api_port)
virtual void stop()