2018-03-02 10:30:36 +00:00
/*!
* \ file ad9361_fpga_signal_source . cc
* \ brief signal source for Analog Devices front - end AD9361 connected directly to FPGA accelerators .
* This source implements only the AD9361 control . It is NOT compatible with conventional SDR acquisition and tracking blocks .
* Please use the fmcomms2 source if conventional SDR acquisition and tracking is selected in the configuration file .
2020-07-16 13:42:55 +00:00
* \ authors < ul >
* < li > Javier Arribas , jarribas ( at ) cttc . es
* < li > Marc Majoral , mmajoral ( at ) cttc . es
* < / ul >
2018-03-02 10:30:36 +00:00
*
2020-07-28 14:57:15 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2018-03-02 10:30:36 +00:00
*
2020-12-30 12:35:06 +00:00
* GNSS - SDR is a Global Navigation Satellite System software - defined receiver .
2018-03-02 10:30:36 +00:00
* This file is part of GNSS - SDR .
*
2020-12-30 12:35:06 +00:00
* Copyright ( C ) 2010 - 2020 ( see AUTHORS file for a list of contributors )
2020-02-08 00:20:02 +00:00
* SPDX - License - Identifier : GPL - 3.0 - or - later
2018-03-02 10:30:36 +00:00
*
2020-07-28 14:57:15 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2018-03-02 10:30:36 +00:00
*/
# include "ad9361_fpga_signal_source.h"
# include "GPS_L1_CA.h"
2019-10-11 10:02:53 +00:00
# include "GPS_L5.h"
2018-12-09 21:00:09 +00:00
# include "ad9361_manager.h"
2021-02-19 12:03:22 +00:00
# include "command_event.h"
2018-12-09 21:00:09 +00:00
# include "configuration_interface.h"
2019-10-13 21:38:06 +00:00
# include "gnss_sdr_flags.h"
2021-02-16 13:27:46 +00:00
# include "gnss_sdr_string_literals.h"
2020-11-26 16:07:15 +00:00
# include "uio_fpga.h"
2018-03-02 10:30:36 +00:00
# include <glog/logging.h>
2019-09-13 06:56:37 +00:00
# include <iio.h>
2019-10-08 10:57:37 +00:00
# include <algorithm> // for max
2019-10-28 12:00:18 +00:00
# include <chrono> // for std::this_thread
2019-10-08 10:57:37 +00:00
# include <cmath> // for abs
# include <exception> // for exceptions
# include <fcntl.h> // for open, O_WRONLY
# include <fstream> // for std::ifstream
2021-02-19 12:03:22 +00:00
# include <iomanip> // for std::setprecision
2020-07-07 16:53:50 +00:00
# include <iostream> // for cout
2019-10-08 10:57:37 +00:00
# include <string> // for string manipulation
2019-10-28 12:00:18 +00:00
# include <thread> // for std::chrono
2019-10-08 10:57:37 +00:00
# include <unistd.h> // for write
2018-12-10 18:29:00 +00:00
# include <utility>
2019-09-28 19:59:05 +00:00
# include <vector>
2018-03-02 10:30:36 +00:00
2019-09-28 19:59:05 +00:00
2021-02-09 22:47:34 +00:00
using namespace std : : string_literals ;
2020-06-29 07:07:41 +00:00
Ad9361FpgaSignalSource : : Ad9361FpgaSignalSource ( const ConfigurationInterface * configuration ,
2019-09-28 19:59:05 +00:00
const std : : string & role , unsigned int in_stream , unsigned int out_stream ,
2021-02-09 22:47:34 +00:00
Concurrent_Queue < pmt : : pmt_t > * queue __attribute__ ( ( unused ) ) )
2021-02-19 12:03:22 +00:00
: SignalSourceBase ( configuration , role , " Ad9361_Fpga_Signal_Source " s ) , in_stream_ ( in_stream ) , out_stream_ ( out_stream ) , queue_ ( queue )
2018-03-02 10:30:36 +00:00
{
2021-02-19 15:34:49 +00:00
// initialize the variables that are used in real-time mode
2021-02-19 12:03:22 +00:00
2020-07-17 07:11:42 +00:00
const std : : string default_gain_mode ( " slow_attack " ) ;
const double default_tx_attenuation_db = - 10.0 ;
const double default_manual_gain_rx1 = 64.0 ;
const double default_manual_gain_rx2 = 64.0 ;
const uint64_t default_bandwidth = 12500000 ;
const std : : string default_rf_port_select ( " A_BALANCED " ) ;
2020-07-03 18:18:42 +00:00
freq_ = configuration - > property ( role + " .freq " , static_cast < uint64_t > ( GPS_L1_FREQ_HZ ) ) ;
2020-07-03 19:52:40 +00:00
sample_rate_ = configuration - > property ( role + " .sampling_frequency " , static_cast < uint64_t > ( 12500000 ) ) ;
2019-10-08 14:38:30 +00:00
bandwidth_ = configuration - > property ( role + " .bandwidth " , default_bandwidth ) ;
2018-03-02 10:30:36 +00:00
quadrature_ = configuration - > property ( role + " .quadrature " , true ) ;
rf_dc_ = configuration - > property ( role + " .rf_dc " , true ) ;
bb_dc_ = configuration - > property ( role + " .bb_dc " , true ) ;
2019-10-13 21:38:06 +00:00
rx1_enable_ = configuration - > property ( role + " .rx1_enable " , true ) ;
rx2_enable_ = configuration - > property ( role + " .rx2_enable " , true ) ;
2019-10-07 20:45:09 +00:00
gain_mode_rx1_ = configuration - > property ( role + " .gain_mode_rx1 " , default_gain_mode ) ;
gain_mode_rx2_ = configuration - > property ( role + " .gain_mode_rx2 " , default_gain_mode ) ;
rf_gain_rx1_ = configuration - > property ( role + " .gain_rx1 " , default_manual_gain_rx1 ) ;
rf_gain_rx2_ = configuration - > property ( role + " .gain_rx2 " , default_manual_gain_rx2 ) ;
rf_port_select_ = configuration - > property ( role + " .rf_port_select " , default_rf_port_select ) ;
2018-03-02 10:30:36 +00:00
filter_file_ = configuration - > property ( role + " .filter_file " , std : : string ( " " ) ) ;
2019-10-09 18:50:06 +00:00
filter_filename_ = configuration - > property ( role + " .filter_filename " , filter_file_ ) ;
2019-10-07 20:45:09 +00:00
filter_auto_ = configuration - > property ( role + " .filter_auto " , false ) ;
2019-10-09 18:50:06 +00:00
if ( filter_auto_ )
{
filter_source_ = configuration - > property ( role + " .filter_source " , std : : string ( " Auto " ) ) ;
}
else
{
filter_source_ = configuration - > property ( role + " .filter_source " , std : : string ( " Off " ) ) ;
}
2020-07-09 22:37:55 +00:00
Fpass_ = configuration - > property ( role + " .Fpass " , static_cast < float > ( 0.0 ) ) ;
Fstop_ = configuration - > property ( role + " .Fstop " , static_cast < float > ( 0.0 ) ) ;
2018-05-01 10:02:50 +00:00
enable_dds_lo_ = configuration - > property ( role + " .enable_dds_lo " , false ) ;
2020-07-03 19:52:40 +00:00
freq_dds_tx_hz_ = configuration - > property ( role + " .freq_dds_tx_hz " , static_cast < uint64_t > ( 10000 ) ) ;
2020-07-03 18:18:42 +00:00
freq_rf_tx_hz_ = configuration - > property ( role + " .freq_rf_tx_hz " , static_cast < uint64_t > ( GPS_L1_FREQ_HZ - GPS_L5_FREQ_HZ - freq_dds_tx_hz_ ) ) ;
2018-05-01 10:02:50 +00:00
scale_dds_dbfs_ = configuration - > property ( role + " .scale_dds_dbfs " , - 3.0 ) ;
2019-10-07 20:45:09 +00:00
tx_attenuation_db_ = configuration - > property ( role + " .tx_attenuation_db " , default_tx_attenuation_db ) ;
2020-07-03 19:52:40 +00:00
tx_bandwidth_ = configuration - > property ( role + " .tx_bandwidth " , static_cast < uint64_t > ( 500000 ) ) ;
2019-10-08 10:57:37 +00:00
phase_dds_deg_ = configuration - > property ( role + " .phase_dds_deg " , 0.0 ) ;
2018-03-27 12:24:07 +00:00
2019-10-13 21:38:06 +00:00
rf_shutdown_ = configuration - > property ( role + " .rf_shutdown " , FLAGS_rf_shutdown ) ;
2021-02-19 15:34:49 +00:00
// initialize the variables that are used in post-processing mode
2021-02-19 12:03:22 +00:00
enable_DMA_ = false ;
const int l1_band = configuration - > property ( " Channels_1C.count " , 0 ) +
configuration - > property ( " Channels_1B.count " , 0 ) ;
const double default_seconds_to_skip = 0.0 ;
const std : : string empty_string ;
filename0 = configuration - > property ( role + " .filename " , empty_string ) ;
// override value with commandline flag, if present
if ( FLAGS_signal_source ! = " - " )
{
filename0 = FLAGS_signal_source ;
}
if ( FLAGS_s ! = " - " )
{
filename0 = FLAGS_s ;
}
if ( filename0 . empty ( ) )
{
filename0 = configuration - > property ( role + " .filename0 " , empty_string ) ;
filename1 = configuration - > property ( role + " .filename1 " , empty_string ) ;
}
2021-03-12 17:01:25 +00:00
// by default the DMA transfers samples corresponding to two frequency bands to the FPGA
num_freq_bands_ = 2 ;
dma_buff_offset_pos_ = 0 ;
// if only one input file is specified in the configuration file then:
// if there is at least one channel assigned to frequency band 1 then the DMA transfers the samples to the L1 frequency band channels
// otherwise the DMA transfers the samples to the L2/L5 frequency band channels
// if more than one input file are specified then the DMA transfer the samples to both the L1 and the L2/L5 frequency channels.
if ( filename1 . empty ( ) )
{
num_freq_bands_ = 1 ;
if ( l1_band ! = 0 )
{
dma_buff_offset_pos_ = 2 ;
}
}
else
{
dma_buff_offset_pos_ = 2 ;
}
2021-03-05 18:02:40 +00:00
samples_ = configuration - > property ( role + " .samples " , static_cast < int64_t > ( 0 ) ) ;
2021-02-19 12:03:22 +00:00
const double seconds_to_skip = configuration - > property ( role + " .seconds_to_skip " , default_seconds_to_skip ) ;
const size_t header_size = configuration - > property ( role + " .header_size " , 0 ) ;
std : : string item_type = " ibyte " ; // for now only the ibyte format is supported
item_size_ = sizeof ( int8_t ) ;
repeat_ = configuration - > property ( role + " .repeat " , false ) ;
2021-03-05 18:02:40 +00:00
samples_to_skip_ = 0 ;
2021-02-19 12:03:22 +00:00
if ( seconds_to_skip > 0 )
{
2021-03-05 18:02:40 +00:00
samples_to_skip_ = static_cast < uint64_t > ( seconds_to_skip * sample_rate_ ) * 2 ;
2021-02-19 12:03:22 +00:00
}
if ( header_size > 0 )
{
samples_to_skip_ + = header_size ;
}
// check the switch status (determines real-time mode or post-processing mode)
std : : string device_io_name ; // Switch UIO device file
2020-11-27 11:21:10 +00:00
// find the uio device file corresponding to the switch.
2020-11-27 10:24:44 +00:00
if ( find_uio_dev_file_name ( device_io_name , switch_device_name , 0 ) < 0 )
2020-11-26 16:07:15 +00:00
{
2021-02-23 20:40:53 +00:00
std : : cerr < < " Cannot find the FPGA uio device file corresponding to device name " < < switch_device_name < < ' \n ' ;
item_size_ = 0 ;
2021-02-19 12:03:22 +00:00
return ;
2020-11-26 16:07:15 +00:00
}
2021-02-13 16:10:43 +00:00
switch_position_ = configuration - > property ( role + " .switch_position " , 0 ) ;
if ( switch_position_ ! = 0 & & switch_position_ ! = 2 )
2019-10-07 20:45:09 +00:00
{
2020-07-07 16:53:50 +00:00
std : : cout < < " SignalSource.switch_position configuration parameter must be either 0: read from file(s) via DMA, or 2: read from AD9361 \n " ;
std : : cout < < " SignalSource.switch_position configuration parameter set to its default value switch_position=0 - read from file(s) \n " ;
2021-02-13 16:10:43 +00:00
switch_position_ = 0 ;
2019-10-07 20:45:09 +00:00
}
2020-11-26 16:07:15 +00:00
switch_fpga = std : : make_shared < Fpga_Switch > ( device_io_name ) ;
2021-02-13 16:10:43 +00:00
switch_fpga - > set_switch_position ( switch_position_ ) ;
2019-09-28 19:59:05 +00:00
2021-02-13 16:10:43 +00:00
if ( switch_position_ = = 0 ) // Inject file(s) via DMA
2019-09-28 19:59:05 +00:00
{
2019-10-01 21:44:07 +00:00
enable_DMA_ = true ;
2020-03-30 15:43:09 +00:00
2021-02-19 12:03:22 +00:00
if ( samples_ = = 0 ) // read all file
2020-03-30 15:43:09 +00:00
{
2021-02-19 12:03:22 +00:00
/*!
* BUG workaround : The GNU Radio file source does not stop the receiver after reaching the End of File .
* A possible solution is to compute the file length in samples using file size , excluding the last 100 milliseconds , and enable always the
* valve block
*/
std : : ifstream file ( filename0 . c_str ( ) , std : : ios : : in | std : : ios : : binary | std : : ios : : ate ) ;
std : : ifstream : : pos_type size ;
if ( file . is_open ( ) )
{
size = file . tellg ( ) ;
DLOG ( INFO ) < < " Total samples in the file= " < < floor ( static_cast < double > ( size ) / static_cast < double > ( item_size_ ) ) ;
}
else
{
2021-02-23 20:40:53 +00:00
std : : cerr < < " SignalSource: Unable to open the samples file " < < filename0 . c_str ( ) < < ' \n ' ;
item_size_ = 0 ;
2021-02-19 12:03:22 +00:00
return ;
}
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 16 ) ;
std : : cout < < " Processing file " < < filename0 < < " , which contains " < < static_cast < double > ( size ) < < " [bytes] \n " ;
std : : cout . precision ( ss ) ;
2020-03-30 15:43:09 +00:00
2021-02-19 12:03:22 +00:00
if ( size > 0 )
{
2021-03-05 18:02:40 +00:00
const uint64_t bytes_to_skip = samples_to_skip_ * item_size_ ;
const uint64_t bytes_to_process = static_cast < uint64_t > ( size ) - bytes_to_skip ;
2021-02-19 12:03:22 +00:00
samples_ = floor ( static_cast < double > ( bytes_to_process ) / static_cast < double > ( item_size_ ) - ceil ( 0.002 * static_cast < double > ( sample_rate_ ) ) ) ; // process all the samples available in the file excluding at least the last 1 ms
}
if ( ! filename1 . empty ( ) )
{
std : : ifstream file ( filename1 . c_str ( ) , std : : ios : : in | std : : ios : : binary | std : : ios : : ate ) ;
std : : ifstream : : pos_type size ;
2019-10-01 21:13:28 +00:00
2021-02-19 12:03:22 +00:00
if ( file . is_open ( ) )
{
size = file . tellg ( ) ;
DLOG ( INFO ) < < " Total samples in the file= " < < floor ( static_cast < double > ( size ) / static_cast < double > ( item_size_ ) ) ;
}
else
{
2021-02-23 20:40:53 +00:00
std : : cerr < < " SignalSource: Unable to open the samples file " < < filename1 . c_str ( ) < < ' \n ' ;
item_size_ = 0 ;
2021-02-19 12:03:22 +00:00
return ;
}
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 16 ) ;
std : : cout < < " Processing file " < < filename1 < < " , which contains " < < static_cast < double > ( size ) < < " [bytes] \n " ;
std : : cout . precision ( ss ) ;
2019-09-28 19:59:05 +00:00
2021-03-05 18:02:40 +00:00
int64_t samples_rx2 = 0 ;
2021-02-19 12:03:22 +00:00
if ( size > 0 )
{
2021-03-05 18:02:40 +00:00
const uint64_t bytes_to_skip = samples_to_skip_ * item_size_ ;
const uint64_t bytes_to_process = static_cast < uint64_t > ( size ) - bytes_to_skip ;
2021-02-19 12:03:22 +00:00
samples_rx2 = floor ( static_cast < double > ( bytes_to_process ) / static_cast < double > ( item_size_ ) - ceil ( 0.002 * static_cast < double > ( sample_rate_ ) ) ) ; // process all the samples available in the file excluding at least the last 1 ms
}
samples_ = std : : min ( samples_ , samples_rx2 ) ;
}
2019-09-28 19:59:05 +00:00
}
2021-02-19 12:03:22 +00:00
CHECK ( samples_ > 0 ) < < " File does not contain enough samples to process. " ;
double signal_duration_s = ( static_cast < double > ( samples_ ) * ( 1 / static_cast < double > ( sample_rate_ ) ) ) / 2.0 ;
DLOG ( INFO ) < < " Total number samples to be processed= " < < samples_ < < " GNSS signal duration= " < < signal_duration_s < < " [s] " ;
std : : cout < < " GNSS signal recorded time to be processed: " < < signal_duration_s < < " [s] \n " ;
if ( filename1 . empty ( ) )
2019-09-28 19:59:05 +00:00
{
2021-02-19 12:03:22 +00:00
DLOG ( INFO ) < < " File source filename " < < filename0 ;
2019-09-28 19:59:05 +00:00
}
2021-02-19 12:03:22 +00:00
else
2019-09-28 19:59:05 +00:00
{
2021-02-19 12:03:22 +00:00
DLOG ( INFO ) < < " File source filename rx1 " < < filename0 ;
DLOG ( INFO ) < < " File source filename rx2 " < < filename1 ;
2019-09-28 19:59:05 +00:00
}
2021-02-19 12:03:22 +00:00
DLOG ( INFO ) < < " Samples " < < samples_ ;
DLOG ( INFO ) < < " Sampling frequency " < < sample_rate_ ;
DLOG ( INFO ) < < " Item type " < < item_type ;
DLOG ( INFO ) < < " Item size " < < item_size_ ;
DLOG ( INFO ) < < " Repeat " < < repeat_ ;
2019-09-28 19:59:05 +00:00
}
2021-02-13 16:10:43 +00:00
if ( switch_position_ = = 2 ) // Real-time via AD9361
2019-09-28 19:59:05 +00:00
{
2021-02-19 12:03:22 +00:00
std : : cout < < " Sample rate: " < < sample_rate_ < < " Sps \n " ;
enable_ovf_check_buffer_monitor_active_ = false ; // check buffer overflow and buffer monitor disabled by default
2019-10-06 17:07:24 +00:00
// some basic checks
if ( ( rf_port_select_ ! = " A_BALANCED " ) and ( rf_port_select_ ! = " B_BALANCED " ) and ( rf_port_select_ ! = " A_N " ) and ( rf_port_select_ ! = " B_N " ) and ( rf_port_select_ ! = " B_P " ) and ( rf_port_select_ ! = " C_N " ) and ( rf_port_select_ ! = " C_P " ) and ( rf_port_select_ ! = " TX_MONITOR1 " ) and ( rf_port_select_ ! = " TX_MONITOR2 " ) and ( rf_port_select_ ! = " TX_MONITOR1_2 " ) )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter rf_port_select should take one of these values: \n " ;
std : : cout < < " A_BALANCED, B_BALANCED, A_N, B_N, B_P, C_N, C_P, TX_MONITOR1, TX_MONITOR2, TX_MONITOR1_2 \n " ;
std : : cout < < " Error: provided value rf_port_select= " < < rf_port_select_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value rf_port_select= " < < default_rf_port_select < < ' \n ' ;
2019-10-07 20:45:09 +00:00
rf_port_select_ = default_rf_port_select ;
LOG ( WARNING ) < < " Invalid configuration value for rf_port_select parameter. Set to rf_port_select= " < < default_rf_port_select ;
2019-10-06 17:07:24 +00:00
}
if ( ( gain_mode_rx1_ ! = " manual " ) and ( gain_mode_rx1_ ! = " slow_attack " ) and ( gain_mode_rx1_ ! = " fast_attack " ) and ( gain_mode_rx1_ ! = " hybrid " ) )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter gain_mode_rx1 should take one of these values: \n " ;
std : : cout < < " manual, slow_attack, fast_attack, hybrid \n " ;
std : : cout < < " Error: provided value gain_mode_rx1= " < < gain_mode_rx1_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value gain_mode_rx1= " < < default_gain_mode < < ' \n ' ;
2019-10-07 20:45:09 +00:00
gain_mode_rx1_ = default_gain_mode ;
LOG ( WARNING ) < < " Invalid configuration value for gain_mode_rx1 parameter. Set to gain_mode_rx1= " < < default_gain_mode ;
2019-10-06 17:07:24 +00:00
}
if ( ( gain_mode_rx2_ ! = " manual " ) and ( gain_mode_rx2_ ! = " slow_attack " ) and ( gain_mode_rx2_ ! = " fast_attack " ) and ( gain_mode_rx2_ ! = " hybrid " ) )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter gain_mode_rx2 should take one of these values: \n " ;
std : : cout < < " manual, slow_attack, fast_attack, hybrid \n " ;
std : : cout < < " Error: provided value gain_mode_rx2= " < < gain_mode_rx2_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value gain_mode_rx2= " < < default_gain_mode < < ' \n ' ;
2019-10-07 20:45:09 +00:00
gain_mode_rx2_ = default_gain_mode ;
LOG ( WARNING ) < < " Invalid configuration value for gain_mode_rx2 parameter. Set to gain_mode_rx2= " < < default_gain_mode ;
2019-10-06 17:07:24 +00:00
}
2019-10-07 20:45:09 +00:00
if ( gain_mode_rx1_ = = " manual " )
{
if ( rf_gain_rx1_ > 73.0 or rf_gain_rx1_ < - 1.0 )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter rf_gain_rx1 should take values between -1.0 and 73 dB \n " ;
std : : cout < < " Error: provided value rf_gain_rx1= " < < rf_gain_rx1_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value rf_gain_rx1= " < < default_manual_gain_rx1 < < ' \n ' ;
2019-10-07 20:45:09 +00:00
rf_gain_rx1_ = default_manual_gain_rx1 ;
LOG ( WARNING ) < < " Invalid configuration value for rf_gain_rx1 parameter. Set to rf_gain_rx1= " < < default_manual_gain_rx1 ;
}
}
if ( gain_mode_rx2_ = = " manual " )
{
if ( rf_gain_rx2_ > 73.0 or rf_gain_rx2_ < - 1.0 )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter rf_gain_rx2 should take values between -1.0 and 73 dB \n " ;
std : : cout < < " Error: provided value rf_gain_rx2= " < < rf_gain_rx2_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value rf_gain_rx2= " < < default_manual_gain_rx2 < < ' \n ' ;
2019-10-07 20:45:09 +00:00
rf_gain_rx2_ = default_manual_gain_rx2 ;
LOG ( WARNING ) < < " Invalid configuration value for rf_gain_rx2 parameter. Set to rf_gain_rx2= " < < default_manual_gain_rx2 ;
}
}
2019-09-28 19:59:05 +00:00
2019-10-09 18:50:06 +00:00
if ( ( filter_source_ ! = " Off " ) and ( filter_source_ ! = " Auto " ) and ( filter_source_ ! = " File " ) and ( filter_source_ ! = " Design " ) )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter filter_source should take one of these values: \n " ;
std : : cout < < " Off: Disable filter \n " ;
std : : cout < < " Auto: Use auto-generated filters \n " ;
std : : cout < < " File: User-provided filter in filter_filename parameter \n " ;
std : : cout < < " Design: Create filter from Fpass, Fstop, sampling_frequency and bandwidth parameters \n " ;
std : : cout < < " Error: provided value filter_source= " < < filter_source_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value filter_source=Off \n " ;
2019-10-09 18:50:06 +00:00
filter_source_ = std : : string ( " Off " ) ;
LOG ( WARNING ) < < " Invalid configuration value for filter_source parameter. Set to filter_source=Off " ;
}
2019-10-08 14:38:30 +00:00
if ( bandwidth_ < 200000 or bandwidth_ > 56000000 )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter bandwidth should take values between 200000 and 56000000 Hz \n " ;
std : : cout < < " Error: provided value bandwidth= " < < bandwidth_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value bandwidth= " < < default_bandwidth < < ' \n ' ;
2019-10-08 14:38:30 +00:00
bandwidth_ = default_bandwidth ;
LOG ( WARNING ) < < " Invalid configuration value for bandwidth parameter. Set to bandwidth= " < < default_bandwidth ;
}
2020-07-07 16:53:50 +00:00
std : : cout < < " LO frequency : " < < freq_ < < " Hz \n " ;
2019-10-07 20:45:09 +00:00
try
{
config_ad9361_rx_local ( bandwidth_ ,
sample_rate_ ,
freq_ ,
rf_port_select_ ,
2019-10-13 21:38:06 +00:00
rx1_enable_ ,
rx2_enable_ ,
2019-10-07 20:45:09 +00:00
gain_mode_rx1_ ,
gain_mode_rx2_ ,
rf_gain_rx1_ ,
rf_gain_rx2_ ,
quadrature_ ,
rf_dc_ ,
2019-10-09 18:50:06 +00:00
bb_dc_ ,
filter_source_ ,
filter_filename_ ,
Fpass_ ,
Fstop_ ) ;
2019-10-07 20:45:09 +00:00
}
catch ( const std : : runtime_error & e )
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Exception cached when configuring the RX chain: " < < e . what ( ) < < ' \n ' ;
2021-02-23 20:40:53 +00:00
item_size_ = 0 ;
2021-02-19 12:03:22 +00:00
return ;
2019-10-07 20:45:09 +00:00
}
2019-09-28 19:59:05 +00:00
// LOCAL OSCILLATOR DDS GENERATOR FOR DUAL FREQUENCY OPERATION
if ( enable_dds_lo_ = = true )
{
2019-10-08 10:57:37 +00:00
if ( tx_bandwidth_ < static_cast < uint64_t > ( std : : floor ( static_cast < float > ( freq_dds_tx_hz_ ) * 1.1 ) ) or ( tx_bandwidth_ < 200000 ) or ( tx_bandwidth_ > 1000000 ) )
2019-10-07 20:45:09 +00:00
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter tx_bandwidth value should be between " < < std : : max ( static_cast < float > ( freq_dds_tx_hz_ ) * 1.1 , 200000.0 ) < < " and 1000000 Hz \n " ;
std : : cout < < " Error: provided value tx_bandwidth= " < < tx_bandwidth_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value tx_bandwidth=500000 \n " ;
2019-10-07 20:45:09 +00:00
tx_bandwidth_ = 500000 ;
LOG ( WARNING ) < < " Invalid configuration value for tx_bandwidth parameter. Set to tx_bandwidth=500000 " ;
}
if ( tx_attenuation_db_ > 0.0 or tx_attenuation_db_ < - 89.75 )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Configuration parameter tx_attenuation_db should take values between 0.0 and -89.95 in 0.25 dB steps \n " ;
std : : cout < < " Error: provided value tx_attenuation_db= " < < tx_attenuation_db_ < < " is not among valid values \n " ;
std : : cout < < " This parameter has been set to its default value tx_attenuation_db= " < < default_tx_attenuation_db < < ' \n ' ;
2019-10-07 20:45:09 +00:00
tx_attenuation_db_ = default_tx_attenuation_db ;
LOG ( WARNING ) < < " Invalid configuration value for tx_attenuation_db parameter. Set to tx_attenuation_db= " < < default_tx_attenuation_db ;
}
2019-10-08 10:57:37 +00:00
try
{
config_ad9361_lo_local ( tx_bandwidth_ ,
sample_rate_ ,
freq_rf_tx_hz_ ,
tx_attenuation_db_ ,
freq_dds_tx_hz_ ,
scale_dds_dbfs_ ,
phase_dds_deg_ ) ;
}
catch ( const std : : runtime_error & e )
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Exception cached when configuring the TX carrier: " < < e . what ( ) < < ' \n ' ;
2021-02-23 20:40:53 +00:00
item_size_ = 0 ;
2021-02-19 12:03:22 +00:00
return ;
2019-10-08 10:57:37 +00:00
}
2019-09-28 19:59:05 +00:00
}
2021-02-13 16:10:43 +00:00
2021-02-15 10:53:16 +00:00
// when the receiver is working in real-time mode via AD9361 perform buffer overflow checking,
// and if dump is enabled perform buffer monitoring
enable_ovf_check_buffer_monitor_active_ = true ;
2021-02-13 16:10:43 +00:00
std : : string device_io_name_buffer_monitor ;
2021-02-15 10:53:16 +00:00
dump_ = configuration - > property ( role + " .dump " , false ) ;
std : : string dump_filename = configuration - > property ( role + " .dump_filename " , default_dump_filename ) ;
2021-02-13 16:10:43 +00:00
// find the uio device file corresponding to the buffer monitor
if ( find_uio_dev_file_name ( device_io_name_buffer_monitor , buffer_monitor_device_name , 0 ) < 0 )
{
2021-02-23 20:40:53 +00:00
std : : cerr < < " Cannot find the FPGA uio device file corresponding to device name " < < buffer_monitor_device_name < < ' \n ' ;
item_size_ = 0 ;
2021-02-19 12:03:22 +00:00
return ;
2021-02-13 16:10:43 +00:00
}
2021-02-19 12:03:22 +00:00
buffer_monitor_fpga = std : : make_shared < Fpga_buffer_monitor > ( device_io_name_buffer_monitor , num_freq_bands_ , dump_ , dump_filename ) ;
2021-02-13 16:10:43 +00:00
thread_buffer_monitor = std : : thread ( [ & ] { run_buffer_monitor_process ( ) ; } ) ;
2019-09-28 19:59:05 +00:00
}
2019-10-07 20:45:09 +00:00
2020-07-16 13:42:55 +00:00
// dynamic bits selection
enable_dynamic_bit_selection_ = configuration - > property ( role + " .enable_dynamic_bit_selection " , true ) ;
if ( enable_dynamic_bit_selection_ )
{
2021-02-24 11:08:10 +00:00
std : : string device_io_name_dyn_bit_sel_0 ;
std : : string device_io_name_dyn_bit_sel_1 ;
2020-11-27 10:24:44 +00:00
2020-11-27 11:21:10 +00:00
// find the uio device file corresponding to the dynamic bit selector 0 module.
2020-11-27 10:24:44 +00:00
if ( find_uio_dev_file_name ( device_io_name_dyn_bit_sel_0 , dyn_bit_sel_device_name , 0 ) < 0 )
{
2021-02-23 20:40:53 +00:00
std : : cerr < < " Cannot find the FPGA uio device file corresponding to device name " < < dyn_bit_sel_device_name < < ' \n ' ;
item_size_ = 0 ;
2021-02-19 12:03:22 +00:00
return ;
2020-11-27 10:24:44 +00:00
}
2020-11-27 11:21:10 +00:00
// find the uio device file corresponding to the dynamic bit selector 1 module.
2020-11-27 10:24:44 +00:00
if ( find_uio_dev_file_name ( device_io_name_dyn_bit_sel_1 , dyn_bit_sel_device_name , 1 ) < 0 )
{
2021-02-23 20:40:53 +00:00
std : : cerr < < " Cannot find the FPGA uio device file corresponding to device name " < < dyn_bit_sel_device_name < < ' \n ' ;
item_size_ = 0 ;
2021-02-19 12:03:22 +00:00
return ;
2020-11-27 10:24:44 +00:00
}
dynamic_bit_selection_fpga = std : : make_shared < Fpga_dynamic_bit_selection > ( device_io_name_dyn_bit_sel_0 , device_io_name_dyn_bit_sel_1 ) ;
2020-07-16 13:42:55 +00:00
thread_dynamic_bit_selection = std : : thread ( [ & ] { run_dynamic_bit_selection_process ( ) ; } ) ;
}
2018-06-03 20:43:53 +00:00
if ( in_stream_ > 0 )
{
LOG ( ERROR ) < < " A signal source does not have an input stream " ;
}
if ( out_stream_ > 1 )
{
LOG ( ERROR ) < < " This implementation only supports one output stream " ;
}
2018-03-02 10:30:36 +00:00
}
Ad9361FpgaSignalSource : : ~ Ad9361FpgaSignalSource ( )
{
/* cleanup and exit */
2021-02-13 16:10:43 +00:00
if ( switch_position_ = = 0 ) // read samples from a file via DMA
2018-05-01 10:02:50 +00:00
{
2020-07-01 15:42:40 +00:00
std : : unique_lock < std : : mutex > lock ( dma_mutex ) ;
2019-10-13 21:38:06 +00:00
enable_DMA_ = false ; // disable the DMA
2020-07-01 15:42:40 +00:00
lock . unlock ( ) ;
2019-10-13 21:38:06 +00:00
if ( thread_file_to_dma . joinable ( ) )
2018-05-19 20:42:08 +00:00
{
2019-10-13 21:38:06 +00:00
thread_file_to_dma . join ( ) ;
2018-05-19 20:42:08 +00:00
}
2018-05-01 10:02:50 +00:00
}
2019-10-13 21:38:06 +00:00
2021-02-13 16:10:43 +00:00
if ( switch_position_ = = 2 ) // Real-time via AD9361
2019-09-28 19:59:05 +00:00
{
2019-10-13 21:38:06 +00:00
if ( rf_shutdown_ )
2019-09-28 19:59:05 +00:00
{
2019-10-13 21:38:06 +00:00
std : : cout < < " * AD9361 Disabling RX streaming channels \n " ;
if ( ! disable_ad9361_rx_local ( ) )
{
LOG ( WARNING ) < < " Problem shutting down the AD9361 RX channels " ;
}
if ( enable_dds_lo_ )
{
try
{
ad9361_disable_lo_local ( ) ;
}
catch ( const std : : exception & e )
{
LOG ( WARNING ) < < " Problem shutting down the AD9361 TX stream: " < < e . what ( ) ;
}
}
2019-09-28 19:59:05 +00:00
}
2021-02-13 16:10:43 +00:00
// disable buffer overflow checking and buffer monitoring
std : : unique_lock < std : : mutex > lock ( buffer_monitor_mutex ) ;
2021-02-15 10:53:16 +00:00
enable_ovf_check_buffer_monitor_active_ = false ;
2021-02-13 16:10:43 +00:00
lock . unlock ( ) ;
if ( thread_buffer_monitor . joinable ( ) )
{
thread_buffer_monitor . join ( ) ;
}
2019-09-28 19:59:05 +00:00
}
2020-07-16 13:42:55 +00:00
std : : unique_lock < std : : mutex > lock ( dynamic_bit_selection_mutex ) ;
bool bit_selection_enabled = enable_dynamic_bit_selection_ ;
lock . unlock ( ) ;
if ( bit_selection_enabled = = true )
{
std : : unique_lock < std : : mutex > lock ( dynamic_bit_selection_mutex ) ;
enable_dynamic_bit_selection_ = false ;
lock . unlock ( ) ;
if ( thread_dynamic_bit_selection . joinable ( ) )
{
thread_dynamic_bit_selection . join ( ) ;
}
}
2018-03-02 10:30:36 +00:00
}
2021-02-23 20:40:53 +00:00
2020-09-09 08:34:23 +00:00
void Ad9361FpgaSignalSource : : start ( )
{
2021-02-19 12:03:22 +00:00
thread_file_to_dma = std : : thread ( [ & ] { run_DMA_process ( filename0 , filename1 , samples_to_skip_ , item_size_ , samples_ , repeat_ , dma_buff_offset_pos_ , queue_ ) ; } ) ;
2020-09-09 08:34:23 +00:00
}
2018-03-02 10:30:36 +00:00
2021-03-05 18:02:40 +00:00
void Ad9361FpgaSignalSource : : run_DMA_process ( const std : : string & filename0 , const std : : string & filename1 , uint64_t & samples_to_skip , size_t & item_size , int64_t & samples , bool & repeat , uint32_t & dma_buff_offset_pos , Concurrent_Queue < pmt : : pmt_t > * queue )
2020-06-18 09:49:28 +00:00
{
std : : ifstream infile1 ;
infile1 . exceptions ( std : : ifstream : : failbit | std : : ifstream : : badbit ) ;
2021-02-19 12:03:22 +00:00
// open the files
2020-06-18 09:49:28 +00:00
try
{
2021-02-19 12:03:22 +00:00
infile1 . open ( filename0 , std : : ios : : binary ) ;
2020-06-18 09:49:28 +00:00
}
catch ( const std : : ifstream : : failure & e )
{
2021-02-23 20:40:53 +00:00
std : : cerr < < " Exception opening file " < < filename0 < < ' \n ' ;
2021-02-19 12:03:22 +00:00
// stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
2020-06-18 09:49:28 +00:00
return ;
}
std : : ifstream infile2 ;
2021-02-19 12:03:22 +00:00
if ( ! filename1 . empty ( ) )
{
infile2 . exceptions ( std : : ifstream : : failbit | std : : ifstream : : badbit ) ;
try
{
infile2 . open ( filename1 , std : : ios : : binary ) ;
}
catch ( const std : : ifstream : : failure & e )
{
2021-02-23 20:40:53 +00:00
std : : cerr < < " Exception opening file " < < filename1 < < ' \n ' ;
2021-02-19 12:03:22 +00:00
// stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
return ;
}
}
// skip the initial samples if needed
uint64_t bytes_to_skeep = samples_to_skip * item_size ;
2020-06-18 09:49:28 +00:00
try
{
2021-02-19 12:03:22 +00:00
infile1 . ignore ( bytes_to_skeep ) ;
2020-06-18 09:49:28 +00:00
}
catch ( const std : : ifstream : : failure & e )
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Exception skipping initial samples file " < < filename0 < < ' \n ' ;
// stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
return ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
if ( ! filename1 . empty ( ) )
{
try
{
infile2 . ignore ( bytes_to_skeep ) ;
}
catch ( const std : : ifstream : : failure & e )
{
std : : cerr < < " Exception skipping initial samples file " < < filename1 < < ' \n ' ;
// stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
return ;
}
}
// rx signal vectors
std : : vector < int8_t > input_samples ( sample_block_size * 2 ) ; // complex samples
std : : vector < int8_t > input_samples_dma ( sample_block_size * 4 ) ; // complex samples, two frequency bands
2020-06-18 09:49:28 +00:00
2021-02-19 12:03:22 +00:00
int nread_elements = 0 ; // num bytes read from the file corresponding to frequency band 1
bool run_DMA = true ;
2020-06-18 09:49:28 +00:00
int num_transferred_bytes ;
// Open DMA device
2021-10-08 08:14:38 +00:00
int tx_fd = open ( " /dev/loop_tx " , O_WRONLY ) ;
if ( tx_fd < 0 )
{
std : : cerr < < " Cannot open loop device \n " ;
// stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
return ;
}
// note: a problem was identified with the DMA: when switching from tx to rx or rx to tx mode
// the DMA transmission may hang. This problem will be fixed soon.
// for the moment this problem can be avoided by closing and opening the DMA a second time
if ( close ( tx_fd ) < 0 )
{
std : : cerr < < " Error closing loop device " < < ' \n ' ;
}
// open the DMA a second time
tx_fd = open ( " /dev/loop_tx " , O_WRONLY ) ;
2020-06-18 09:49:28 +00:00
if ( tx_fd < 0 )
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Cannot open loop device \n " ;
// stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
2020-06-18 09:49:28 +00:00
return ;
}
2021-02-19 12:03:22 +00:00
// if only one frequency band is used then clear the samples corresponding to the unused frequency band
uint32_t dma_index = 0 ;
if ( num_freq_bands_ = = 1 )
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
// if only one file is enabled then clear the samples corresponding to the frequency band that is not used.
for ( int index0 = 0 ; index0 < ( nread_elements ) ; index0 + = 2 )
{
input_samples_dma [ dma_index + ( 2 - dma_buff_offset_pos ) ] = 0 ;
input_samples_dma [ dma_index + 1 + ( 2 - dma_buff_offset_pos ) ] = 0 ;
dma_index + = 4 ;
}
}
uint64_t nbytes_remaining = samples * item_size ;
uint32_t read_buffer_size = sample_block_size * 2 ; // complex samples
2020-06-18 09:49:28 +00:00
2021-02-19 12:03:22 +00:00
// run the DMA
while ( run_DMA )
{
2021-03-12 17:01:25 +00:00
dma_index = 0 ;
2021-02-19 12:03:22 +00:00
if ( nbytes_remaining < read_buffer_size )
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
read_buffer_size = nbytes_remaining ;
}
nbytes_remaining = nbytes_remaining - read_buffer_size ;
2020-06-18 09:49:28 +00:00
2021-02-19 12:03:22 +00:00
// read filename 0
try
{
infile1 . read ( reinterpret_cast < char * > ( input_samples . data ( ) ) , read_buffer_size ) ;
}
catch ( const std : : ifstream : : failure & e )
{
std : : cerr < < " Exception reading file " < < filename0 < < ' \n ' ;
break ;
}
if ( infile1 )
{
nread_elements = read_buffer_size ;
}
else
{
// FLAG AS ERROR !! IT SHOULD NEVER HAPPEN
nread_elements = infile1 . gcount ( ) ;
}
2020-06-18 09:49:28 +00:00
2021-02-19 12:03:22 +00:00
for ( int index0 = 0 ; index0 < ( nread_elements ) ; index0 + = 2 )
{
// dma_buff_offset_pos is 1 for the L1 band and 0 for the other bands
input_samples_dma [ dma_index + dma_buff_offset_pos ] = input_samples [ index0 ] ;
input_samples_dma [ dma_index + 1 + dma_buff_offset_pos ] = input_samples [ index0 + 1 ] ;
dma_index + = 4 ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
// read filename 1 (if enabled)
if ( num_freq_bands_ > 1 )
2020-06-18 09:49:28 +00:00
{
2021-03-12 17:01:25 +00:00
dma_index = 0 ;
2020-06-18 09:49:28 +00:00
try
{
2021-03-12 17:01:25 +00:00
infile2 . read ( reinterpret_cast < char * > ( input_samples . data ( ) ) , read_buffer_size ) ;
2020-06-18 09:49:28 +00:00
}
catch ( const std : : ifstream : : failure & e )
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Exception reading file " < < filename1 < < ' \n ' ;
break ;
2020-06-18 09:49:28 +00:00
}
2021-03-12 17:01:25 +00:00
if ( infile2 )
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
nread_elements = read_buffer_size ;
2020-06-18 09:49:28 +00:00
}
else
{
2021-02-19 12:03:22 +00:00
// FLAG AS ERROR !! IT SHOULD NEVER HAPPEN
2021-03-12 17:01:25 +00:00
nread_elements = infile2 . gcount ( ) ;
2020-06-18 09:49:28 +00:00
}
for ( int index0 = 0 ; index0 < ( nread_elements ) ; index0 + = 2 )
{
2021-02-19 12:03:22 +00:00
// filename2 is never the L1 band
2020-06-18 09:49:28 +00:00
input_samples_dma [ dma_index ] = input_samples [ index0 ] ;
input_samples_dma [ dma_index + 1 ] = input_samples [ index0 + 1 ] ;
dma_index + = 4 ;
}
}
2021-02-19 12:03:22 +00:00
if ( nread_elements > 0 )
{
num_transferred_bytes = nread_elements * 2 ;
const int num_bytes_sent = write ( tx_fd , input_samples_dma . data ( ) , nread_elements * 2 ) ;
if ( num_bytes_sent ! = num_transferred_bytes )
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Error: DMA could not send all the required samples \n " ;
break ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
// Throttle the DMA
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
}
2020-06-18 09:49:28 +00:00
2021-02-19 12:03:22 +00:00
if ( nbytes_remaining = = 0 )
{
if ( repeat )
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
// read the file again
nbytes_remaining = samples * item_size ;
read_buffer_size = sample_block_size * 2 ;
try
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
infile1 . seekg ( 0 ) ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
catch ( const std : : ifstream : : failure & e )
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Exception resetting the position of the next byte to be extracted to zero " < < filename0 < < ' \n ' ;
break ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
// skip the initial samples if needed
uint64_t bytes_to_skeep = samples_to_skip * item_size ;
try
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
infile1 . ignore ( bytes_to_skeep ) ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
catch ( const std : : ifstream : : failure & e )
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Exception skipping initial samples file " < < filename0 < < ' \n ' ;
break ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
if ( ! filename1 . empty ( ) )
{
try
{
infile2 . seekg ( 0 ) ;
}
catch ( const std : : ifstream : : failure & e )
{
std : : cerr < < " Exception setting the position of the next byte to be extracted to zero " < < filename1 < < ' \n ' ;
break ;
}
try
{
infile2 . ignore ( bytes_to_skeep ) ;
}
catch ( const std : : ifstream : : failure & e )
{
std : : cerr < < " Exception skipping initial samples file " < < filename1 < < ' \n ' ;
break ;
}
}
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
else
2020-06-18 09:49:28 +00:00
{
2021-02-19 12:03:22 +00:00
// the input file is completely processed. Stop the receiver.
2021-02-19 15:34:49 +00:00
run_DMA = false ;
2020-06-18 09:49:28 +00:00
}
}
2020-07-01 15:42:40 +00:00
std : : unique_lock < std : : mutex > lock ( dma_mutex ) ;
if ( enable_DMA_ = = false )
{
2021-02-19 12:03:22 +00:00
run_DMA = false ;
2020-07-01 15:42:40 +00:00
}
lock . unlock ( ) ;
2020-06-18 09:49:28 +00:00
}
2020-10-15 21:55:36 +00:00
if ( close ( tx_fd ) < 0 )
{
std : : cerr < < " Error closing loop device " < < ' \n ' ;
}
2020-06-18 09:49:28 +00:00
try
{
infile1 . close ( ) ;
}
catch ( const std : : ifstream : : failure & e )
{
2021-02-19 12:03:22 +00:00
std : : cerr < < " Exception closing file " < < filename0 < < ' \n ' ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
if ( num_freq_bands_ > 1 )
{
try
{
infile2 . close ( ) ;
}
catch ( const std : : ifstream : : failure & e )
{
std : : cerr < < " Exception closing file " < < filename1 < < ' \n ' ;
}
}
// Stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
2020-06-18 09:49:28 +00:00
}
2020-07-17 07:11:42 +00:00
2020-08-27 10:48:20 +00:00
void Ad9361FpgaSignalSource : : run_dynamic_bit_selection_process ( )
2020-07-16 13:42:55 +00:00
{
bool dynamic_bit_selection_active = true ;
while ( dynamic_bit_selection_active )
{
// setting the bit selection to the top bits
dynamic_bit_selection_fpga - > bit_selection ( ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( Gain_control_period_ms ) ) ;
std : : unique_lock < std : : mutex > lock ( dynamic_bit_selection_mutex ) ;
if ( enable_dynamic_bit_selection_ = = false )
{
dynamic_bit_selection_active = false ;
}
lock . unlock ( ) ;
}
}
2020-06-18 09:49:28 +00:00
2021-02-23 20:40:53 +00:00
2021-02-13 16:10:43 +00:00
void Ad9361FpgaSignalSource : : run_buffer_monitor_process ( )
{
bool enable_ovf_check_buffer_monitor_active = true ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( buffer_monitoring_initial_delay_ms ) ) ;
while ( enable_ovf_check_buffer_monitor_active )
{
2021-02-15 10:53:16 +00:00
buffer_monitor_fpga - > check_buffer_overflow_and_monitor_buffer_status ( ) ;
2021-02-13 16:10:43 +00:00
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( buffer_monitor_period_ms ) ) ;
std : : unique_lock < std : : mutex > lock ( buffer_monitor_mutex ) ;
2021-02-15 10:53:16 +00:00
if ( enable_ovf_check_buffer_monitor_active_ = = false )
2021-02-13 16:10:43 +00:00
{
enable_ovf_check_buffer_monitor_active = false ;
}
lock . unlock ( ) ;
}
}
2020-07-17 07:11:42 +00:00
2018-03-02 10:30:36 +00:00
void Ad9361FpgaSignalSource : : connect ( gr : : top_block_sptr top_block )
{
2018-05-19 19:36:17 +00:00
if ( top_block )
{ /* top_block is not null */
} ;
2018-03-02 10:30:36 +00:00
DLOG ( INFO ) < < " AD9361 FPGA source nothing to connect " ;
}
void Ad9361FpgaSignalSource : : disconnect ( gr : : top_block_sptr top_block )
{
2018-05-19 19:36:17 +00:00
if ( top_block )
{ /* top_block is not null */
} ;
2018-03-02 10:30:36 +00:00
DLOG ( INFO ) < < " AD9361 FPGA source nothing to disconnect " ;
}
gr : : basic_block_sptr Ad9361FpgaSignalSource : : get_left_block ( )
{
LOG ( WARNING ) < < " Trying to get signal source left block. " ;
return gr : : basic_block_sptr ( ) ;
}
gr : : basic_block_sptr Ad9361FpgaSignalSource : : get_right_block ( )
{
return gr : : basic_block_sptr ( ) ;
}