2018-04-27 18:00:50 +00:00
/*!
* \ file pcps_acquisition_fpga . cc
2019-02-26 17:28:14 +00:00
* \ brief This class implements a Parallel Code Phase Search Acquisition for the FPGA
2018-04-27 18:00:50 +00:00
* \ authors < ul >
2019-02-26 17:28:14 +00:00
* < li > Marc Majoral , 2019. mmajoral ( at ) cttc . es
2019-02-28 20:45:30 +00:00
* < li > Javier Arribas , 2019. jarribas ( at ) cttc . es
2018-04-27 18:00:50 +00:00
* < / ul >
*
2020-07-28 14:57:15 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2018-04-27 18:00:50 +00:00
*
2020-07-28 14:57:15 +00:00
* Copyright ( C ) 2010 - 2020 ( see AUTHORS file for a list of contributors )
2018-04-27 18:00:50 +00:00
*
* GNSS - SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS - SDR .
*
2020-02-08 00:20:02 +00:00
* SPDX - License - Identifier : GPL - 3.0 - or - later
2018-04-27 18:00:50 +00:00
*
2020-07-28 14:57:15 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2019-02-27 16:27:31 +00:00
*/
2018-04-27 18:00:50 +00:00
2018-04-30 09:59:56 +00:00
2018-12-09 21:00:09 +00:00
# include "pcps_acquisition_fpga.h"
2020-06-19 01:51:50 +00:00
# include "gnss_sdr_make_unique.h"
2019-03-06 12:49:14 +00:00
# include "gnss_synchro.h"
2018-04-27 18:00:50 +00:00
# include <glog/logging.h>
2019-03-20 17:08:39 +00:00
# include <cmath> // for ceil
# include <iostream> // for operator<<
# include <utility> // for move
2019-03-06 12:49:14 +00:00
2018-05-09 11:09:26 +00:00
2018-05-03 08:38:21 +00:00
pcps_acquisition_fpga_sptr pcps_make_acquisition_fpga ( pcpsconf_fpga_t conf_ )
2018-04-27 18:00:50 +00:00
{
2018-12-10 21:59:10 +00:00
return pcps_acquisition_fpga_sptr ( new pcps_acquisition_fpga ( std : : move ( conf_ ) ) ) ;
2018-04-27 18:00:50 +00:00
}
2019-03-20 15:57:50 +00:00
pcps_acquisition_fpga : : pcps_acquisition_fpga ( pcpsconf_fpga_t conf_ )
2018-04-27 18:00:50 +00:00
{
2020-06-19 01:51:50 +00:00
d_acq_parameters = std : : move ( conf_ ) ;
2019-04-04 17:55:02 +00:00
d_sample_counter = 0ULL ; // Sample Counter
2018-04-27 18:00:50 +00:00
d_active = false ;
d_state = 0 ;
2020-06-19 01:51:50 +00:00
d_fft_size = d_acq_parameters . samples_per_code ;
2018-04-27 18:00:50 +00:00
d_mag = 0 ;
d_input_power = 0.0 ;
2018-08-12 22:54:23 +00:00
d_num_doppler_bins = 0U ;
2018-04-27 18:00:50 +00:00
d_threshold = 0.0 ;
2018-08-12 22:54:23 +00:00
d_doppler_step = 0U ;
2019-07-24 11:02:14 +00:00
d_doppler_center = 0U ;
2019-03-01 19:49:45 +00:00
d_doppler_index = 0U ;
2018-04-27 18:00:50 +00:00
d_test_statistics = 0.0 ;
2018-08-12 22:54:23 +00:00
d_channel = 0U ;
2018-12-10 18:05:12 +00:00
d_gnss_synchro = nullptr ;
2018-04-27 18:00:50 +00:00
2020-06-19 01:51:50 +00:00
d_downsampling_factor = d_acq_parameters . downsampling_factor ;
d_select_queue_Fpga = d_acq_parameters . select_queue_Fpga ;
2018-10-31 17:48:08 +00:00
2020-06-19 01:51:50 +00:00
d_total_block_exp = d_acq_parameters . total_block_exp ;
2018-10-31 17:48:08 +00:00
2020-06-19 01:51:50 +00:00
d_make_2_steps = d_acq_parameters . make_2_steps ;
d_num_doppler_bins_step2 = d_acq_parameters . num_doppler_bins_step2 ;
d_doppler_step2 = d_acq_parameters . doppler_step2 ;
2019-02-28 19:49:35 +00:00
d_doppler_center_step_two = 0.0 ;
2020-06-19 01:51:50 +00:00
d_doppler_max = d_acq_parameters . doppler_max ;
2019-02-28 19:49:35 +00:00
2020-06-19 01:51:50 +00:00
d_max_num_acqs = d_acq_parameters . max_num_acqs ;
2019-04-04 14:10:29 +00:00
2020-06-19 01:51:50 +00:00
d_acquisition_fpga = std : : make_unique < Fpga_Acquisition > ( d_acq_parameters . device_name , d_acq_parameters . code_length , d_acq_parameters . doppler_max , d_fft_size ,
d_acq_parameters . fs_in , d_acq_parameters . select_queue_Fpga , d_acq_parameters . all_fft_codes , d_acq_parameters . excludelimit ) ;
2018-04-27 18:00:50 +00:00
}
void pcps_acquisition_fpga : : set_local_code ( )
{
2020-06-19 01:51:50 +00:00
d_acquisition_fpga - > set_local_code ( d_gnss_synchro - > PRN ) ;
2018-04-27 18:00:50 +00:00
}
void pcps_acquisition_fpga : : init ( )
{
d_gnss_synchro - > Flag_valid_acquisition = false ;
d_gnss_synchro - > Flag_valid_symbol_output = false ;
d_gnss_synchro - > Flag_valid_pseudorange = false ;
d_gnss_synchro - > Flag_valid_word = false ;
d_gnss_synchro - > Acq_delay_samples = 0.0 ;
d_gnss_synchro - > Acq_doppler_hz = 0.0 ;
d_gnss_synchro - > Acq_samplestamp_samples = 0 ;
d_mag = 0.0 ;
d_input_power = 0.0 ;
2018-11-07 19:21:05 +00:00
2019-02-28 19:49:35 +00:00
d_num_doppler_bins = static_cast < uint32_t > ( std : : ceil ( static_cast < double > ( static_cast < int32_t > ( d_doppler_max ) - static_cast < int32_t > ( - d_doppler_max ) ) / static_cast < double > ( d_doppler_step ) ) ) + 1 ;
2018-04-27 18:00:50 +00:00
}
2018-08-11 10:56:52 +00:00
void pcps_acquisition_fpga : : set_state ( int32_t state )
2018-04-27 18:00:50 +00:00
{
d_state = state ;
if ( d_state = = 1 )
{
d_gnss_synchro - > Acq_delay_samples = 0.0 ;
d_gnss_synchro - > Acq_doppler_hz = 0.0 ;
d_gnss_synchro - > Acq_samplestamp_samples = 0 ;
d_mag = 0.0 ;
d_input_power = 0.0 ;
d_test_statistics = 0.0 ;
d_active = true ;
}
else if ( d_state = = 0 )
{
}
else
{
LOG ( ERROR ) < < " State can only be set to 0 or 1 " ;
}
}
void pcps_acquisition_fpga : : send_positive_acquisition ( )
{
2019-02-26 17:28:14 +00:00
// Declare positive acquisition using a message port
2019-03-06 12:49:14 +00:00
// 0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
2018-04-27 18:00:50 +00:00
DLOG ( INFO ) < < " positive acquisition "
< < " , satellite " < < d_gnss_synchro - > System < < " " < < d_gnss_synchro - > PRN
2019-12-16 17:44:22 +00:00
< < " , sample_stamp " < < d_gnss_synchro - > Acq_samplestamp_samples
2018-04-27 18:00:50 +00:00
< < " , test statistics value " < < d_test_statistics
< < " , test statistics threshold " < < d_threshold
< < " , code phase " < < d_gnss_synchro - > Acq_delay_samples
< < " , doppler " < < d_gnss_synchro - > Acq_doppler_hz
< < " , magnitude " < < d_mag
2019-07-24 11:02:14 +00:00
< < " , input signal power " < < d_input_power
< < " , Assist doppler_center " < < d_doppler_center ;
2019-06-18 16:22:01 +00:00
2019-08-18 20:16:13 +00:00
// the channel FSM is set, so, notify it directly the positive acquisition to minimize delays
2019-04-09 18:01:30 +00:00
d_channel_fsm . lock ( ) - > Event_valid_acquisition ( ) ;
2018-04-27 18:00:50 +00:00
}
void pcps_acquisition_fpga : : send_negative_acquisition ( )
{
2019-02-26 17:28:14 +00:00
// Declare negative acquisition using a message port
2018-04-27 18:00:50 +00:00
DLOG ( INFO ) < < " negative acquisition "
< < " , satellite " < < d_gnss_synchro - > System < < " " < < d_gnss_synchro - > PRN
2019-12-16 17:44:22 +00:00
< < " , sample_stamp " < < d_gnss_synchro - > Acq_samplestamp_samples
2018-04-27 18:00:50 +00:00
< < " , test statistics value " < < d_test_statistics
< < " , test statistics threshold " < < d_threshold
< < " , code phase " < < d_gnss_synchro - > Acq_delay_samples
< < " , doppler " < < d_gnss_synchro - > Acq_doppler_hz
< < " , magnitude " < < d_mag
< < " , input signal power " < < d_input_power ;
2020-06-19 01:51:50 +00:00
if ( d_acq_parameters . repeat_satellite = = true )
2019-03-20 15:57:50 +00:00
{
2019-04-09 18:01:30 +00:00
d_channel_fsm . lock ( ) - > Event_failed_acquisition_repeat ( ) ;
2019-03-20 15:57:50 +00:00
}
else
{
2019-04-09 18:01:30 +00:00
d_channel_fsm . lock ( ) - > Event_failed_acquisition_no_repeat ( ) ;
2019-03-20 15:57:50 +00:00
}
2018-04-27 18:00:50 +00:00
}
2019-07-01 19:54:52 +00:00
2019-03-01 19:37:14 +00:00
void pcps_acquisition_fpga : : acquisition_core ( uint32_t num_doppler_bins , uint32_t doppler_step , int32_t doppler_min )
2018-04-27 18:00:50 +00:00
{
2018-08-12 22:54:23 +00:00
uint32_t indext = 0U ;
2018-10-31 17:48:08 +00:00
float firstpeak = 0.0 ;
float secondpeak = 0.0 ;
uint32_t total_block_exp ;
2018-08-11 10:56:52 +00:00
uint64_t initial_sample ;
2020-07-19 07:39:32 +00:00
2020-06-19 01:51:50 +00:00
d_acquisition_fpga - > set_doppler_sweep ( num_doppler_bins , doppler_step , doppler_min ) ;
d_acquisition_fpga - > run_acquisition ( ) ;
d_acquisition_fpga - > read_acquisition_results ( & indext ,
2019-03-22 18:03:46 +00:00
& firstpeak ,
& secondpeak ,
& initial_sample ,
& d_input_power ,
& d_doppler_index ,
& total_block_exp ) ;
2018-10-31 17:48:08 +00:00
2020-07-19 07:39:32 +00:00
const auto doppler = static_cast < int32_t > ( doppler_min ) + doppler_step * ( d_doppler_index - 1 ) ;
2019-03-18 18:37:19 +00:00
2018-10-31 17:48:08 +00:00
if ( total_block_exp > d_total_block_exp )
2019-02-27 16:27:31 +00:00
{
// if the attenuation factor of the FPGA FFT-IFFT is smaller than the reference attenuation factor then we need to update the reference attenuation factor
d_total_block_exp = total_block_exp ;
2019-03-18 18:37:19 +00:00
d_test_statistics = 0 ;
2019-02-27 16:27:31 +00:00
}
else
{
2019-03-18 18:37:19 +00:00
if ( secondpeak > 0 )
{
d_test_statistics = firstpeak / secondpeak ;
}
else
{
d_test_statistics = 0.0 ;
}
2019-02-27 16:27:31 +00:00
}
2018-08-29 16:20:41 +00:00
2018-08-01 13:55:40 +00:00
d_gnss_synchro - > Acq_doppler_hz = static_cast < double > ( doppler ) ;
d_sample_counter = initial_sample ;
2018-08-29 16:20:41 +00:00
if ( d_select_queue_Fpga = = 0 )
2019-02-27 16:27:31 +00:00
{
if ( d_downsampling_factor > 1 )
{
d_gnss_synchro - > Acq_delay_samples = static_cast < double > ( d_downsampling_factor * ( indext ) ) ;
2019-08-18 20:16:13 +00:00
d_gnss_synchro - > Acq_samplestamp_samples = d_downsampling_factor * static_cast < uint64_t > ( d_sample_counter ) - static_cast < uint64_t > ( 44 ) ; // 33; // 41; // + 81*0.5; // delay due to the downsampling filter in the acquisition
2019-02-27 16:27:31 +00:00
}
else
{
d_gnss_synchro - > Acq_delay_samples = static_cast < double > ( indext ) ;
d_gnss_synchro - > Acq_samplestamp_samples = d_sample_counter ; // delay due to the downsampling filter in the acquisition
}
2018-08-29 16:20:41 +00:00
}
else
2019-02-27 16:27:31 +00:00
{
d_gnss_synchro - > Acq_delay_samples = static_cast < double > ( indext ) ;
d_gnss_synchro - > Acq_samplestamp_samples = d_sample_counter ; // delay due to the downsampling filter in the acquisition
}
2019-02-28 19:49:35 +00:00
}
2019-04-08 09:14:41 +00:00
2019-02-28 19:49:35 +00:00
void pcps_acquisition_fpga : : set_active ( bool active )
{
d_active = active ;
d_input_power = 0.0 ;
d_mag = 0.0 ;
DLOG ( INFO ) < < " Channel: " < < d_channel
< < " , doing acquisition of satellite: " < < d_gnss_synchro - > System < < " " < < d_gnss_synchro - > PRN
< < " ,sample stamp: " < < d_sample_counter < < " , threshold: "
< < d_threshold < < " , doppler_max: " < < d_doppler_max
2020-02-05 21:15:50 +00:00
< < " , doppler_step: " < < d_doppler_step ;
2019-02-28 19:49:35 +00:00
2020-06-19 01:51:50 +00:00
d_acquisition_fpga - > open_device ( ) ;
d_acquisition_fpga - > configure_acquisition ( ) ;
d_acquisition_fpga - > write_local_code ( ) ;
d_acquisition_fpga - > set_block_exp ( d_total_block_exp ) ;
2019-03-18 18:37:19 +00:00
2019-07-24 11:02:14 +00:00
acquisition_core ( d_num_doppler_bins , d_doppler_step , - d_doppler_max + d_doppler_center ) ;
2019-02-28 19:49:35 +00:00
if ( ! d_make_2_steps )
2018-04-27 18:00:50 +00:00
{
2020-06-19 01:51:50 +00:00
d_acquisition_fpga - > close_device ( ) ;
2019-02-28 19:49:35 +00:00
if ( d_test_statistics > d_threshold )
{
d_active = false ;
send_positive_acquisition ( ) ;
d_state = 0 ; // Positive acquisition
}
else
{
d_state = 0 ;
d_active = false ;
send_negative_acquisition ( ) ;
}
2018-04-27 18:00:50 +00:00
}
else
{
2019-02-28 19:49:35 +00:00
if ( d_test_statistics > d_threshold )
{
d_doppler_center_step_two = static_cast < float > ( d_gnss_synchro - > Acq_doppler_hz ) ;
2019-03-22 18:03:46 +00:00
2019-04-04 14:10:29 +00:00
uint32_t num_second_acq = 1 ;
2019-03-26 15:35:19 +00:00
2019-04-04 14:10:29 +00:00
while ( num_second_acq < d_max_num_acqs )
2019-02-28 19:49:35 +00:00
{
2019-07-24 11:02:14 +00:00
acquisition_core ( d_num_doppler_bins_step2 , d_doppler_step2 , d_doppler_center_step_two - static_cast < float > ( floor ( d_num_doppler_bins_step2 / 2.0 ) ) * d_doppler_step2 + d_doppler_center ) ;
2019-04-04 14:10:29 +00:00
if ( d_test_statistics > d_threshold )
{
d_active = false ;
send_positive_acquisition ( ) ;
d_state = 0 ; // Positive acquisition
break ;
}
2020-07-19 07:39:32 +00:00
num_second_acq + = 1 ;
2019-02-28 19:49:35 +00:00
}
2020-06-19 01:51:50 +00:00
d_acquisition_fpga - > close_device ( ) ;
2019-04-04 14:10:29 +00:00
if ( d_test_statistics < = d_threshold )
2019-02-28 19:49:35 +00:00
{
d_state = 0 ;
d_active = false ;
send_negative_acquisition ( ) ;
}
}
else
{
2020-06-19 01:51:50 +00:00
d_acquisition_fpga - > close_device ( ) ;
2019-02-28 19:49:35 +00:00
d_state = 0 ;
d_active = false ;
send_negative_acquisition ( ) ;
}
2018-04-27 18:00:50 +00:00
}
}
2019-08-14 00:14:29 +00:00
void pcps_acquisition_fpga : : reset_acquisition ( )
2018-09-12 14:02:23 +00:00
{
2019-02-27 16:27:31 +00:00
// this function triggers a HW reset of the FPGA PL.
2020-06-19 01:51:50 +00:00
d_acquisition_fpga - > open_device ( ) ;
d_acquisition_fpga - > reset_acquisition ( ) ;
d_acquisition_fpga - > close_device ( ) ;
2018-09-12 14:02:23 +00:00
}