2019-05-08 00:30:40 +02:00
///////////////////////////////////////////////////////////////////////////////////
2023-11-19 06:43:20 +01:00
// Copyright (C) 2016, 2019-2020, 2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// Copyright (C) 2022-2023 Jon Beniston, M7RCE <jon@beniston.com> //
2019-05-08 00:30:40 +02:00
// //
// 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 //
// (at your option) any later version. //
// //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "plugin/plugininterface.h"
2019-05-09 12:10:27 +02:00
#include "dsp/dspdevicesourceengine.h"
#include "dsp/dspdevicesinkengine.h"
2019-05-18 06:30:37 +02:00
#include "dsp/dspdevicemimoengine.h"
2019-05-08 00:30:40 +02:00
#include "dsp/dspengine.h"
#include "dsp/devicesamplesource.h"
#include "dsp/devicesamplesink.h"
2019-05-18 06:30:37 +02:00
#include "dsp/devicesamplemimo.h"
2019-05-08 00:30:40 +02:00
#include "settings/preset.h"
2019-05-09 17:27:12 +02:00
#include "channel/channelapi.h"
2023-08-24 15:51:50 +01:00
#include "util/simpleserializer.h"
2019-05-08 00:30:40 +02:00
#include "deviceapi.h"
2024-02-27 07:13:09 +08:00
#include <algorithm>
2019-05-08 00:30:40 +02:00
DeviceAPI :: DeviceAPI (
StreamType streamType ,
int deviceTabIndex ,
DSPDeviceSourceEngine * deviceSourceEngine ,
2019-05-18 06:30:37 +02:00
DSPDeviceSinkEngine * deviceSinkEngine ,
DSPDeviceMIMOEngine * deviceMIMOEngine
2019-05-08 00:30:40 +02:00
) :
m_streamType ( streamType ),
m_deviceTabIndex ( deviceTabIndex ),
2019-05-21 00:27:08 +02:00
m_deviceNbItems ( 1 ),
m_deviceItemIndex ( 0 ),
m_nbSourceStreams ( 0 ),
m_nbSinkStreams ( 0 ),
m_pluginInterface ( nullptr ),
2019-05-08 00:30:40 +02:00
m_masterTimer ( DSPEngine :: instance () -> getMasterTimer ()),
2019-05-08 22:11:53 +02:00
m_samplingDeviceSequence ( 0 ),
2022-05-13 22:24:48 +02:00
m_workspaceIndex ( 0 ),
2019-05-21 00:27:08 +02:00
m_buddySharedPtr ( nullptr ),
2019-05-08 00:30:40 +02:00
m_isBuddyLeader ( false ),
m_deviceSourceEngine ( deviceSourceEngine ),
2019-05-18 06:30:37 +02:00
m_deviceSinkEngine ( deviceSinkEngine ),
m_deviceMIMOEngine ( deviceMIMOEngine )
2019-05-08 00:30:40 +02:00
{
2022-08-27 10:18:17 +01:00
if ( m_deviceSourceEngine ) {
QObject :: connect ( m_deviceSourceEngine , & DSPDeviceSourceEngine :: stateChanged , this , & DeviceAPI :: engineStateChanged );
}
if ( m_deviceSinkEngine ) {
QObject :: connect ( m_deviceSinkEngine , & DSPDeviceSinkEngine :: stateChanged , this , & DeviceAPI :: engineStateChanged );
}
if ( m_deviceMIMOEngine ) {
QObject :: connect ( m_deviceMIMOEngine , & DSPDeviceMIMOEngine :: stateChanged , this , & DeviceAPI :: engineStateChanged );
}
2019-05-08 00:30:40 +02:00
}
2024-08-24 13:17:02 +02:00
DeviceAPI ::~ DeviceAPI () = default ;
2019-05-08 00:30:40 +02:00
2019-05-19 10:23:18 +02:00
void DeviceAPI :: setSpectrumSinkInput ( bool sourceElseSink , unsigned int index )
{
if ( m_deviceMIMOEngine ) { // In practice this is only used in the MIMO case
m_deviceMIMOEngine -> setSpectrumSinkInput ( sourceElseSink , index );
}
}
2019-11-23 07:39:57 +01:00
void DeviceAPI :: addChannelSink ( BasebandSampleSink * sink , int streamIndex )
{
if ( m_deviceSourceEngine ) {
m_deviceSourceEngine -> addSink ( sink );
} else if ( m_deviceMIMOEngine ) {
2020-09-07 00:13:27 +02:00
m_deviceMIMOEngine -> addChannelSink ( sink , streamIndex );
2019-11-23 07:39:57 +01:00
}
}
2024-11-25 17:16:08 +00:00
void DeviceAPI :: removeChannelSink ( BasebandSampleSink * sink , bool deleting , int streamIndex )
2019-11-23 07:39:57 +01:00
{
if ( m_deviceSourceEngine ) {
2024-11-25 17:16:08 +00:00
m_deviceSourceEngine -> removeSink ( sink , deleting );
2020-07-13 03:42:58 +02:00
} else if ( m_deviceMIMOEngine ) {
2020-09-07 00:13:27 +02:00
m_deviceMIMOEngine -> removeChannelSink ( sink , streamIndex );
2019-11-23 07:39:57 +01:00
}
}
2019-11-15 01:04:24 +01:00
void DeviceAPI :: addChannelSource ( BasebandSampleSource * source , int streamIndex )
2019-05-08 00:30:40 +02:00
{
if ( m_deviceSinkEngine ) {
2019-11-15 01:04:24 +01:00
m_deviceSinkEngine -> addChannelSource ( source );
2019-09-04 05:00:22 +02:00
} else if ( m_deviceMIMOEngine ) {
2019-11-17 01:56:54 +01:00
m_deviceMIMOEngine -> addChannelSource ( source , streamIndex );
2019-05-08 00:30:40 +02:00
}
}
2024-11-25 17:16:08 +00:00
void DeviceAPI :: removeChannelSource ( BasebandSampleSource * source , bool deleting , int streamIndex )
2019-05-08 00:30:40 +02:00
{
if ( m_deviceSinkEngine ) {
2024-11-25 17:16:08 +00:00
m_deviceSinkEngine -> removeChannelSource ( source , deleting );
2019-09-04 05:00:22 +02:00
} else if ( m_deviceMIMOEngine ) {
2024-11-25 17:16:08 +00:00
m_deviceMIMOEngine -> removeChannelSource ( source , deleting , streamIndex );
2019-09-04 05:00:22 +02:00
}
}
void DeviceAPI :: addMIMOChannel ( MIMOChannel * channel )
{
if ( m_deviceMIMOEngine ) {
m_deviceMIMOEngine -> addMIMOChannel ( channel );
}
}
void DeviceAPI :: removeMIMOChannel ( MIMOChannel * channel )
{
if ( m_deviceMIMOEngine ) {
m_deviceMIMOEngine -> removeMIMOChannel ( channel );
2019-05-08 00:30:40 +02:00
}
}
2019-12-23 23:41:35 +01:00
void DeviceAPI :: addChannelSinkAPI ( ChannelAPI * channelAPI )
2019-05-08 00:30:40 +02:00
{
m_channelSinkAPIs . append ( channelAPI );
renumerateChannels ();
}
2019-12-23 23:41:35 +01:00
void DeviceAPI :: removeChannelSinkAPI ( ChannelAPI * channelAPI )
2019-05-08 00:30:40 +02:00
{
if ( m_channelSinkAPIs . removeOne ( channelAPI )) {
renumerateChannels ();
}
channelAPI -> setIndexInDeviceSet ( - 1 );
}
2019-12-23 23:41:35 +01:00
void DeviceAPI :: addChannelSourceAPI ( ChannelAPI * channelAPI )
2019-05-08 00:30:40 +02:00
{
m_channelSourceAPIs . append ( channelAPI );
renumerateChannels ();
}
2019-12-23 23:41:35 +01:00
void DeviceAPI :: removeChannelSourceAPI ( ChannelAPI * channelAPI )
2019-05-08 00:30:40 +02:00
{
if ( m_channelSourceAPIs . removeOne ( channelAPI )) {
renumerateChannels ();
}
channelAPI -> setIndexInDeviceSet ( - 1 );
}
2019-09-04 05:00:22 +02:00
void DeviceAPI :: addMIMOChannelAPI ( ChannelAPI * channelAPI )
{
m_mimoChannelAPIs . append ( channelAPI );
2019-12-24 19:08:11 +01:00
renumerateChannels ();
2019-09-04 05:00:22 +02:00
}
void DeviceAPI :: removeMIMOChannelAPI ( ChannelAPI * channelAPI )
{
if ( m_mimoChannelAPIs . removeOne ( channelAPI )) {
renumerateChannels ();
}
2019-12-24 19:08:11 +01:00
channelAPI -> setIndexInDeviceSet ( - 1 );
2019-09-04 05:00:22 +02:00
}
2019-05-08 00:30:40 +02:00
void DeviceAPI :: setSampleSource ( DeviceSampleSource * source )
{
if ( m_deviceSourceEngine ) {
m_deviceSourceEngine -> setSource ( source );
}
}
void DeviceAPI :: setSampleSink ( DeviceSampleSink * sink )
{
if ( m_deviceSinkEngine ) {
m_deviceSinkEngine -> setSink ( sink );
}
}
2019-05-18 06:30:37 +02:00
void DeviceAPI :: setSampleMIMO ( DeviceSampleMIMO * mimo )
{
if ( m_deviceMIMOEngine ) {
m_deviceMIMOEngine -> setMIMO ( mimo );
}
}
2019-05-08 00:30:40 +02:00
DeviceSampleSource * DeviceAPI :: getSampleSource ()
{
if ( m_deviceSourceEngine ) {
return m_deviceSourceEngine -> getSource ();
} else {
return nullptr ;
}
}
DeviceSampleSink * DeviceAPI :: getSampleSink ()
{
if ( m_deviceSinkEngine ) {
return m_deviceSinkEngine -> getSink ();
} else {
return nullptr ;
}
}
2019-05-18 06:30:37 +02:00
DeviceSampleMIMO * DeviceAPI :: getSampleMIMO ()
{
if ( m_deviceMIMOEngine ) {
return m_deviceMIMOEngine -> getMIMO ();
} else {
return nullptr ;
}
}
2019-10-20 20:05:01 +02:00
bool DeviceAPI :: initDeviceEngine ( int subsystemIndex )
2019-05-08 00:30:40 +02:00
{
if ( m_deviceSourceEngine ) {
return m_deviceSourceEngine -> initAcquisition ();
} else if ( m_deviceSinkEngine ) {
return m_deviceSinkEngine -> initGeneration ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
2019-10-20 20:05:01 +02:00
return m_deviceMIMOEngine -> initProcess ( subsystemIndex );
2019-05-08 00:30:40 +02:00
} else {
2019-05-18 06:30:37 +02:00
return false ;
2019-05-08 00:30:40 +02:00
}
}
2019-10-20 20:05:01 +02:00
bool DeviceAPI :: startDeviceEngine ( int subsystemIndex )
2019-05-08 00:30:40 +02:00
{
if ( m_deviceSourceEngine ) {
return m_deviceSourceEngine -> startAcquisition ();
} else if ( m_deviceSinkEngine ) {
return m_deviceSinkEngine -> startGeneration ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
2019-10-20 20:05:01 +02:00
return m_deviceMIMOEngine -> startProcess ( subsystemIndex );
2019-05-08 00:30:40 +02:00
} else {
2019-05-18 06:30:37 +02:00
return false ;
2019-05-08 00:30:40 +02:00
}
}
2019-10-20 20:05:01 +02:00
void DeviceAPI :: stopDeviceEngine ( int subsystemIndex )
2019-05-08 00:30:40 +02:00
{
if ( m_deviceSourceEngine ) {
m_deviceSourceEngine -> stopAcquistion ();
} else if ( m_deviceSinkEngine ) {
m_deviceSinkEngine -> stopGeneration ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
2019-10-20 20:05:01 +02:00
m_deviceMIMOEngine -> stopProcess ( subsystemIndex );
2019-05-08 00:30:40 +02:00
}
}
2019-10-20 20:05:01 +02:00
DeviceAPI :: EngineState DeviceAPI :: state ( int subsystemIndex ) const
2019-05-08 00:30:40 +02:00
{
if ( m_deviceSourceEngine ) {
return ( DeviceAPI :: EngineState ) m_deviceSourceEngine -> state ();
} else if ( m_deviceSinkEngine ) {
return ( DeviceAPI :: EngineState ) m_deviceSinkEngine -> state ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
2019-10-20 20:05:01 +02:00
return ( DeviceAPI :: EngineState ) m_deviceMIMOEngine -> state ( subsystemIndex );
2019-05-08 00:30:40 +02:00
} else {
2019-05-18 06:30:37 +02:00
return StError ;
2019-05-08 00:30:40 +02:00
}
}
2024-08-24 13:17:02 +02:00
QString DeviceAPI :: errorMessage ( int subsystemIndex ) const
2019-05-08 00:30:40 +02:00
{
if ( m_deviceSourceEngine ) {
return m_deviceSourceEngine -> errorMessage ();
} else if ( m_deviceSinkEngine ) {
return m_deviceSinkEngine -> errorMessage ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
2019-10-20 20:05:01 +02:00
return m_deviceMIMOEngine -> errorMessage ( subsystemIndex );
2019-05-08 00:30:40 +02:00
} else {
2019-05-18 06:30:37 +02:00
return "Not implemented" ;
2019-05-08 00:30:40 +02:00
}
}
uint DeviceAPI :: getDeviceUID () const
{
if ( m_deviceSourceEngine ) {
return m_deviceSourceEngine -> getUID ();
} else if ( m_deviceSinkEngine ) {
return m_deviceSinkEngine -> getUID ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
return m_deviceMIMOEngine -> getUID ();
2019-05-08 00:30:40 +02:00
} else {
2019-05-18 06:30:37 +02:00
return 0 ;
2019-05-08 00:30:40 +02:00
}
}
MessageQueue * DeviceAPI :: getDeviceEngineInputMessageQueue ()
{
if ( m_deviceSourceEngine ) {
return m_deviceSourceEngine -> getInputMessageQueue ();
} else if ( m_deviceSinkEngine ) {
return m_deviceSinkEngine -> getInputMessageQueue ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
return m_deviceMIMOEngine -> getInputMessageQueue ();
2019-05-08 00:30:40 +02:00
} else {
2019-05-18 06:30:37 +02:00
return nullptr ;
2019-05-08 00:30:40 +02:00
}
}
MessageQueue * DeviceAPI :: getSamplingDeviceInputMessageQueue ()
{
if ( m_deviceSourceEngine ) {
return m_deviceSourceEngine -> getSource () -> getInputMessageQueue ();
} else if ( m_deviceSinkEngine ) {
return m_deviceSinkEngine -> getSink () -> getInputMessageQueue ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
return m_deviceMIMOEngine -> getMIMO () -> getInputMessageQueue ();
2019-05-08 00:30:40 +02:00
} else {
2019-05-18 06:30:37 +02:00
return nullptr ;
2019-05-08 00:30:40 +02:00
}
}
MessageQueue * DeviceAPI :: getSamplingDeviceGUIMessageQueue ()
{
if ( m_deviceSourceEngine ) {
return m_deviceSourceEngine -> getSource () -> getMessageQueueToGUI ();
} else if ( m_deviceSinkEngine ) {
return m_deviceSinkEngine -> getSink () -> getMessageQueueToGUI ();
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
return m_deviceMIMOEngine -> getMIMO () -> getMessageQueueToGUI ();
2019-05-08 00:30:40 +02:00
} else {
2019-05-18 06:30:37 +02:00
return nullptr ;
2019-05-08 00:30:40 +02:00
}
}
void DeviceAPI :: configureCorrections ( bool dcOffsetCorrection , bool iqImbalanceCorrection , int streamIndex )
{
if ( m_deviceSourceEngine ) {
m_deviceSourceEngine -> configureCorrections ( dcOffsetCorrection , iqImbalanceCorrection );
2019-05-18 06:30:37 +02:00
} else if ( m_deviceMIMOEngine ) {
m_deviceMIMOEngine -> configureCorrections ( dcOffsetCorrection , iqImbalanceCorrection , streamIndex );
2019-05-08 00:30:40 +02:00
}
}
void DeviceAPI :: setHardwareId ( const QString & id )
{
m_hardwareId = id ;
}
2019-05-21 00:27:08 +02:00
void DeviceAPI :: setDeviceNbItems ( uint32_t nbItems )
2019-05-08 00:30:40 +02:00
{
2019-05-21 00:27:08 +02:00
m_deviceNbItems = nbItems ;
2019-05-08 00:30:40 +02:00
}
2019-05-21 00:27:08 +02:00
void DeviceAPI :: setDeviceItemIndex ( uint32_t index )
2019-05-08 00:30:40 +02:00
{
2019-05-21 00:27:08 +02:00
m_deviceItemIndex = index ;
2019-05-08 00:30:40 +02:00
}
void DeviceAPI :: setSamplingDevicePluginInterface ( PluginInterface * iface )
{
2024-08-24 13:17:02 +02:00
m_pluginInterface = iface ;
2019-05-08 00:30:40 +02:00
}
2024-08-24 13:17:02 +02:00
void DeviceAPI :: getDeviceEngineStateStr ( QString & state , int subsystemIndex ) const
2019-05-08 00:30:40 +02:00
{
if ( m_deviceSourceEngine )
{
switch ( m_deviceSourceEngine -> state ())
{
2024-08-24 13:17:02 +02:00
case DSPDeviceSourceEngine :: State :: StNotStarted :
2019-05-08 00:30:40 +02:00
state = "notStarted" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceSourceEngine :: State :: StIdle :
2019-05-08 00:30:40 +02:00
state = "idle" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceSourceEngine :: State :: StReady :
2019-05-08 00:30:40 +02:00
state = "ready" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceSourceEngine :: State :: StRunning :
2019-05-08 00:30:40 +02:00
state = "running" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceSourceEngine :: State :: StError :
2019-05-08 00:30:40 +02:00
state = "error" ;
break ;
default :
state = "notStarted" ;
break ;
}
}
else if ( m_deviceSinkEngine )
{
switch ( m_deviceSinkEngine -> state ())
{
2024-08-24 13:17:02 +02:00
case DSPDeviceSinkEngine :: State :: StNotStarted :
2019-05-08 00:30:40 +02:00
state = "notStarted" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceSinkEngine :: State :: StIdle :
2019-05-08 00:30:40 +02:00
state = "idle" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceSinkEngine :: State :: StReady :
2019-05-08 00:30:40 +02:00
state = "ready" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceSinkEngine :: State :: StRunning :
2019-05-08 00:30:40 +02:00
state = "running" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceSinkEngine :: State :: StError :
2019-05-08 00:30:40 +02:00
state = "error" ;
break ;
default :
state = "notStarted" ;
break ;
}
}
2019-12-23 18:49:06 +01:00
else if ( m_deviceMIMOEngine )
{
switch ( m_deviceMIMOEngine -> state ( subsystemIndex ))
{
2024-08-24 13:17:02 +02:00
case DSPDeviceMIMOEngine :: State :: StNotStarted :
2019-12-23 18:49:06 +01:00
state = "notStarted" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceMIMOEngine :: State :: StIdle :
2019-12-23 18:49:06 +01:00
state = "idle" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceMIMOEngine :: State :: StReady :
2019-12-23 18:49:06 +01:00
state = "ready" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceMIMOEngine :: State :: StRunning :
2019-12-23 18:49:06 +01:00
state = "running" ;
break ;
2024-08-24 13:17:02 +02:00
case DSPDeviceMIMOEngine :: State :: StError :
2019-12-23 18:49:06 +01:00
state = "error" ;
break ;
default :
state = "notStarted" ;
break ;
}
}
2019-05-08 00:30:40 +02:00
else
{
state = "notStarted" ;
}
}
2019-12-23 18:49:06 +01:00
ChannelAPI * DeviceAPI :: getChanelSinkAPIAt ( int index )
2019-05-08 00:30:40 +02:00
{
2019-12-23 18:49:06 +01:00
if ( index < m_channelSinkAPIs . size ()) {
return m_channelSinkAPIs . at ( index );
} else {
2019-05-08 00:30:40 +02:00
return nullptr ;
}
}
2019-12-23 18:49:06 +01:00
ChannelAPI * DeviceAPI :: getChanelSourceAPIAt ( int index )
2019-05-08 00:30:40 +02:00
{
2019-12-23 18:49:06 +01:00
if ( index < m_channelSourceAPIs . size ()) {
return m_channelSourceAPIs . at ( index );
} else {
return nullptr ;
2019-05-08 00:30:40 +02:00
}
2019-12-23 18:49:06 +01:00
}
ChannelAPI * DeviceAPI :: getMIMOChannelAPIAt ( int index )
{
if ( index < m_mimoChannelAPIs . size ()) {
return m_mimoChannelAPIs . at ( index );
} else {
2019-05-08 00:30:40 +02:00
return nullptr ;
}
}
2023-08-24 15:51:50 +01:00
QList < quint64 > DeviceAPI :: getCenterFrequency () const
{
QList < quint64 > frequencies ;
if ( m_deviceSourceEngine && m_deviceSourceEngine -> getSource ())
{
frequencies . append ( m_deviceSourceEngine -> getSource () -> getCenterFrequency ());
}
else if ( m_deviceSinkEngine && m_deviceSinkEngine -> getSink ())
{
frequencies . append ( m_deviceSinkEngine -> getSink () -> getCenterFrequency ());
}
else if ( m_deviceMIMOEngine && m_deviceMIMOEngine -> getMIMO ())
{
2023-08-24 16:05:57 +01:00
for ( uint32_t i = 0 ; i < m_deviceMIMOEngine -> getMIMO () -> getNbSourceStreams (); i ++ ) {
2023-08-24 15:51:50 +01:00
frequencies . append ( m_deviceMIMOEngine -> getMIMO () -> getSourceCenterFrequency ( i ));
}
2023-08-24 16:05:57 +01:00
for ( uint32_t i = 0 ; i < m_deviceMIMOEngine -> getMIMO () -> getNbSinkStreams (); i ++ ) {
2023-08-24 15:51:50 +01:00
frequencies . append ( m_deviceMIMOEngine -> getMIMO () -> getSinkCenterFrequency ( i ));
}
}
return frequencies ;
}
void DeviceAPI :: setCenterFrequency ( QList < quint64 > centerFrequency )
{
if ( m_deviceSourceEngine && m_deviceSourceEngine -> getSource ())
{
m_deviceSourceEngine -> getSource () -> setCenterFrequency ( centerFrequency [ 0 ]);
}
else if ( m_deviceSinkEngine && m_deviceSinkEngine -> getSink ())
{
m_deviceSinkEngine -> getSink () -> setCenterFrequency ( centerFrequency [ 0 ]);
}
else if ( m_deviceMIMOEngine && m_deviceMIMOEngine -> getMIMO ())
{
int idx = 0 ;
2023-08-24 16:05:57 +01:00
for ( uint32_t i = 0 ; i < m_deviceMIMOEngine -> getMIMO () -> getNbSourceStreams (); i ++ , idx ++ ) {
2023-08-24 15:51:50 +01:00
m_deviceMIMOEngine -> getMIMO () -> setSourceCenterFrequency ( centerFrequency [ idx ], i );
}
2023-08-24 16:05:57 +01:00
for ( uint32_t i = 0 ; i < m_deviceMIMOEngine -> getMIMO () -> getNbSinkStreams (); i ++ , idx ++ ) {
2023-08-24 15:51:50 +01:00
m_deviceMIMOEngine -> getMIMO () -> setSinkCenterFrequency ( centerFrequency [ idx ], i );
}
}
}
// Serialization is only currently used for saving device settings as part of a Device preset
// loadSamplingDeviceSettings/saveSamplingDeviceSettings is used for Device Set presets (which includes channel settings)
QByteArray DeviceAPI :: serialize () const
{
SimpleSerializer s ( 1 );
if ( m_deviceSourceEngine && m_deviceSourceEngine -> getSource ()) {
s . writeBlob ( 1 , m_deviceSourceEngine -> getSource () -> serialize ());
}
if ( m_deviceSinkEngine && m_deviceSinkEngine -> getSink ()) {
s . writeBlob ( 2 , m_deviceSinkEngine -> getSink () -> serialize ());
}
if ( m_deviceMIMOEngine && m_deviceMIMOEngine -> getMIMO ()) {
s . writeBlob ( 3 , m_deviceMIMOEngine -> getMIMO () -> serialize ());
}
s . writeList < quint64 > ( 4 , getCenterFrequency ());
return s . final ();
}
bool DeviceAPI :: deserialize ( const QByteArray & data )
{
SimpleDeserializer d ( data );
if ( ! d . isValid ()) {
return false ;
}
if ( d . getVersion () == 1 )
{
2024-08-24 13:17:02 +02:00
QByteArray bdata ;
2023-08-24 15:51:50 +01:00
QList < quint64 > centerFrequency ;
if ( m_deviceSourceEngine && m_deviceSourceEngine -> getSource ())
{
2024-08-24 13:17:02 +02:00
d . readBlob ( 1 , & bdata );
2024-10-07 09:34:23 +01:00
if ( bdata . size () > 0 ) {
m_deviceSourceEngine -> getSource () -> deserialize ( bdata );
2023-08-24 15:51:50 +01:00
}
}
if ( m_deviceSinkEngine && m_deviceSinkEngine -> getSink ())
{
2024-08-24 13:17:02 +02:00
d . readBlob ( 2 , & bdata );
2024-10-07 09:34:23 +01:00
if ( bdata . size () > 0 ) {
m_deviceSinkEngine -> getSink () -> deserialize ( bdata );
2023-08-24 15:51:50 +01:00
}
}
if ( m_deviceMIMOEngine && m_deviceMIMOEngine -> getMIMO ())
{
2024-08-24 13:17:02 +02:00
d . readBlob ( 3 , & bdata );
2024-10-07 09:34:23 +01:00
if ( bdata . size () > 0 ) {
m_deviceMIMOEngine -> getMIMO () -> deserialize ( bdata );
2023-08-24 15:51:50 +01:00
}
}
d . readList < quint64 > ( 4 , & centerFrequency );
setCenterFrequency ( centerFrequency );
2023-08-24 16:05:57 +01:00
return true ;
2023-08-24 15:51:50 +01:00
}
else
{
return false ;
}
}
2019-05-08 00:30:40 +02:00
void DeviceAPI :: loadSamplingDeviceSettings ( const Preset * preset )
{
if ( m_deviceSourceEngine && ( preset -> isSourcePreset ()))
{
2019-09-13 13:40:31 +02:00
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: Loading Rx preset [%s | %s]" , qPrintable ( preset -> getGroup ()), qPrintable ( preset -> getDescription ()));
2019-05-08 00:30:40 +02:00
2019-05-08 22:11:53 +02:00
const QByteArray * sourceConfig = preset -> findBestDeviceConfig ( m_samplingDeviceId , m_samplingDeviceSerial , m_samplingDeviceSequence );
2019-05-08 00:30:40 +02:00
qint64 centerFrequency = preset -> getCenterFrequency ();
2019-09-13 13:40:31 +02:00
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: source center frequency: %llu Hz" , centerFrequency );
2019-05-08 00:30:40 +02:00
2019-09-13 13:40:31 +02:00
if ( sourceConfig )
2019-05-08 00:30:40 +02:00
{
2019-05-08 22:11:53 +02:00
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: deserializing source %s[%d]: %s" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
2019-05-08 00:30:40 +02:00
2024-08-24 13:17:02 +02:00
if ( m_deviceSourceEngine -> getSource () != nullptr ) // Server flavor
2019-05-08 00:30:40 +02:00
{
m_deviceSourceEngine -> getSource () -> deserialize ( * sourceConfig );
}
else
{
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: deserializing no source" );
}
}
else
{
2019-05-08 22:11:53 +02:00
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: source %s[%d]: %s not found" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
2019-05-08 00:30:40 +02:00
}
// set center frequency anyway
2020-11-10 19:09:44 +01:00
if ( m_deviceSourceEngine -> getSource ())
2019-05-08 00:30:40 +02:00
{
m_deviceSourceEngine -> getSource () -> setCenterFrequency ( centerFrequency );
}
else
{
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: no source" );
}
}
2019-09-13 13:40:31 +02:00
else if ( m_deviceSinkEngine && preset -> isSinkPreset ())
2019-05-08 00:30:40 +02:00
{
2019-09-13 13:40:31 +02:00
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: Loading Tx preset [%s | %s]" , qPrintable ( preset -> getGroup ()), qPrintable ( preset -> getDescription ()));
2019-05-08 00:30:40 +02:00
2019-05-08 22:11:53 +02:00
const QByteArray * sinkConfig = preset -> findBestDeviceConfig ( m_samplingDeviceId , m_samplingDeviceSerial , m_samplingDeviceSequence );
2019-05-08 00:30:40 +02:00
qint64 centerFrequency = preset -> getCenterFrequency ();
2019-09-13 13:40:31 +02:00
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: sink center frequency: %llu Hz" , centerFrequency );
2019-05-08 00:30:40 +02:00
2019-09-13 13:40:31 +02:00
if ( sinkConfig )
2019-05-08 00:30:40 +02:00
{
2019-05-08 22:11:53 +02:00
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: deserializing sink %s[%d]: %s" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
2019-05-08 00:30:40 +02:00
2020-11-10 19:09:44 +01:00
if ( m_deviceSinkEngine -> getSink ())
2019-05-08 00:30:40 +02:00
{
m_deviceSinkEngine -> getSink () -> deserialize ( * sinkConfig );
m_deviceSinkEngine -> getSink () -> setCenterFrequency ( centerFrequency );
}
else
{
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: no sink" );
}
}
else
{
2019-05-08 22:11:53 +02:00
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: sink %s[%d]: %s not found" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
2019-05-08 00:30:40 +02:00
}
}
2019-09-13 13:40:31 +02:00
else if ( m_deviceMIMOEngine && preset -> isMIMOPreset ())
{
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: Loading MIMO preset [%s | %s]" , qPrintable ( preset -> getGroup ()), qPrintable ( preset -> getDescription ()));
const QByteArray * mimoConfig = preset -> findBestDeviceConfig ( m_samplingDeviceId , m_samplingDeviceSerial , m_samplingDeviceSequence );
qint64 centerFrequency = preset -> getCenterFrequency ();
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: MIMO center frequency: %llu Hz" , centerFrequency );
if ( mimoConfig )
{
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: deserializing MIMO %s[%d]: %s" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
2020-11-10 19:09:44 +01:00
if ( m_deviceMIMOEngine -> getMIMO ())
2019-09-13 13:40:31 +02:00
{
2020-11-10 19:09:44 +01:00
m_deviceMIMOEngine -> getMIMO () -> deserialize ( * mimoConfig );
m_deviceMIMOEngine -> getMIMO () -> setSourceCenterFrequency ( centerFrequency , 0 );
m_deviceMIMOEngine -> getMIMO () -> setSinkCenterFrequency ( centerFrequency , 0 );
2019-09-13 13:40:31 +02:00
}
else
{
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: no MIMO" );
}
}
else
{
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: MIMO %s[%d]: %s not found" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
}
}
2019-05-08 00:30:40 +02:00
else
{
qDebug ( "DeviceAPI::loadSamplingDeviceSettings: Loading preset [%s | %s] is not a suitable preset" , qPrintable ( preset -> getGroup ()), qPrintable ( preset -> getDescription ()));
}
}
void DeviceAPI :: saveSamplingDeviceSettings ( Preset * preset )
{
if ( m_deviceSourceEngine && ( preset -> isSourcePreset ()))
{
2019-05-08 22:11:53 +02:00
qDebug ( "DeviceAPI::saveSamplingDeviceSettings: serializing source %s[%d]: %s" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
2019-05-08 00:30:40 +02:00
2020-10-03 06:58:57 +02:00
if ( m_deviceSourceEngine -> getSource ()) // Server flavor
2019-05-08 00:30:40 +02:00
{
2019-05-08 22:11:53 +02:00
preset -> addOrUpdateDeviceConfig ( m_samplingDeviceId , m_samplingDeviceSerial , m_samplingDeviceSequence , m_deviceSourceEngine -> getSource () -> serialize ());
2019-05-08 00:30:40 +02:00
preset -> setCenterFrequency ( m_deviceSourceEngine -> getSource () -> getCenterFrequency ());
}
else
{
qDebug ( "DeviceAPI::saveSamplingDeviceSettings: no source" );
}
}
2019-09-13 13:40:31 +02:00
else if ( m_deviceSinkEngine && preset -> isSinkPreset ())
2019-05-08 00:30:40 +02:00
{
2019-05-08 22:11:53 +02:00
qDebug ( "DeviceAPI::saveSamplingDeviceSettings: serializing sink %s[%d]: %s" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
2019-05-08 00:30:40 +02:00
2020-10-03 06:58:57 +02:00
if ( m_deviceSinkEngine -> getSink ()) // Server flavor
2019-05-08 00:30:40 +02:00
{
2019-05-08 22:11:53 +02:00
preset -> addOrUpdateDeviceConfig ( m_samplingDeviceId , m_samplingDeviceSerial , m_samplingDeviceSequence , m_deviceSinkEngine -> getSink () -> serialize ());
2019-05-08 00:30:40 +02:00
preset -> setCenterFrequency ( m_deviceSinkEngine -> getSink () -> getCenterFrequency ());
}
else
{
qDebug ( "DeviceAPI::saveSamplingDeviceSettings: no sink" );
}
}
2019-09-13 13:40:31 +02:00
else if ( m_deviceMIMOEngine && preset -> isMIMOPreset ())
{
qDebug ( "DeviceAPI::saveSamplingDeviceSettings: serializing MIMO %s[%d]: %s" ,
qPrintable ( m_samplingDeviceId ), m_samplingDeviceSequence , qPrintable ( m_samplingDeviceSerial ));
2020-10-03 06:58:57 +02:00
if ( m_deviceMIMOEngine -> getMIMO ()) // Server flavor
2019-09-13 13:40:31 +02:00
{
preset -> addOrUpdateDeviceConfig ( m_samplingDeviceId , m_samplingDeviceSerial , m_samplingDeviceSequence , m_deviceMIMOEngine -> getMIMO () -> serialize ());
preset -> setCenterFrequency ( m_deviceMIMOEngine -> getMIMO () -> getMIMOCenterFrequency ());
}
else
{
qDebug ( "DeviceAPI::saveSamplingDeviceSettings: no MIMO" );
}
}
2019-05-08 00:30:40 +02:00
else
{
qDebug ( "DeviceAPI::saveSamplingDeviceSettings: not a suitable preset" );
}
}
2024-02-27 07:13:09 +08:00
void DeviceAPI :: addBuddy ( DeviceAPI * buddy )
2019-05-08 00:30:40 +02:00
{
2024-02-27 07:13:09 +08:00
if ( buddy -> m_streamType == StreamSingleRx )
2019-05-08 00:30:40 +02:00
{
2024-02-27 07:13:09 +08:00
m_sourceBuddies . push_back ( buddy ); // this is a source
2019-05-08 00:30:40 +02:00
}
2024-02-27 07:13:09 +08:00
else if ( buddy -> m_streamType == StreamSingleTx )
{
m_sinkBuddies . push_back ( buddy ); // this is a sink
2019-05-08 00:30:40 +02:00
}
2024-02-27 07:13:09 +08:00
else
2019-05-08 00:30:40 +02:00
{
2024-02-27 07:13:09 +08:00
qDebug ( "DeviceAPI::addBuddy: not relevant if buddy is not a single Rx or Tx" );
2019-05-08 00:30:40 +02:00
return ;
}
if ( m_streamType == StreamSingleRx ) {
buddy -> m_sourceBuddies . push_back ( this ); // this is a source
} else if ( m_streamType == StreamSingleTx ) {
buddy -> m_sinkBuddies . push_back ( this ); // this is a sink
} else {
2024-02-27 07:13:09 +08:00
qDebug ( "DeviceAPI::addBuddy: not relevant if this is not a single Rx or Tx" );
2019-05-08 00:30:40 +02:00
return ;
}
2024-02-27 07:13:09 +08:00
qDebug ( "DeviceAPI::addBuddy: added buddy %s(%s) [%llu] <-> [%llu]" ,
2019-05-08 00:30:40 +02:00
qPrintable ( buddy -> getHardwareId ()),
qPrintable ( buddy -> getSamplingDeviceSerial ()),
( quint64 ) buddy ,
( quint64 ) this );
}
2024-02-27 07:13:09 +08:00
void DeviceAPI :: removeBuddy ( DeviceAPI * buddy )
2019-05-08 00:30:40 +02:00
{
2024-02-27 07:13:09 +08:00
switch ( buddy -> m_streamType ) {
case StreamSingleRx :
2026-08-01 16:44:34 -04:00
{
auto it = std :: find ( m_sourceBuddies . begin (), m_sourceBuddies . end (), buddy );
if ( it != m_sourceBuddies . end ())
{
m_sourceBuddies . erase ( it );
}
2024-02-27 07:13:09 +08:00
break ;
2026-08-01 16:44:34 -04:00
}
2024-02-27 07:13:09 +08:00
case StreamSingleTx :
2026-08-01 16:44:34 -04:00
{
auto it = std :: find ( m_sinkBuddies . begin (), m_sinkBuddies . end (), buddy );
if ( it != m_sinkBuddies . end ())
{
m_sinkBuddies . erase ( it );
}
2024-02-27 07:13:09 +08:00
break ;
2026-08-01 16:44:34 -04:00
}
2024-02-27 07:13:09 +08:00
default :
2026-08-01 16:44:34 -04:00
qDebug ( "DeviceAPI::removeBuddy: buddy %s(%s) is not of single Rx or Tx type" ,
2019-05-08 00:30:40 +02:00
qPrintable ( buddy -> getHardwareId ()),
qPrintable ( buddy -> getSamplingDeviceSerial ()));
return ;
}
}
void DeviceAPI :: clearBuddiesLists ()
{
2026-08-01 17:06:39 -04:00
// Make copies before iterating because removeBuddy() modifies the buddy
// relationship lists. Iterating directly over m_sourceBuddies/m_sinkBuddies
// could invalidate iterators while the relationships are being removed.
auto sourceCopy = m_sourceBuddies ;
auto sinkCopy = m_sinkBuddies ;
2019-05-08 00:30:40 +02:00
bool leaderElected = false ;
2026-08-01 17:06:39 -04:00
for ( auto * buddy : sourceCopy )
2019-05-08 00:30:40 +02:00
{
if ( isBuddyLeader () && ! leaderElected )
{
2026-08-01 17:06:39 -04:00
buddy -> setBuddyLeader ( true );
2019-05-08 00:30:40 +02:00
leaderElected = true ;
}
2026-08-01 17:06:39 -04:00
buddy -> removeBuddy ( this );
2019-05-08 00:30:40 +02:00
}
m_sourceBuddies . clear ();
2026-08-01 17:06:39 -04:00
for ( auto * buddy : sinkCopy )
2019-05-08 00:30:40 +02:00
{
if ( isBuddyLeader () && ! leaderElected )
{
2026-08-01 17:06:39 -04:00
buddy -> setBuddyLeader ( true );
2019-05-08 00:30:40 +02:00
leaderElected = true ;
}
2026-08-01 17:06:39 -04:00
buddy -> removeBuddy ( this );
2019-05-08 00:30:40 +02:00
}
m_sinkBuddies . clear ();
}
void DeviceAPI :: renumerateChannels ()
{
if ( m_streamType == StreamSingleRx )
{
for ( int i = 0 ; i < m_channelSinkAPIs . size (); ++ i )
{
m_channelSinkAPIs . at ( i ) -> setIndexInDeviceSet ( i );
m_channelSinkAPIs . at ( i ) -> setDeviceSetIndex ( m_deviceTabIndex );
2019-05-09 17:27:12 +02:00
m_channelSinkAPIs . at ( i ) -> setDeviceAPI ( this );
2019-05-08 00:30:40 +02:00
}
}
else if ( m_streamType == StreamSingleTx )
{
for ( int i = 0 ; i < m_channelSourceAPIs . size (); ++ i )
{
m_channelSourceAPIs . at ( i ) -> setIndexInDeviceSet ( i );
m_channelSourceAPIs . at ( i ) -> setDeviceSetIndex ( m_deviceTabIndex );
2019-05-09 17:27:12 +02:00
m_channelSourceAPIs . at ( i ) -> setDeviceAPI ( this );
2019-05-08 00:30:40 +02:00
}
}
2019-09-04 05:00:22 +02:00
else if ( m_streamType == StreamMIMO )
{
2019-12-23 23:00:11 +01:00
int index = 0 ;
for (; index < m_channelSinkAPIs . size (); ++ index )
{
m_channelSinkAPIs . at ( index ) -> setIndexInDeviceSet ( index );
m_channelSinkAPIs . at ( index ) -> setDeviceSetIndex ( m_deviceTabIndex );
m_channelSinkAPIs . at ( index ) -> setDeviceAPI ( this );
}
for (; index < m_channelSourceAPIs . size () + m_channelSinkAPIs . size (); ++ index )
{
2020-07-13 04:12:15 +02:00
int sourceIndex = index - m_channelSinkAPIs . size ();
m_channelSourceAPIs . at ( sourceIndex ) -> setIndexInDeviceSet ( index );
m_channelSourceAPIs . at ( sourceIndex ) -> setDeviceSetIndex ( m_deviceTabIndex );
m_channelSourceAPIs . at ( sourceIndex ) -> setDeviceAPI ( this );
2019-12-23 23:00:11 +01:00
}
for (; index < m_mimoChannelAPIs . size () + m_channelSourceAPIs . size () + m_channelSinkAPIs . size (); ++ index )
2019-09-04 05:00:22 +02:00
{
2020-07-13 04:12:15 +02:00
int mimoIndex = index - m_channelSourceAPIs . size () - m_channelSinkAPIs . size ();
m_mimoChannelAPIs . at ( mimoIndex ) -> setIndexInDeviceSet ( index );
m_mimoChannelAPIs . at ( mimoIndex ) -> setDeviceSetIndex ( m_deviceTabIndex );
m_mimoChannelAPIs . at ( mimoIndex ) -> setDeviceAPI ( this );
2019-09-04 05:00:22 +02:00
}
}
2020-10-03 06:58:57 +02:00
}
2022-04-12 16:20:45 +02:00
void DeviceAPI :: setDeviceSetIndex ( int deviceSetIndex )
{
m_deviceTabIndex = deviceSetIndex ;
renumerateChannels ();
}
2022-08-27 10:18:17 +01:00
void DeviceAPI :: engineStateChanged ()
{
emit stateChanged ( this );
}