2015-10-15 04:05:19 +02:00
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
2019-04-11 14:32:15 +02:00
// (at your option) any later version. //
2015-10-15 04:05:19 +02:00
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
2016-10-03 18:29:05 +02:00
#include "dspdevicesourceengine.h"
2016-10-02 22:29:04 +02:00
#include <dsp/basebandsamplesink.h>
2016-10-02 23:16:40 +02:00
#include <dsp/devicesamplesource.h>
2016-10-02 21:52:39 +02:00
#include <dsp/downchannelizer.h>
2015-10-15 04:05:19 +02:00
#include <stdio.h>
#include <QDebug>
#include "dsp/dspcommands.h"
2018-02-04 10:49:13 +01:00
#include "util/fixed.h"
2016-10-06 19:18:02 +02:00
#include "samplesinkfifo.h"
2016-10-03 15:55:16 +02:00
#include "threadedbasebandsamplesink.h"
2015-10-15 04:05:19 +02:00
2016-10-03 18:29:05 +02:00
DSPDeviceSourceEngine :: DSPDeviceSourceEngine ( uint uid , QObject * parent ) :
2015-10-15 04:05:19 +02:00
QThread ( parent ),
2017-05-25 20:13:34 +02:00
m_uid ( uid ),
2015-10-15 04:05:19 +02:00
m_state ( StNotStarted ),
2019-05-18 11:59:56 +02:00
m_deviceSampleSource ( nullptr ),
2015-10-15 04:05:19 +02:00
m_sampleSourceSequence ( 0 ),
2016-10-04 01:49:28 +02:00
m_basebandSampleSinks (),
2015-10-15 04:05:19 +02:00
m_sampleRate ( 0 ),
m_centerFrequency ( 0 ),
m_dcOffsetCorrection ( false ),
m_iqImbalanceCorrection ( false ),
m_iOffset ( 0 ),
m_qOffset ( 0 ),
m_iRange ( 1 << 16 ),
m_qRange ( 1 << 16 ),
m_imbalance ( 65536 )
{
2015-10-21 02:32:21 +02:00
connect ( & m_inputMessageQueue , SIGNAL ( messageEnqueued ()), this , SLOT ( handleInputMessages ()), Qt :: QueuedConnection );
connect ( & m_syncMessenger , SIGNAL ( messageSent ()), this , SLOT ( handleSynchronousMessages ()), Qt :: QueuedConnection );
2015-10-15 04:05:19 +02:00
moveToThread ( this );
}
2016-10-03 18:29:05 +02:00
DSPDeviceSourceEngine ::~ DSPDeviceSourceEngine ()
2015-10-15 04:05:19 +02:00
{
2018-02-14 11:27:57 +01:00
stop ();
wait ();
2015-10-15 04:05:19 +02:00
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: run ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::run" ;
2015-10-15 04:05:19 +02:00
m_state = StIdle ;
2018-02-14 17:33:08 +01:00
exec ();
2015-10-15 04:05:19 +02:00
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: start ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::start" ;
2015-10-15 04:05:19 +02:00
QThread :: start ();
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: stop ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::stop" ;
2017-10-04 00:50:42 +02:00
gotoIdle ();
m_state = StNotStarted ;
QThread :: exit ();
// DSPExit cmd;
// m_syncMessenger.sendWait(cmd);
2015-10-15 04:05:19 +02:00
}
2016-10-03 18:29:05 +02:00
bool DSPDeviceSourceEngine :: initAcquisition ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::initAcquisition" ;
2015-10-15 04:05:19 +02:00
DSPAcquisitionInit cmd ;
return m_syncMessenger . sendWait ( cmd ) == StReady ;
}
2016-10-03 18:29:05 +02:00
bool DSPDeviceSourceEngine :: startAcquisition ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::startAcquisition" ;
2015-10-15 04:05:19 +02:00
DSPAcquisitionStart cmd ;
return m_syncMessenger . sendWait ( cmd ) == StRunning ;
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: stopAcquistion ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::stopAcquistion" ;
2015-10-15 04:05:19 +02:00
DSPAcquisitionStop cmd ;
m_syncMessenger . storeMessage ( cmd );
handleSynchronousMessages ();
if ( m_dcOffsetCorrection )
{
qDebug ( "DC offset:%f,%f" , m_iOffset , m_qOffset );
}
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: setSource ( DeviceSampleSource * source )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::setSource" ;
2015-10-15 04:05:19 +02:00
DSPSetSource cmd ( source );
m_syncMessenger . sendWait ( cmd );
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: setSourceSequence ( int sequence )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug ( "DSPDeviceSourceEngine::setSourceSequence: seq: %d" , sequence );
2015-10-15 04:05:19 +02:00
m_sampleSourceSequence = sequence ;
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: addSink ( BasebandSampleSink * sink )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::addSink: " << sink -> objectName (). toStdString (). c_str ();
2018-01-02 01:04:49 +01:00
DSPAddBasebandSampleSink cmd ( sink );
2015-10-15 04:05:19 +02:00
m_syncMessenger . sendWait ( cmd );
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: removeSink ( BasebandSampleSink * sink )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::removeSink: " << sink -> objectName (). toStdString (). c_str ();
2018-01-02 01:04:49 +01:00
DSPRemoveBasebandSampleSink cmd ( sink );
2015-10-15 04:05:19 +02:00
m_syncMessenger . sendWait ( cmd );
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: addThreadedSink ( ThreadedBasebandSampleSink * sink )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::addThreadedSink: " << sink -> objectName (). toStdString (). c_str ();
2018-01-02 01:04:49 +01:00
DSPAddThreadedBasebandSampleSink cmd ( sink );
2015-10-15 04:05:19 +02:00
m_syncMessenger . sendWait ( cmd );
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: removeThreadedSink ( ThreadedBasebandSampleSink * sink )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::removeThreadedSink: " << sink -> objectName (). toStdString (). c_str ();
2018-01-02 01:04:49 +01:00
DSPRemoveThreadedBasebandSampleSink cmd ( sink );
2015-10-15 04:05:19 +02:00
m_syncMessenger . sendWait ( cmd );
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: configureCorrections ( bool dcOffsetCorrection , bool iqImbalanceCorrection )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::configureCorrections" ;
2015-10-15 04:05:19 +02:00
DSPConfigureCorrection * cmd = new DSPConfigureCorrection ( dcOffsetCorrection , iqImbalanceCorrection );
m_inputMessageQueue . push ( cmd );
}
2016-10-03 18:29:05 +02:00
QString DSPDeviceSourceEngine :: errorMessage ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::errorMessage" ;
2015-10-15 04:05:19 +02:00
DSPGetErrorMessage cmd ;
m_syncMessenger . sendWait ( cmd );
return cmd . getErrorMessage ();
}
2016-10-03 18:29:05 +02:00
QString DSPDeviceSourceEngine :: sourceDeviceDescription ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::sourceDeviceDescription" ;
2015-10-15 04:05:19 +02:00
DSPGetSourceDeviceDescription cmd ;
m_syncMessenger . sendWait ( cmd );
return cmd . getDeviceDescription ();
}
2018-02-01 02:45:55 +01:00
void DSPDeviceSourceEngine :: iqCorrections ( SampleVector :: iterator begin , SampleVector :: iterator end , bool imbalanceCorrection )
{
for ( SampleVector :: iterator it = begin ; it < end ; it ++ )
{
m_iBeta ( it -> real ());
m_qBeta ( it -> imag ());
if ( imbalanceCorrection )
{
2018-02-04 18:20:16 +01:00
#if IMBALANCE_INT
// acquisition
int64_t xi = ( it -> m_real - ( int32_t ) m_iBeta ) << 5 ;
int64_t xq = ( it -> m_imag - ( int32_t ) m_qBeta ) << 5 ;
// phase imbalance
m_avgII (( xi * xi ) >> 28 ); // <I", I">
m_avgIQ (( xi * xq ) >> 28 ); // <I", Q">
if (( int64_t ) m_avgII != 0 )
{
int64_t phi = ((( int64_t ) m_avgIQ ) << 28 ) / ( int64_t ) m_avgII ;
m_avgPhi ( phi );
}
int64_t corrPhi = ((( int64_t ) m_avgPhi ) * xq ) >> 28 ; //(m_avgPhi.asDouble()/16777216.0) * ((double) xq);
int64_t yi = xi - corrPhi ;
int64_t yq = xq ;
// amplitude I/Q imbalance
m_avgII2 (( yi * yi ) >> 28 ); // <I, I>
m_avgQQ2 (( yq * yq ) >> 28 ); // <Q, Q>
if (( int64_t ) m_avgQQ2 != 0 )
{
int64_t a = ((( int64_t ) m_avgII2 ) << 28 ) / ( int64_t ) m_avgQQ2 ;
Fixed < int64_t , 28 > fA ( Fixed < int64_t , 28 >:: internal (), a );
Fixed < int64_t , 28 > sqrtA = sqrt (( Fixed < int64_t , 28 > ) fA );
m_avgAmp ( sqrtA . as_internal ());
}
int64_t zq = ((( int64_t ) m_avgAmp ) * yq ) >> 28 ;
it -> m_real = yi >> 5 ;
it -> m_imag = zq >> 5 ;
#else
2018-02-04 10:49:13 +01:00
// DC correction and conversion
float xi = ( it -> m_real - ( int32_t ) m_iBeta ) / SDR_RX_SCALEF ;
float xq = ( it -> m_imag - ( int32_t ) m_qBeta ) / SDR_RX_SCALEF ;
// phase imbalance
m_avgII ( xi * xi ); // <I", I">
m_avgIQ ( xi * xq ); // <I", Q">
if ( m_avgII . asDouble () != 0 ) {
m_avgPhi ( m_avgIQ . asDouble () / m_avgII . asDouble ());
}
2018-02-11 01:42:35 +01:00
float & yi = xi ; // the in phase remains the reference
float yq = xq - m_avgPhi . asDouble () * xi ;
2018-02-04 10:49:13 +01:00
// amplitude I/Q imbalance
m_avgII2 ( yi * yi ); // <I, I>
m_avgQQ2 ( yq * yq ); // <Q, Q>
if ( m_avgQQ2 . asDouble () != 0 ) {
m_avgAmp ( sqrt ( m_avgII2 . asDouble () / m_avgQQ2 . asDouble ()));
}
// final correction
2018-02-11 01:42:35 +01:00
float & zi = yi ; // the in phase remains the reference
2018-02-04 10:49:13 +01:00
float zq = m_avgAmp . asDouble () * yq ;
// convert and store
it -> m_real = zi * SDR_RX_SCALEF ;
it -> m_imag = zq * SDR_RX_SCALEF ;
2018-02-04 18:20:16 +01:00
#endif
2018-02-01 02:45:55 +01:00
}
else
{
2018-02-04 10:49:13 +01:00
// DC correction only
2018-02-01 02:45:55 +01:00
it -> m_real -= ( int32_t ) m_iBeta ;
it -> m_imag -= ( int32_t ) m_qBeta ;
}
}
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: dcOffset ( SampleVector :: iterator begin , SampleVector :: iterator end )
2015-10-15 04:05:19 +02:00
{
// sum and correct in one pass
for ( SampleVector :: iterator it = begin ; it < end ; it ++ )
{
2018-02-01 02:45:55 +01:00
m_iBeta ( it -> real ());
m_qBeta ( it -> imag ());
it -> m_real -= ( int32_t ) m_iBeta ;
it -> m_imag -= ( int32_t ) m_qBeta ;
2015-10-15 04:05:19 +02:00
}
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: imbalance ( SampleVector :: iterator begin , SampleVector :: iterator end )
2015-10-15 04:05:19 +02:00
{
int iMin = 0 ;
int iMax = 0 ;
int qMin = 0 ;
int qMax = 0 ;
// find value ranges for both I and Q
// both intervals should be same same size (for a perfect circle)
for ( SampleVector :: iterator it = begin ; it < end ; it ++ )
{
if ( it != begin )
{
if ( it -> real () < iMin ) {
iMin = it -> real ();
} else if ( it -> real () > iMax ) {
iMax = it -> real ();
}
if ( it -> imag () < qMin ) {
qMin = it -> imag ();
} else if ( it -> imag () > qMax ) {
qMax = it -> imag ();
}
}
else
{
iMin = it -> real ();
iMax = it -> real ();
qMin = it -> imag ();
qMax = it -> imag ();
}
}
// sliding average (el cheapo again)
m_iRange = ( m_iRange * 15 + ( iMax - iMin )) >> 4 ;
m_qRange = ( m_qRange * 15 + ( qMax - qMin )) >> 4 ;
2018-01-25 00:48:11 +01:00
// calculate imbalance on 32 bit full scale
2015-10-15 04:05:19 +02:00
if ( m_qRange != 0 ) {
2018-01-25 00:48:11 +01:00
m_imbalance = (( uint ) m_iRange << ( 32 - SDR_RX_SAMP_SZ )) / ( uint ) m_qRange ;
2015-10-15 04:05:19 +02:00
}
2018-01-25 00:48:11 +01:00
// correct imbalance and convert back to sample size
2015-10-15 04:05:19 +02:00
for ( SampleVector :: iterator it = begin ; it < end ; it ++ ) {
2018-01-25 00:48:11 +01:00
it -> m_imag = ( it -> m_imag * m_imbalance ) >> ( 32 - SDR_RX_SAMP_SZ );
2015-10-15 04:05:19 +02:00
}
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: work ()
2015-10-15 04:05:19 +02:00
{
2016-10-06 19:18:02 +02:00
SampleSinkFifo * sampleFifo = m_deviceSampleSource -> getSampleFifo ();
2015-10-15 04:05:19 +02:00
std :: size_t samplesDone = 0 ;
bool positiveOnly = false ;
while (( sampleFifo -> fill () > 0 ) && ( m_inputMessageQueue . size () == 0 ) && ( samplesDone < m_sampleRate ))
{
SampleVector :: iterator part1begin ;
SampleVector :: iterator part1end ;
SampleVector :: iterator part2begin ;
SampleVector :: iterator part2end ;
std :: size_t count = sampleFifo -> readBegin ( sampleFifo -> fill (), & part1begin , & part1end , & part2begin , & part2end );
// first part of FIFO data
if ( part1begin != part1end )
{
// correct stuff
2018-02-04 10:49:13 +01:00
if ( m_dcOffsetCorrection )
{
iqCorrections ( part1begin , part1end , m_iqImbalanceCorrection );
}
// if (m_dcOffsetCorrection)
// {
// dcOffset(part1begin, part1end);
// }
//
// if (m_iqImbalanceCorrection)
// {
// imbalance(part1begin, part1end);
// }
2015-10-15 04:05:19 +02:00
// feed data to direct sinks
2016-10-04 01:49:28 +02:00
for ( BasebandSampleSinks :: const_iterator it = m_basebandSampleSinks . begin (); it != m_basebandSampleSinks . end (); ++ it )
2015-10-15 04:05:19 +02:00
{
( * it ) -> feed ( part1begin , part1end , positiveOnly );
}
// feed data to threaded sinks
2016-10-04 01:49:28 +02:00
for ( ThreadedBasebandSampleSinks :: const_iterator it = m_threadedBasebandSampleSinks . begin (); it != m_threadedBasebandSampleSinks . end (); ++ it )
2015-10-15 04:05:19 +02:00
{
( * it ) -> feed ( part1begin , part1end , positiveOnly );
}
}
// second part of FIFO data (used when block wraps around)
if ( part2begin != part2end )
{
// correct stuff
2018-02-04 10:49:13 +01:00
if ( m_dcOffsetCorrection )
{
iqCorrections ( part2begin , part2end , m_iqImbalanceCorrection );
}
// if (m_dcOffsetCorrection)
// {
// dcOffset(part2begin, part2end);
// }
//
// if (m_iqImbalanceCorrection)
// {
// imbalance(part2begin, part2end);
// }
2015-10-15 04:05:19 +02:00
// feed data to direct sinks
2016-10-04 01:49:28 +02:00
for ( BasebandSampleSinks :: const_iterator it = m_basebandSampleSinks . begin (); it != m_basebandSampleSinks . end (); it ++ )
2015-10-15 04:05:19 +02:00
{
( * it ) -> feed ( part2begin , part2end , positiveOnly );
}
// feed data to threaded sinks
2016-10-04 01:49:28 +02:00
for ( ThreadedBasebandSampleSinks :: const_iterator it = m_threadedBasebandSampleSinks . begin (); it != m_threadedBasebandSampleSinks . end (); ++ it )
2015-10-15 04:05:19 +02:00
{
( * it ) -> feed ( part2begin , part2end , positiveOnly );
}
}
// adjust FIFO pointers
sampleFifo -> readCommit (( unsigned int ) count );
samplesDone += count ;
}
}
// notStarted -> idle -> init -> running -+
// ^ |
// +-----------------------+
2016-10-03 18:29:05 +02:00
DSPDeviceSourceEngine :: State DSPDeviceSourceEngine :: gotoIdle ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::gotoIdle" ;
2015-10-15 04:05:19 +02:00
switch ( m_state ) {
case StNotStarted :
return StNotStarted ;
case StIdle :
case StError :
return StIdle ;
case StReady :
case StRunning :
break ;
}
2016-10-04 01:49:28 +02:00
if ( m_deviceSampleSource == 0 )
2015-10-15 04:05:19 +02:00
{
return StIdle ;
}
// stop everything
2016-10-04 01:49:28 +02:00
for ( BasebandSampleSinks :: const_iterator it = m_basebandSampleSinks . begin (); it != m_basebandSampleSinks . end (); it ++ )
2015-10-15 04:05:19 +02:00
{
( * it ) -> stop ();
}
2016-10-17 22:40:02 +02:00
for ( ThreadedBasebandSampleSinks :: const_iterator it = m_threadedBasebandSampleSinks . begin (); it != m_threadedBasebandSampleSinks . end (); it ++ )
{
( * it ) -> stop ();
}
2016-10-17 18:15:08 +02:00
2016-10-04 01:49:28 +02:00
m_deviceSampleSource -> stop ();
2015-10-15 04:05:19 +02:00
m_deviceDescription . clear ();
m_sampleRate = 0 ;
return StIdle ;
}
2016-10-03 18:29:05 +02:00
DSPDeviceSourceEngine :: State DSPDeviceSourceEngine :: gotoInit ()
2015-10-15 04:05:19 +02:00
{
switch ( m_state ) {
case StNotStarted :
return StNotStarted ;
case StRunning : // FIXME: assumes it goes first through idle state. Could we get back to init from running directly?
return StRunning ;
case StReady :
return StReady ;
case StIdle :
case StError :
break ;
}
2016-10-04 01:49:28 +02:00
if ( m_deviceSampleSource == 0 )
2015-10-15 04:05:19 +02:00
{
return gotoError ( "No sample source configured" );
}
// init: pass sample rate and center frequency to all sample rate and/or center frequency dependent sinks and wait for completion
m_iOffset = 0 ;
m_qOffset = 0 ;
m_iRange = 1 << 16 ;
m_qRange = 1 << 16 ;
2016-10-04 01:49:28 +02:00
m_deviceDescription = m_deviceSampleSource -> getDeviceDescription ();
m_centerFrequency = m_deviceSampleSource -> getCenterFrequency ();
m_sampleRate = m_deviceSampleSource -> getSampleRate ();
2015-10-15 04:05:19 +02:00
2017-12-25 09:10:19 +01:00
qDebug () << "DSPDeviceSourceEngine::gotoInit: "
<< " m_deviceDescription: " << m_deviceDescription . toStdString (). c_str ()
2015-10-15 04:05:19 +02:00
<< " sampleRate: " << m_sampleRate
<< " centerFrequency: " << m_centerFrequency ;
DSPSignalNotification notif ( m_sampleRate , m_centerFrequency );
2016-10-04 01:49:28 +02:00
for ( BasebandSampleSinks :: const_iterator it = m_basebandSampleSinks . begin (); it != m_basebandSampleSinks . end (); ++ it )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::gotoInit: initializing " << ( * it ) -> objectName (). toStdString (). c_str ();
2015-10-15 04:05:19 +02:00
( * it ) -> handleMessage ( notif );
}
2016-10-04 01:49:28 +02:00
for ( ThreadedBasebandSampleSinks :: const_iterator it = m_threadedBasebandSampleSinks . begin (); it != m_threadedBasebandSampleSinks . end (); ++ it )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::gotoInit: initializing ThreadedSampleSink(" << ( * it ) -> getSampleSinkObjectName (). toStdString (). c_str () << ")" ;
2015-10-15 04:05:19 +02:00
( * it ) -> handleSinkMessage ( notif );
}
// pass data to listeners
2017-09-17 17:35:03 +02:00
if ( m_deviceSampleSource -> getMessageQueueToGUI ())
{
DSPSignalNotification * rep = new DSPSignalNotification ( notif ); // make a copy for the output queue
m_deviceSampleSource -> getMessageQueueToGUI () -> push ( rep );
}
2015-10-15 04:05:19 +02:00
return StReady ;
}
2016-10-03 18:29:05 +02:00
DSPDeviceSourceEngine :: State DSPDeviceSourceEngine :: gotoRunning ()
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::gotoRunning" ;
2015-10-15 04:05:19 +02:00
switch ( m_state )
{
case StNotStarted :
return StNotStarted ;
case StIdle :
return StIdle ;
case StRunning :
return StRunning ;
case StReady :
case StError :
break ;
}
2016-10-04 01:49:28 +02:00
if ( m_deviceSampleSource == NULL ) {
2016-10-08 10:35:07 +02:00
return gotoError ( "DSPDeviceSourceEngine::gotoRunning: No sample source configured" );
2015-10-15 04:05:19 +02:00
}
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::gotoRunning: " << m_deviceDescription . toStdString (). c_str () << " started" ;
2015-10-15 04:05:19 +02:00
// Start everything
2017-04-14 03:40:45 +02:00
if ( ! m_deviceSampleSource -> start ())
2015-10-15 04:05:19 +02:00
{
return gotoError ( "Could not start sample source" );
}
2016-10-04 01:49:28 +02:00
for ( BasebandSampleSinks :: const_iterator it = m_basebandSampleSinks . begin (); it != m_basebandSampleSinks . end (); it ++ )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::gotoRunning: starting " << ( * it ) -> objectName (). toStdString (). c_str ();
2015-10-15 04:05:19 +02:00
( * it ) -> start ();
}
2016-10-04 01:49:28 +02:00
for ( ThreadedBasebandSampleSinks :: const_iterator it = m_threadedBasebandSampleSinks . begin (); it != m_threadedBasebandSampleSinks . end (); ++ it )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::gotoRunning: starting ThreadedSampleSink(" << ( * it ) -> getSampleSinkObjectName (). toStdString (). c_str () << ")" ;
2015-10-15 04:05:19 +02:00
( * it ) -> start ();
}
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::gotoRunning:input message queue pending: " << m_inputMessageQueue . size ();
2015-10-15 04:05:19 +02:00
return StRunning ;
}
2016-10-03 18:29:05 +02:00
DSPDeviceSourceEngine :: State DSPDeviceSourceEngine :: gotoError ( const QString & errorMessage )
2015-10-15 04:05:19 +02:00
{
2016-11-16 02:38:21 +01:00
qDebug () << "DSPDeviceSourceEngine::gotoError: " << errorMessage ;
2015-10-15 04:05:19 +02:00
m_errorMessage = errorMessage ;
m_deviceDescription . clear ();
m_state = StError ;
return StError ;
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: handleSetSource ( DeviceSampleSource * source )
2015-10-15 04:05:19 +02:00
{
gotoIdle ();
2016-05-20 00:49:55 +02:00
// if(m_sampleSource != 0)
// {
// disconnect(m_sampleSource->getSampleFifo(), SIGNAL(dataReady()), this, SLOT(handleData()));
// }
2015-10-15 04:05:19 +02:00
2016-10-04 01:49:28 +02:00
m_deviceSampleSource = source ;
2015-10-15 04:05:19 +02:00
2016-10-04 01:49:28 +02:00
if ( m_deviceSampleSource != 0 )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug ( "DSPDeviceSourceEngine::handleSetSource: set %s" , qPrintable ( source -> getDeviceDescription ()));
2016-10-04 01:49:28 +02:00
connect ( m_deviceSampleSource -> getSampleFifo (), SIGNAL ( dataReady ()), this , SLOT ( handleData ()), Qt :: QueuedConnection );
2015-10-15 04:05:19 +02:00
}
else
{
2016-10-08 10:35:07 +02:00
qDebug ( "DSPDeviceSourceEngine::handleSetSource: set none" );
2015-10-15 04:05:19 +02:00
}
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: handleData ()
2015-10-15 04:05:19 +02:00
{
if ( m_state == StRunning )
{
work ();
}
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: handleSynchronousMessages ()
2015-10-15 04:05:19 +02:00
{
Message * message = m_syncMessenger . getMessage ();
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::handleSynchronousMessages: " << message -> getIdentifier ();
2015-10-15 04:05:19 +02:00
2018-02-14 17:33:08 +01:00
if ( DSPAcquisitionInit :: match ( * message ))
2015-10-15 04:05:19 +02:00
{
m_state = gotoIdle ();
if ( m_state == StIdle ) {
m_state = gotoInit (); // State goes ready if init is performed
}
}
else if ( DSPAcquisitionStart :: match ( * message ))
{
if ( m_state == StReady ) {
m_state = gotoRunning ();
}
}
else if ( DSPAcquisitionStop :: match ( * message ))
{
m_state = gotoIdle ();
}
else if ( DSPGetSourceDeviceDescription :: match ( * message ))
{
(( DSPGetSourceDeviceDescription * ) message ) -> setDeviceDescription ( m_deviceDescription );
}
else if ( DSPGetErrorMessage :: match ( * message ))
{
(( DSPGetErrorMessage * ) message ) -> setErrorMessage ( m_errorMessage );
}
else if ( DSPSetSource :: match ( * message )) {
handleSetSource ((( DSPSetSource * ) message ) -> getSampleSource ());
}
2018-01-02 01:04:49 +01:00
else if ( DSPAddBasebandSampleSink :: match ( * message ))
2015-10-15 04:05:19 +02:00
{
2018-01-02 01:04:49 +01:00
BasebandSampleSink * sink = (( DSPAddBasebandSampleSink * ) message ) -> getSampleSink ();
2016-10-04 01:49:28 +02:00
m_basebandSampleSinks . push_back ( sink );
2018-01-02 16:25:34 +01:00
// initialize sample rate and center frequency in the sink:
DSPSignalNotification msg ( m_sampleRate , m_centerFrequency );
sink -> handleMessage ( msg );
// start the sink:
if ( m_state == StRunning ) {
sink -> start ();
}
2015-10-15 04:05:19 +02:00
}
2018-01-02 01:04:49 +01:00
else if ( DSPRemoveBasebandSampleSink :: match ( * message ))
2015-10-15 04:05:19 +02:00
{
2018-01-02 01:04:49 +01:00
BasebandSampleSink * sink = (( DSPRemoveBasebandSampleSink * ) message ) -> getSampleSink ();
2015-10-15 04:05:19 +02:00
if ( m_state == StRunning ) {
sink -> stop ();
}
2016-10-04 01:49:28 +02:00
m_basebandSampleSinks . remove ( sink );
2015-10-15 04:05:19 +02:00
}
2018-01-02 01:04:49 +01:00
else if ( DSPAddThreadedBasebandSampleSink :: match ( * message ))
2015-10-15 04:05:19 +02:00
{
2018-01-02 01:04:49 +01:00
ThreadedBasebandSampleSink * threadedSink = (( DSPAddThreadedBasebandSampleSink * ) message ) -> getThreadedSampleSink ();
2016-10-04 01:49:28 +02:00
m_threadedBasebandSampleSinks . push_back ( threadedSink );
2017-02-14 21:46:35 +01:00
// initialize sample rate and center frequency in the sink:
DSPSignalNotification msg ( m_sampleRate , m_centerFrequency );
threadedSink -> handleSinkMessage ( msg );
// start the sink:
2018-01-02 16:25:34 +01:00
if ( m_state == StRunning ) {
threadedSink -> start ();
}
2015-10-15 04:05:19 +02:00
}
2018-01-02 01:04:49 +01:00
else if ( DSPRemoveThreadedBasebandSampleSink :: match ( * message ))
2015-10-15 04:05:19 +02:00
{
2018-01-02 01:04:49 +01:00
ThreadedBasebandSampleSink * threadedSink = (( DSPRemoveThreadedBasebandSampleSink * ) message ) -> getThreadedSampleSink ();
2015-10-15 04:05:19 +02:00
threadedSink -> stop ();
2016-10-04 01:49:28 +02:00
m_threadedBasebandSampleSinks . remove ( threadedSink );
2015-10-15 04:05:19 +02:00
}
m_syncMessenger . done ( m_state );
}
2016-10-03 18:29:05 +02:00
void DSPDeviceSourceEngine :: handleInputMessages ()
2015-10-15 04:05:19 +02:00
{
Message * message ;
while (( message = m_inputMessageQueue . pop ()) != 0 )
{
2016-10-08 10:35:07 +02:00
qDebug ( "DSPDeviceSourceEngine::handleInputMessages: message: %s" , message -> getIdentifier ());
2015-10-15 04:05:19 +02:00
if ( DSPConfigureCorrection :: match ( * message ))
{
DSPConfigureCorrection * conf = ( DSPConfigureCorrection * ) message ;
m_iqImbalanceCorrection = conf -> getIQImbalanceCorrection ();
if ( m_dcOffsetCorrection != conf -> getDCOffsetCorrection ())
{
m_dcOffsetCorrection = conf -> getDCOffsetCorrection ();
m_iOffset = 0 ;
m_qOffset = 0 ;
}
if ( m_iqImbalanceCorrection != conf -> getIQImbalanceCorrection ())
{
m_iqImbalanceCorrection = conf -> getIQImbalanceCorrection ();
m_iRange = 1 << 16 ;
m_qRange = 1 << 16 ;
m_imbalance = 65536 ;
}
2018-02-16 01:23:49 +01:00
m_avgAmp . reset ();
m_avgII . reset ();
m_avgII2 . reset ();
m_avgIQ . reset ();
m_avgPhi . reset ();
m_avgQQ2 . reset ();
m_iBeta . reset ();
m_qBeta . reset ();
2015-10-15 04:05:19 +02:00
delete message ;
}
else if ( DSPSignalNotification :: match ( * message ))
{
DSPSignalNotification * notif = ( DSPSignalNotification * ) message ;
// update DSP values
m_sampleRate = notif -> getSampleRate ();
m_centerFrequency = notif -> getCenterFrequency ();
2019-01-04 10:49:47 +01:00
qDebug () << "DSPDeviceSourceEngine::handleInputMessages: DSPSignalNotification:"
<< " m_sampleRate: " << m_sampleRate
<< " m_centerFrequency: " << m_centerFrequency ;
2015-10-15 04:05:19 +02:00
2017-09-17 00:06:09 +02:00
// forward source changes to channel sinks with immediate execution (no queuing)
2015-10-15 04:05:19 +02:00
2016-10-04 01:49:28 +02:00
for ( BasebandSampleSinks :: const_iterator it = m_basebandSampleSinks . begin (); it != m_basebandSampleSinks . end (); it ++ )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::handleInputMessages: forward message to " << ( * it ) -> objectName (). toStdString (). c_str ();
2015-10-15 04:05:19 +02:00
( * it ) -> handleMessage ( * message );
}
2016-10-04 01:49:28 +02:00
for ( ThreadedBasebandSampleSinks :: const_iterator it = m_threadedBasebandSampleSinks . begin (); it != m_threadedBasebandSampleSinks . end (); ++ it )
2015-10-15 04:05:19 +02:00
{
2016-10-08 10:35:07 +02:00
qDebug () << "DSPDeviceSourceEngine::handleSourceMessages: forward message to ThreadedSampleSink(" << ( * it ) -> getSampleSinkObjectName (). toStdString (). c_str () << ")" ;
2015-10-15 04:05:19 +02:00
( * it ) -> handleSinkMessage ( * message );
}
2017-09-17 00:06:09 +02:00
// forward changes to source GUI input queue
2015-10-15 04:05:19 +02:00
2017-09-17 00:06:09 +02:00
MessageQueue * guiMessageQueue = m_deviceSampleSource -> getMessageQueueToGUI ();
2017-12-25 09:10:19 +01:00
qDebug ( "DSPDeviceSourceEngine::handleInputMessages: DSPSignalNotification: guiMessageQueue: %p" , guiMessageQueue );
2017-09-17 00:06:09 +02:00
if ( guiMessageQueue ) {
DSPSignalNotification * rep = new DSPSignalNotification ( * notif ); // make a copy for the source GUI
2019-01-04 10:49:47 +01:00
guiMessageQueue -> push ( rep );
2017-09-17 00:06:09 +02:00
}
//m_outputMessageQueue.push(rep);
2015-10-15 04:05:19 +02:00
delete message ;
}
}
}