2018-03-02 10:30:36 +00:00
/*!
* \ file ad9361_fpga_signal_source . cc
2021-12-28 18:14:18 +00:00
* \ 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>
2021-12-28 18:14:18 +00:00
# include <algorithm> // for std::max
# include <chrono> // for std::chrono
# include <cmath> // for std::floor
# include <exception> // for std::exception
2019-10-08 10:57:37 +00:00
# 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
2021-12-28 18:14:18 +00:00
# include <iostream> // for std::cout
2019-10-08 10:57:37 +00:00
# include <unistd.h> // for write
2021-12-28 18:14:18 +00:00
# include <vector> // fr std::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-12-28 18:14:18 +00:00
: SignalSourceBase ( configuration , role , " Ad9361_Fpga_Signal_Source " s ) ,
queue_ ( queue ) ,
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_port_select_ ( configuration - > property ( role + " .rf_port_select " , default_rf_port_select ) ) ,
filter_filename_ ( configuration - > property ( role + " .filter_filename " , filter_file_ ) ) ,
2022-04-28 16:41:31 +00:00
filename0_ ( configuration - > property ( role + " .filename " , empty_string ) ) ,
2021-12-28 18:14:18 +00:00
rf_gain_rx1_ ( configuration - > property ( role + " .gain_rx1 " , default_manual_gain_rx1 ) ) ,
2022-05-18 16:04:43 +00:00
rf_gain_rx2_ ( configuration - > property ( role + " .gain_rx2 " , default_manual_gain_rx2 ) ) ,
2023-09-13 15:19:10 +00:00
scale_dds_dbfs_ ( configuration - > property ( role + " .scale_dds_dbfs " , - 3.0 ) ) ,
phase_dds_deg_ ( configuration - > property ( role + " .phase_dds_deg " , 0.0 ) ) ,
tx_attenuation_db_ ( configuration - > property ( role + " .tx_attenuation_db " , default_tx_attenuation_db ) ) ,
2022-05-13 16:12:25 +00:00
freq0_ ( configuration - > property ( role + " .freq " , 0 ) ) ,
2022-05-30 07:02:22 +00:00
freq1_ ( configuration - > property ( role + " .freq1 " , static_cast < uint64_t > ( GPS_L5_FREQ_HZ ) ) ) ,
2021-12-28 18:14:18 +00:00
sample_rate_ ( configuration - > property ( role + " .sampling_frequency " , default_bandwidth ) ) ,
bandwidth_ ( configuration - > property ( role + " .bandwidth " , default_bandwidth ) ) ,
samples_to_skip_ ( 0 ) ,
samples_ ( configuration - > property ( role + " .samples " , static_cast < int64_t > ( 0 ) ) ) ,
2023-09-13 15:19:10 +00:00
freq_dds_tx_hz_ ( configuration - > property ( role + " .freq_dds_tx_hz " , uint64_t ( 10000 ) ) ) ,
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_ ) ) ) ,
tx_bandwidth_ ( configuration - > property ( role + " .tx_bandwidth " , static_cast < uint64_t > ( 500000 ) ) ) ,
2021-12-28 18:14:18 +00:00
Fpass_ ( configuration - > property ( role + " .Fpass " , static_cast < float > ( 0.0 ) ) ) ,
Fstop_ ( configuration - > property ( role + " .Fstop " , static_cast < float > ( 0.0 ) ) ) ,
2023-12-20 15:32:40 +00:00
num_input_files_ ( 1 ) ,
2021-12-28 18:14:18 +00:00
dma_buff_offset_pos_ ( 0 ) ,
in_stream_ ( in_stream ) ,
out_stream_ ( out_stream ) ,
switch_position_ ( configuration - > property ( role + " .switch_position " , 0 ) ) ,
2023-09-13 15:19:10 +00:00
item_size_ ( sizeof ( int8_t ) ) ,
2021-12-28 18:14:18 +00:00
enable_dds_lo_ ( configuration - > property ( role + " .enable_dds_lo " , false ) ) ,
filter_auto_ ( configuration - > property ( role + " .filter_auto " , false ) ) ,
quadrature_ ( configuration - > property ( role + " .quadrature " , true ) ) ,
rf_dc_ ( configuration - > property ( role + " .rf_dc " , true ) ) ,
bb_dc_ ( configuration - > property ( role + " .bb_dc " , true ) ) ,
rx1_enable_ ( configuration - > property ( role + " .rx1_enable " , true ) ) ,
rx2_enable_ ( configuration - > property ( role + " .rx2_enable " , true ) ) ,
enable_DMA_ ( false ) ,
enable_dynamic_bit_selection_ ( configuration - > property ( role + " .enable_dynamic_bit_selection " , true ) ) ,
enable_ovf_check_buffer_monitor_active_ ( false ) ,
dump_ ( configuration - > property ( role + " .dump " , false ) ) ,
rf_shutdown_ ( configuration - > property ( role + " .rf_shutdown " , FLAGS_rf_shutdown ) ) ,
repeat_ ( configuration - > property ( role + " .repeat " , false ) )
2018-03-02 10:30:36 +00:00
{
2021-12-28 18:14:18 +00:00
const double seconds_to_skip = configuration - > property ( role + " .seconds_to_skip " , 0.0 ) ;
const size_t header_size = configuration - > property ( role + " .header_size " , 0 ) ;
2023-09-13 15:19:10 +00:00
2023-12-20 15:32:40 +00:00
const bool enable_rx1_band ( ( configuration - > property ( " Channels_1C.count " , 0 ) > 0 ) | |
( configuration - > property ( " Channels_1B.count " , 0 ) > 0 ) ) ;
const bool enable_rx2_band ( ( configuration - > property ( " Channels_L2.count " , 0 ) > 0 ) | |
( configuration - > property ( " Channels_L5.count " , 0 ) > 0 ) | |
( configuration - > property ( " Channels_5X.count " , 0 ) > 0 ) ) ;
2021-12-28 18:14:18 +00:00
2023-12-20 15:32:40 +00:00
const uint32_t num_freq_bands = ( ( enable_rx1_band = = true ) and ( enable_rx2_band = = true ) ) ? 2 : 1 ;
2022-05-13 16:12:25 +00:00
if ( freq0_ = = 0 )
{
2022-05-30 07:02:22 +00:00
// use ".freq0"
2022-05-13 16:12:25 +00:00
freq0_ = configuration - > property ( role + " .freq0 " , static_cast < uint64_t > ( GPS_L1_FREQ_HZ ) ) ;
}
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 " ) ) ;
}
2021-02-19 12:03:22 +00:00
// override value with commandline flag, if present
if ( FLAGS_signal_source ! = " - " )
{
2022-04-28 16:41:31 +00:00
filename0_ = FLAGS_signal_source ;
2021-02-19 12:03:22 +00:00
}
if ( FLAGS_s ! = " - " )
{
2022-04-28 16:41:31 +00:00
filename0_ = FLAGS_s ;
2021-02-19 12:03:22 +00:00
}
2022-04-28 16:41:31 +00:00
if ( filename0_ . empty ( ) )
{
2023-12-20 15:32:40 +00:00
num_input_files_ = 2 ;
2022-04-28 17:09:26 +00:00
filename0_ = configuration - > property ( role + " .filename0 " , empty_string ) ;
filename1_ = configuration - > property ( role + " .filename1 " , empty_string ) ;
2022-04-28 16:41:31 +00:00
}
2021-03-12 17:01:25 +00:00
// 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.
2022-04-28 16:41:31 +00:00
if ( filename1_ . empty ( ) )
2021-03-12 17:01:25 +00:00
{
2023-12-20 15:32:40 +00:00
if ( enable_rx1_band )
2021-03-12 17:01:25 +00:00
{
dma_buff_offset_pos_ = 2 ;
}
}
else
{
dma_buff_offset_pos_ = 2 ;
}
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 ;
}
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 ' ;
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
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
*/
2022-04-28 16:41:31 +00:00
std : : ifstream file ( filename0_ . c_str ( ) , std : : ios : : in | std : : ios : : binary | std : : ios : : ate ) ;
2021-02-19 12:03:22 +00:00
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
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " SignalSource: Unable to open the samples file " < < filename0_ . c_str ( ) < < ' \n ' ;
2021-02-19 12:03:22 +00:00
return ;
}
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 16 ) ;
2022-04-28 16:41:31 +00:00
std : : cout < < " Processing file " < < filename0_ < < " , which contains " < < static_cast < double > ( size ) < < " [bytes] \n " ;
2021-02-19 12:03:22 +00:00
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
}
2022-04-28 16:41:31 +00:00
if ( ! filename1_ . empty ( ) )
2021-02-19 12:03:22 +00:00
{
2022-04-28 16:41:31 +00:00
std : : ifstream file ( filename1_ . c_str ( ) , std : : ios : : in | std : : ios : : binary | std : : ios : : ate ) ;
2021-02-19 12:03:22 +00:00
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
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " SignalSource: Unable to open the samples file " < < filename1_ . c_str ( ) < < ' \n ' ;
2021-02-19 12:03:22 +00:00
return ;
}
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 16 ) ;
2022-04-28 16:41:31 +00:00
std : : cout < < " Processing file " < < filename1_ < < " , which contains " < < static_cast < double > ( size ) < < " [bytes] \n " ;
2021-02-19 12:03:22 +00:00
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 " ;
2022-04-28 16:41:31 +00:00
if ( filename1_ . empty ( ) )
2019-09-28 19:59:05 +00:00
{
2022-04-28 16:41:31 +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
{
2022-04-28 16:41:31 +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_ ;
2021-12-28 18:14:18 +00:00
DLOG ( INFO ) < < " Item type " < < std : : string ( " ibyte " ) ;
2021-02-19 12:03:22 +00:00
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
2021-12-17 18:24:05 +00:00
if ( ( rf_port_select_ ! = " A_BALANCED " ) & & ( rf_port_select_ ! = " B_BALANCED " ) & & ( rf_port_select_ ! = " A_N " ) & & ( rf_port_select_ ! = " B_N " ) & & ( rf_port_select_ ! = " B_P " ) & & ( rf_port_select_ ! = " C_N " ) & & ( rf_port_select_ ! = " C_P " ) & & ( rf_port_select_ ! = " TX_MONITOR1 " ) & & ( rf_port_select_ ! = " TX_MONITOR2 " ) & & ( rf_port_select_ ! = " TX_MONITOR1_2 " ) )
2019-10-06 17:07:24 +00:00
{
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
}
2021-12-17 18:24:05 +00:00
if ( ( gain_mode_rx1_ ! = " manual " ) & & ( gain_mode_rx1_ ! = " slow_attack " ) & & ( gain_mode_rx1_ ! = " fast_attack " ) & & ( gain_mode_rx1_ ! = " hybrid " ) )
2019-10-06 17:07:24 +00:00
{
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
}
2021-12-17 18:24:05 +00:00
if ( ( gain_mode_rx2_ ! = " manual " ) & & ( gain_mode_rx2_ ! = " slow_attack " ) & & ( gain_mode_rx2_ ! = " fast_attack " ) & & ( gain_mode_rx2_ ! = " hybrid " ) )
2019-10-06 17:07:24 +00:00
{
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 " )
{
2021-12-17 18:24:05 +00:00
if ( rf_gain_rx1_ > 73.0 | | rf_gain_rx1_ < - 1.0 )
2019-10-07 20:45:09 +00:00
{
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 " )
{
2021-12-17 18:24:05 +00:00
if ( rf_gain_rx2_ > 73.0 | | rf_gain_rx2_ < - 1.0 )
2019-10-07 20:45:09 +00:00
{
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
2021-12-17 18:24:05 +00:00
if ( ( filter_source_ ! = " Off " ) & & ( filter_source_ ! = " Auto " ) & & ( filter_source_ ! = " File " ) & & ( filter_source_ ! = " Design " ) )
2019-10-09 18:50:06 +00:00
{
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 " ;
}
2021-12-17 18:24:05 +00:00
if ( bandwidth_ < 200000 | | bandwidth_ > 56000000 )
2019-10-08 14:38:30 +00:00
{
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 ;
}
2022-05-13 16:12:25 +00:00
std : : cout < < " LO frequency : " < < freq0_ < < " Hz \n " ;
2019-10-07 20:45:09 +00:00
try
{
config_ad9361_rx_local ( bandwidth_ ,
sample_rate_ ,
2022-05-13 16:12:25 +00:00
freq0_ ,
freq1_ ,
2019-10-07 20:45:09 +00:00
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 ' ;
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 )
{
2021-12-17 18:24:05 +00:00
if ( tx_bandwidth_ < static_cast < uint64_t > ( std : : floor ( static_cast < float > ( freq_dds_tx_hz_ ) * 1.1 ) ) | | ( tx_bandwidth_ < 200000 ) | | ( 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 " ;
}
2021-12-17 18:24:05 +00:00
if ( tx_attenuation_db_ > 0.0 | | tx_attenuation_db_ < - 89.75 )
2019-10-07 20:45:09 +00:00
{
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 ' ;
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
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 ' ;
2021-02-19 12:03:22 +00:00
return ;
2021-02-13 16:10:43 +00:00
}
2023-12-20 15:32:40 +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
if ( enable_dynamic_bit_selection_ )
{
2023-12-20 15:32:40 +00:00
dynamic_bit_selection_fpga = std : : make_shared < Fpga_dynamic_bit_selection > ( enable_rx1_band , enable_rx2_band ) ;
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 ( )
{
2022-04-28 16:41:31 +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
2022-04-28 16:41:31 +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 ) ;
2022-04-28 16:41:31 +00:00
// FPGA DMA control
dma_fpga = std : : make_shared < Fpga_DMA > ( ) ;
2021-02-19 12:03:22 +00:00
// open the files
2020-06-18 09:49:28 +00:00
try
{
2022-04-28 16:41:31 +00:00
infile1 . open ( filename0_ , std : : ios : : binary ) ;
2020-06-18 09:49:28 +00:00
}
catch ( const std : : ifstream : : failure & e )
{
2022-04-28 16:41:31 +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 ;
2022-04-28 16:41:31 +00:00
if ( ! filename1_ . empty ( ) )
2021-02-19 12:03:22 +00:00
{
infile2 . exceptions ( std : : ifstream : : failbit | std : : ifstream : : badbit ) ;
try
{
2022-04-28 16:41:31 +00:00
infile2 . open ( filename1_ , std : : ios : : binary ) ;
2021-02-19 12:03:22 +00:00
}
catch ( const std : : ifstream : : failure & e )
{
2022-04-28 16:41:31 +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 ;
}
}
2023-12-20 15:32:40 +00:00
// skip the initial samples if neededsrc/algorithms/signal_source/libs/ad9361_manager.cc
2021-02-19 12:03:22 +00:00
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 )
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception skipping initial samples file " < < filename0_ < < ' \n ' ;
2021-02-19 12:03:22 +00:00
// stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
return ;
2020-06-18 09:49:28 +00:00
}
2022-04-28 16:41:31 +00:00
if ( ! filename1_ . empty ( ) )
2021-02-19 12:03:22 +00:00
{
try
{
infile2 . ignore ( bytes_to_skeep ) ;
}
catch ( const std : : ifstream : : failure & e )
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception skipping initial samples 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 ;
}
}
// rx signal vectors
2022-04-28 20:33:29 +00:00
std : : vector < int8_t > input_samples ( sample_block_size * 2 ) ; // complex samples
2022-04-28 16:41:31 +00:00
// pointer to DMA buffer
2022-12-05 18:18:31 +00:00
int8_t * dma_buffer ;
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
// Open DMA device
2022-04-28 16:41:31 +00:00
if ( dma_fpga - > DMA_open ( ) )
{
std : : cerr < < " Cannot open loop device \n " ;
// stop the receiver
queue - > push ( pmt : : make_any ( command_event_make ( 200 , 0 ) ) ) ;
return ;
}
dma_buffer = dma_fpga - > get_buffer_address ( ) ;
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 ;
2023-12-20 15:32:40 +00:00
if ( num_input_files_ = = 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 )
{
2022-12-05 18:18:31 +00:00
dma_buffer [ dma_index + ( 2 - dma_buff_offset_pos ) ] = 0 ;
dma_buffer [ dma_index + 1 + ( 2 - dma_buff_offset_pos ) ] = 0 ;
2021-02-19 12:03:22 +00:00
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 )
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception reading file " < < filename0_ < < ' \n ' ;
2021-02-19 12:03:22 +00:00
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
2022-12-05 18:18:31 +00:00
dma_buffer [ dma_index + dma_buff_offset_pos ] = input_samples [ index0 ] ;
dma_buffer [ dma_index + 1 + dma_buff_offset_pos ] = input_samples [ index0 + 1 ] ;
2021-02-19 12:03:22 +00:00
dma_index + = 4 ;
2020-06-18 09:49:28 +00:00
}
2021-02-19 12:03:22 +00:00
// read filename 1 (if enabled)
2023-12-20 15:32:40 +00:00
if ( num_input_files_ > 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 )
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception reading file " < < filename1_ < < ' \n ' ;
2021-02-19 12:03:22 +00:00
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
2022-12-05 18:18:31 +00:00
dma_buffer [ dma_index ] = input_samples [ index0 ] ;
dma_buffer [ dma_index + 1 ] = input_samples [ index0 + 1 ] ;
2020-06-18 09:49:28 +00:00
dma_index + = 4 ;
}
}
2021-02-19 12:03:22 +00:00
if ( nread_elements > 0 )
{
2022-04-28 16:41:31 +00:00
if ( dma_fpga - > DMA_write ( nread_elements * 2 ) )
{
std : : cerr < < " Error: DMA could not send all the required samples \n " ;
break ;
}
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
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception resetting the position of the next byte to be extracted to zero " < < filename0_ < < ' \n ' ;
2021-02-19 12:03:22 +00:00
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
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception skipping initial samples file " < < filename0_ < < ' \n ' ;
2021-02-19 12:03:22 +00:00
break ;
2020-06-18 09:49:28 +00:00
}
2022-04-28 16:41:31 +00:00
if ( ! filename1_ . empty ( ) )
2021-02-19 12:03:22 +00:00
{
try
{
infile2 . seekg ( 0 ) ;
}
catch ( const std : : ifstream : : failure & e )
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception setting the position of the next byte to be extracted to zero " < < filename1_ < < ' \n ' ;
2021-02-19 12:03:22 +00:00
break ;
}
try
{
infile2 . ignore ( bytes_to_skeep ) ;
}
catch ( const std : : ifstream : : failure & e )
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception skipping initial samples file " < < filename1_ < < ' \n ' ;
2021-02-19 12:03:22 +00:00
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
}
2022-04-28 16:41:31 +00:00
if ( dma_fpga - > DMA_close ( ) )
{
std : : cerr < < " Error closing loop device " < < ' \n ' ;
}
2020-06-18 09:49:28 +00:00
try
{
infile1 . close ( ) ;
}
catch ( const std : : ifstream : : failure & e )
{
2022-04-28 16:41:31 +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
2023-12-20 15:32:40 +00:00
if ( num_input_files_ > 1 )
2021-02-19 12:03:22 +00:00
{
try
{
infile2 . close ( ) ;
}
catch ( const std : : ifstream : : failure & e )
{
2022-04-28 16:41:31 +00:00
std : : cerr < < " Exception closing file " < < filename1_ < < ' \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
}
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. " ;
2021-12-17 18:24:05 +00:00
return { } ;
2018-03-02 10:30:36 +00:00
}
gr : : basic_block_sptr Ad9361FpgaSignalSource : : get_right_block ( )
{
2021-12-17 18:24:05 +00:00
return { } ;
2018-03-02 10:30:36 +00:00
}