2015-09-23 20:50:24 -04: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 //
// //
// 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>
# include <QDebug>
# include "util/simpleserializer.h"
# include "dsp/dspcommands.h"
2015-09-27 06:50:38 -04:00
# include "dsp/dspengine.h"
2015-09-23 20:50:24 -04:00
# include "hackrfinput.h"
# include "hackrfgui.h"
# include "hackrfthread.h"
2015-09-27 01:37:15 -04:00
MESSAGE_CLASS_DEFINITION ( HackRFInput : : MsgConfigureHackRF , Message )
2015-09-23 20:50:24 -04:00
MESSAGE_CLASS_DEFINITION ( HackRFInput : : MsgReportHackRF , Message )
HackRFInput : : HackRFInput ( ) :
m_settings ( ) ,
m_dev ( 0 ) ,
2015-09-27 01:37:15 -04:00
m_hackRFThread ( 0 ) ,
m_deviceDescription ( " HackRF " )
2015-09-23 20:50:24 -04:00
{
}
HackRFInput : : ~ HackRFInput ( )
{
stop ( ) ;
}
bool HackRFInput : : init ( const Message & cmd )
{
return false ;
}
bool HackRFInput : : start ( int device )
{
QMutexLocker mutexLocker ( & m_mutex ) ;
2015-09-27 01:37:15 -04:00
hackrf_error rc ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
rc = ( hackrf_error ) hackrf_init ( ) ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
if ( rc ! = HACKRF_SUCCESS )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
qCritical ( " HackRFInput::start: failed to initiate HackRF library %s " , hackrf_error_name ( rc ) ) ;
2015-09-23 20:50:24 -04:00
}
if ( m_dev ! = 0 )
{
stop ( ) ;
}
if ( ! m_sampleFifo . setSize ( 1 < < 19 ) )
{
2015-09-27 01:37:15 -04:00
qCritical ( " HackRFInput::start: could not allocate SampleFifo " ) ;
2015-09-23 20:50:24 -04:00
return false ;
}
2015-09-27 01:37:15 -04:00
if ( ( m_dev = open_hackrf_from_sequence ( device ) ) = = 0 )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
qCritical ( " HackRFInput::start: could not open HackRF #%d " , device ) ;
2015-09-23 20:50:24 -04:00
return false ;
}
2015-09-27 01:37:15 -04:00
if ( ( m_hackRFThread = new HackRFThread ( m_dev , & m_sampleFifo ) ) = = 0 )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
qFatal ( " HackRFInput::start: out of memory " ) ;
2015-09-23 20:50:24 -04:00
stop ( ) ;
return false ;
}
2015-09-27 01:37:15 -04:00
m_hackRFThread - > startWork ( ) ;
2015-09-23 20:50:24 -04:00
mutexLocker . unlock ( ) ;
applySettings ( m_settings , true ) ;
2015-09-27 01:37:15 -04:00
qDebug ( " HackRFInput::startInput: started " ) ;
2015-09-23 20:50:24 -04:00
return true ;
}
void HackRFInput : : stop ( )
{
2015-09-27 01:37:15 -04:00
qDebug ( " HackRFInput::stop " ) ;
2015-09-23 20:50:24 -04:00
QMutexLocker mutexLocker ( & m_mutex ) ;
2015-09-27 01:37:15 -04:00
if ( m_hackRFThread ! = 0 )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
m_hackRFThread - > stopWork ( ) ;
delete m_hackRFThread ;
m_hackRFThread = 0 ;
2015-09-23 20:50:24 -04:00
}
if ( m_dev ! = 0 )
{
2015-09-27 01:37:15 -04:00
hackrf_stop_rx ( m_dev ) ;
hackrf_close ( m_dev ) ;
2015-09-23 20:50:24 -04:00
m_dev = 0 ;
}
2015-09-27 01:37:15 -04:00
hackrf_exit ( ) ;
2015-09-23 20:50:24 -04:00
}
const QString & HackRFInput : : getDeviceDescription ( ) const
{
return m_deviceDescription ;
}
int HackRFInput : : getSampleRate ( ) const
{
2015-09-27 01:37:15 -04:00
int rate = HackRFSampleRates : : m_rates_k [ m_settings . m_devSampleRateIndex ] * 1000 ;
2015-09-23 20:50:24 -04:00
return ( rate / ( 1 < < m_settings . m_log2Decim ) ) ;
}
quint64 HackRFInput : : getCenterFrequency ( ) const
{
return m_settings . m_centerFrequency ;
}
bool HackRFInput : : handleMessage ( const Message & message )
{
2015-09-27 01:37:15 -04:00
if ( MsgConfigureHackRF : : match ( message ) )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
MsgConfigureHackRF & conf = ( MsgConfigureHackRF & ) message ;
qDebug ( ) < < " HackRFInput::handleMessage: MsgConfigureHackRF " ;
2015-09-23 20:50:24 -04:00
bool success = applySettings ( conf . getSettings ( ) , false ) ;
if ( ! success )
{
2015-09-27 01:37:15 -04:00
qDebug ( " HackRFInput::handleMessage: config error " ) ;
2015-09-23 20:50:24 -04:00
}
return true ;
}
else
{
return false ;
}
}
void HackRFInput : : setCenterFrequency ( quint64 freq_hz )
{
2015-09-27 12:32:19 -04:00
qint64 df = ( ( qint64 ) freq_hz * m_settings . m_LOppmTenths ) / 10000000LL ;
freq_hz + = df ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
hackrf_error rc = ( hackrf_error ) hackrf_set_freq ( m_dev , static_cast < uint64_t > ( freq_hz ) ) ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
if ( rc ! = HACKRF_SUCCESS )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
qWarning ( " HackRFInput::setCenterFrequency: could not frequency to %llu Hz " , freq_hz ) ;
2015-09-23 20:50:24 -04:00
}
else
{
2015-09-27 01:37:15 -04:00
qWarning ( " HackRFInput::setCenterFrequency: frequency set to %llu Hz " , freq_hz ) ;
2015-09-23 20:50:24 -04:00
}
}
2015-09-29 21:46:46 -04:00
bool HackRFInput : : applySettings ( const HackRFSettings & settings , bool force )
2015-09-23 20:50:24 -04:00
{
QMutexLocker mutexLocker ( & m_mutex ) ;
bool forwardChange = false ;
2015-09-27 01:37:15 -04:00
hackrf_error rc ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
qDebug ( ) < < " HackRFInput::applySettings " ;
2015-09-23 20:50:24 -04:00
2015-09-29 22:39:09 -04:00
if ( m_settings . m_dcBlock ! = settings . m_dcBlock )
{
m_settings . m_dcBlock = settings . m_dcBlock ;
DSPEngine : : instance ( ) - > configureCorrections ( m_settings . m_dcBlock , m_settings . m_iqCorrection ) ;
}
if ( m_settings . m_iqCorrection ! = settings . m_iqCorrection )
{
m_settings . m_iqCorrection = settings . m_iqCorrection ;
DSPEngine : : instance ( ) - > configureCorrections ( m_settings . m_dcBlock , m_settings . m_iqCorrection ) ;
}
2015-09-23 20:50:24 -04:00
if ( ( m_settings . m_devSampleRateIndex ! = settings . m_devSampleRateIndex ) | | force )
{
forwardChange = true ;
2015-09-27 01:37:15 -04:00
if ( settings . m_devSampleRateIndex < HackRFSampleRates : : m_nb_rates )
2015-09-23 20:50:24 -04:00
{
m_settings . m_devSampleRateIndex = settings . m_devSampleRateIndex ;
}
else
{
2015-09-27 01:37:15 -04:00
m_settings . m_devSampleRateIndex = HackRFSampleRates : : m_nb_rates - 1 ;
2015-09-23 20:50:24 -04:00
}
if ( m_dev ! = 0 )
{
2015-09-27 01:37:15 -04:00
rc = ( hackrf_error ) hackrf_set_sample_rate_manual ( m_dev , HackRFSampleRates : : m_rates_k [ m_settings . m_devSampleRateIndex ] * 1000 , 1 ) ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
if ( rc ! = HACKRF_SUCCESS )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
qCritical ( " HackRFInput::applySettings: could not set sample rate index %u (%d kS/s): %s " , m_settings . m_devSampleRateIndex , HackRFSampleRates : : m_rates_k [ m_settings . m_devSampleRateIndex ] , hackrf_error_name ( rc ) ) ;
2015-09-23 20:50:24 -04:00
}
else
{
2015-09-27 01:37:15 -04:00
qDebug ( " HackRFInput::applySettings: sample rate set to index: %u (%d kS/s) " , m_settings . m_devSampleRateIndex , HackRFSampleRates : : m_rates_k [ m_settings . m_devSampleRateIndex ] ) ;
m_hackRFThread - > setSamplerate ( HackRFSampleRates : : m_rates_k [ m_settings . m_devSampleRateIndex ] ) ;
2015-09-23 20:50:24 -04:00
}
}
}
if ( ( m_settings . m_log2Decim ! = settings . m_log2Decim ) | | force )
{
m_settings . m_log2Decim = settings . m_log2Decim ;
forwardChange = true ;
if ( m_dev ! = 0 )
{
2015-09-27 01:37:15 -04:00
m_hackRFThread - > setLog2Decimation ( m_settings . m_log2Decim ) ;
qDebug ( ) < < " HackRFInput: set decimation to " < < ( 1 < < m_settings . m_log2Decim ) ;
2015-09-23 20:50:24 -04:00
}
}
if ( ( m_settings . m_fcPos ! = settings . m_fcPos ) | | force )
{
m_settings . m_fcPos = settings . m_fcPos ;
if ( m_dev ! = 0 )
{
2015-09-27 01:37:15 -04:00
m_hackRFThread - > setFcPos ( ( int ) m_settings . m_fcPos ) ;
qDebug ( ) < < " HackRFInput: set fc pos (enum) to " < < ( int ) m_settings . m_fcPos ;
2015-09-23 20:50:24 -04:00
}
}
qint64 deviceCenterFrequency = m_settings . m_centerFrequency ;
qint64 f_img = deviceCenterFrequency ;
2015-09-27 01:37:15 -04:00
quint32 devSampleRate = HackRFSampleRates : : m_rates_k [ m_settings . m_devSampleRateIndex ] * 1000 ;
2015-09-23 20:50:24 -04:00
if ( force | | ( m_settings . m_centerFrequency ! = settings . m_centerFrequency ) | |
( m_settings . m_LOppmTenths ! = settings . m_LOppmTenths ) )
{
m_settings . m_centerFrequency = settings . m_centerFrequency ;
m_settings . m_LOppmTenths = settings . m_LOppmTenths ;
2015-09-29 21:46:46 -04:00
if ( ( m_settings . m_log2Decim = = 0 ) | | ( m_settings . m_fcPos = = HackRFSettings : : FC_POS_CENTER ) )
2015-09-23 20:50:24 -04:00
{
deviceCenterFrequency = m_settings . m_centerFrequency ;
f_img = deviceCenterFrequency ;
}
else
{
2015-09-29 21:46:46 -04:00
if ( m_settings . m_fcPos = = HackRFSettings : : FC_POS_INFRA )
2015-09-23 20:50:24 -04:00
{
deviceCenterFrequency = m_settings . m_centerFrequency + ( devSampleRate / 4 ) ;
f_img = deviceCenterFrequency + devSampleRate / 2 ;
}
2015-09-29 21:46:46 -04:00
else if ( m_settings . m_fcPos = = HackRFSettings : : FC_POS_SUPRA )
2015-09-23 20:50:24 -04:00
{
deviceCenterFrequency = m_settings . m_centerFrequency - ( devSampleRate / 4 ) ;
f_img = deviceCenterFrequency - devSampleRate / 2 ;
}
}
if ( m_dev ! = 0 )
{
setCenterFrequency ( deviceCenterFrequency ) ;
2015-09-27 01:37:15 -04:00
qDebug ( ) < < " HackRFInput::applySettings: center freq: " < < m_settings . m_centerFrequency < < " Hz "
2015-09-23 20:50:24 -04:00
< < " device center freq: " < < deviceCenterFrequency < < " Hz "
< < " device sample rate: " < < devSampleRate < < " Hz "
< < " Actual sample rate: " < < devSampleRate / ( 1 < < m_settings . m_log2Decim ) < < " Hz "
< < " img: " < < f_img < < " Hz " ;
}
forwardChange = true ;
}
if ( ( m_settings . m_lnaGain ! = settings . m_lnaGain ) | | force )
{
m_settings . m_lnaGain = settings . m_lnaGain ;
if ( m_dev ! = 0 )
{
2015-09-27 01:37:15 -04:00
rc = ( hackrf_error ) hackrf_set_lna_gain ( m_dev , m_settings . m_lnaGain ) ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
if ( rc ! = HACKRF_SUCCESS )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
qDebug ( " HackRFInput::applySettings: airspy_set_lna_gain failed: %s " , hackrf_error_name ( rc ) ) ;
2015-09-23 20:50:24 -04:00
}
else
{
2015-09-27 01:37:15 -04:00
qDebug ( ) < < " HackRFInput:applySettings: LNA gain set to " < < m_settings . m_lnaGain ;
2015-09-23 20:50:24 -04:00
}
}
}
2015-09-27 01:37:15 -04:00
if ( ( m_settings . m_vgaGain ! = settings . m_vgaGain ) | | force )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
m_settings . m_vgaGain = settings . m_vgaGain ;
2015-09-23 20:50:24 -04:00
if ( m_dev ! = 0 )
{
2015-09-27 01:37:15 -04:00
rc = ( hackrf_error ) hackrf_set_vga_gain ( m_dev , m_settings . m_vgaGain ) ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
if ( rc ! = HACKRF_SUCCESS )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
qDebug ( " HackRFInput::applySettings: hackrf_set_vga_gain failed: %s " , hackrf_error_name ( rc ) ) ;
2015-09-23 20:50:24 -04:00
}
else
{
2015-09-27 01:37:15 -04:00
qDebug ( ) < < " HackRFInput:applySettings: VGA gain set to " < < m_settings . m_vgaGain ;
2015-09-23 20:50:24 -04:00
}
}
}
2015-09-27 01:37:15 -04:00
if ( ( m_settings . m_bandwidthIndex ! = settings . m_bandwidthIndex ) | | force )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
if ( settings . m_bandwidthIndex < HackRFBandwidths : : m_nb_bw )
{
m_settings . m_bandwidthIndex = settings . m_bandwidthIndex ;
}
else
{
m_settings . m_bandwidthIndex = HackRFBandwidths : : m_nb_bw - 1 ;
}
2015-09-23 20:50:24 -04:00
if ( m_dev ! = 0 )
{
2015-09-27 06:50:38 -04:00
uint32_t bw_index = hackrf_compute_baseband_filter_bw_round_down_lt ( HackRFBandwidths : : m_bw_k [ m_settings . m_bandwidthIndex ] * 1000 ) ;
2015-09-27 01:37:15 -04:00
rc = ( hackrf_error ) hackrf_set_baseband_filter_bandwidth ( m_dev , bw_index ) ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
if ( rc ! = HACKRF_SUCCESS )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
qDebug ( " HackRFInput::applySettings: hackrf_set_baseband_filter_bandwidth failed: %s " , hackrf_error_name ( rc ) ) ;
2015-09-23 20:50:24 -04:00
}
else
{
2015-09-27 06:50:38 -04:00
qDebug ( ) < < " HackRFInput:applySettings: Baseband BW filter set to " < < HackRFBandwidths : : m_bw_k [ m_settings . m_bandwidthIndex ] < < " kHz " ;
2015-09-23 20:50:24 -04:00
}
}
}
if ( ( m_settings . m_biasT ! = settings . m_biasT ) | | force )
{
m_settings . m_biasT = settings . m_biasT ;
if ( m_dev ! = 0 )
{
2015-09-27 01:37:15 -04:00
rc = ( hackrf_error ) hackrf_set_antenna_enable ( m_dev , ( m_settings . m_biasT ? 1 : 0 ) ) ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
if ( rc ! = HACKRF_SUCCESS )
2015-09-23 20:50:24 -04:00
{
2015-09-27 05:27:02 -04:00
qDebug ( " HackRFInput::applySettings: hackrf_set_antenna_enable failed: %s " , hackrf_error_name ( rc ) ) ;
2015-09-23 20:50:24 -04:00
}
else
{
2015-09-27 01:37:15 -04:00
qDebug ( ) < < " HackRFInput:applySettings: bias tee set to " < < m_settings . m_biasT ;
2015-09-23 20:50:24 -04:00
}
}
}
2015-09-27 05:27:02 -04:00
if ( ( m_settings . m_lnaExt ! = settings . m_lnaExt ) | | force )
{
m_settings . m_lnaExt = settings . m_lnaExt ;
if ( m_dev ! = 0 )
{
rc = ( hackrf_error ) hackrf_set_amp_enable ( m_dev , ( m_settings . m_lnaExt ? 1 : 0 ) ) ;
if ( rc ! = HACKRF_SUCCESS )
{
qDebug ( " HackRFInput::applySettings: hackrf_set_amp_enable failed: %s " , hackrf_error_name ( rc ) ) ;
}
else
{
qDebug ( ) < < " HackRFInput:applySettings: extra LNA set to " < < m_settings . m_lnaExt ;
}
}
}
2015-09-23 20:50:24 -04:00
if ( forwardChange )
{
int sampleRate = devSampleRate / ( 1 < < m_settings . m_log2Decim ) ;
DSPSignalNotification * notif = new DSPSignalNotification ( sampleRate , m_settings . m_centerFrequency ) ;
2015-09-27 06:50:38 -04:00
DSPEngine : : instance ( ) - > getInputMessageQueue ( ) - > push ( notif ) ;
//getOutputMessageQueue()->push(notif);
2015-09-23 20:50:24 -04:00
}
return true ;
}
2015-09-27 01:37:15 -04:00
hackrf_device * HackRFInput : : open_hackrf_from_sequence ( int sequence )
2015-09-23 20:50:24 -04:00
{
2015-09-27 01:37:15 -04:00
hackrf_device_list_t * hackrf_devices = hackrf_device_list ( ) ;
hackrf_device * hackrf_ptr ;
hackrf_error rc ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
rc = ( hackrf_error ) hackrf_device_list_open ( hackrf_devices , sequence , & hackrf_ptr ) ;
2015-09-23 20:50:24 -04:00
2015-09-27 01:37:15 -04:00
if ( rc = = HACKRF_SUCCESS )
{
return hackrf_ptr ;
}
else
{
return 0 ;
}
2015-09-23 20:50:24 -04:00
}