2015-09-24 02:50:24 +02:00
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
// //
// 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 06:57:41 +02:00
// (at your option) any later version. //
2015-09-24 02:50:24 +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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <errno.h>
2018-12-26 11:29:20 +01:00
2015-09-24 02:50:24 +02:00
#include <QDebug>
2018-12-26 11:29:20 +01:00
#include <QNetworkReply>
#include <QBuffer>
2015-09-24 02:50:24 +02:00
2017-12-10 01:57:50 +01:00
#include "SWGDeviceSettings.h"
#include "SWGDeviceState.h"
2015-09-24 02:50:24 +02:00
#include "util/simpleserializer.h"
#include "dsp/dspcommands.h"
2015-09-27 12:50:38 +02:00
#include "dsp/dspengine.h"
2017-09-04 23:49:51 +02:00
#include "dsp/filerecord.h"
2019-05-08 22:11:53 +02:00
#include "device/deviceapi.h"
2017-01-08 02:48:01 +01:00
#include "hackrf/devicehackrfvalues.h"
2017-07-21 00:44:30 +02:00
#include "hackrf/devicehackrfshared.h"
2016-10-11 01:17:55 +02:00
2018-12-26 11:29:20 +01:00
#include "hackrfinput.h"
2017-01-07 11:24:09 +01:00
#include "hackrfinputthread.h"
2015-09-24 02:50:24 +02:00
2015-09-27 07:37:15 +02:00
MESSAGE_CLASS_DEFINITION ( HackRFInput :: MsgConfigureHackRF , Message )
2015-09-24 02:50:24 +02:00
MESSAGE_CLASS_DEFINITION ( HackRFInput :: MsgReportHackRF , Message )
2017-09-04 23:49:51 +02:00
MESSAGE_CLASS_DEFINITION ( HackRFInput :: MsgFileRecord , Message )
2017-12-14 18:02:49 +01:00
MESSAGE_CLASS_DEFINITION ( HackRFInput :: MsgStartStop , Message )
2015-09-24 02:50:24 +02:00
2019-05-08 22:11:53 +02:00
HackRFInput :: HackRFInput ( DeviceAPI * deviceAPI ) :
2016-05-16 02:14:36 +02:00
m_deviceAPI ( deviceAPI ),
2015-09-24 02:50:24 +02:00
m_settings (),
m_dev ( 0 ),
2015-09-27 07:37:15 +02:00
m_hackRFThread ( 0 ),
2017-04-14 00:14:40 +02:00
m_deviceDescription ( "HackRF" ),
m_running ( false )
2015-09-24 02:50:24 +02:00
{
2017-04-14 00:14:40 +02:00
openDevice ();
2017-09-04 23:49:51 +02:00
2018-05-08 11:03:09 +02:00
m_fileSink = new FileRecord ( QString ( "test_%1.sdriq" ). arg ( m_deviceAPI -> getDeviceUID ()));
2019-05-08 22:11:53 +02:00
m_deviceAPI -> addAncillarySink ( m_fileSink );
2017-09-04 23:49:51 +02:00
2017-01-08 00:33:11 +01:00
m_deviceAPI -> setBuddySharedPtr ( & m_sharedParams );
2018-12-26 11:29:20 +01:00
m_networkManager = new QNetworkAccessManager ();
connect ( m_networkManager , SIGNAL ( finished ( QNetworkReply * )), this , SLOT ( networkManagerFinished ( QNetworkReply * )));
2015-09-24 02:50:24 +02:00
}
HackRFInput ::~ HackRFInput ()
{
2018-12-26 11:29:20 +01:00
disconnect ( m_networkManager , SIGNAL ( finished ( QNetworkReply * )), this , SLOT ( networkManagerFinished ( QNetworkReply * )));
delete m_networkManager ;
if ( m_running ) {
stop ();
}
2019-05-08 22:11:53 +02:00
m_deviceAPI -> removeAncillarySink ( m_fileSink );
2017-09-04 23:49:51 +02:00
delete m_fileSink ;
2017-04-14 00:14:40 +02:00
closeDevice ();
2017-01-08 00:33:11 +01:00
m_deviceAPI -> setBuddySharedPtr ( 0 );
2015-09-24 02:50:24 +02:00
}
2017-09-15 02:32:30 +02:00
void HackRFInput :: destroy ()
{
delete this ;
}
2017-04-14 00:14:40 +02:00
bool HackRFInput :: openDevice ()
2015-09-24 02:50:24 +02:00
{
2017-01-08 00:33:11 +01:00
if ( m_dev != 0 )
{
2017-04-14 00:14:40 +02:00
closeDevice ();
2017-01-08 00:33:11 +01:00
}
2017-04-14 00:14:40 +02:00
if ( ! m_sampleFifo . setSize ( 1 << 19 ))
{
qCritical ( "HackRFInput::start: could not allocate SampleFifo" );
return false ;
}
2015-09-24 02:50:24 +02:00
2017-01-08 00:33:11 +01:00
if ( m_deviceAPI -> getSinkBuddies (). size () > 0 )
{
2019-05-08 22:11:53 +02:00
DeviceAPI * buddy = m_deviceAPI -> getSinkBuddies ()[ 0 ];
2017-01-08 00:33:11 +01:00
DeviceHackRFParams * buddySharedParams = ( DeviceHackRFParams * ) buddy -> getBuddySharedPtr ();
if ( buddySharedParams == 0 )
{
2017-04-14 00:14:40 +02:00
qCritical ( "HackRFInput::openDevice: could not get shared parameters from buddy" );
2017-01-08 00:33:11 +01:00
return false ;
}
2017-04-14 01:41:02 +02:00
if ( buddySharedParams -> m_dev == 0 ) // device is not opened by buddy
2017-01-08 00:33:11 +01:00
{
2017-04-14 01:41:02 +02:00
qCritical ( "HackRFInput::openDevice: could not get HackRF handle from buddy" );
return false ;
2017-01-08 00:33:11 +01:00
}
2017-04-14 01:41:02 +02:00
m_sharedParams = * ( buddySharedParams ); // copy parameters from buddy
m_dev = m_sharedParams . m_dev ; // get HackRF handle
2017-01-08 00:33:11 +01:00
}
2017-04-14 01:41:02 +02:00
else
2017-01-08 00:33:11 +01:00
{
2019-05-08 22:11:53 +02:00
if (( m_dev = DeviceHackRF :: open_hackrf ( qPrintable ( m_deviceAPI -> getSamplingDeviceSerial ()))) == 0 )
2017-01-08 00:33:11 +01:00
{
2019-05-08 22:11:53 +02:00
qCritical ( "HackRFInput::openDevice: could not open HackRF %s" , qPrintable ( m_deviceAPI -> getSamplingDeviceSerial ()));
2017-01-08 00:33:11 +01:00
return false ;
}
m_sharedParams . m_dev = m_dev ;
}
2015-09-24 02:50:24 +02:00
2017-04-14 00:14:40 +02:00
return true ;
}
2017-12-25 09:10:19 +01:00
void HackRFInput :: init ()
{
applySettings ( m_settings , true );
}
2017-04-14 03:40:45 +02:00
bool HackRFInput :: start ()
2017-04-14 00:14:40 +02:00
{
// QMutexLocker mutexLocker(&m_mutex);
2017-04-14 01:41:02 +02:00
if ( ! m_dev ) {
return false ;
2017-04-14 00:14:40 +02:00
}
2019-03-31 00:40:42 +01:00
if ( m_running ) {
stop ();
}
2017-04-14 00:14:40 +02:00
2018-02-24 10:29:27 +01:00
m_hackRFThread = new HackRFInputThread ( m_dev , & m_sampleFifo );
2015-09-24 02:50:24 +02:00
2017-01-08 00:33:11 +01:00
// mutexLocker.unlock();
2015-09-24 02:50:24 +02:00
applySettings ( m_settings , true );
2017-04-14 00:14:40 +02:00
m_hackRFThread -> setSamplerate ( m_settings . m_devSampleRate );
m_hackRFThread -> setLog2Decimation ( m_settings . m_log2Decim );
m_hackRFThread -> setFcPos (( int ) m_settings . m_fcPos );
2015-10-21 02:32:21 +02:00
m_hackRFThread -> startWork ();
2015-09-27 07:37:15 +02:00
qDebug ( "HackRFInput::startInput: started" );
2017-04-14 00:14:40 +02:00
m_running = true ;
2015-09-24 02:50:24 +02:00
return true ;
}
2017-04-14 00:14:40 +02:00
void HackRFInput :: closeDevice ()
2015-09-24 02:50:24 +02:00
{
2017-04-14 01:41:02 +02:00
if ( m_deviceAPI -> getSinkBuddies (). size () == 0 )
2017-01-08 00:33:11 +01:00
{
2017-04-14 01:41:02 +02:00
qDebug ( "HackRFInput::closeDevice: closing device since Tx side is not open" );
2017-01-08 00:33:11 +01:00
if ( m_dev != 0 ) // close BladeRF
{
hackrf_close ( m_dev );
2017-04-14 01:49:48 +02:00
//hackrf_exit(); // TODO: this may not work if several HackRF Devices are running concurrently. It should be handled globally in the application
2017-01-08 00:33:11 +01:00
}
}
m_sharedParams . m_dev = 0 ;
m_dev = 0 ;
2017-04-14 00:14:40 +02:00
}
void HackRFInput :: stop ()
{
qDebug ( "HackRFInput::stop" );
// QMutexLocker mutexLocker(&m_mutex);
if ( m_hackRFThread != 0 )
{
m_hackRFThread -> stopWork ();
delete m_hackRFThread ;
m_hackRFThread = 0 ;
}
2017-01-08 00:33:11 +01:00
2017-04-14 00:14:40 +02:00
m_running = false ;
2015-09-24 02:50:24 +02:00
}
2017-12-28 03:21:48 +01:00
QByteArray HackRFInput :: serialize () const
{
return m_settings . serialize ();
}
bool HackRFInput :: deserialize ( const QByteArray & data )
{
bool success = true ;
if ( ! m_settings . deserialize ( data ))
{
m_settings . resetToDefaults ();
success = false ;
}
MsgConfigureHackRF * message = MsgConfigureHackRF :: create ( m_settings , true );
m_inputMessageQueue . push ( message );
if ( m_guiMessageQueue )
{
MsgConfigureHackRF * messageToGUI = MsgConfigureHackRF :: create ( m_settings , true );
m_guiMessageQueue -> push ( messageToGUI );
}
return success ;
}
2015-09-24 02:50:24 +02:00
const QString & HackRFInput :: getDeviceDescription () const
{
return m_deviceDescription ;
}
int HackRFInput :: getSampleRate () const
{
2017-01-08 02:48:01 +01:00
return ( m_settings . m_devSampleRate / ( 1 << m_settings . m_log2Decim ));
2015-09-24 02:50:24 +02:00
}
quint64 HackRFInput :: getCenterFrequency () const
{
return m_settings . m_centerFrequency ;
}
2017-12-28 03:21:48 +01:00
void HackRFInput :: setCenterFrequency ( qint64 centerFrequency )
{
HackRFInputSettings settings = m_settings ;
settings . m_centerFrequency = centerFrequency ;
MsgConfigureHackRF * message = MsgConfigureHackRF :: create ( settings , false );
m_inputMessageQueue . push ( message );
if ( m_guiMessageQueue )
{
MsgConfigureHackRF * messageToGUI = MsgConfigureHackRF :: create ( settings , false );
m_guiMessageQueue -> push ( messageToGUI );
}
}
2015-09-24 02:50:24 +02:00
bool HackRFInput :: handleMessage ( const Message & message )
{
2015-09-27 07:37:15 +02:00
if ( MsgConfigureHackRF :: match ( message ))
2015-09-24 02:50:24 +02:00
{
2015-09-27 07:37:15 +02:00
MsgConfigureHackRF & conf = ( MsgConfigureHackRF & ) message ;
qDebug () << "HackRFInput::handleMessage: MsgConfigureHackRF" ;
2015-09-24 02:50:24 +02:00
2017-05-26 17:42:57 +02:00
bool success = applySettings ( conf . getSettings (), conf . getForce ());
2015-09-24 02:50:24 +02:00
if ( ! success )
{
2015-09-27 07:37:15 +02:00
qDebug ( "HackRFInput::handleMessage: config error" );
2015-09-24 02:50:24 +02:00
}
return true ;
}
2017-09-04 23:49:51 +02:00
else if ( MsgFileRecord :: match ( message ))
{
MsgFileRecord & conf = ( MsgFileRecord & ) message ;
qDebug () << "HackRFInput::handleMessage: MsgFileRecord: " << conf . getStartStop ();
2018-05-08 11:03:09 +02:00
if ( conf . getStartStop ())
{
if ( m_settings . m_fileRecordName . size () != 0 ) {
m_fileSink -> setFileName ( m_settings . m_fileRecordName );
} else {
2018-05-11 09:08:20 +02:00
m_fileSink -> genUniqueFileName ( m_deviceAPI -> getDeviceUID ());
2018-05-08 11:03:09 +02:00
}
2017-09-04 23:49:51 +02:00
m_fileSink -> startRecording ();
2018-05-08 11:03:09 +02:00
}
else
{
2017-09-04 23:49:51 +02:00
m_fileSink -> stopRecording ();
}
return true ;
}
2017-12-14 18:02:49 +01:00
else if ( MsgStartStop :: match ( message ))
{
MsgStartStop & cmd = ( MsgStartStop & ) message ;
qDebug () << "HackRFInput::handleMessage: MsgStartStop: " << ( cmd . getStartStop () ? "start" : "stop" );
if ( cmd . getStartStop ())
{
2019-05-08 22:11:53 +02:00
if ( m_deviceAPI -> initDeviceEngine ())
2017-12-14 18:02:49 +01:00
{
2019-05-08 22:11:53 +02:00
m_deviceAPI -> startDeviceEngine ();
2017-12-14 18:02:49 +01:00
}
}
else
{
2019-05-08 22:11:53 +02:00
m_deviceAPI -> stopDeviceEngine ();
2017-12-14 18:02:49 +01:00
}
2018-12-26 11:29:20 +01:00
if ( m_settings . m_useReverseAPI ) {
webapiReverseSendStartStop ( cmd . getStartStop ());
}
2017-12-14 18:02:49 +01:00
return true ;
}
2019-03-30 20:44:55 +01:00
else if ( DeviceHackRFShared :: MsgSynchronizeFrequency :: match ( message ))
{
DeviceHackRFShared :: MsgSynchronizeFrequency & freqMsg = ( DeviceHackRFShared :: MsgSynchronizeFrequency & ) message ;
qint64 centerFrequency = DeviceSampleSource :: calculateCenterFrequency (
freqMsg . getFrequency (),
0 ,
m_settings . m_log2Decim ,
( DeviceSampleSource :: fcPos_t ) m_settings . m_fcPos ,
2019-04-02 01:10:03 +02:00
m_settings . m_devSampleRate ,
DeviceSampleSource :: FSHIFT_TXSYNC );
2019-03-30 20:44:55 +01:00
qDebug ( "HackRFInput::handleMessage: MsgSynchronizeFrequency: centerFrequency: %lld Hz" , centerFrequency );
2019-03-31 00:40:42 +01:00
HackRFInputSettings settings = m_settings ;
settings . m_centerFrequency = centerFrequency ;
if ( m_guiMessageQueue )
{
MsgConfigureHackRF * messageToGUI = MsgConfigureHackRF :: create ( settings , false );
m_guiMessageQueue -> push ( messageToGUI );
}
m_settings . m_centerFrequency = settings . m_centerFrequency ;
int sampleRate = m_settings . m_devSampleRate / ( 1 << m_settings . m_log2Decim );
DSPSignalNotification * notif = new DSPSignalNotification ( sampleRate , m_settings . m_centerFrequency );
m_fileSink -> handleMessage ( * notif ); // forward to file sink
m_deviceAPI -> getDeviceEngineInputMessageQueue () -> push ( notif );
2019-03-30 20:44:55 +01:00
return true ;
}
2015-09-24 02:50:24 +02:00
else
{
return false ;
}
}
2019-03-31 00:40:42 +01:00
void HackRFInput :: setDeviceCenterFrequency ( quint64 freq_hz , qint32 LOppmTenths )
2015-09-24 02:50:24 +02:00
{
2019-03-31 00:40:42 +01:00
if ( ! m_dev ) {
return ;
}
2015-09-24 02:50:24 +02:00
2019-03-31 00:40:42 +01:00
qint64 df = (( qint64 ) freq_hz * LOppmTenths ) / 10000000LL ;
hackrf_error rc = ( hackrf_error ) hackrf_set_freq ( m_dev , static_cast < uint64_t > ( freq_hz + df ));
2015-09-24 02:50:24 +02:00
2019-03-31 00:40:42 +01:00
if ( rc != HACKRF_SUCCESS ) {
qWarning ( "HackRFInput::setDeviceCenterFrequency: could not frequency to %llu Hz" , freq_hz + df );
} else {
qDebug ( "HackRFInput::setDeviceCenterFrequency: frequency set to %llu Hz" , freq_hz + df );
2015-09-24 02:50:24 +02:00
}
}
2016-12-27 02:25:06 +01:00
bool HackRFInput :: applySettings ( const HackRFInputSettings & settings , bool force )
2015-09-24 02:50:24 +02:00
{
2017-01-08 00:33:11 +01:00
// QMutexLocker mutexLocker(&m_mutex);
2015-09-24 02:50:24 +02:00
bool forwardChange = false ;
2015-09-27 07:37:15 +02:00
hackrf_error rc ;
2018-12-26 11:29:20 +01:00
QList < QString > reverseAPIKeys ;
2015-09-24 02:50:24 +02:00
2015-09-27 07:37:15 +02:00
qDebug () << "HackRFInput::applySettings" ;
2015-09-24 02:50:24 +02:00
2018-12-26 11:29:20 +01:00
if (( m_settings . m_dcBlock != settings . m_dcBlock ) || force ) {
reverseAPIKeys . append ( "dcBlock" );
}
if (( m_settings . m_iqCorrection != settings . m_iqCorrection ) || force ) {
reverseAPIKeys . append ( "iqCorrection" );
}
2017-11-06 02:12:44 +01:00
if (( m_settings . m_dcBlock != settings . m_dcBlock ) ||
( m_settings . m_iqCorrection != settings . m_iqCorrection ) || force )
2015-09-30 04:39:09 +02:00
{
2017-12-29 02:44:35 +01:00
m_deviceAPI -> configureCorrections ( settings . m_dcBlock , settings . m_iqCorrection );
2015-09-30 04:39:09 +02:00
}
2017-01-08 02:48:01 +01:00
if (( m_settings . m_devSampleRate != settings . m_devSampleRate ) || force )
2015-09-24 02:50:24 +02:00
{
2018-12-26 11:29:20 +01:00
reverseAPIKeys . append ( "devSampleRate" );
2017-01-08 04:13:20 +01:00
forwardChange = true ;
2015-09-24 02:50:24 +02:00
2017-01-08 04:13:20 +01:00
if ( m_dev != 0 )
2015-09-24 02:50:24 +02:00
{
2017-12-29 02:44:35 +01:00
rc = ( hackrf_error ) hackrf_set_sample_rate_manual ( m_dev , settings . m_devSampleRate , 1 );
2015-09-24 02:50:24 +02:00
2015-09-27 07:37:15 +02:00
if ( rc != HACKRF_SUCCESS )
2015-09-24 02:50:24 +02:00
{
2017-12-29 02:44:35 +01:00
qCritical ( "HackRFInput::applySettings: could not set sample rate TO %llu S/s: %s" , settings . m_devSampleRate , hackrf_error_name ( rc ));
2015-09-24 02:50:24 +02:00
}
else
{
2017-04-14 00:14:40 +02:00
if ( m_hackRFThread != 0 )
{
2017-12-29 02:44:35 +01:00
qDebug ( "HackRFInput::applySettings: sample rate set to %llu S/s" , settings . m_devSampleRate );
m_hackRFThread -> setSamplerate ( settings . m_devSampleRate );
2017-04-14 00:14:40 +02:00
}
2015-09-24 02:50:24 +02:00
}
}
}
if (( m_settings . m_log2Decim != settings . m_log2Decim ) || force )
{
2018-12-26 11:29:20 +01:00
reverseAPIKeys . append ( "log2Decim" );
2015-09-24 02:50:24 +02:00
forwardChange = true ;
2017-04-14 00:14:40 +02:00
if ( m_hackRFThread != 0 )
2015-09-24 02:50:24 +02:00
{
2017-12-29 02:44:35 +01:00
m_hackRFThread -> setLog2Decimation ( settings . m_log2Decim );
qDebug () << "HackRFInput: set decimation to " << ( 1 << settings . m_log2Decim );
2015-09-24 02:50:24 +02:00
}
}
2019-03-31 00:40:42 +01:00
if ( force || ( m_settings . m_centerFrequency != settings . m_centerFrequency )) {
2018-12-26 11:29:20 +01:00
reverseAPIKeys . append ( "centerFrequency" );
2017-07-21 00:44:30 +02:00
}
2018-12-26 11:29:20 +01:00
if (( m_settings . m_LOppmTenths != settings . m_LOppmTenths ) || force ) {
reverseAPIKeys . append ( "LOppmTenths" );
}
if (( m_settings . m_fcPos != settings . m_fcPos ) || force ) {
reverseAPIKeys . append ( "fcPos" );
}
2018-01-20 03:28:30 +01:00
if (( m_settings . m_centerFrequency != settings . m_centerFrequency ) ||
2018-05-10 15:06:46 +02:00
( m_settings . m_devSampleRate != settings . m_devSampleRate ) ||
2018-01-20 03:28:30 +01:00
( m_settings . m_LOppmTenths != settings . m_LOppmTenths ) ||
( m_settings . m_log2Decim != settings . m_log2Decim ) ||
( m_settings . m_fcPos != settings . m_fcPos ) || force )
2015-09-24 02:50:24 +02:00
{
2018-05-10 15:06:46 +02:00
qint64 deviceCenterFrequency = DeviceSampleSource :: calculateDeviceCenterFrequency (
settings . m_centerFrequency ,
0 ,
settings . m_log2Decim ,
( DeviceSampleSource :: fcPos_t ) settings . m_fcPos ,
2019-04-02 01:10:03 +02:00
settings . m_devSampleRate ,
DeviceSampleSource :: FrequencyShiftScheme :: FSHIFT_TXSYNC ,
false );
2019-03-31 00:40:42 +01:00
setDeviceCenterFrequency ( deviceCenterFrequency , settings . m_LOppmTenths );
if ( m_deviceAPI -> getSinkBuddies (). size () > 0 ) // forward to buddy if necessary
{
2019-05-08 22:11:53 +02:00
DeviceAPI * buddy = m_deviceAPI -> getSinkBuddies ()[ 0 ];
2019-03-31 00:40:42 +01:00
DeviceHackRFShared :: MsgSynchronizeFrequency * freqMsg = DeviceHackRFShared :: MsgSynchronizeFrequency :: create ( deviceCenterFrequency );
2019-05-08 22:11:53 +02:00
buddy -> getSamplingDeviceInputMessageQueue () -> push ( freqMsg );
2019-03-31 00:40:42 +01:00
}
2015-09-24 02:50:24 +02:00
forwardChange = true ;
}
2015-10-01 06:34:08 +02:00
if (( m_settings . m_fcPos != settings . m_fcPos ) || force )
{
2017-04-14 00:14:40 +02:00
if ( m_hackRFThread != 0 )
2015-10-01 06:34:08 +02:00
{
2017-12-29 02:44:35 +01:00
m_hackRFThread -> setFcPos (( int ) settings . m_fcPos );
qDebug () << "HackRFInput: set fc pos (enum) to " << ( int ) settings . m_fcPos ;
2015-10-01 06:34:08 +02:00
}
}
2015-09-24 02:50:24 +02:00
if (( m_settings . m_lnaGain != settings . m_lnaGain ) || force )
{
2018-12-26 11:29:20 +01:00
reverseAPIKeys . append ( "lnaGain" );
2015-09-24 02:50:24 +02:00
if ( m_dev != 0 )
{
2017-12-29 02:44:35 +01:00
rc = ( hackrf_error ) hackrf_set_lna_gain ( m_dev , settings . m_lnaGain );
2015-09-24 02:50:24 +02:00
2018-12-26 11:29:20 +01:00
if ( rc != HACKRF_SUCCESS ) {
2015-09-27 07:37:15 +02:00
qDebug ( "HackRFInput::applySettings: airspy_set_lna_gain failed: %s" , hackrf_error_name ( rc ));
2018-12-26 11:29:20 +01:00
} else {
2017-12-29 02:44:35 +01:00
qDebug () << "HackRFInput:applySettings: LNA gain set to " << settings . m_lnaGain ;
2015-09-24 02:50:24 +02:00
}
}
}
2015-09-27 07:37:15 +02:00
if (( m_settings . m_vgaGain != settings . m_vgaGain ) || force )
2015-09-24 02:50:24 +02:00
{
2018-12-26 11:29:20 +01:00
reverseAPIKeys . append ( "vgaGain" );
2015-09-24 02:50:24 +02:00
if ( m_dev != 0 )
{
2017-12-29 02:44:35 +01:00
rc = ( hackrf_error ) hackrf_set_vga_gain ( m_dev , settings . m_vgaGain );
2015-09-24 02:50:24 +02:00
2018-12-26 11:29:20 +01:00
if ( rc != HACKRF_SUCCESS ) {
2015-09-27 07:37:15 +02:00
qDebug ( "HackRFInput::applySettings: hackrf_set_vga_gain failed: %s" , hackrf_error_name ( rc ));
2018-12-26 11:29:20 +01:00
} else {
2017-12-29 02:44:35 +01:00
qDebug () << "HackRFInput:applySettings: VGA gain set to " << settings . m_vgaGain ;
2015-09-24 02:50:24 +02:00
}
}
}
2017-01-08 02:48:01 +01:00
if (( m_settings . m_bandwidth != settings . m_bandwidth ) || force )
2015-09-24 02:50:24 +02:00
{
2018-12-26 11:29:20 +01:00
reverseAPIKeys . append ( "bandwidth" );
2017-01-08 04:13:20 +01:00
if ( m_dev != 0 )
2015-09-24 02:50:24 +02:00
{
2017-12-29 02:44:35 +01:00
uint32_t bw_index = hackrf_compute_baseband_filter_bw_round_down_lt ( settings . m_bandwidth + 1 ); // +1 so the round down to lower than yields desired bandwidth
2015-09-27 07:37:15 +02:00
rc = ( hackrf_error ) hackrf_set_baseband_filter_bandwidth ( m_dev , bw_index );
2015-09-24 02:50:24 +02:00
2018-12-26 11:29:20 +01:00
if ( rc != HACKRF_SUCCESS ) {
2015-09-27 07:37:15 +02:00
qDebug ( "HackRFInput::applySettings: hackrf_set_baseband_filter_bandwidth failed: %s" , hackrf_error_name ( rc ));
2018-12-26 11:29:20 +01:00
} else {
2017-12-29 02:44:35 +01:00
qDebug () << "HackRFInput:applySettings: Baseband BW filter set to " << settings . m_bandwidth << " Hz" ;
2015-09-24 02:50:24 +02:00
}
}
}
if (( m_settings . m_biasT != settings . m_biasT ) || force )
{
2018-12-26 11:29:20 +01:00
reverseAPIKeys . append ( "biasT" );
2015-09-24 02:50:24 +02:00
if ( m_dev != 0 )
{
2017-12-29 02:44:35 +01:00
rc = ( hackrf_error ) hackrf_set_antenna_enable ( m_dev , ( settings . m_biasT ? 1 : 0 ));
2015-09-24 02:50:24 +02:00
2018-12-26 11:29:20 +01:00
if ( rc != HACKRF_SUCCESS ) {
2015-09-27 11:27:02 +02:00
qDebug ( "HackRFInput::applySettings: hackrf_set_antenna_enable failed: %s" , hackrf_error_name ( rc ));
2018-12-26 11:29:20 +01:00
} else {
2017-12-29 02:44:35 +01:00
qDebug () << "HackRFInput:applySettings: bias tee set to " << settings . m_biasT ;
2015-09-24 02:50:24 +02:00
}
}
}
2015-09-27 11:27:02 +02:00
if (( m_settings . m_lnaExt != settings . m_lnaExt ) || force )
{
2018-12-26 11:29:20 +01:00
reverseAPIKeys . append ( "lnaExt" );
2015-09-27 11:27:02 +02:00
if ( m_dev != 0 )
{
2017-12-29 02:44:35 +01:00
rc = ( hackrf_error ) hackrf_set_amp_enable ( m_dev , ( settings . m_lnaExt ? 1 : 0 ));
2015-09-27 11:27:02 +02:00
2018-12-26 11:29:20 +01:00
if ( rc != HACKRF_SUCCESS ) {
2015-09-27 11:27:02 +02:00
qDebug ( "HackRFInput::applySettings: hackrf_set_amp_enable failed: %s" , hackrf_error_name ( rc ));
2018-12-26 11:29:20 +01:00
} else {
2017-12-29 02:44:35 +01:00
qDebug () << "HackRFInput:applySettings: extra LNA set to " << settings . m_lnaExt ;
2015-09-27 11:27:02 +02:00
}
}
}
2015-09-24 02:50:24 +02:00
if ( forwardChange )
{
2018-05-10 15:06:46 +02:00
int sampleRate = settings . m_devSampleRate / ( 1 << settings . m_log2Decim );
2017-12-29 02:44:35 +01:00
DSPSignalNotification * notif = new DSPSignalNotification ( sampleRate , settings . m_centerFrequency );
2017-09-04 23:49:51 +02:00
m_fileSink -> handleMessage ( * notif ); // forward to file sink
2017-09-13 23:40:06 +02:00
m_deviceAPI -> getDeviceEngineInputMessageQueue () -> push ( notif );
2015-09-24 02:50:24 +02:00
}
2018-12-26 11:29:20 +01:00
if ( settings . m_useReverseAPI )
{
bool fullUpdate = (( m_settings . m_useReverseAPI != settings . m_useReverseAPI ) && settings . m_useReverseAPI ) ||
( m_settings . m_reverseAPIAddress != settings . m_reverseAPIAddress ) ||
( m_settings . m_reverseAPIPort != settings . m_reverseAPIPort ) ||
( m_settings . m_reverseAPIDeviceIndex != settings . m_reverseAPIDeviceIndex );
webapiReverseSendSettings ( reverseAPIKeys , settings , fullUpdate || force );
}
2017-12-29 02:44:35 +01:00
m_settings = settings ;
qDebug () << "HackRFInput::applySettings: "
<< " m_centerFrequency: " << m_settings . m_centerFrequency << " Hz"
<< " m_LOppmTenths: " << m_settings . m_LOppmTenths
<< " m_bandwidth: " << m_settings . m_bandwidth
<< " m_lnaGain: " << m_settings . m_lnaGain
<< " m_vgaGain: " << m_settings . m_vgaGain
<< " m_log2Decim: " << m_settings . m_log2Decim
<< " m_fcPos: " << m_settings . m_fcPos
<< " m_devSampleRate: " << m_settings . m_devSampleRate
<< " m_biasT: " << m_settings . m_biasT
<< " m_lnaExt: " << m_settings . m_lnaExt
2019-03-30 20:44:55 +01:00
<< " m_dcBlock: " << m_settings . m_dcBlock ;
2017-01-08 02:48:01 +01:00
2015-09-24 02:50:24 +02:00
return true ;
}
2017-12-29 01:40:34 +01:00
int HackRFInput :: webapiSettingsGet (
SWGSDRangel :: SWGDeviceSettings & response ,
2018-11-13 08:51:14 +01:00
QString & errorMessage )
2017-12-29 01:40:34 +01:00
{
2018-11-13 08:51:14 +01:00
( void ) errorMessage ;
2017-12-29 01:40:34 +01:00
response . setHackRfInputSettings ( new SWGSDRangel :: SWGHackRFInputSettings ());
2018-02-21 13:50:50 +01:00
response . getHackRfInputSettings () -> init ();
2017-12-29 01:40:34 +01:00
webapiFormatDeviceSettings ( response , m_settings );
return 200 ;
}
int HackRFInput :: webapiSettingsPutPatch (
bool force ,
const QStringList & deviceSettingsKeys ,
SWGSDRangel :: SWGDeviceSettings & response , // query + response
2018-11-13 08:51:14 +01:00
QString & errorMessage )
2017-12-29 01:40:34 +01:00
{
2018-11-13 08:51:14 +01:00
( void ) errorMessage ;
2017-12-29 01:40:34 +01:00
HackRFInputSettings settings = m_settings ;
if ( deviceSettingsKeys . contains ( "centerFrequency" )) {
settings . m_centerFrequency = response . getHackRfInputSettings () -> getCenterFrequency ();
}
if ( deviceSettingsKeys . contains ( "LOppmTenths" )) {
settings . m_LOppmTenths = response . getHackRfInputSettings () -> getLOppmTenths ();
}
if ( deviceSettingsKeys . contains ( "bandwidth" )) {
settings . m_bandwidth = response . getHackRfInputSettings () -> getBandwidth ();
}
if ( deviceSettingsKeys . contains ( "lnaGain" )) {
settings . m_lnaGain = response . getHackRfInputSettings () -> getLnaGain ();
}
if ( deviceSettingsKeys . contains ( "vgaGain" )) {
settings . m_vgaGain = response . getHackRfInputSettings () -> getVgaGain ();
}
2017-12-29 02:44:35 +01:00
if ( deviceSettingsKeys . contains ( "log2Decim" )) {
2017-12-29 01:40:34 +01:00
settings . m_log2Decim = response . getHackRfInputSettings () -> getLog2Decim ();
}
2018-05-25 02:02:21 +02:00
if ( deviceSettingsKeys . contains ( "fcPos" ))
{
int fcPos = response . getHackRfInputSettings () -> getFcPos ();
fcPos = fcPos < 0 ? 0 : fcPos > 2 ? 2 : fcPos ;
settings . m_fcPos = ( HackRFInputSettings :: fcPos_t ) fcPos ;
}
2017-12-29 01:40:34 +01:00
if ( deviceSettingsKeys . contains ( "devSampleRate" )) {
settings . m_devSampleRate = response . getHackRfInputSettings () -> getDevSampleRate ();
}
if ( deviceSettingsKeys . contains ( "biasT" )) {
settings . m_biasT = response . getHackRfInputSettings () -> getBiasT () != 0 ;
}
if ( deviceSettingsKeys . contains ( "lnaExt" )) {
settings . m_lnaExt = response . getHackRfInputSettings () -> getLnaExt () != 0 ;
}
if ( deviceSettingsKeys . contains ( "dcBlock" )) {
settings . m_dcBlock = response . getHackRfInputSettings () -> getDcBlock () != 0 ;
}
if ( deviceSettingsKeys . contains ( "iqCorrection" )) {
settings . m_iqCorrection = response . getHackRfInputSettings () -> getIqCorrection () != 0 ;
}
2018-05-09 18:59:39 +02:00
if ( deviceSettingsKeys . contains ( "fileRecordName" )) {
settings . m_fileRecordName = * response . getHackRfInputSettings () -> getFileRecordName ();
}
2019-01-11 14:45:00 +01:00
if ( deviceSettingsKeys . contains ( "useReverseAPI" )) {
settings . m_useReverseAPI = response . getHackRfInputSettings () -> getUseReverseApi () != 0 ;
}
if ( deviceSettingsKeys . contains ( "reverseAPIAddress" )) {
settings . m_reverseAPIAddress = * response . getHackRfInputSettings () -> getReverseApiAddress ();
}
if ( deviceSettingsKeys . contains ( "reverseAPIPort" )) {
settings . m_reverseAPIPort = response . getHackRfInputSettings () -> getReverseApiPort ();
}
if ( deviceSettingsKeys . contains ( "reverseAPIDeviceIndex" )) {
settings . m_reverseAPIDeviceIndex = response . getHackRfInputSettings () -> getReverseApiDeviceIndex ();
}
2017-12-29 01:40:34 +01:00
MsgConfigureHackRF * msg = MsgConfigureHackRF :: create ( settings , force );
m_inputMessageQueue . push ( msg );
if ( m_guiMessageQueue ) // forward to GUI if any
{
MsgConfigureHackRF * msgToGUI = MsgConfigureHackRF :: create ( settings , force );
m_guiMessageQueue -> push ( msgToGUI );
}
webapiFormatDeviceSettings ( response , settings );
return 200 ;
}
void HackRFInput :: webapiFormatDeviceSettings ( SWGSDRangel :: SWGDeviceSettings & response , const HackRFInputSettings & settings )
{
response . getHackRfInputSettings () -> setCenterFrequency ( settings . m_centerFrequency );
response . getHackRfInputSettings () -> setLOppmTenths ( settings . m_LOppmTenths );
response . getHackRfInputSettings () -> setBandwidth ( settings . m_bandwidth );
response . getHackRfInputSettings () -> setLnaGain ( settings . m_lnaGain );
response . getHackRfInputSettings () -> setVgaGain ( settings . m_vgaGain );
response . getHackRfInputSettings () -> setLog2Decim ( settings . m_log2Decim );
response . getHackRfInputSettings () -> setFcPos ( settings . m_fcPos );
response . getHackRfInputSettings () -> setDevSampleRate ( settings . m_devSampleRate );
response . getHackRfInputSettings () -> setBiasT ( settings . m_biasT ? 1 : 0 );
response . getHackRfInputSettings () -> setLnaExt ( settings . m_lnaExt ? 1 : 0 );
response . getHackRfInputSettings () -> setDcBlock ( settings . m_dcBlock ? 1 : 0 );
response . getHackRfInputSettings () -> setIqCorrection ( settings . m_iqCorrection ? 1 : 0 );
2018-05-09 18:59:39 +02:00
if ( response . getHackRfInputSettings () -> getFileRecordName ()) {
* response . getHackRfInputSettings () -> getFileRecordName () = settings . m_fileRecordName ;
} else {
response . getHackRfInputSettings () -> setFileRecordName ( new QString ( settings . m_fileRecordName ));
}
2019-01-11 14:45:00 +01:00
response . getHackRfInputSettings () -> setUseReverseApi ( settings . m_useReverseAPI ? 1 : 0 );
if ( response . getHackRfInputSettings () -> getReverseApiAddress ()) {
* response . getHackRfInputSettings () -> getReverseApiAddress () = settings . m_reverseAPIAddress ;
} else {
response . getHackRfInputSettings () -> setReverseApiAddress ( new QString ( settings . m_reverseAPIAddress ));
}
response . getHackRfInputSettings () -> setReverseApiPort ( settings . m_reverseAPIPort );
response . getHackRfInputSettings () -> setReverseApiDeviceIndex ( settings . m_reverseAPIDeviceIndex );
2017-12-29 01:40:34 +01:00
}
2017-12-10 01:57:50 +01:00
int HackRFInput :: webapiRunGet (
SWGSDRangel :: SWGDeviceState & response ,
2018-11-13 08:51:14 +01:00
QString & errorMessage )
2017-12-10 01:57:50 +01:00
{
2018-11-13 08:51:14 +01:00
( void ) errorMessage ;
2017-12-10 01:57:50 +01:00
m_deviceAPI -> getDeviceEngineStateStr ( * response . getState ());
return 200 ;
}
int HackRFInput :: webapiRun (
bool run ,
SWGSDRangel :: SWGDeviceState & response ,
2018-11-13 08:51:14 +01:00
QString & errorMessage )
2017-12-10 01:57:50 +01:00
{
2018-11-13 08:51:14 +01:00
( void ) errorMessage ;
2017-12-14 23:29:12 +01:00
m_deviceAPI -> getDeviceEngineStateStr ( * response . getState ());
2017-12-14 18:02:49 +01:00
MsgStartStop * message = MsgStartStop :: create ( run );
m_inputMessageQueue . push ( message );
if ( m_guiMessageQueue ) // forward to GUI if any
2017-12-10 01:57:50 +01:00
{
2017-12-14 18:02:49 +01:00
MsgStartStop * msgToGUI = MsgStartStop :: create ( run );
m_guiMessageQueue -> push ( msgToGUI );
2017-12-10 01:57:50 +01:00
}
return 200 ;
}
2018-12-26 11:29:20 +01:00
void HackRFInput :: webapiReverseSendSettings ( QList < QString >& deviceSettingsKeys , const HackRFInputSettings & settings , bool force )
{
SWGSDRangel :: SWGDeviceSettings * swgDeviceSettings = new SWGSDRangel :: SWGDeviceSettings ();
2019-05-07 14:43:38 +02:00
swgDeviceSettings -> setDirection ( 0 ); // single Rx
2019-03-25 13:41:38 +01:00
swgDeviceSettings -> setOriginatorIndex ( m_deviceAPI -> getDeviceSetIndex ());
2018-12-26 11:29:20 +01:00
swgDeviceSettings -> setDeviceHwType ( new QString ( "HackRF" ));
swgDeviceSettings -> setHackRfInputSettings ( new SWGSDRangel :: SWGHackRFInputSettings ());
SWGSDRangel :: SWGHackRFInputSettings * swgHackRFInputSettings = swgDeviceSettings -> getHackRfInputSettings ();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if ( deviceSettingsKeys . contains ( "centerFrequency" ) || force ) {
swgHackRFInputSettings -> setCenterFrequency ( settings . m_centerFrequency );
}
if ( deviceSettingsKeys . contains ( "LOppmTenths" ) || force ) {
swgHackRFInputSettings -> setLOppmTenths ( settings . m_LOppmTenths );
}
if ( deviceSettingsKeys . contains ( "bandwidth" ) || force ) {
swgHackRFInputSettings -> setBandwidth ( settings . m_bandwidth );
}
if ( deviceSettingsKeys . contains ( "lnaGain" ) || force ) {
swgHackRFInputSettings -> setLnaGain ( settings . m_lnaGain );
}
if ( deviceSettingsKeys . contains ( "vgaGain" ) || force ) {
swgHackRFInputSettings -> setVgaGain ( settings . m_vgaGain );
}
if ( deviceSettingsKeys . contains ( "log2Decim" ) || force ) {
swgHackRFInputSettings -> setLog2Decim ( settings . m_log2Decim );
}
if ( deviceSettingsKeys . contains ( "fcPos" ) || force ) {
swgHackRFInputSettings -> setFcPos (( int ) settings . m_fcPos );
}
if ( deviceSettingsKeys . contains ( "devSampleRate" ) || force ) {
swgHackRFInputSettings -> setDevSampleRate ( settings . m_devSampleRate );
}
if ( deviceSettingsKeys . contains ( "biasT" ) || force ) {
swgHackRFInputSettings -> setBiasT ( settings . m_biasT ? 1 : 0 );
}
if ( deviceSettingsKeys . contains ( "lnaExt" ) || force ) {
swgHackRFInputSettings -> setLnaExt ( settings . m_lnaExt ? 1 : 0 );
}
if ( deviceSettingsKeys . contains ( "dcBlock" ) || force ) {
swgHackRFInputSettings -> setDcBlock ( settings . m_dcBlock ? 1 : 0 );
}
if ( deviceSettingsKeys . contains ( "iqCorrection" ) || force ) {
swgHackRFInputSettings -> setIqCorrection ( settings . m_iqCorrection ? 1 : 0 );
}
if ( deviceSettingsKeys . contains ( "fileRecordName" ) || force ) {
swgHackRFInputSettings -> setFileRecordName ( new QString ( settings . m_fileRecordName ));
}
QString deviceSettingsURL = QString ( "http://%1:%2/sdrangel/deviceset/%3/device/settings" )
. arg ( settings . m_reverseAPIAddress )
. arg ( settings . m_reverseAPIPort )
. arg ( settings . m_reverseAPIDeviceIndex );
m_networkRequest . setUrl ( QUrl ( deviceSettingsURL ));
m_networkRequest . setHeader ( QNetworkRequest :: ContentTypeHeader , "application/json" );
QBuffer * buffer = new QBuffer ();
buffer -> open (( QBuffer :: ReadWrite ));
buffer -> write ( swgDeviceSettings -> asJson (). toUtf8 ());
buffer -> seek ( 0 );
// Always use PATCH to avoid passing reverse API settings
m_networkManager -> sendCustomRequest ( m_networkRequest , "PATCH" , buffer );
delete swgDeviceSettings ;
}
void HackRFInput :: webapiReverseSendStartStop ( bool start )
{
2019-03-25 15:21:17 +01:00
SWGSDRangel :: SWGDeviceSettings * swgDeviceSettings = new SWGSDRangel :: SWGDeviceSettings ();
2019-05-07 14:43:38 +02:00
swgDeviceSettings -> setDirection ( 0 ); // single Rx
2019-03-25 15:21:17 +01:00
swgDeviceSettings -> setOriginatorIndex ( m_deviceAPI -> getDeviceSetIndex ());
swgDeviceSettings -> setDeviceHwType ( new QString ( "HackRF" ));
2018-12-26 11:29:20 +01:00
QString deviceSettingsURL = QString ( "http://%1:%2/sdrangel/deviceset/%3/device/run" )
. arg ( m_settings . m_reverseAPIAddress )
. arg ( m_settings . m_reverseAPIPort )
. arg ( m_settings . m_reverseAPIDeviceIndex );
m_networkRequest . setUrl ( QUrl ( deviceSettingsURL ));
2019-03-25 15:21:17 +01:00
m_networkRequest . setHeader ( QNetworkRequest :: ContentTypeHeader , "application/json" );
QBuffer * buffer = new QBuffer ();
buffer -> open (( QBuffer :: ReadWrite ));
buffer -> write ( swgDeviceSettings -> asJson (). toUtf8 ());
buffer -> seek ( 0 );
2018-12-26 11:29:20 +01:00
if ( start ) {
2019-03-25 15:21:17 +01:00
m_networkManager -> sendCustomRequest ( m_networkRequest , "POST" , buffer );
2018-12-26 11:29:20 +01:00
} else {
2019-03-25 15:21:17 +01:00
m_networkManager -> sendCustomRequest ( m_networkRequest , "DELETE" , buffer );
2018-12-26 11:29:20 +01:00
}
}
void HackRFInput :: networkManagerFinished ( QNetworkReply * reply )
{
QNetworkReply :: NetworkError replyError = reply -> error ();
if ( replyError )
{
qWarning () << "HackRFInput::networkManagerFinished:"
<< " error(" << ( int ) replyError
<< "): " << replyError
<< ": " << reply -> errorString ();
return ;
}
QString answer = reply -> readAll ();
answer . chop ( 1 ); // remove last \n
qDebug ( "HackRFInput::networkManagerFinished: reply: \n %s" , answer . toStdString (). c_str ());
}