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.
dspdevicesourceengine.cpp
Go to the documentation of this file.
1 // Copyright (C) 2015 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 #include "dspdevicesourceengine.h"
20 
21 #include <dsp/basebandsamplesink.h>
22 #include <dsp/devicesamplesource.h>
23 #include <dsp/downchannelizer.h>
24 #include <stdio.h>
25 #include <QDebug>
26 #include "dsp/dspcommands.h"
27 #include "util/fixed.h"
28 #include "samplesinkfifo.h"
30 
32  QThread(parent),
33  m_uid(uid),
34  m_state(StNotStarted),
35  m_deviceSampleSource(nullptr),
36  m_sampleSourceSequence(0),
37  m_basebandSampleSinks(),
38  m_sampleRate(0),
39  m_centerFrequency(0),
40  m_dcOffsetCorrection(false),
41  m_iqImbalanceCorrection(false),
42  m_iOffset(0),
43  m_qOffset(0),
44  m_iRange(1 << 16),
45  m_qRange(1 << 16),
46  m_imbalance(65536)
47 {
48  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
49  connect(&m_syncMessenger, SIGNAL(messageSent()), this, SLOT(handleSynchronousMessages()), Qt::QueuedConnection);
50 
51  moveToThread(this);
52 }
53 
55 {
56  stop();
57  wait();
58 }
59 
61 {
62  qDebug() << "DSPDeviceSourceEngine::run";
63  m_state = StIdle;
64  exec();
65 }
66 
68 {
69  qDebug() << "DSPDeviceSourceEngine::start";
70  QThread::start();
71 }
72 
74 {
75  qDebug() << "DSPDeviceSourceEngine::stop";
76  gotoIdle();
78  QThread::exit();
79 // DSPExit cmd;
80 // m_syncMessenger.sendWait(cmd);
81 }
82 
84 {
85  qDebug() << "DSPDeviceSourceEngine::initAcquisition";
87 
88  return m_syncMessenger.sendWait(cmd) == StReady;
89 }
90 
92 {
93  qDebug() << "DSPDeviceSourceEngine::startAcquisition";
95 
96  return m_syncMessenger.sendWait(cmd) == StRunning;
97 }
98 
100 {
101  qDebug() << "DSPDeviceSourceEngine::stopAcquistion";
102  DSPAcquisitionStop cmd;
105 
107  {
108  qDebug("DC offset:%f,%f", m_iOffset, m_qOffset);
109  }
110 }
111 
113 {
114  qDebug() << "DSPDeviceSourceEngine::setSource";
115  DSPSetSource cmd(source);
117 }
118 
120 {
121  qDebug("DSPDeviceSourceEngine::setSourceSequence: seq: %d", sequence);
122  m_sampleSourceSequence = sequence;
123 }
124 
126 {
127  qDebug() << "DSPDeviceSourceEngine::addSink: " << sink->objectName().toStdString().c_str();
128  DSPAddBasebandSampleSink cmd(sink);
130 }
131 
133 {
134  qDebug() << "DSPDeviceSourceEngine::removeSink: " << sink->objectName().toStdString().c_str();
135  DSPRemoveBasebandSampleSink cmd(sink);
137 }
138 
140 {
141  qDebug() << "DSPDeviceSourceEngine::addThreadedSink: " << sink->objectName().toStdString().c_str();
144 }
145 
147 {
148  qDebug() << "DSPDeviceSourceEngine::removeThreadedSink: " << sink->objectName().toStdString().c_str();
151 }
152 
153 void DSPDeviceSourceEngine::configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection)
154 {
155  qDebug() << "DSPDeviceSourceEngine::configureCorrections";
156  DSPConfigureCorrection* cmd = new DSPConfigureCorrection(dcOffsetCorrection, iqImbalanceCorrection);
158 }
159 
161 {
162  qDebug() << "DSPDeviceSourceEngine::errorMessage";
163  DSPGetErrorMessage cmd;
165  return cmd.getErrorMessage();
166 }
167 
169 {
170  qDebug() << "DSPDeviceSourceEngine::sourceDeviceDescription";
173  return cmd.getDeviceDescription();
174 }
175 
176 void DSPDeviceSourceEngine::iqCorrections(SampleVector::iterator begin, SampleVector::iterator end, bool imbalanceCorrection)
177 {
178  for(SampleVector::iterator it = begin; it < end; it++)
179  {
180  m_iBeta(it->real());
181  m_qBeta(it->imag());
182 
183  if (imbalanceCorrection)
184  {
185 #if IMBALANCE_INT
186  // acquisition
187  int64_t xi = (it->m_real - (int32_t) m_iBeta) << 5;
188  int64_t xq = (it->m_imag - (int32_t) m_qBeta) << 5;
189 
190  // phase imbalance
191  m_avgII((xi*xi)>>28); // <I", I">
192  m_avgIQ((xi*xq)>>28); // <I", Q">
193 
194  if ((int64_t) m_avgII != 0)
195  {
196  int64_t phi = (((int64_t) m_avgIQ)<<28) / (int64_t) m_avgII;
197  m_avgPhi(phi);
198  }
199 
200  int64_t corrPhi = (((int64_t) m_avgPhi) * xq) >> 28; //(m_avgPhi.asDouble()/16777216.0) * ((double) xq);
201 
202  int64_t yi = xi - corrPhi;
203  int64_t yq = xq;
204 
205  // amplitude I/Q imbalance
206  m_avgII2((yi*yi)>>28); // <I, I>
207  m_avgQQ2((yq*yq)>>28); // <Q, Q>
208 
209  if ((int64_t) m_avgQQ2 != 0)
210  {
211  int64_t a = (((int64_t) m_avgII2)<<28) / (int64_t) m_avgQQ2;
214  m_avgAmp(sqrtA.as_internal());
215  }
216 
217  int64_t zq = (((int64_t) m_avgAmp) * yq) >> 28;
218 
219  it->m_real = yi >> 5;
220  it->m_imag = zq >> 5;
221 
222 #else
223  // DC correction and conversion
224  float xi = (it->m_real - (int32_t) m_iBeta) / SDR_RX_SCALEF;
225  float xq = (it->m_imag - (int32_t) m_qBeta) / SDR_RX_SCALEF;
226 
227  // phase imbalance
228  m_avgII(xi*xi); // <I", I">
229  m_avgIQ(xi*xq); // <I", Q">
230 
231 
232  if (m_avgII.asDouble() != 0) {
234  }
235 
236  float& yi = xi; // the in phase remains the reference
237  float yq = xq - m_avgPhi.asDouble()*xi;
238 
239  // amplitude I/Q imbalance
240  m_avgII2(yi*yi); // <I, I>
241  m_avgQQ2(yq*yq); // <Q, Q>
242 
243  if (m_avgQQ2.asDouble() != 0) {
245  }
246 
247  // final correction
248  float& zi = yi; // the in phase remains the reference
249  float zq = m_avgAmp.asDouble() * yq;
250 
251  // convert and store
252  it->m_real = zi * SDR_RX_SCALEF;
253  it->m_imag = zq * SDR_RX_SCALEF;
254 #endif
255  }
256  else
257  {
258  // DC correction only
259  it->m_real -= (int32_t) m_iBeta;
260  it->m_imag -= (int32_t) m_qBeta;
261  }
262  }
263 }
264 
265 void DSPDeviceSourceEngine::dcOffset(SampleVector::iterator begin, SampleVector::iterator end)
266 {
267  // sum and correct in one pass
268  for(SampleVector::iterator it = begin; it < end; it++)
269  {
270  m_iBeta(it->real());
271  m_qBeta(it->imag());
272  it->m_real -= (int32_t) m_iBeta;
273  it->m_imag -= (int32_t) m_qBeta;
274  }
275 }
276 
277 void DSPDeviceSourceEngine::imbalance(SampleVector::iterator begin, SampleVector::iterator end)
278 {
279  int iMin = 0;
280  int iMax = 0;
281  int qMin = 0;
282  int qMax = 0;
283 
284  // find value ranges for both I and Q
285  // both intervals should be same same size (for a perfect circle)
286  for (SampleVector::iterator it = begin; it < end; it++)
287  {
288  if (it != begin)
289  {
290  if (it->real() < iMin) {
291  iMin = it->real();
292  } else if (it->real() > iMax) {
293  iMax = it->real();
294  }
295 
296  if (it->imag() < qMin) {
297  qMin = it->imag();
298  } else if (it->imag() > qMax) {
299  qMax = it->imag();
300  }
301  }
302  else
303  {
304  iMin = it->real();
305  iMax = it->real();
306  qMin = it->imag();
307  qMax = it->imag();
308  }
309  }
310 
311  // sliding average (el cheapo again)
312  m_iRange = (m_iRange * 15 + (iMax - iMin)) >> 4;
313  m_qRange = (m_qRange * 15 + (qMax - qMin)) >> 4;
314 
315  // calculate imbalance on 32 bit full scale
316  if(m_qRange != 0) {
317  m_imbalance = ((uint)m_iRange << (32-SDR_RX_SAMP_SZ)) / (uint)m_qRange;
318  }
319 
320  // correct imbalance and convert back to sample size
321  for(SampleVector::iterator it = begin; it < end; it++) {
322  it->m_imag = (it->m_imag * m_imbalance) >> (32-SDR_RX_SAMP_SZ);
323  }
324 }
325 
327 {
329  std::size_t samplesDone = 0;
330  bool positiveOnly = false;
331 
332  while ((sampleFifo->fill() > 0) && (m_inputMessageQueue.size() == 0) && (samplesDone < m_sampleRate))
333  {
334  SampleVector::iterator part1begin;
335  SampleVector::iterator part1end;
336  SampleVector::iterator part2begin;
337  SampleVector::iterator part2end;
338 
339  std::size_t count = sampleFifo->readBegin(sampleFifo->fill(), &part1begin, &part1end, &part2begin, &part2end);
340 
341  // first part of FIFO data
342  if (part1begin != part1end)
343  {
344  // correct stuff
346  {
347  iqCorrections(part1begin, part1end, m_iqImbalanceCorrection);
348  }
349 
350 // if (m_dcOffsetCorrection)
351 // {
352 // dcOffset(part1begin, part1end);
353 // }
354 //
355 // if (m_iqImbalanceCorrection)
356 // {
357 // imbalance(part1begin, part1end);
358 // }
359 
360  // feed data to direct sinks
361  for (BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); ++it)
362  {
363  (*it)->feed(part1begin, part1end, positiveOnly);
364  }
365 
366  // feed data to threaded sinks
367  for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks.begin(); it != m_threadedBasebandSampleSinks.end(); ++it)
368  {
369  (*it)->feed(part1begin, part1end, positiveOnly);
370  }
371  }
372 
373  // second part of FIFO data (used when block wraps around)
374  if(part2begin != part2end)
375  {
376  // correct stuff
378  {
379  iqCorrections(part2begin, part2end, m_iqImbalanceCorrection);
380  }
381 
382 // if (m_dcOffsetCorrection)
383 // {
384 // dcOffset(part2begin, part2end);
385 // }
386 //
387 // if (m_iqImbalanceCorrection)
388 // {
389 // imbalance(part2begin, part2end);
390 // }
391 
392  // feed data to direct sinks
393  for (BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); it++)
394  {
395  (*it)->feed(part2begin, part2end, positiveOnly);
396  }
397 
398  // feed data to threaded sinks
399  for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks.begin(); it != m_threadedBasebandSampleSinks.end(); ++it)
400  {
401  (*it)->feed(part2begin, part2end, positiveOnly);
402  }
403  }
404 
405  // adjust FIFO pointers
406  sampleFifo->readCommit((unsigned int) count);
407  samplesDone += count;
408  }
409 }
410 
411 // notStarted -> idle -> init -> running -+
412 // ^ |
413 // +-----------------------+
414 
416 {
417  qDebug() << "DSPDeviceSourceEngine::gotoIdle";
418 
419  switch(m_state) {
420  case StNotStarted:
421  return StNotStarted;
422 
423  case StIdle:
424  case StError:
425  return StIdle;
426 
427  case StReady:
428  case StRunning:
429  break;
430  }
431 
432  if(m_deviceSampleSource == 0)
433  {
434  return StIdle;
435  }
436 
437  // stop everything
438 
439  for(BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); it++)
440  {
441  (*it)->stop();
442  }
443 
444  for(ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks.begin(); it != m_threadedBasebandSampleSinks.end(); it++)
445  {
446  (*it)->stop();
447  }
448 
450  m_deviceDescription.clear();
451  m_sampleRate = 0;
452 
453  return StIdle;
454 }
455 
457 {
458  switch(m_state) {
459  case StNotStarted:
460  return StNotStarted;
461 
462  case StRunning: // FIXME: assumes it goes first through idle state. Could we get back to init from running directly?
463  return StRunning;
464 
465  case StReady:
466  return StReady;
467 
468  case StIdle:
469  case StError:
470  break;
471  }
472 
473  if (m_deviceSampleSource == 0)
474  {
475  return gotoError("No sample source configured");
476  }
477 
478  // init: pass sample rate and center frequency to all sample rate and/or center frequency dependent sinks and wait for completion
479 
480  m_iOffset = 0;
481  m_qOffset = 0;
482  m_iRange = 1 << 16;
483  m_qRange = 1 << 16;
484 
488 
489  qDebug() << "DSPDeviceSourceEngine::gotoInit: "
490  << " m_deviceDescription: " << m_deviceDescription.toStdString().c_str()
491  << " sampleRate: " << m_sampleRate
492  << " centerFrequency: " << m_centerFrequency;
493 
494  DSPSignalNotification notif(m_sampleRate, m_centerFrequency);
495 
496  for (BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); ++it)
497  {
498  qDebug() << "DSPDeviceSourceEngine::gotoInit: initializing " << (*it)->objectName().toStdString().c_str();
499  (*it)->handleMessage(notif);
500  }
501 
502  for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks.begin(); it != m_threadedBasebandSampleSinks.end(); ++it)
503  {
504  qDebug() << "DSPDeviceSourceEngine::gotoInit: initializing ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
505  (*it)->handleSinkMessage(notif);
506  }
507 
508  // pass data to listeners
510  {
511  DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy for the output queue
513  }
514 
515  return StReady;
516 }
517 
519 {
520  qDebug() << "DSPDeviceSourceEngine::gotoRunning";
521 
522  switch(m_state)
523  {
524  case StNotStarted:
525  return StNotStarted;
526 
527  case StIdle:
528  return StIdle;
529 
530  case StRunning:
531  return StRunning;
532 
533  case StReady:
534  case StError:
535  break;
536  }
537 
538  if(m_deviceSampleSource == NULL) {
539  return gotoError("DSPDeviceSourceEngine::gotoRunning: No sample source configured");
540  }
541 
542  qDebug() << "DSPDeviceSourceEngine::gotoRunning: " << m_deviceDescription.toStdString().c_str() << " started";
543 
544  // Start everything
545 
547  {
548  return gotoError("Could not start sample source");
549  }
550 
551  for(BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); it++)
552  {
553  qDebug() << "DSPDeviceSourceEngine::gotoRunning: starting " << (*it)->objectName().toStdString().c_str();
554  (*it)->start();
555  }
556 
557  for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks.begin(); it != m_threadedBasebandSampleSinks.end(); ++it)
558  {
559  qDebug() << "DSPDeviceSourceEngine::gotoRunning: starting ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
560  (*it)->start();
561  }
562 
563  qDebug() << "DSPDeviceSourceEngine::gotoRunning:input message queue pending: " << m_inputMessageQueue.size();
564 
565  return StRunning;
566 }
567 
569 {
570  qDebug() << "DSPDeviceSourceEngine::gotoError: " << errorMessage;
571 
573  m_deviceDescription.clear();
574  m_state = StError;
575  return StError;
576 }
577 
579 {
580  gotoIdle();
581 
582 // if(m_sampleSource != 0)
583 // {
584 // disconnect(m_sampleSource->getSampleFifo(), SIGNAL(dataReady()), this, SLOT(handleData()));
585 // }
586 
587  m_deviceSampleSource = source;
588 
589  if(m_deviceSampleSource != 0)
590  {
591  qDebug("DSPDeviceSourceEngine::handleSetSource: set %s", qPrintable(source->getDeviceDescription()));
592  connect(m_deviceSampleSource->getSampleFifo(), SIGNAL(dataReady()), this, SLOT(handleData()), Qt::QueuedConnection);
593  }
594  else
595  {
596  qDebug("DSPDeviceSourceEngine::handleSetSource: set none");
597  }
598 }
599 
601 {
602  if(m_state == StRunning)
603  {
604  work();
605  }
606 }
607 
609 {
610  Message *message = m_syncMessenger.getMessage();
611  qDebug() << "DSPDeviceSourceEngine::handleSynchronousMessages: " << message->getIdentifier();
612 
613  if (DSPAcquisitionInit::match(*message))
614  {
615  m_state = gotoIdle();
616 
617  if(m_state == StIdle) {
618  m_state = gotoInit(); // State goes ready if init is performed
619  }
620  }
621  else if (DSPAcquisitionStart::match(*message))
622  {
623  if(m_state == StReady) {
624  m_state = gotoRunning();
625  }
626  }
627  else if (DSPAcquisitionStop::match(*message))
628  {
629  m_state = gotoIdle();
630  }
631  else if (DSPGetSourceDeviceDescription::match(*message))
632  {
633  ((DSPGetSourceDeviceDescription*) message)->setDeviceDescription(m_deviceDescription);
634  }
635  else if (DSPGetErrorMessage::match(*message))
636  {
637  ((DSPGetErrorMessage*) message)->setErrorMessage(m_errorMessage);
638  }
639  else if (DSPSetSource::match(*message)) {
640  handleSetSource(((DSPSetSource*) message)->getSampleSource());
641  }
642  else if (DSPAddBasebandSampleSink::match(*message))
643  {
644  BasebandSampleSink* sink = ((DSPAddBasebandSampleSink*) message)->getSampleSink();
645  m_basebandSampleSinks.push_back(sink);
646  // initialize sample rate and center frequency in the sink:
648  sink->handleMessage(msg);
649  // start the sink:
650  if(m_state == StRunning) {
651  sink->start();
652  }
653  }
654  else if (DSPRemoveBasebandSampleSink::match(*message))
655  {
656  BasebandSampleSink* sink = ((DSPRemoveBasebandSampleSink*) message)->getSampleSink();
657 
658  if(m_state == StRunning) {
659  sink->stop();
660  }
661 
662  m_basebandSampleSinks.remove(sink);
663  }
664  else if (DSPAddThreadedBasebandSampleSink::match(*message))
665  {
666  ThreadedBasebandSampleSink *threadedSink = ((DSPAddThreadedBasebandSampleSink*) message)->getThreadedSampleSink();
667  m_threadedBasebandSampleSinks.push_back(threadedSink);
668  // initialize sample rate and center frequency in the sink:
670  threadedSink->handleSinkMessage(msg);
671  // start the sink:
672  if(m_state == StRunning) {
673  threadedSink->start();
674  }
675  }
677  {
678  ThreadedBasebandSampleSink* threadedSink = ((DSPRemoveThreadedBasebandSampleSink*) message)->getThreadedSampleSink();
679  threadedSink->stop();
680  m_threadedBasebandSampleSinks.remove(threadedSink);
681  }
682 
684 }
685 
687 {
688  Message* message;
689 
690  while ((message = m_inputMessageQueue.pop()) != 0)
691  {
692  qDebug("DSPDeviceSourceEngine::handleInputMessages: message: %s", message->getIdentifier());
693 
694  if (DSPConfigureCorrection::match(*message))
695  {
698 
700  {
702  m_iOffset = 0;
703  m_qOffset = 0;
704  }
705 
707  {
709  m_iRange = 1 << 16;
710  m_qRange = 1 << 16;
711  m_imbalance = 65536;
712  }
713 
714  m_avgAmp.reset();
715  m_avgII.reset();
716  m_avgII2.reset();
717  m_avgIQ.reset();
718  m_avgPhi.reset();
719  m_avgQQ2.reset();
720  m_iBeta.reset();
721  m_qBeta.reset();
722 
723  delete message;
724  }
725  else if (DSPSignalNotification::match(*message))
726  {
727  DSPSignalNotification *notif = (DSPSignalNotification *) message;
728 
729  // update DSP values
730 
731  m_sampleRate = notif->getSampleRate();
733 
734  qDebug() << "DSPDeviceSourceEngine::handleInputMessages: DSPSignalNotification:"
735  << " m_sampleRate: " << m_sampleRate
736  << " m_centerFrequency: " << m_centerFrequency;
737 
738  // forward source changes to channel sinks with immediate execution (no queuing)
739 
740  for(BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); it++)
741  {
742  qDebug() << "DSPDeviceSourceEngine::handleInputMessages: forward message to " << (*it)->objectName().toStdString().c_str();
743  (*it)->handleMessage(*message);
744  }
745 
746  for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks.begin(); it != m_threadedBasebandSampleSinks.end(); ++it)
747  {
748  qDebug() << "DSPDeviceSourceEngine::handleSourceMessages: forward message to ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
749  (*it)->handleSinkMessage(*message);
750  }
751 
752  // forward changes to source GUI input queue
753 
755  qDebug("DSPDeviceSourceEngine::handleInputMessages: DSPSignalNotification: guiMessageQueue: %p", guiMessageQueue);
756 
757  if (guiMessageQueue) {
758  DSPSignalNotification* rep = new DSPSignalNotification(*notif); // make a copy for the source GUI
759  guiMessageQueue->push(rep);
760  }
761 
762  //m_outputMessageQueue.push(rep);
763 
764  delete message;
765  }
766  }
767 }
void handleSetSource(DeviceSampleSource *source)
Manage source setting.
Message * pop()
Pop message from queue.
State gotoInit()
Go to the acquisition init state from idle.
MovingAverageUtil< float, double, 128 > m_avgIQ
const QString & getErrorMessage() const
Definition: dspcommands.h:86
SampleSinkFifo * getSampleFifo()
void push(Message *message, bool emitSignal=true)
Push message onto queue.
MovingAverageUtil< double, double, 128 > m_avgAmp
int size()
Returns queue size.
engine is before initialization
QString errorMessage()
Return the current error message.
BasebandSampleSinks m_basebandSampleSinks
sample sinks within main thread (usually spectrum, file output)
bool handleSinkMessage(const Message &cmd)
Send message to sink synchronously.
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection)
Configure DSP corrections.
bool getIQImbalanceCorrection() const
Definition: dspcommands.h:271
void start()
this thread start()
void handleSynchronousMessages()
Handle synchronous messages with the thread.
void removeSink(BasebandSampleSink *sink)
Remove a sample sink.
void stop()
This thread stop.
void storeMessage(Message &message)
Definition: syncmessenger.h:42
DeviceSampleSource * m_deviceSampleSource
DSPDeviceSourceEngine(uint uid, QObject *parent=NULL)
MovingAverageUtil< float, double, 128 > m_avgQQ2
__int64 int64_t
Definition: rtptypes_win.h:47
MovingAverageUtil< float, double, 128 > m_avgII2
uint readCommit(uint count)
void work()
transfer samples from source to sinks if in running state
MessageQueue * getMessageQueueToGUI()
#define SDR_RX_SCALEF
Definition: dsptypes.h:33
MovingAverageUtil< double, double, 128 > m_avgPhi
void handleData()
Handle data when samples from source FIFO are ready to be processed.
virtual void start()=0
qint64 getCenterFrequency() const
Definition: dspcommands.h:329
#define SDR_RX_SAMP_SZ
Definition: dsptypes.h:32
virtual int getSampleRate() const =0
Sample rate exposed by the source.
bool getDCOffsetCorrection() const
Definition: dspcommands.h:270
virtual const QString & getDeviceDescription() const =0
void setSourceSequence(int sequence)
Set the sample source sequence in type.
virtual bool handleMessage(const Message &cmd)=0
Processing of a message. Returns true if message has actually been processed.
void setSource(DeviceSampleSource *source)
Set the sample source type.
bool initAcquisition()
Initialize acquisition sequence.
virtual bool start()=0
void stopAcquistion()
Stop acquisition sequence.
static bool match(const Message *message)
Definition: message.cpp:45
MovingAverageUtil< int32_t, int64_t, 1024 > m_iBeta
Definition: fixed.h:42
int int32_t
Definition: rtptypes_win.h:45
State gotoRunning()
Go to the running state from ready state.
void addSink(BasebandSampleSink *sink)
Add a sample sink.
Fixed< IntType, IntBits > sqrt(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2283
void dcOffset(SampleVector::iterator begin, SampleVector::iterator end)
State gotoError(const QString &errorMsg)
Go to an error state.
IntType as_internal() const
Definition: fixed.h:154
Message * getMessage() const
Definition: syncmessenger.h:41
void imbalance(SampleVector::iterator begin, SampleVector::iterator end)
void removeThreadedSink(ThreadedBasebandSampleSink *sink)
Remove a sample sink that runs on its own thread.
QString sourceDeviceDescription()
Return the source device description.
void done(int result=0)
Processing of the message is complete.
void iqCorrections(SampleVector::iterator begin, SampleVector::iterator end, bool imbalanceCorrection)
const QString & getDeviceDescription() const
Definition: dspcommands.h:64
void start()
This thread start.
void stop()
this thread exit() and wait()
int getSampleRate() const
Definition: dspcommands.h:328
bool startAcquisition()
Start acquisition sequence.
virtual const char * getIdentifier() const
Definition: message.cpp:35
virtual void stop()=0
ThreadedBasebandSampleSinks m_threadedBasebandSampleSinks
sample sinks on their own threads (usually channels)
void addThreadedSink(ThreadedBasebandSampleSink *sink)
Add a sample sink that will run on its own thread.
int sendWait(Message &message, unsigned long msPollTime=100)
Send message and waits for its process completion.
void handleInputMessages()
Handle input message queue.
virtual void stop()=0
State gotoIdle()
Go to the idle state.
MovingAverageUtil< float, double, 128 > m_avgII
virtual quint64 getCenterFrequency() const =0
Center frequency exposed by the source.
double asDouble() const
Definition: movingaverage.h:57
uint readBegin(uint count, SampleVector::iterator *part1Begin, SampleVector::iterator *part1End, SampleVector::iterator *part2Begin, SampleVector::iterator *part2End)
SyncMessenger m_syncMessenger
Used to process messages synchronously with the thread.
MovingAverageUtil< int32_t, int64_t, 1024 > m_qBeta