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.
bladerf2input.cpp
Go to the documentation of this file.
1 // Copyright (C) 2018 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include <QDebug>
19 #include <QNetworkReply>
20 #include <QBuffer>
21 
22 #include "libbladeRF.h"
23 
24 #include "SWGDeviceSettings.h"
26 #include "SWGDeviceState.h"
27 #include "SWGDeviceReport.h"
28 #include "SWGBladeRF2InputReport.h"
29 
30 #include "device/deviceapi.h"
31 #include "dsp/dspcommands.h"
32 #include "dsp/filerecord.h"
33 #include "dsp/dspengine.h"
34 
37 #include "bladerf2inputthread.h"
38 #include "bladerf2input.h"
39 
40 
45 
47  m_deviceAPI(deviceAPI),
48  m_settings(),
49  m_deviceDescription("BladeRF2Input"),
50  m_running(false),
51  m_thread(0)
52 {
53  openDevice();
54 
55  if (m_deviceShared.m_dev)
56  {
57  const bladerf_gain_modes *modes = 0;
58  int nbModes = m_deviceShared.m_dev->getGainModesRx(&modes);
59 
60  if (modes)
61  {
62  for (int i = 0; i < nbModes; i++) {
63  m_gainModes.push_back(GainMode{QString(modes[i].name), modes[i].mode});
64  }
65  }
66  }
67 
68  m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
69  m_deviceAPI->setNbSourceStreams(1);
70  m_deviceAPI->addAncillarySink(m_fileSink);
71  m_networkManager = new QNetworkAccessManager();
72  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
73 }
74 
76 {
77  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
78  delete m_networkManager;
79 
80  if (m_running) {
81  stop();
82  }
83 
85  delete m_fileSink;
86  closeDevice();
87 }
88 
90 {
91  delete this;
92 }
93 
95 {
96  if (!m_sampleFifo.setSize(96000 * 4))
97  {
98  qCritical("BladeRF2Input::openDevice: could not allocate SampleFifo");
99  return false;
100  }
101  else
102  {
103  qDebug("BladeRF2Input::openDevice: allocated SampleFifo");
104  }
105 
106  // look for Rx buddies and get reference to the device object
107  if (m_deviceAPI->getSourceBuddies().size() > 0) // look source sibling first
108  {
109  qDebug("BladeRF2Input::openDevice: look in Rx buddies");
110 
111  DeviceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0];
112  DeviceBladeRF2Shared *deviceBladeRF2Shared = (DeviceBladeRF2Shared*) sourceBuddy->getBuddySharedPtr();
113 
114  if (deviceBladeRF2Shared == 0)
115  {
116  qCritical("BladeRF2Input::openDevice: the source buddy shared pointer is null");
117  return false;
118  }
119 
120  DeviceBladeRF2 *device = deviceBladeRF2Shared->m_dev;
121 
122  if (device == 0)
123  {
124  qCritical("BladeRF2Input::openDevice: cannot get device pointer from Rx buddy");
125  return false;
126  }
127 
128  m_deviceShared.m_dev = device;
129  }
130  // look for Tx buddies and get reference to the device object
131  else if (m_deviceAPI->getSinkBuddies().size() > 0) // then sink
132  {
133  qDebug("BladeRF2Input::openDevice: look in Tx buddies");
134 
135  DeviceAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0];
136  DeviceBladeRF2Shared *deviceBladeRF2Shared = (DeviceBladeRF2Shared*) sinkBuddy->getBuddySharedPtr();
137 
138  if (deviceBladeRF2Shared == 0)
139  {
140  qCritical("BladeRF2Input::openDevice: the sink buddy shared pointer is null");
141  return false;
142  }
143 
144  DeviceBladeRF2 *device = deviceBladeRF2Shared->m_dev;
145 
146  if (device == 0)
147  {
148  qCritical("BladeRF2Input::openDevice: cannot get device pointer from Tx buddy");
149  return false;
150  }
151 
152  m_deviceShared.m_dev = device;
153  }
154  // There are no buddies then create the first BladeRF2 device
155  else
156  {
157  qDebug("BladeRF2Input::openDevice: open device here");
158 
160  char serial[256];
161  strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
162 
163  if (!m_deviceShared.m_dev->open(serial))
164  {
165  qCritical("BladeRF2Input::openDevice: cannot open BladeRF2 device");
166  return false;
167  }
168  }
169 
170  m_deviceShared.m_channel = m_deviceAPI->getDeviceItemIndex(); // publicly allocate channel
171  m_deviceShared.m_source = this;
172  m_deviceAPI->setBuddySharedPtr(&m_deviceShared); // propagate common parameters to API
173  return true;
174 }
175 
177 {
178  if (m_deviceShared.m_dev == 0) { // was never open
179  return;
180  }
181 
182  if (m_running) {
183  stop();
184  }
185 
186  if (m_thread) { // stills own the thread => transfer to a buddy
188  }
189 
190  m_deviceShared.m_channel = -1; // publicly release channel
192 
193  // No buddies so effectively close the device
194 
195  if ((m_deviceAPI->getSinkBuddies().size() == 0) && (m_deviceAPI->getSourceBuddies().size() == 0))
196  {
198  delete m_deviceShared.m_dev;
199  m_deviceShared.m_dev = 0;
200  }
201 }
202 
204 {
205  applySettings(m_settings, true);
206 }
207 
209 {
210  if (m_thread == 0) // this does not own the thread
211  {
212  BladeRF2InputThread *bladerf2InputThread = 0;
213 
214  // find a buddy that has allocated the thread
215  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
216  std::vector<DeviceAPI*>::const_iterator it = sourceBuddies.begin();
217 
218  for (; it != sourceBuddies.end(); ++it)
219  {
220  BladeRF2Input *buddySource = ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_source;
221 
222  if (buddySource)
223  {
224  bladerf2InputThread = buddySource->getThread();
225 
226  if (bladerf2InputThread) {
227  break;
228  }
229  }
230  }
231 
232  return bladerf2InputThread;
233  }
234  else
235  {
236  return m_thread; // own thread
237  }
238 }
239 
241 {
242  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
243  std::vector<DeviceAPI*>::const_iterator it = sourceBuddies.begin();
244 
245  for (; it != sourceBuddies.end(); ++it)
246  {
247  BladeRF2Input *buddySource = ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_source;
248 
249  if (buddySource)
250  {
251  buddySource->setThread(m_thread);
252  m_thread = 0; // zero for others
253  }
254  }
255 }
256 
258 {
259  // There is a single thread per physical device (Rx side). This thread is unique and referenced by a unique
260  // buddy in the group of source buddies associated with this physical device.
261  //
262  // This start method is responsible for managing the thread and channel enabling when the streaming of a Rx channel is started
263  //
264  // It checks the following conditions
265  // - the thread is allocated or not (by itself or one of its buddies). If it is it grabs the thread pointer.
266  // - the requested channel is the first (0) or the following (just 1 in BladeRF 2 case)
267  //
268  // The BladeRF support library lets you work in two possible modes:
269  // - Single Input (SI) with only one channel streaming. This HAS to be channel 0.
270  // - Multiple Input (MI) with two channels streaming using interleaved samples. It MUST be in this configuration if channel 1
271  // is used irrespective of what you actually do with samples coming from channel 0. When we will run with only channel 1
272  // streaming from the client perspective the channel 0 will actually be enabled and streaming but its samples will
273  // just be disregarded.
274  //
275  // It manages the transition form SI where only one channel (the first or channel 0) should be running to the
276  // Multiple Input (MI) if the requested channel is 1. More generally it checks if the requested channel is within the current
277  // channel range allocated in the thread or past it. To perform the transition it stops the thread, deletes it and creates a new one.
278  // It marks the thread as needing start.
279  //
280  // If the requested channel is within the thread channel range (this thread being already allocated) it simply adds its FIFO reference
281  // so that the samples are fed to the FIFO and leaves the thread unchanged (no stop, no delete/new)
282  //
283  // If there is no thread allocated it creates a new one with a number of channels that fits the requested channel. That is
284  // 1 if channel 0 is requested (SI mode) and 2 if channel 1 is requested (MI mode). It marks the thread as needing start.
285  //
286  // Eventually it registers the FIFO in the thread. If the thread has to be started it enables the channels up to the number of channels
287  // allocated in the thread and starts the thread.
288 
289  if (!m_deviceShared.m_dev)
290  {
291  qDebug("BladeRF2Input::start: no device object");
292  return false;
293  }
294 
295  int requestedChannel = m_deviceAPI->getDeviceItemIndex();
296  BladeRF2InputThread *bladerf2InputThread = findThread();
297  bool needsStart = false;
298 
299  if (bladerf2InputThread) // if thread is already allocated
300  {
301  qDebug("BladeRF2Input::start: thread is already allocated");
302 
303  int nbOriginalChannels = bladerf2InputThread->getNbChannels();
304 
305  if (requestedChannel+1 > nbOriginalChannels) // expansion by deleting and re-creating the thread
306  {
307  qDebug("BladeRF2Input::start: expand channels. Re-allocate thread and take ownership");
308 
309  SampleSinkFifo **fifos = new SampleSinkFifo*[nbOriginalChannels];
310  unsigned int *log2Decims = new unsigned int[nbOriginalChannels];
311  int *fcPoss = new int[nbOriginalChannels];
312 
313  for (int i = 0; i < nbOriginalChannels; i++) // save original FIFO references and data
314  {
315  fifos[i] = bladerf2InputThread->getFifo(i);
316  log2Decims[i] = bladerf2InputThread->getLog2Decimation(i);
317  fcPoss[i] = bladerf2InputThread->getFcPos(i);
318  }
319 
320  bladerf2InputThread->stopWork();
321  delete bladerf2InputThread;
322  bladerf2InputThread = new BladeRF2InputThread(m_deviceShared.m_dev->getDev(), requestedChannel+1);
323  m_thread = bladerf2InputThread; // take ownership
324 
325  for (int i = 0; i < nbOriginalChannels; i++) // restore original FIFO references
326  {
327  bladerf2InputThread->setFifo(i, fifos[i]);
328  bladerf2InputThread->setLog2Decimation(i, log2Decims[i]);
329  bladerf2InputThread->setFcPos(i, fcPoss[i]);
330  }
331 
332  // remove old thread address from buddies (reset in all buddies). The address being held only in the owning source.
333  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
334  std::vector<DeviceAPI*>::const_iterator it = sourceBuddies.begin();
335 
336  for (; it != sourceBuddies.end(); ++it) {
337  ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_source->setThread(0);
338  }
339 
340  // was used as temporary storage:
341  delete[] fifos;
342  delete[] log2Decims;
343  delete[] fcPoss;
344 
345  needsStart = true;
346  }
347  else
348  {
349  qDebug("BladeRF2Input::start: keep buddy thread");
350  }
351  }
352  else // first allocation
353  {
354  qDebug("BladeRF2Input::start: allocate thread and take ownership");
355  bladerf2InputThread = new BladeRF2InputThread(m_deviceShared.m_dev->getDev(), requestedChannel+1);
356  m_thread = bladerf2InputThread; // take ownership
357  needsStart = true;
358  }
359 
360  bladerf2InputThread->setFifo(requestedChannel, &m_sampleFifo);
361  bladerf2InputThread->setLog2Decimation(requestedChannel, m_settings.m_log2Decim);
362  bladerf2InputThread->setFcPos(requestedChannel, (int) m_settings.m_fcPos);
363 
364  if (needsStart)
365  {
366  qDebug("BladeRF2Input::start: enabling channel(s) and (re)sart buddy thread");
367 
368  int nbChannels = bladerf2InputThread->getNbChannels();
369 
370  for (int i = 0; i < nbChannels; i++)
371  {
372  if (!m_deviceShared.m_dev->openRx(i)) {
373  qCritical("BladeRF2Input::start: channel %u cannot be enabled", i);
374  }
375  }
376 
377  bladerf2InputThread->startWork();
378  }
379 
380  applySettings(m_settings, true);
381 
382  qDebug("BladeRF2Input::start: started");
383  m_running = true;
384 
385  return true;
386 }
387 
389 {
390  // This stop method is responsible for managing the thread and channel disabling when the streaming of
391  // a Rx channel is stopped
392  //
393  // If the thread is currently managing only one channel (SI mode). The thread can be just stopped and deleted.
394  // Then the channel is closed (disabled).
395  //
396  // If the thread is currently managing many channels (MI mode) and we are removing the last channel. The transition
397  // from MI to SI or reduction of MI size is handled by stopping the thread, deleting it and creating a new one
398  // with one channel less if (and only if) there is still a channel active.
399  //
400  // If the thread is currently managing many channels (MI mode) but the channel being stopped is not the last
401  // channel then the FIFO reference is simply removed from the thread so that it will not stream into this FIFO
402  // anymore. In this case the channel is not closed (disabled) so that other channels can continue with the
403  // same configuration. The device continues streaming on this channel but the samples are simply dropped (by
404  // removing FIFO reference).
405 
406  if (!m_running) {
407  return;
408  }
409 
410  int requestedChannel = m_deviceAPI->getDeviceItemIndex();
411  BladeRF2InputThread *bladerf2InputThread = findThread();
412 
413  if (bladerf2InputThread == 0) { // no thread allocated
414  return;
415  }
416 
417  int nbOriginalChannels = bladerf2InputThread->getNbChannels();
418 
419  if (nbOriginalChannels == 1) // SI mode => just stop and delete the thread
420  {
421  qDebug("BladeRF2Input::stop: SI mode. Just stop and delete the thread");
422  bladerf2InputThread->stopWork();
423  delete bladerf2InputThread;
424  m_thread = 0;
425 
426  // remove old thread address from buddies (reset in all buddies)
427  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
428  std::vector<DeviceAPI*>::const_iterator it = sourceBuddies.begin();
429 
430  for (; it != sourceBuddies.end(); ++it) {
431  ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_source->setThread(0);
432  }
433 
434  m_deviceShared.m_dev->closeRx(0); // close the unique channel
435  }
436  else if (requestedChannel == nbOriginalChannels - 1) // remove last MI channel => reduce by deleting and re-creating the thread
437  {
438  qDebug("BladeRF2Input::stop: MI mode. Reduce by deleting and re-creating the thread");
439  bladerf2InputThread->stopWork();
440  SampleSinkFifo **fifos = new SampleSinkFifo*[nbOriginalChannels-1];
441  unsigned int *log2Decims = new unsigned int[nbOriginalChannels-1];
442  int *fcPoss = new int[nbOriginalChannels-1];
443  bool stillActiveFIFO = false;
444 
445  for (int i = 0; i < nbOriginalChannels-1; i++) // save original FIFO references
446  {
447  fifos[i] = bladerf2InputThread->getFifo(i);
448  stillActiveFIFO = stillActiveFIFO || (bladerf2InputThread->getFifo(i) != 0);
449  log2Decims[i] = bladerf2InputThread->getLog2Decimation(i);
450  fcPoss[i] = bladerf2InputThread->getFcPos(i);
451  }
452 
453  delete bladerf2InputThread;
454  m_thread = 0;
455 
456  if (stillActiveFIFO)
457  {
458  bladerf2InputThread = new BladeRF2InputThread(m_deviceShared.m_dev->getDev(), nbOriginalChannels-1);
459  m_thread = bladerf2InputThread; // take ownership
460 
461  for (int i = 0; i < nbOriginalChannels-1; i++) // restore original FIFO references
462  {
463  bladerf2InputThread->setFifo(i, fifos[i]);
464  bladerf2InputThread->setLog2Decimation(i, log2Decims[i]);
465  bladerf2InputThread->setFcPos(i, fcPoss[i]);
466  }
467  }
468  else
469  {
470  qDebug("BladeRF2Input::stop: do not re-create thread as there are no more FIFOs active");
471  }
472 
473  // remove old thread address from buddies (reset in all buddies). The address being held only in the owning source.
474  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
475  std::vector<DeviceAPI*>::const_iterator it = sourceBuddies.begin();
476 
477  for (; it != sourceBuddies.end(); ++it) {
478  ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_source->setThread(0);
479  }
480 
481  m_deviceShared.m_dev->closeRx(requestedChannel); // close the last channel
482 
483  if (stillActiveFIFO) {
484  bladerf2InputThread->startWork();
485  }
486 
487  // was used as temporary storage:
488  delete[] fifos;
489  delete[] log2Decims;
490  delete[] fcPoss;
491  }
492  else // remove channel from existing thread
493  {
494  qDebug("BladeRF2Input::stop: MI mode. Not changing MI configuration. Just remove FIFO reference");
495  bladerf2InputThread->setFifo(requestedChannel, 0); // remove FIFO
496  }
497 
498  m_running = false;
499 }
500 
501 QByteArray BladeRF2Input::serialize() const
502 {
503  return m_settings.serialize();
504 }
505 
506 bool BladeRF2Input::deserialize(const QByteArray& data)
507 {
508  bool success = true;
509 
510  if (!m_settings.deserialize(data))
511  {
513  success = false;
514  }
515 
517  m_inputMessageQueue.push(message);
518 
519  if (m_guiMessageQueue)
520  {
522  m_guiMessageQueue->push(messageToGUI);
523  }
524 
525  return success;
526 }
527 
529 {
530  return m_deviceDescription;
531 }
532 
534 {
535  int rate = m_settings.m_devSampleRate;
536  return (rate / (1<<m_settings.m_log2Decim));
537 }
538 
540 {
542 }
543 
544 void BladeRF2Input::setCenterFrequency(qint64 centerFrequency)
545 {
547  settings.m_centerFrequency = centerFrequency;
548 
549  MsgConfigureBladeRF2* message = MsgConfigureBladeRF2::create(settings, false);
550  m_inputMessageQueue.push(message);
551 
552  if (m_guiMessageQueue)
553  {
554  MsgConfigureBladeRF2* messageToGUI = MsgConfigureBladeRF2::create(settings, false);
555  m_guiMessageQueue->push(messageToGUI);
556  }
557 }
558 
559 bool BladeRF2Input::setDeviceCenterFrequency(struct bladerf *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths)
560 {
561  qint64 df = ((qint64)freq_hz * loPpmTenths) / 10000000LL;
562  freq_hz += df;
563 
564  int status = bladerf_set_frequency(dev, BLADERF_CHANNEL_RX(requestedChannel), freq_hz);
565 
566  if (status < 0) {
567  qWarning("BladeRF2Input::setDeviceCenterFrequency: bladerf_set_frequency(%lld) failed: %s",
568  freq_hz, bladerf_strerror(status));
569  return false;
570  }
571  else
572  {
573  qDebug("BladeRF2Input::setDeviceCenterFrequency: bladerf_set_frequency(%lld)", freq_hz);
574  return true;
575  }
576 }
577 
579 {
580  if (m_deviceShared.m_dev) {
581  m_deviceShared.m_dev->getFrequencyRangeRx(min, max, step);
582  }
583 }
584 
585 void BladeRF2Input::getSampleRateRange(int& min, int& max, int& step)
586 {
587  if (m_deviceShared.m_dev) {
588  m_deviceShared.m_dev->getSampleRateRangeRx(min, max, step);
589  }
590 }
591 
592 void BladeRF2Input::getBandwidthRange(int& min, int& max, int& step)
593 {
594  if (m_deviceShared.m_dev) {
595  m_deviceShared.m_dev->getBandwidthRangeRx(min, max, step);
596  }
597 }
598 
599 void BladeRF2Input::getGlobalGainRange(int& min, int& max, int& step)
600 {
601  if (m_deviceShared.m_dev) {
602  m_deviceShared.m_dev->getGlobalGainRangeRx(min, max, step);
603  }
604 }
605 
607 {
608  if (MsgConfigureBladeRF2::match(message))
609  {
610  MsgConfigureBladeRF2& conf = (MsgConfigureBladeRF2&) message;
611  qDebug() << "BladeRF2Input::handleMessage: MsgConfigureBladeRF2";
612 
613  if (!applySettings(conf.getSettings(), conf.getForce()))
614  {
615  qDebug("BladeRF2Input::handleMessage: MsgConfigureBladeRF2 config error");
616  }
617 
618  return true;
619  }
621  {
623  struct bladerf *dev = m_deviceShared.m_dev->getDev();
625  int status;
626  unsigned int tmp_uint;
627  bool tmp_bool;
628 
629  // evaluate changes that may have been introduced by changes in a buddy
630 
631  if (dev) // The BladeRF device must have been open to do so
632  {
633  int requestedChannel = m_deviceAPI->getDeviceItemIndex();
634 
635  if (report.getRxElseTx()) // Rx buddy change: check for: frequency, LO correction, gain mode and value, bias tee, sample rate, bandwidth
636  {
637  settings.m_devSampleRate = report.getDevSampleRate();
638  settings.m_LOppmTenths = report.getLOppmTenths();
639  settings.m_centerFrequency = report.getCenterFrequency();
640  settings.m_fcPos = (BladeRF2InputSettings::fcPos_t) report.getFcPos();
641 
642  BladeRF2InputThread *inputThread = findThread();
643 
644  if (inputThread) {
645  inputThread->setFcPos(requestedChannel, (int) settings.m_fcPos);
646  }
647 
648  status = bladerf_get_bandwidth(dev, BLADERF_CHANNEL_RX(requestedChannel), &tmp_uint);
649 
650  if (status < 0) {
651  qCritical("BladeRF2Input::handleMessage: MsgReportBuddyChange: bladerf_get_bandwidth error: %s", bladerf_strerror(status));
652  } else {
653  settings.m_bandwidth = tmp_uint;
654  }
655 
656  status = bladerf_get_bias_tee(dev, BLADERF_CHANNEL_RX(requestedChannel), &tmp_bool);
657 
658  if (status < 0) {
659  qCritical("BladeRF2Input::handleMessage: MsgReportBuddyChange: bladerf_get_bias_tee error: %s", bladerf_strerror(status));
660  } else {
661  settings.m_biasTee = tmp_bool;
662  }
663  }
664  else // Tx buddy change: check for sample rate change only
665  {
666  settings.m_devSampleRate = report.getDevSampleRate();
667 // status = bladerf_get_sample_rate(dev, BLADERF_CHANNEL_RX(requestedChannel), &tmp_uint);
668 //
669 // if (status < 0) {
670 // qCritical("BladeRF2Input::handleMessage: MsgReportBuddyChange: bladerf_get_sample_rate error: %s", bladerf_strerror(status));
671 // } else {
672 // settings.m_devSampleRate = tmp_uint;
673 // }
674 
675  qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency(
676  settings.m_centerFrequency,
677  0,
678  settings.m_log2Decim,
680  settings.m_devSampleRate,
681  DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD,
682  false);
683 
684  if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency, settings.m_LOppmTenths))
685  {
686  if (getMessageQueueToGUI())
687  {
688  int min, max, step;
689  getGlobalGainRange(min, max, step);
690  MsgReportGainRange *msg = MsgReportGainRange::create(min, max, step);
691  getMessageQueueToGUI()->push(msg);
692  }
693  }
694  }
695 
696  // change DSP settings if buddy change introduced a change in center frequency or base rate
698  {
699  int sampleRate = settings.m_devSampleRate/(1<<settings.m_log2Decim);
700  DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_centerFrequency);
701  m_fileSink->handleMessage(*notif); // forward to file sink
703  }
704 
705  m_settings = settings; // acknowledge the new settings
706 
707  // propagate settings to GUI if any
708  if (getMessageQueueToGUI())
709  {
711  getMessageQueueToGUI()->push(reportToGUI);
712  }
713  }
714 
715  return true;
716  }
717  else if (MsgFileRecord::match(message))
718  {
719  MsgFileRecord& conf = (MsgFileRecord&) message;
720  qDebug() << "BladeRF2Input::handleMessage: MsgFileRecord: " << conf.getStartStop();
721 
722  if (conf.getStartStop())
723  {
724  if (m_settings.m_fileRecordName.size() != 0) {
726  } else {
728  }
729 
731  }
732  else
733  {
735  }
736 
737  return true;
738  }
739  else if (MsgStartStop::match(message))
740  {
741  MsgStartStop& cmd = (MsgStartStop&) message;
742  qDebug() << "BladeRF2Input::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
743 
744  if (cmd.getStartStop())
745  {
747  {
749  }
750  }
751  else
752  {
754  }
755 
758  }
759 
760  return true;
761  }
762  else
763  {
764  return false;
765  }
766 }
767 
768 bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool force)
769 {
770  bool forwardChangeOwnDSP = false;
771  bool forwardChangeRxBuddies = false;
772  bool forwardChangeTxBuddies = false;
773 
774  struct bladerf *dev = m_deviceShared.m_dev->getDev();
775  int requestedChannel = m_deviceAPI->getDeviceItemIndex();
776  qint64 xlatedDeviceCenterFrequency = settings.m_centerFrequency;
777  xlatedDeviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0;
778  xlatedDeviceCenterFrequency = xlatedDeviceCenterFrequency < 0 ? 0 : xlatedDeviceCenterFrequency;
779  QList<QString> reverseAPIKeys;
780 
781  if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) {
782  reverseAPIKeys.append("dcBlock");
783  }
784  if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) {
785  reverseAPIKeys.append("iqCorrection");
786  }
787 
788  if ((m_settings.m_dcBlock != settings.m_dcBlock) ||
789  (m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
790  {
792  }
793 
794  if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force)
795  {
796  reverseAPIKeys.append("devSampleRate");
797  forwardChangeOwnDSP = true;
798  forwardChangeRxBuddies = true;
799  forwardChangeTxBuddies = true;
800 
801  if (dev != 0)
802  {
803  unsigned int actualSamplerate;
804  int status = bladerf_set_sample_rate(dev, BLADERF_CHANNEL_RX(requestedChannel), settings.m_devSampleRate, &actualSamplerate);
805 
806  if (status < 0)
807  {
808  qCritical("BladeRF2Input::applySettings: could not set sample rate: %d: %s",
809  settings.m_devSampleRate, bladerf_strerror(status));
810  }
811  else
812  {
813  qDebug() << "BladeRF2Input::applySettings: bladerf_set_sample_rate: actual sample rate is " << actualSamplerate;
814  }
815  }
816  }
817 
818  if ((m_settings.m_bandwidth != settings.m_bandwidth) || force)
819  {
820  reverseAPIKeys.append("bandwidth");
821  forwardChangeRxBuddies = true;
822 
823  if (dev != 0)
824  {
825  unsigned int actualBandwidth;
826  int status = bladerf_set_bandwidth(dev, BLADERF_CHANNEL_RX(requestedChannel), settings.m_bandwidth, &actualBandwidth);
827 
828  if(status < 0)
829  {
830  qCritical("BladeRF2Input::applySettings: could not set bandwidth: %d: %s",
831  settings.m_bandwidth, bladerf_strerror(status));
832  }
833  else
834  {
835  qDebug() << "BladeRF2Input::applySettings: bladerf_set_bandwidth: actual bandwidth is " << actualBandwidth;
836  }
837  }
838  }
839 
840  if ((m_settings.m_fcPos != settings.m_fcPos) || force)
841  {
842  reverseAPIKeys.append("fcPos");
843  BladeRF2InputThread *inputThread = findThread();
844 
845  if (inputThread != 0)
846  {
847  inputThread->setFcPos(requestedChannel, (int) settings.m_fcPos);
848  qDebug() << "BladeRF2Input::applySettings: set fc pos (enum) to " << (int) settings.m_fcPos;
849  }
850  }
851 
852  if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
853  {
854  reverseAPIKeys.append("log2Decim");
855  forwardChangeOwnDSP = true;
856  BladeRF2InputThread *inputThread = findThread();
857 
858  if (inputThread != 0)
859  {
860  inputThread->setLog2Decimation(requestedChannel, settings.m_log2Decim);
861  qDebug() << "BladeRF2Input::applySettings: set decimation to " << (1<<settings.m_log2Decim);
862  }
863  }
864 
865  if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) {
866  reverseAPIKeys.append("centerFrequency");
867  }
868  if ((m_settings.m_transverterMode != settings.m_transverterMode) || force) {
869  reverseAPIKeys.append("transverterMode");
870  }
872  reverseAPIKeys.append("transverterDeltaFrequency");
873  }
874  if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) {
875  reverseAPIKeys.append("LOppmTenths");
876  }
877  if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) {
878  reverseAPIKeys.append("devSampleRate");
879  }
880 
884  || (m_settings.m_LOppmTenths != settings.m_LOppmTenths)
886  || (m_settings.m_fcPos != settings.m_fcPos)
887  || (m_settings.m_log2Decim != settings.m_log2Decim) || force)
888  {
889  qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency(
890  xlatedDeviceCenterFrequency,
891  0,
892  settings.m_log2Decim,
894  settings.m_devSampleRate,
895  DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD,
896  false);
897 
898  forwardChangeOwnDSP = true;
899  forwardChangeRxBuddies = true;
900 
901  if (dev != 0)
902  {
903  if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency, settings.m_LOppmTenths))
904  {
905  if (getMessageQueueToGUI())
906  {
907  int min, max, step;
908  getGlobalGainRange(min, max, step);
909  MsgReportGainRange *msg = MsgReportGainRange::create(min, max, step);
910  getMessageQueueToGUI()->push(msg);
911  }
912  }
913  }
914  }
915 
916  if ((m_settings.m_biasTee != settings.m_biasTee) || force)
917  {
918  reverseAPIKeys.append("biasTee");
919  forwardChangeRxBuddies = true;
921  }
922 
923  if ((m_settings.m_gainMode != settings.m_gainMode) || force)
924  {
925  reverseAPIKeys.append("gainMode");
926  forwardChangeRxBuddies = true;
927 
928  if (dev)
929  {
930  int status = bladerf_set_gain_mode(dev, BLADERF_CHANNEL_RX(requestedChannel), (bladerf_gain_mode) settings.m_gainMode);
931 
932  if (status < 0) {
933  qWarning("BladeRF2Input::applySettings: bladerf_set_gain_mode(%d) failed: %s",
934  settings.m_gainMode, bladerf_strerror(status));
935  } else {
936  qDebug("BladeRF2Input::applySettings: bladerf_set_gain_mode(%d)", settings.m_gainMode);
937  }
938  }
939  }
940 
941  if ((m_settings.m_globalGain != settings.m_globalGain) || force) {
942  reverseAPIKeys.append("globalGain");
943  }
944  if ((m_settings.m_gainMode != settings.m_gainMode) || force) {
945  reverseAPIKeys.append("gainMode");
946  }
947 
948  if ((m_settings.m_globalGain != settings.m_globalGain)
949  || ((m_settings.m_gainMode != settings.m_gainMode) && (settings.m_gainMode == BLADERF_GAIN_MANUAL)) || force)
950  {
951  forwardChangeRxBuddies = true;
952 
953  if (dev)
954  {
955 // qDebug("BladeRF2Input::applySettings: channel: %d gain: %d", requestedChannel, settings.m_globalGain);
956  int status = bladerf_set_gain(dev, BLADERF_CHANNEL_RX(requestedChannel), settings.m_globalGain);
957 
958  if (status < 0) {
959  qWarning("BladeRF2Input::applySettings: bladerf_set_gain(%d) failed: %s",
960  settings.m_globalGain, bladerf_strerror(status));
961  } else {
962  qDebug("BladeRF2Input::applySettings: bladerf_set_gain(%d)", settings.m_globalGain);
963  }
964  }
965  }
966 
967  if (forwardChangeOwnDSP)
968  {
969  int sampleRate = settings.m_devSampleRate/(1<<settings.m_log2Decim);
970  DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_centerFrequency);
971  m_fileSink->handleMessage(*notif); // forward to file sink
973  }
974 
975  if (forwardChangeRxBuddies)
976  {
977  // send to source buddies
978  const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
979  std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
980 
981  for (; itSource != sourceBuddies.end(); ++itSource)
982  {
984  settings.m_centerFrequency,
985  settings.m_LOppmTenths,
986  (int) settings.m_fcPos,
987  settings.m_devSampleRate,
988  true);
989  (*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
990  }
991  }
992 
993  if (forwardChangeTxBuddies)
994  {
995  // send to sink buddies
996  const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
997  std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
998 
999  for (; itSink != sinkBuddies.end(); ++itSink)
1000  {
1002  settings.m_centerFrequency,
1003  settings.m_LOppmTenths,
1004  (int) settings.m_fcPos,
1005  settings.m_devSampleRate,
1006  true);
1007  (*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
1008  }
1009  }
1010 
1011  if (settings.m_useReverseAPI)
1012  {
1013  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
1017  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
1018  }
1019 
1020  m_settings = settings;
1021 
1022  qDebug() << "BladeRF2Input::applySettings: "
1023  << " m_transverterMode: " << m_settings.m_transverterMode
1024  << " m_transverterDeltaFrequency: " << m_settings.m_transverterDeltaFrequency
1025  << " m_centerFrequency: " << m_settings.m_centerFrequency << " Hz"
1026  << " m_LOppmTenths: " << m_settings.m_LOppmTenths
1027  << " m_bandwidth: " << m_settings.m_bandwidth
1028  << " m_log2Decim: " << m_settings.m_log2Decim
1029  << " m_fcPos: " << m_settings.m_fcPos
1030  << " m_devSampleRate: " << m_settings.m_devSampleRate
1031  << " m_globalGain: " << m_settings.m_globalGain
1032  << " m_gainMode: " << m_settings.m_gainMode
1033  << " m_dcBlock: " << m_settings.m_dcBlock
1034  << " m_iqCorrection: " << m_settings.m_iqCorrection
1035  << " m_biasTee: " << m_settings.m_biasTee;
1036 
1037  return true;
1038 }
1039 
1042  QString& errorMessage)
1043 {
1044  (void) errorMessage;
1046  response.getBladeRf2InputSettings()->init();
1048  return 200;
1049 }
1050 
1052  bool force,
1053  const QStringList& deviceSettingsKeys,
1054  SWGSDRangel::SWGDeviceSettings& response, // query + response
1055  QString& errorMessage)
1056 {
1057  (void) errorMessage;
1058  BladeRF2InputSettings settings = m_settings;
1059 
1060  if (deviceSettingsKeys.contains("centerFrequency")) {
1062  }
1063  if (deviceSettingsKeys.contains("LOppmTenths")) {
1064  settings.m_LOppmTenths = response.getBladeRf2InputSettings()->getLOppmTenths();
1065  }
1066  if (deviceSettingsKeys.contains("devSampleRate")) {
1068  }
1069  if (deviceSettingsKeys.contains("bandwidth")) {
1070  settings.m_bandwidth = response.getBladeRf2InputSettings()->getBandwidth();
1071  }
1072  if (deviceSettingsKeys.contains("log2Decim")) {
1073  settings.m_log2Decim = response.getBladeRf2InputSettings()->getLog2Decim();
1074  }
1075  if (deviceSettingsKeys.contains("fcPos")) {
1076  settings.m_fcPos = static_cast<BladeRF2InputSettings::fcPos_t>(response.getBladeRf2InputSettings()->getFcPos());
1077  }
1078  if (deviceSettingsKeys.contains("dcBlock")) {
1079  settings.m_dcBlock = response.getBladeRf2InputSettings()->getDcBlock() != 0;
1080  }
1081  if (deviceSettingsKeys.contains("iqCorrection")) {
1082  settings.m_iqCorrection = response.getBladeRf2InputSettings()->getIqCorrection() != 0;
1083  }
1084  if (deviceSettingsKeys.contains("biasTee")) {
1085  settings.m_biasTee = response.getBladeRf2InputSettings()->getBiasTee() != 0;
1086  }
1087  if (deviceSettingsKeys.contains("gainMode")) {
1088  settings.m_gainMode = response.getBladeRf2InputSettings()->getGainMode();
1089  }
1090  if (deviceSettingsKeys.contains("globalGain")) {
1091  settings.m_globalGain = response.getBladeRf2InputSettings()->getGlobalGain();
1092  }
1093  if (deviceSettingsKeys.contains("transverterDeltaFrequency")) {
1095  }
1096  if (deviceSettingsKeys.contains("transverterMode")) {
1097  settings.m_transverterMode = response.getBladeRf2InputSettings()->getTransverterMode() != 0;
1098  }
1099  if (deviceSettingsKeys.contains("fileRecordName")) {
1101  }
1102  if (deviceSettingsKeys.contains("useReverseAPI")) {
1103  settings.m_useReverseAPI = response.getBladeRf2InputSettings()->getUseReverseApi() != 0;
1104  }
1105  if (deviceSettingsKeys.contains("reverseAPIAddress")) {
1107  }
1108  if (deviceSettingsKeys.contains("reverseAPIPort")) {
1110  }
1111  if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
1113  }
1114 
1115  MsgConfigureBladeRF2 *msg = MsgConfigureBladeRF2::create(settings, force);
1117 
1118  if (m_guiMessageQueue) // forward to GUI if any
1119  {
1120  MsgConfigureBladeRF2 *msgToGUI = MsgConfigureBladeRF2::create(settings, force);
1121  m_guiMessageQueue->push(msgToGUI);
1122  }
1123 
1124  webapiFormatDeviceSettings(response, settings);
1125  return 200;
1126 }
1127 
1129 {
1130  (void) errorMessage;
1132  response.getBladeRf2InputReport()->init();
1133  webapiFormatDeviceReport(response);
1134  return 200;
1135 }
1136 
1138 {
1142  response.getBladeRf2InputSettings()->setBandwidth(settings.m_bandwidth);
1143  response.getBladeRf2InputSettings()->setLog2Decim(settings.m_log2Decim);
1144  response.getBladeRf2InputSettings()->setFcPos((int) settings.m_fcPos);
1145  response.getBladeRf2InputSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
1146  response.getBladeRf2InputSettings()->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
1147  response.getBladeRf2InputSettings()->setBiasTee(settings.m_biasTee ? 1 : 0);
1148  response.getBladeRf2InputSettings()->setGainMode(settings.m_gainMode);
1149  response.getBladeRf2InputSettings()->setGlobalGain(settings.m_globalGain);
1151  response.getBladeRf2InputSettings()->setTransverterMode(settings.m_transverterMode ? 1 : 0);
1152 
1153  if (response.getBladeRf2InputSettings()->getFileRecordName()) {
1155  } else {
1156  response.getBladeRf2InputSettings()->setFileRecordName(new QString(settings.m_fileRecordName));
1157  }
1158 
1159  response.getBladeRf2InputSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
1160 
1161  if (response.getBladeRf2InputSettings()->getReverseApiAddress()) {
1163  } else {
1164  response.getBladeRf2InputSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
1165  }
1166 
1169 }
1170 
1172 {
1174 
1175  if (device)
1176  {
1177  int min, max, step;
1178  uint64_t f_min, f_max;
1179 
1180  device->getBandwidthRangeRx(min, max, step);
1181 
1183  response.getBladeRf2InputReport()->getBandwidthRange()->setMin(min);
1184  response.getBladeRf2InputReport()->getBandwidthRange()->setMax(max);
1185  response.getBladeRf2InputReport()->getBandwidthRange()->setStep(step);
1186 
1187  device->getFrequencyRangeRx(f_min, f_max, step);
1188 
1190  response.getBladeRf2InputReport()->getFrequencyRange()->setMin(f_min);
1191  response.getBladeRf2InputReport()->getFrequencyRange()->setMax(f_max);
1192  response.getBladeRf2InputReport()->getFrequencyRange()->setStep(step);
1193 
1194  device->getGlobalGainRangeRx(min, max, step);
1195 
1197  response.getBladeRf2InputReport()->getGlobalGainRange()->setMin(min);
1198  response.getBladeRf2InputReport()->getGlobalGainRange()->setMax(max);
1199  response.getBladeRf2InputReport()->getGlobalGainRange()->setStep(step);
1200 
1201  device->getSampleRateRangeRx(min, max, step);
1202 
1204  response.getBladeRf2InputReport()->getSampleRateRange()->setMin(min);
1205  response.getBladeRf2InputReport()->getSampleRateRange()->setMax(max);
1206  response.getBladeRf2InputReport()->getSampleRateRange()->setStep(step);
1207 
1208  response.getBladeRf2InputReport()->setGainModes(new QList<SWGSDRangel::SWGNamedEnum*>);
1209 
1210  const std::vector<GainMode>& modes = getGainModes();
1211  std::vector<GainMode>::const_iterator it = modes.begin();
1212 
1213  for (; it != modes.end(); ++it)
1214  {
1216  response.getBladeRf2InputReport()->getGainModes()->back()->setName(new QString(it->m_name));
1217  response.getBladeRf2InputReport()->getGainModes()->back()->setValue(it->m_value);
1218  }
1219  }
1220 }
1221 
1223  SWGSDRangel::SWGDeviceState& response,
1224  QString& errorMessage)
1225 {
1226  (void) errorMessage;
1228  return 200;
1229 }
1230 
1232  bool run,
1233  SWGSDRangel::SWGDeviceState& response,
1234  QString& errorMessage)
1235 {
1236  (void) errorMessage;
1238  MsgStartStop *message = MsgStartStop::create(run);
1239  m_inputMessageQueue.push(message);
1240 
1241  if (m_guiMessageQueue) // forward to GUI if any
1242  {
1243  MsgStartStop *msgToGUI = MsgStartStop::create(run);
1244  m_guiMessageQueue->push(msgToGUI);
1245  }
1246 
1247  return 200;
1248 }
1249 
1250 void BladeRF2Input::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const BladeRF2InputSettings& settings, bool force)
1251 {
1253  swgDeviceSettings->setDirection(0); // single Rx
1254  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
1255  swgDeviceSettings->setDeviceHwType(new QString("BladeRF2"));
1257  SWGSDRangel::SWGBladeRF2InputSettings *swgBladeRF2Settings = swgDeviceSettings->getBladeRf2InputSettings();
1258 
1259  // transfer data that has been modified. When force is on transfer all data except reverse API data
1260 
1261  if (deviceSettingsKeys.contains("centerFrequency") || force) {
1262  swgBladeRF2Settings->setCenterFrequency(settings.m_centerFrequency);
1263  }
1264  if (deviceSettingsKeys.contains("LOppmTenths") || force) {
1265  swgBladeRF2Settings->setLOppmTenths(settings.m_LOppmTenths);
1266  }
1267  if (deviceSettingsKeys.contains("log2Decim") || force) {
1268  swgBladeRF2Settings->setLog2Decim(settings.m_log2Decim);
1269  }
1270  if (deviceSettingsKeys.contains("fcPos") || force) {
1271  swgBladeRF2Settings->setFcPos((int) settings.m_fcPos);
1272  }
1273  if (deviceSettingsKeys.contains("dcBlock") || force) {
1274  swgBladeRF2Settings->setDcBlock(settings.m_dcBlock ? 1 : 0);
1275  }
1276  if (deviceSettingsKeys.contains("iqCorrection") || force) {
1277  swgBladeRF2Settings->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
1278  }
1279  if (deviceSettingsKeys.contains("transverterDeltaFrequency") || force) {
1280  swgBladeRF2Settings->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency);
1281  }
1282  if (deviceSettingsKeys.contains("transverterMode") || force) {
1283  swgBladeRF2Settings->setTransverterMode(settings.m_transverterMode ? 1 : 0);
1284  }
1285  if (deviceSettingsKeys.contains("fileRecordName") || force) {
1286  swgBladeRF2Settings->setFileRecordName(new QString(settings.m_fileRecordName));
1287  }
1288  if (deviceSettingsKeys.contains("devSampleRate")) {
1289  swgBladeRF2Settings->setDevSampleRate(settings.m_devSampleRate);
1290  }
1291  if (deviceSettingsKeys.contains("bandwidth")) {
1292  swgBladeRF2Settings->setBandwidth(settings.m_bandwidth);
1293  }
1294  if (deviceSettingsKeys.contains("biasTee")) {
1295  swgBladeRF2Settings->setBiasTee(settings.m_biasTee);
1296  }
1297  if (deviceSettingsKeys.contains("gainMode")) {
1298  swgBladeRF2Settings->setGainMode(settings.m_gainMode);
1299  }
1300  if (deviceSettingsKeys.contains("globalGain")) {
1301  swgBladeRF2Settings->setGlobalGain(settings.m_globalGain);
1302  }
1303 
1304  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings")
1305  .arg(settings.m_reverseAPIAddress)
1306  .arg(settings.m_reverseAPIPort)
1307  .arg(settings.m_reverseAPIDeviceIndex);
1308  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
1309  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
1310 
1311  QBuffer *buffer=new QBuffer();
1312  buffer->open((QBuffer::ReadWrite));
1313  buffer->write(swgDeviceSettings->asJson().toUtf8());
1314  buffer->seek(0);
1315 
1316  // Always use PATCH to avoid passing reverse API settings
1317  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
1318 
1319  delete swgDeviceSettings;
1320 }
1321 
1323 {
1325  swgDeviceSettings->setDirection(0); // single Rx
1326  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
1327  swgDeviceSettings->setDeviceHwType(new QString("BladeRF2"));
1328 
1329  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
1333  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
1334  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
1335 
1336  QBuffer *buffer=new QBuffer();
1337  buffer->open((QBuffer::ReadWrite));
1338  buffer->write(swgDeviceSettings->asJson().toUtf8());
1339  buffer->seek(0);
1340 
1341  if (start) {
1342  m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer);
1343  } else {
1344  m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer);
1345  }
1346 
1347  delete swgDeviceSettings;
1348 }
1349 
1350 void BladeRF2Input::networkManagerFinished(QNetworkReply *reply)
1351 {
1352  QNetworkReply::NetworkError replyError = reply->error();
1353 
1354  if (replyError)
1355  {
1356  qWarning() << "BladeRF2Input::networkManagerFinished:"
1357  << " error(" << (int) replyError
1358  << "): " << replyError
1359  << ": " << reply->errorString();
1360  return;
1361  }
1362 
1363  QString answer = reply->readAll();
1364  answer.chop(1); // remove last \n
1365  qDebug("BladeRF2Input::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
1366 }
virtual int webapiRun(bool run, SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
virtual int webapiReportGet(SWGSDRangel::SWGDeviceReport &response, QString &errorMessage)
virtual ~BladeRF2Input()
bool startDeviceEngine()
Start the device engine corresponding to the stream type.
Definition: deviceapi.cpp:253
unsigned int getLog2Decimation(unsigned int channel) const
QByteArray serialize() const
BladeRF2InputThread * findThread()
static qint64 calculateDeviceCenterFrequency(quint64 centerFrequency, qint64 transverterDeltaFrequency, int log2Decim, fcPos_t fcPos, quint32 devSampleRate, FrequencyShiftScheme frequencyShiftScheme, bool transverterMode=false)
QString m_deviceDescription
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 setFileName(const QString &filename)
Definition: filerecord.cpp:59
uint getDeviceUID() const
Return the current device engine unique ID.
Definition: deviceapi.cpp:303
void setFrequencyRange(SWGFrequencyRange *frequency_range)
const std::vector< DeviceAPI * > & getSinkBuddies() const
Definition: deviceapi.h:166
void startRecording()
Definition: filerecord.cpp:105
BladeRF2InputSettings m_settings
MessageQueue m_inputMessageQueue
Input queue to the source.
SWGBladeRF2InputReport * getBladeRf2InputReport()
virtual QString asJson() override
const std::vector< GainMode > & getGainModes()
MessageQueue * getDeviceEngineInputMessageQueue()
Device engine message queue.
Definition: deviceapi.cpp:316
void setReverseApiAddress(QString *reverse_api_address)
uint32_t getDeviceItemIndex() const
Definition: deviceapi.h:129
void setFileRecordName(QString *file_record_name)
void setTransverterMode(qint32 transverter_mode)
void setStep(qint32 step)
Definition: SWGRange.cpp:131
void networkManagerFinished(QNetworkReply *reply)
void getFrequencyRange(uint64_t &min, uint64_t &max, int &step)
void getGlobalGainRange(int &min, int &max, int &step)
bool initDeviceEngine()
Init the device engine corresponding to the stream type.
Definition: deviceapi.cpp:240
void setFcPos(unsigned int channel, int fcPos)
unsigned int getNbChannels() const
void webapiReverseSendStartStop(bool start)
void webapiReverseSendSettings(QList< QString > &deviceSettingsKeys, const BladeRF2InputSettings &settings, bool force)
void setMax(qint32 max)
Definition: SWGRange.cpp:121
virtual quint64 getCenterFrequency() const
Center frequency exposed by the source.
DeviceAPI * m_deviceAPI
static MsgReportGainRange * create(int min, int max, int step)
void setOriginatorIndex(qint32 originator_index)
void setCenterFrequency(qint64 center_frequency)
void getBandwidthRange(int &min, int &max, int &step)
FileRecord * m_fileSink
File sink to record device I/Q output.
void getBandwidthRangeRx(int &min, int &max, int &step)
static MsgStartStop * create(bool startStop)
Definition: bladerf2input.h:90
SampleSinkFifo m_sampleFifo
bool setSize(int size)
MessageQueue * getMessageQueueToGUI()
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
bool applySettings(const BladeRF2InputSettings &settings, bool force=false)
virtual const QString & getDeviceDescription() const
virtual void stop()
int getDeviceSetIndex() const
Definition: deviceapi.h:131
void * getBuddySharedPtr() const
Definition: deviceapi.h:161
void setGlobalGainRange(SWGRange *global_gain_range)
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
void genUniqueFileName(uint deviceUID, int istream=-1)
Definition: filerecord.cpp:67
virtual int webapiRunGet(SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
virtual bool deserialize(const QByteArray &data)
void getFrequencyRangeRx(uint64_t &min, uint64_t &max, int &step)
BladeRF2InputThread * getThread()
void getSampleRateRangeRx(int &min, int &max, int &step)
void moveThreadToBuddy()
void setBuddySharedPtr(void *ptr)
Definition: deviceapi.h:162
void stopRecording()
Definition: filerecord.cpp:117
int32_t i
Definition: decimators.h:244
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport &response)
static bool match(const Message *message)
Definition: message.cpp:45
void setBiasTeeRx(bool enable)
int getFcPos(unsigned int channel) const
void removeAncillarySink(BasebandSampleSink *sink, unsigned int index=0)
Removes it.
Definition: deviceapi.cpp:100
BladeRF2InputThread * m_thread
void setBladeRf2InputSettings(SWGBladeRF2InputSettings *blade_rf2_input_settings)
void setFifo(unsigned int channel, SampleSinkFifo *sampleFifo)
static MsgReportBuddyChange * create(uint64_t centerFrequency, int LOppmTenths, int fcPos, int devSampleRate, bool rxElseTx)
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
bool setDeviceCenterFrequency(struct bladerf *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths)
void setThread(BladeRF2InputThread *thread)
virtual void setCenterFrequency(qint64 centerFrequency)
void setBladeRf2InputReport(SWGBladeRF2InputReport *blade_rf2_input_report)
void setMin(qint32 min)
Definition: SWGRange.cpp:111
bool openRx(int channel)
void getDeviceEngineStateStr(QString &state)
Definition: deviceapi.cpp:389
const QString & getSamplingDeviceSerial() const
Definition: deviceapi.h:121
void setBandwidthRange(SWGRange *bandwidth_range)
void setTransverterDeltaFrequency(qint64 transverter_delta_frequency)
bladerf * getDev()
virtual void init()
initializations to be done when all collaborating objects are created and possibly connected ...
int m_channel
allocated channel (-1 if none)
bool open(const char *serial)
void closeRx(int channel)
QNetworkRequest m_networkRequest
void getSampleRateRange(int &min, int &max, int &step)
void setReverseApiPort(qint32 reverse_api_port)
virtual bool handleMessage(const Message &message)
void setSampleRateRange(SWGRange *sample_rate_range)
void setLog2Decimation(unsigned int channel, unsigned int log2_decim)
const std::vector< DeviceAPI * > & getSourceBuddies() const
Definition: deviceapi.h:165
virtual int getSampleRate() const
Sample rate exposed by the source.
void setGainModes(QList< SWGNamedEnum *> *gain_modes)
QNetworkAccessManager * m_networkManager
virtual int webapiSettingsGet(SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings &response, const BladeRF2InputSettings &settings)
DeviceBladeRF2Shared m_deviceShared
virtual int webapiSettingsPutPatch(bool force, const QStringList &deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection, int streamIndex=0)
Configure current device engine DSP corrections (Rx)
Definition: deviceapi.cpp:355
virtual void destroy()
void setDirection(qint32 direction)
SampleSinkFifo * getFifo(unsigned int channel)
void getGlobalGainRangeRx(int &min, int &max, int &step)
static MsgConfigureBladeRF2 * create(const BladeRF2InputSettings &settings, bool force)
Definition: bladerf2input.h:49
const BladeRF2InputSettings & getSettings() const
Definition: bladerf2input.h:46
T max(const T &x, const T &y)
Definition: framework.h:446
SWGBladeRF2InputSettings * getBladeRf2InputSettings()
virtual bool start()
void setDeviceHwType(QString *device_hw_type)
bool deserialize(const QByteArray &data)
virtual QByteArray serialize() const
T min(const T &x, const T &y)
Definition: framework.h:440
unsigned __int64 uint64_t
Definition: rtptypes_win.h:48