diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc
index 00ff2008c..f585fdbc0 100644
--- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc
+++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc
@@ -1,14 +1,18 @@
+
/*!
* \file gps_l1_ca_pcps_acquisition_fpga.cc
- * \brief Adapts a PCPS acquisition block to an FPGA Acquisition Interface for
- * GPS L1 C/A signals. This file is based on the file gps_l1_ca_pcps_acquisition.cc
+ * \brief Adapts a PCPS acquisition block to an FPGA AcquisitionInterface
+ * for GPS L1 C/A signals
* \authors
- * - Marc Majoral, 2017. mmajoral(at)cttc.cat
+ *
- Marc Majoral, 2018. mmajoral(at)cttc.es
+ *
- Javier Arribas, 2011. jarribas(at)cttc.es
+ *
- Luis Esteve, 2012. luis(at)epsilon-formacion.com
+ *
- Marc Molina, 2013. marc.molina.pena(at)gmail.com
*
*
* -------------------------------------------------------------------------
*
- * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
+ * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@@ -30,88 +34,109 @@
*
* -------------------------------------------------------------------------
*/
-
-#include "gps_l1_ca_pcps_acquisition_fpga.h"
-#include
+#include
+#include
+#include
#include
-#include "GPS_L1_CA.h"
+#include "gps_l1_ca_pcps_acquisition_fpga.h"
#include "configuration_interface.h"
+#include "gps_sdr_signal_processing.h"
+#include "GPS_L1_CA.h"
+#include "gnss_sdr_flags.h"
+
+#define NUM_PRNs 32
using google::LogMessage;
GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
- ConfigurationInterface* configuration, std::string role,
- unsigned int in_streams, unsigned int out_streams) :
- role_(role), in_streams_(in_streams), out_streams_(out_streams)
+ ConfigurationInterface* configuration, std::string role,
+ unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
- unsigned int code_length;
- bool bit_transition_flag;
- bool use_CFAR_algorithm_flag;
- unsigned int sampled_ms;
- long fs_in;
- long ifreq;
- bool dump;
- std::string dump_filename;
- unsigned int nsamples_total;
- unsigned int select_queue_Fpga;
- std::string device_name;
+ pcpsconf_fpga_t acq_parameters;
configuration_ = configuration;
- std::string default_item_type = "cshort";
- std::string default_dump_filename = "./data/acquisition.dat";
+ std::string default_item_type = "gr_complex";
+
DLOG(INFO) << "role " << role;
- item_type_ = configuration_->property(role + ".item_type",
- default_item_type);
- fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", 2048000);
- ifreq = configuration_->property(role + ".if", 0);
- dump = configuration_->property(role + ".dump", false);
+
+ long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
+ fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
+ acq_parameters.fs_in = fs_in_;
+ if_ = configuration_->property(role + ".if", 0);
+ acq_parameters.freq = if_;
doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
- sampled_ms = configuration_->property(
- role + ".coherent_integration_time_ms", 1);
- // note : the FPGA is implemented according to bit transition flag = 0. Setting bit transition flag to 1 has no effect.
- bit_transition_flag = configuration_->property(
- role + ".bit_transition_flag", false);
- // note : the FPGA is implemented according to use_CFAR_algorithm = 0. Setting use_CFAR_algorithm to 1 has no effect.
- use_CFAR_algorithm_flag = configuration_->property(
- role + ".use_CFAR_algorithm", false);
- // note : the FPGA does not use the max_dwells variable.
- max_dwells_ = configuration_->property(role + ".max_dwells", 1);
- dump_filename = configuration_->property(role + ".dump_filename",
- default_dump_filename);
- //--- Find number of samples per spreading code -------------------------
- code_length = round(
- fs_in / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS));
- // code length has the same value as d_fft_size
- float nbits;
- nbits = ceilf(log2f(code_length));
- nsamples_total = pow(2, nbits);
- //vector_length_ = code_length_ * sampled_ms_;
- vector_length_ = nsamples_total * sampled_ms;
- // if( bit_transition_flag_ )
- // {
- // vector_length_ *= 2;
- // }
- select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga",
- 0);
- std::string default_device_name = "/dev/uio0";
- device_name = configuration_->property(role + ".devicename",
- default_device_name);
- if (item_type_.compare("cshort") == 0)
+ if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
+ acq_parameters.doppler_max = doppler_max_;
+ sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1);
+ acq_parameters.sampled_ms = sampled_ms_;
+ code_length_ = static_cast(std::round(static_cast(fs_in_) / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)));
+
+ // The FPGA can only use FFT lengths that are a power of two.
+ float nbits = ceilf(log2f((float) code_length_));
+ unsigned int nsamples_total = pow(2, nbits);
+ vector_length_ = nsamples_total * sampled_ms_;
+ unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga",0);
+ acq_parameters.select_queue_Fpga = select_queue_Fpga;
+ std::string default_device_name = "/dev/uio0";
+ std::string device_name = configuration_->property(role + ".devicename", default_device_name);
+ acq_parameters.device_name = device_name;
+ acq_parameters.samples_per_ms = nsamples_total;
+ acq_parameters.samples_per_code = nsamples_total;
+
+ // compute all the GPS L1 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time
+ // a channel is assigned)
+
+ // Direct FFT
+ gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length_, true);
+ // allocate memory to compute all the PRNs
+ // and compute all the possible codes
+ std::complex* code = new std::complex[nsamples_total]; // buffer for the local code
+ gr_complex* fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
+ d_all_fft_codes = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32
+ float max; // temporary maxima search
+
+ for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
{
- item_size_ = sizeof(lv_16sc_t);
- gps_acquisition_fpga_sc_ = gps_pcps_make_acquisition_fpga_sc(
- sampled_ms, max_dwells_, doppler_max_, ifreq, fs_in,
- code_length, code_length, vector_length_, nsamples_total,
- bit_transition_flag, use_CFAR_algorithm_flag,
- select_queue_Fpga, device_name, dump, dump_filename);
- DLOG(INFO) << "acquisition("
- << gps_acquisition_fpga_sc_->unique_id() << ")";
- }
- else
- {
- LOG(FATAL) << item_type_ << " FPGA only accepts chsort";
- }
+ gps_l1_ca_code_gen_complex_sampled(code, PRN, fs_in_, 0); // generate PRN code
+ // fill in zero padding
+ for (int s=code_length_;sget_inbuf() + offset, code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer
+ fft_if->execute(); // Run the FFT of local code
+ volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values
+ max = 0; // initialize maximum value
+ for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima
+ {
+ if (std::abs(fft_codes_padded[i].real()) > max)
+ {
+ max = std::abs(fft_codes_padded[i].real());
+ }
+ if (std::abs(fft_codes_padded[i].imag()) > max)
+ {
+ max = std::abs(fft_codes_padded[i].imag());
+ }
+ }
+ for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
+ {
+ d_all_fft_codes[i + nsamples_total * (PRN -1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
+ static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max)));
+
+ }
+ }
+
+ acq_parameters.all_fft_codes = d_all_fft_codes;
+ //acq_parameters
+ // temporary buffers that we can delete
+ delete[] code;
+ delete fft_if;
+ delete[] fft_codes_padded;
+
+ acquisition_fpga_ = pcps_make_acquisition(acq_parameters);
+ DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
+
channel_ = 0;
- threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = 0;
}
@@ -119,123 +144,94 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
GpsL1CaPcpsAcquisitionFpga::~GpsL1CaPcpsAcquisitionFpga()
{
+ //delete[] code_;
+ delete[] d_all_fft_codes;
}
void GpsL1CaPcpsAcquisitionFpga::set_channel(unsigned int channel)
{
channel_ = channel;
- gps_acquisition_fpga_sc_->set_channel(channel_);
+ acquisition_fpga_->set_channel(channel_);
}
void GpsL1CaPcpsAcquisitionFpga::set_threshold(float threshold)
{
- float pfa = configuration_->property(role_ + ".pfa", 0.0);
-
- if (pfa == 0.0)
- {
- threshold_ = threshold;
- }
- else
- {
- threshold_ = calculate_threshold(pfa);
- }
-
- DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_;
- gps_acquisition_fpga_sc_->set_threshold(threshold_);
+ DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold;
+ acquisition_fpga_->set_threshold(threshold);
}
void GpsL1CaPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max)
{
doppler_max_ = doppler_max;
- gps_acquisition_fpga_sc_->set_doppler_max(doppler_max_);
+ acquisition_fpga_->set_doppler_max(doppler_max_);
}
void GpsL1CaPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step)
{
doppler_step_ = doppler_step;
- gps_acquisition_fpga_sc_->set_doppler_step(doppler_step_);
+ acquisition_fpga_->set_doppler_step(doppler_step_);
}
void GpsL1CaPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
{
gnss_synchro_ = gnss_synchro;
- gps_acquisition_fpga_sc_->set_gnss_synchro(gnss_synchro_);
+ acquisition_fpga_->set_gnss_synchro(gnss_synchro_);
}
signed int GpsL1CaPcpsAcquisitionFpga::mag()
{
- return gps_acquisition_fpga_sc_->mag();
+ return acquisition_fpga_->mag();
}
void GpsL1CaPcpsAcquisitionFpga::init()
{
- gps_acquisition_fpga_sc_->init();
+ acquisition_fpga_->init();
}
void GpsL1CaPcpsAcquisitionFpga::set_local_code()
{
- gps_acquisition_fpga_sc_->set_local_code();
+ acquisition_fpga_->set_local_code();
}
void GpsL1CaPcpsAcquisitionFpga::reset()
{
- gps_acquisition_fpga_sc_->set_active(true);
+ acquisition_fpga_->set_active(true);
}
void GpsL1CaPcpsAcquisitionFpga::set_state(int state)
{
- gps_acquisition_fpga_sc_->set_state(state);
-}
-
-
-float GpsL1CaPcpsAcquisitionFpga::calculate_threshold(float pfa)
-{
- //Calculate the threshold
- unsigned int frequency_bins = 0;
- for (int doppler = static_cast(-doppler_max_); doppler <= static_cast(doppler_max_);
- doppler += doppler_step_)
- {
- frequency_bins++;
- }
- DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
- unsigned int ncells = vector_length_ * frequency_bins;
- double exponent = 1 / static_cast(ncells);
- double val = pow(1.0 - pfa, exponent);
- double lambda = double(vector_length_);
- boost::math::exponential_distribution mydist(lambda);
- float threshold = static_cast(quantile(mydist, val));
- return threshold;
+ acquisition_fpga_->set_state(state);
}
void GpsL1CaPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block)
{
- //nothing to connect
+ // nothing to connect
}
void GpsL1CaPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block)
{
- //nothing to disconnect
+ // nothing to disconnect
}
gr::basic_block_sptr GpsL1CaPcpsAcquisitionFpga::get_left_block()
{
- return gps_acquisition_fpga_sc_;
+ return acquisition_fpga_;
}
gr::basic_block_sptr GpsL1CaPcpsAcquisitionFpga::get_right_block()
{
- return gps_acquisition_fpga_sc_;
+ return acquisition_fpga_;
}
diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h
index 2c8f9eed4..d65e677e7 100644
--- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h
+++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h
@@ -1,14 +1,17 @@
/*!
* \file gps_l1_ca_pcps_acquisition_fpga.h
- * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
- * GPS L1 C/A signals. This file is based on the file gps_l1_ca_pcps_acquisition.h
+ * \brief Adapts a PCPS acquisition block that uses the FPGA to
+ * an AcquisitionInterface for GPS L1 C/A signals
* \authors
- * - Marc Majoral, 2017. mmajoral(at)cttc.cat
+ *
- Marc Majoral, 2018. mmajoral(at)cttc.es
+ *
- Javier Arribas, 2011. jarribas(at)cttc.es
+ *
- Luis Esteve, 2012. luis(at)epsilon-formacion.com
+ *
- Marc Molina, 2013. marc.molina.pena(at)gmail.com
*
*
* -------------------------------------------------------------------------
*
- * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
+ * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@@ -34,14 +37,11 @@
#ifndef GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_
#define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_
-#include
-#include
-#include
-#include "gnss_synchro.h"
#include "acquisition_interface.h"
-#include "gps_pcps_acquisition_fpga_sc.h"
-#include "complex_byte_to_float_x2.h"
-#include
+#include "gnss_synchro.h"
+#include "pcps_acquisition_fpga.h"
+#include
+
class ConfigurationInterface;
@@ -68,12 +68,13 @@ public:
*/
inline std::string implementation() override
{
- return "GPS_L1_CA_PCPS_Acquisition_Fpga";
+ return "GPS_L1_CA_PCPS_Acquisition";
}
inline size_t item_size() override
{
- return item_size_;
+ size_t item_size = sizeof(lv_16sc_t);
+ return item_size;
}
void connect(gr::top_block_sptr top_block) override;
@@ -135,21 +136,21 @@ public:
private:
ConfigurationInterface* configuration_;
- gps_pcps_acquisition_fpga_sc_sptr gps_acquisition_fpga_sc_;
- size_t item_size_;
- std::string item_type_;
+ pcps_acquisition_fpga_sptr acquisition_fpga_;
unsigned int vector_length_;
+ unsigned int code_length_;
unsigned int channel_;
- float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;
- unsigned int max_dwells_;
+ unsigned int sampled_ms_;
+ long fs_in_;
+ long if_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
+ lv_16sc_t *d_all_fft_codes; // memory that contains all the code ffts
- float calculate_threshold(float pfa);
};
-#endif /* GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_H_ */
+#endif /* GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ */
diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt
index ca02bb952..9bfd4fc73 100644
--- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt
+++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt
@@ -29,7 +29,7 @@ set(ACQ_GR_BLOCKS_SOURCES
)
if(ENABLE_FPGA)
- set(ACQ_GR_BLOCKS_SOURCES ${ACQ_GR_BLOCKS_SOURCES} gps_pcps_acquisition_fpga_sc.cc)
+ set(ACQ_GR_BLOCKS_SOURCES ${ACQ_GR_BLOCKS_SOURCES} pcps_acquisition_fpga.cc)
endif(ENABLE_FPGA)
if(OPENCL_FOUND)
diff --git a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc
deleted file mode 100644
index 53b54686d..000000000
--- a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc
+++ /dev/null
@@ -1,298 +0,0 @@
-/*!
- * \file gps_pcps_acquisition_fpga_sc.cc
- * \brief This class implements a Parallel Code Phase Search Acquisition in the FPGA.
- * This file is based on the file gps_pcps_acquisition_sc.cc
- * \authors
- * - Marc Majoral, 2017. mmajoral(at)cttc.cat
- *
- *
- * -------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
- *
- * GNSS-SDR is a software defined Global Navigation
- * Satellite Systems receiver
- *
- * This file is part of GNSS-SDR.
- *
- * GNSS-SDR is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNSS-SDR is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNSS-SDR. If not, see .
- *
- * -------------------------------------------------------------------------
- */
-
-#include "gps_pcps_acquisition_fpga_sc.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include "control_message_factory.h"
-#include "GPS_L1_CA.h"
-
-#include
-
-using google::LogMessage;
-
-void wait3(int seconds)
-{
- boost::this_thread::sleep_for(boost::chrono::seconds
- { seconds });
-}
-
-
-gps_pcps_acquisition_fpga_sc_sptr gps_pcps_make_acquisition_fpga_sc(
- unsigned int sampled_ms, unsigned int max_dwells,
- unsigned int doppler_max, long freq, long fs_in, int samples_per_ms,
- int samples_per_code, int vector_length, unsigned int nsamples_total,
- bool bit_transition_flag, bool use_CFAR_algorithm_flag,
- unsigned int select_queue_Fpga, std::string device_name, bool dump,
- std::string dump_filename)
-{
- return gps_pcps_acquisition_fpga_sc_sptr(
- new gps_pcps_acquisition_fpga_sc(sampled_ms, max_dwells,
- doppler_max, freq, fs_in, samples_per_ms, samples_per_code,
- vector_length, nsamples_total, bit_transition_flag,
- use_CFAR_algorithm_flag, select_queue_Fpga, device_name,
- dump, dump_filename));
-}
-
-
-gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_sc(
- unsigned int sampled_ms, unsigned int max_dwells,
- unsigned int doppler_max, long freq, long fs_in, int samples_per_ms,
- int samples_per_code, int vector_length, unsigned int nsamples_total,
- bool bit_transition_flag, bool use_CFAR_algorithm_flag,
- unsigned int select_queue_Fpga, std::string device_name, bool dump,
- std::string dump_filename) :
-
- //gr::block("pcps_acquisition_fpga_sc",
- gr::block("gps_pcps_acquisition_fpga_sc",
- gr::io_signature::make(0, 0, sizeof(lv_16sc_t)),
- gr::io_signature::make(0, 0, 0))
-{
- this->message_port_register_out(pmt::mp("events"));
- d_sample_counter = 0; // sample counter
- d_active = false;
- d_state = 0;
- d_samples_per_code = samples_per_code;
- d_max_dwells = max_dwells; // Note : d_max_dwells is not used in the FPGA implementation
- d_well_count = 0;
- d_doppler_max = doppler_max;
- d_fft_size = sampled_ms * samples_per_ms;
- d_mag = 0;
- d_num_doppler_bins = 0;
- d_bit_transition_flag = bit_transition_flag; // Note : bit transition flag is ignored and assumed 0 in the FPGA implementation
- d_use_CFAR_algorithm_flag = use_CFAR_algorithm_flag; // Note : user CFAR algorithm flag is ignored and assumed 0 in the FPGA implementation
- d_threshold = 0.0;
- d_doppler_step = 250;
- d_channel = 0;
- // For dumping samples into a file
- d_dump = dump;
- d_dump_filename = dump_filename;
- d_gnss_synchro = 0;
- // instantiate HW accelerator class
- acquisition_fpga_8sc = std::make_shared < gps_fpga_acquisition_8sc>
- (device_name, vector_length, d_fft_size, doppler_max, nsamples_total, fs_in, freq, sampled_ms, select_queue_Fpga);
-}
-
-
-gps_pcps_acquisition_fpga_sc::~gps_pcps_acquisition_fpga_sc()
-{
- if (d_dump)
- {
- d_dump_file.close();
- }
- acquisition_fpga_8sc->free();
-}
-
-
-void gps_pcps_acquisition_fpga_sc::set_local_code()
-{
- acquisition_fpga_8sc->set_local_code(d_gnss_synchro->PRN);
-}
-
-
-void gps_pcps_acquisition_fpga_sc::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_num_doppler_bins = ceil(
- static_cast(static_cast(d_doppler_max)
- - static_cast(-d_doppler_max))
- / static_cast(d_doppler_step));
- //acquisition_fpga_8sc->open_device();
- acquisition_fpga_8sc->init();
-}
-
-
-void gps_pcps_acquisition_fpga_sc::set_state(int state)
-{
- 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_well_count = 0;
- d_mag = 0.0;
- }
- else if (d_state == 0)
- {
- }
- else
- {
- LOG(ERROR) << "State can only be set to 0 or 1";
- }
-}
-
-
-
-
-void gps_pcps_acquisition_fpga_sc::set_active(bool active)
-{
- float temp_peak_to_noise_level = 0.0;
- float peak_to_noise_level = 0.0;
- float input_power;
- float test_statistics = 0.0;
- //printf("ACQ : Block samples for PRN %d\n", d_gnss_synchro->PRN);
-// acquisition_fpga_8sc->block_samples(); // block the samples to run the acquisition this is only necessary for the tests
- d_active = active;
- int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
- d_state = 1;
- // initialize acquisition algorithm
- int doppler;
- uint32_t indext = 0;
- float magt = 0.0;
- //int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size );
- int effective_fft_size = d_fft_size;
- d_mag = 0.0;
- unsigned int initial_sample;
- d_well_count++;
- DLOG(INFO) << "Channel: " << d_channel
- << " , doing acquisition of satellite: " << d_gnss_synchro->System
- << " " << d_gnss_synchro->PRN << " ,sample stamp: "
- << d_sample_counter << ", threshold: " << ", threshold: "
- << d_threshold << ", doppler_max: " << d_doppler_max
- << ", doppler_step: " << d_doppler_step;
-
- // Doppler frequency search loop
- for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins;
- doppler_index++)
- {
-
- doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index;
-
- acquisition_fpga_8sc->set_phase_step(doppler_index);
- acquisition_fpga_8sc->run_acquisition(); // runs acquisition and waits until it is finished
- acquisition_fpga_8sc->read_acquisition_results(&indext, &magt,
- &initial_sample, &input_power);
- d_sample_counter = initial_sample;
- temp_peak_to_noise_level = static_cast(magt) / static_cast(input_power);
- if (peak_to_noise_level < temp_peak_to_noise_level)
- {
- peak_to_noise_level = temp_peak_to_noise_level;
- d_mag = magt;
- input_power = (input_power - d_mag)
- / (effective_fft_size - 1);
- d_gnss_synchro->Acq_delay_samples =
- static_cast(indext % d_samples_per_code);
- d_gnss_synchro->Acq_doppler_hz =
- static_cast(doppler);
- d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter;
- test_statistics = d_mag / input_power;
- }
- // Record results to file if required
- if (d_dump)
- {
- std::stringstream filename;
- //std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write
- filename.str("");
- boost::filesystem::path p = d_dump_filename;
- filename << p.parent_path().string()
- << boost::filesystem::path::preferred_separator
- << p.stem().string() << "_"
- << d_gnss_synchro->System << "_"
- << d_gnss_synchro->Signal << "_sat_"
- << d_gnss_synchro->PRN << "_doppler_" << doppler
- << p.extension().string();
- DLOG(INFO) << "Writing ACQ out to " << filename.str();
- d_dump_file.open(filename.str().c_str(),
- std::ios::out | std::ios::binary);
- d_dump_file.close();
- }
-
- }
-
-
- //printf("ACQ : unblocking samples for satellite %d\n", d_gnss_synchro->PRN);
-// acquisition_fpga_8sc->unblock_samples(); // unblock samples before sending positive or negative acquisition message to let the samples flow when the
- // set local code function is called
- if (test_statistics > d_threshold)
- {
- d_state = 2; // Positive acquisition
- // 6.1- Declare positive acquisition using a message port
- DLOG(INFO) << "positive acquisition";
- DLOG(INFO) << "satellite " << d_gnss_synchro->System << " "
- << d_gnss_synchro->PRN;
- DLOG(INFO) << "sample_stamp " << d_sample_counter;
- DLOG(INFO) << "test statistics value " << test_statistics;
- DLOG(INFO) << "test statistics threshold " << d_threshold;
- DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples;
- DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz;
- DLOG(INFO) << "magnitude " << d_mag;
- DLOG(INFO) << "input signal power " << input_power;
- d_active = false;
- d_state = 0;
- acquisition_message = 1;
- this->message_port_pub(pmt::mp("events"),
- pmt::from_long(acquisition_message));
- }
- else
- {
- d_state = 3; // Negative acquisition
- // 6.2- Declare negative acquisition using a message port
- DLOG(INFO) << "negative acquisition";
- DLOG(INFO) << "satellite " << d_gnss_synchro->System << " "
- << d_gnss_synchro->PRN;
- DLOG(INFO) << "sample_stamp " << d_sample_counter;
- DLOG(INFO) << "test statistics value " << test_statistics;
- DLOG(INFO) << "test statistics threshold " << d_threshold;
- DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples;
- DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz;
- DLOG(INFO) << "magnitude " << d_mag;
- DLOG(INFO) << "input signal power " << input_power;
- d_active = false;
- d_state = 0;
- acquisition_message = 2;
- this->message_port_pub(pmt::mp("events"),
- pmt::from_long(acquisition_message));
- }
- DLOG(INFO) << "Done. Consumed 1 item.";
-}
-
-
-int gps_pcps_acquisition_fpga_sc::general_work(int noutput_items,
- gr_vector_int &ninput_items __attribute__((unused)), gr_vector_const_void_star &input_items __attribute__((unused)),
- gr_vector_void_star &output_items __attribute__((unused)))
-{
- // general work not used with the acquisition
- return noutput_items;
-}
diff --git a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h
deleted file mode 100644
index a8316c634..000000000
--- a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*!
- * \file gps_pcps_acquisition_fpga_sc.h
- * \brief This class implements a Parallel Code Phase Search Acquisition in the FPGA.
- * This file is based on the file gps_pcps_acquisition_sc.h
- *
- * Acquisition strategy (Kay Borre book + CFAR threshold).
- *
- * - Compute the input signal power estimation
- *
- Doppler serial search loop
- *
- Perform the FFT-based circular convolution (parallel time search)
- *
- Record the maximum peak and the associated synchronization parameters
- *
- Compute the test statistics and compare to the threshold
- *
- Declare positive or negative acquisition using a message port
- *
- *
- * Kay Borre book: K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
- * "A Software-Defined GPS and Galileo Receiver. A Single-Frequency
- * Approach", Birkhauser, 2007. pp 81-84
- *
- * \authors
- * - Marc Majoral, 2017. mmajoral(at)cttc.cat
- *
- *
- * -------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
- *
- * GNSS-SDR is a software defined Global Navigation
- * Satellite Systems receiver
- *
- * This file is part of GNSS-SDR.
- *
- * GNSS-SDR is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNSS-SDR is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNSS-SDR. If not, see .
- *
- * -------------------------------------------------------------------------
- */
-
-#ifndef GNSS_SDR_GPS_PCPS_ACQUISITION_FPGA_SC_H_
-#define GNSS_SDR_GPS_PCPS_ACQUISITION_FPGA_SC_H_
-
-#include
-#include
-#include
-#include
-#include
-#include "gnss_synchro.h"
-#include "gps_fpga_acquisition_8sc.h"
-
-#include
-
-class gps_pcps_acquisition_fpga_sc;
-
-typedef boost::shared_ptr gps_pcps_acquisition_fpga_sc_sptr;
-
-gps_pcps_acquisition_fpga_sc_sptr
-gps_pcps_make_acquisition_fpga_sc(unsigned int sampled_ms,
- unsigned int max_dwells, unsigned int doppler_max, long freq,
- long fs_in, int samples_per_ms, int samples_per_code,
- int vector_length_, unsigned int nsamples_total_,
- bool bit_transition_flag, bool use_CFAR_algorithm_flag,
- unsigned int select_queue_Fpga, std::string device_name, bool dump,
- std::string dump_filename);
-
-/*!
- * \brief This class implements a Parallel Code Phase Search Acquisition.
- *
- * Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver",
- * Algorithm 1, for a pseudocode description of this implementation.
- */
-class gps_pcps_acquisition_fpga_sc : public gr::block
-{
-private:
- friend gps_pcps_acquisition_fpga_sc_sptr
- gps_pcps_make_acquisition_fpga_sc(unsigned int sampled_ms,
- unsigned int max_dwells, unsigned int doppler_max, long freq,
- long fs_in, int samples_per_ms, int samples_per_code,
- int vector_length, unsigned int nsamples_total,
- bool bit_transition_flag, bool use_CFAR_algorithm_flag,
- unsigned int select_queue_Fpga, std::string device_name, bool dump,
- std::string dump_filename);
-
- gps_pcps_acquisition_fpga_sc(unsigned int sampled_ms,
- unsigned int max_dwells, unsigned int doppler_max, long freq,
- long fs_in, int samples_per_ms, int samples_per_code,
- int vector_length, unsigned int nsamples_total,
- bool bit_transition_flag, bool use_CFAR_algorithm_flag,
- unsigned int select_queue_Fpga, std::string device_name, bool dump,
- std::string dump_filename);
- int d_samples_per_code;
- float d_threshold;
- unsigned int d_doppler_max;
- unsigned int d_doppler_step;
- unsigned int d_max_dwells;
- unsigned int d_well_count;
- unsigned int d_fft_size;
- unsigned long int d_sample_counter;
- unsigned int d_num_doppler_bins;
- Gnss_Synchro *d_gnss_synchro;
- float d_mag;bool d_bit_transition_flag;bool d_use_CFAR_algorithm_flag;
- std::ofstream d_dump_file;
- bool d_active;
- int d_state;bool d_dump;
- unsigned int d_channel;
- std::string d_dump_filename;
- std::shared_ptr acquisition_fpga_8sc;
- //void set_active2(bool active);
- boost::thread d_acq_thread;
-
-public:
- /*!
- * \brief Default destructor.
- */
- ~gps_pcps_acquisition_fpga_sc();
-
- /*!
- * \brief Set acquisition/tracking common Gnss_Synchro object pointer
- * to exchange synchronization data between acquisition and tracking blocks.
- * \param p_gnss_synchro Satellite information shared by the processing blocks.
- */
- inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
- {
- d_gnss_synchro = p_gnss_synchro;
- }
-
- /*!
- * \brief Returns the maximum peak of grid search.
- */
- inline unsigned int mag() const
- {
- return d_mag;
- }
-
- /*!
- * \brief Initializes acquisition algorithm.
- */
- void init();
-
- /*!
- * \brief Sets local code for PCPS acquisition algorithm.
- * \param code - Pointer to the PRN code.
- */
- void set_local_code();
-
- /*!
- * \brief Starts acquisition algorithm, turning from standby mode to
- * active mode
- * \param active - bool that activates/deactivates the block.
- */
-
-
- void set_active(bool active);
-
- /*!
- * \brief If set to 1, ensures that acquisition starts at the
- * first available sample.
- * \param state - int=1 forces start of acquisition
- */
- void set_state(int state);
-
- /*!
- * \brief Set acquisition channel unique ID
- * \param channel - receiver channel.
- */
- inline void set_channel(unsigned int channel)
- {
- d_channel = channel;
- }
-
- /*!
- * \brief Set statistics threshold of PCPS algorithm.
- * \param threshold - Threshold for signal detection (check \ref Navitec2012,
- * Algorithm 1, for a definition of this threshold).
- */
- inline void set_threshold(float threshold)
- {
- d_threshold = threshold;
- }
-
- /*!
- * \brief Set maximum Doppler grid search
- * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz].
- */
- inline void set_doppler_max(unsigned int doppler_max)
- {
- d_doppler_max = doppler_max;
- acquisition_fpga_8sc->set_doppler_max(doppler_max);
- }
-
- /*!
- * \brief Set Doppler steps for the grid search
- * \param doppler_step - Frequency bin of the search grid [Hz].
- */
- inline void set_doppler_step(unsigned int doppler_step)
- {
- d_doppler_step = doppler_step;
- acquisition_fpga_8sc->set_doppler_step(doppler_step);
- }
-
- /*!
- * \brief Parallel Code Phase Search Acquisition signal processing.
- */
- int general_work(int noutput_items, gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
-};
-
-#endif /* GNSS_SDR_GPS_PCPS_ACQUISITION_SC_H_*/
diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc
new file mode 100644
index 000000000..4f21ffa7a
--- /dev/null
+++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc
@@ -0,0 +1,247 @@
+/*!
+ * \file pcps_acquisition_fpga.cc
+ * \brief This class implements a Parallel Code Phase Search Acquisition in the FPGA
+ *
+ * Note: The CFAR algorithm is not implemented in the FPGA.
+ * Note 2: The bit transition flag is not implemented in the FPGA
+ *
+ * \authors
+ * - Marc Majoral, 2017. mmajoral(at)cttc.cat
+ *
- Javier Arribas, 2011. jarribas(at)cttc.es
+ *
- Luis Esteve, 2012. luis(at)epsilon-formacion.com
+ *
- Marc Molina, 2013. marc.molina.pena@gmail.com
+ *
- Cillian O'Driscoll, 2017. cillian(at)ieee.org
+ *
+ *
+ * -------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
+ *
+ * GNSS-SDR is a software defined Global Navigation
+ * Satellite Systems receiver
+ *
+ * This file is part of GNSS-SDR.
+ *
+ * GNSS-SDR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNSS-SDR is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNSS-SDR. If not, see .
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include "pcps_acquisition_fpga.h"
+#include "GPS_L1_CA.h" // for GPS_TWO_PI
+#include "GLONASS_L1_L2_CA.h" // for GLONASS_TWO_PI"
+#include
+#include
+
+using google::LogMessage;
+
+pcps_acquisition_fpga_sptr pcps_make_acquisition(pcpsconf_fpga_t conf_)
+{
+ return pcps_acquisition_fpga_sptr(new pcps_acquisition_fpga(conf_));
+}
+
+
+pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_) : gr::block("pcps_acquisition_fpga",
+ gr::io_signature::make(0, 0, 0),
+ gr::io_signature::make(0, 0, 0))
+{
+ this->message_port_register_out(pmt::mp("events"));
+
+ acq_parameters = conf_;
+ d_sample_counter = 0; // SAMPLE COUNTER
+ d_active = false;
+ d_state = 0;
+ d_fft_size = acq_parameters.sampled_ms * acq_parameters.samples_per_ms;
+ d_mag = 0;
+ d_input_power = 0.0;
+ d_num_doppler_bins = 0;
+ d_threshold = 0.0;
+ d_doppler_step = 0;
+ d_test_statistics = 0.0;
+ d_channel = 0;
+ d_gnss_synchro = 0;
+
+ acquisition_fpga = std::make_shared
+ (acq_parameters.device_name, d_fft_size, acq_parameters.doppler_max, acq_parameters.samples_per_ms,
+ acq_parameters.fs_in, acq_parameters.freq, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes);
+
+}
+
+
+pcps_acquisition_fpga::~pcps_acquisition_fpga()
+{
+ acquisition_fpga->free();
+}
+
+
+void pcps_acquisition_fpga::set_local_code()
+{
+ acquisition_fpga->set_local_code(d_gnss_synchro->PRN);
+}
+
+
+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;
+ d_num_doppler_bins = static_cast(std::ceil(static_cast(static_cast(acq_parameters.doppler_max) - static_cast(-acq_parameters.doppler_max)) / static_cast(d_doppler_step)));
+
+ acquisition_fpga->init();
+}
+
+
+void pcps_acquisition_fpga::set_state(int state)
+{
+ 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_well_count = 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()
+{
+ // 6.1- Declare positive acquisition using a message port
+ //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
+ DLOG(INFO) << "positive acquisition"
+ << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
+ << ", sample_stamp " << d_sample_counter
+ << ", 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;
+
+ this->message_port_pub(pmt::mp("events"), pmt::from_long(1));
+}
+
+
+void pcps_acquisition_fpga::send_negative_acquisition()
+{
+ // 6.2- Declare negative acquisition using a message port
+ //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
+ DLOG(INFO) << "negative acquisition"
+ << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
+ << ", sample_stamp " << d_sample_counter
+ << ", 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;
+
+ this->message_port_pub(pmt::mp("events"), pmt::from_long(2));
+}
+
+
+void pcps_acquisition_fpga::set_active(bool active)
+{
+ d_active = active;
+
+ // initialize acquisition algorithm
+ uint32_t indext = 0;
+ float magt = 0.0;
+ int effective_fft_size = d_fft_size;
+ float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size);
+
+ d_input_power = 0.0;
+ d_mag = 0.0;
+ //d_well_count++;
+
+ 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: " << acq_parameters.doppler_max
+ << ", doppler_step: " << d_doppler_step
+ // no CFAR algorithm in the FPGA
+ << ", use_CFAR_algorithm_flag: false";
+
+ unsigned int initial_sample;
+ float input_power_all = 0.0;
+ float input_power_computed = 0.0;
+ for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
+ {
+ // doppler search steps
+ int doppler = -static_cast(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
+
+ acquisition_fpga->set_phase_step(doppler_index);
+ acquisition_fpga->run_acquisition(); // runs acquisition and waits until it is finished
+ acquisition_fpga->read_acquisition_results(&indext, &magt,
+ &initial_sample, &d_input_power);
+ d_sample_counter = initial_sample;
+
+ if (d_mag < magt)
+ {
+ d_mag = magt;
+
+ input_power_all = d_input_power / (effective_fft_size - 1);
+ input_power_computed = (d_input_power - d_mag) / (effective_fft_size - 1);
+ d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1);
+
+ d_gnss_synchro->Acq_delay_samples = static_cast(indext % acq_parameters.samples_per_code);
+ d_gnss_synchro->Acq_doppler_hz = static_cast(doppler);
+ d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter;
+
+ d_test_statistics = (d_mag / d_input_power); //* correction_factor;
+ }
+
+ // In the case of the FPGA the option of dumping the results of the acquisition to a file is not available
+ // because the IFFT vector is not available
+ }
+
+ 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();
+ }
+}
+
+
+int pcps_acquisition_fpga::general_work(int noutput_items __attribute__((unused)),
+ gr_vector_int& ninput_items, gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items __attribute__((unused)))
+{
+ // the general work is not used with the acquisition that uses the FPGA
+ return noutput_items;
+}
diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h
new file mode 100644
index 000000000..d140f538c
--- /dev/null
+++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h
@@ -0,0 +1,216 @@
+/*!
+ * \file pcps_acquisition_fpga.h
+ * \brief This class implements a Parallel Code Phase Search Acquisition in the FPGA.
+ *
+ * Note: The CFAR algorithm is not implemented in the FPGA.
+ * Note 2: The bit transition flag is not implemented in the FPGA
+ *
+ * Acquisition strategy (Kay Borre book + CFAR threshold).
+ *
+ * - Compute the input signal power estimation
+ *
- Doppler serial search loop
+ *
- Perform the FFT-based circular convolution (parallel time search)
+ *
- Record the maximum peak and the associated synchronization parameters
+ *
- Compute the test statistics and compare to the threshold
+ *
- Declare positive or negative acquisition using a message queue
+ *
+ *
+ * Kay Borre book: K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
+ * "A Software-Defined GPS and Galileo Receiver. A Single-Frequency
+ * Approach", Birkhauser, 2007. pp 81-84
+ *
+ * \authors
+ * - Marc Majoral, 2017. mmajoral(at)cttc.cat
+ *
- Javier Arribas, 2011. jarribas(at)cttc.es
+ *
- Luis Esteve, 2012. luis(at)epsilon-formacion.com
+ *
- Marc Molina, 2013. marc.molina.pena@gmail.com
+ *
- Cillian O'Driscoll, 2017. cillian(at)ieee.org
+ *
- Antonio Ramos, 2017. antonio.ramos@cttc.es
+ *
+ *
+ * -------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
+ *
+ * GNSS-SDR is a software defined Global Navigation
+ * Satellite Systems receiver
+ *
+ * This file is part of GNSS-SDR.
+ *
+ * GNSS-SDR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNSS-SDR is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNSS-SDR. If not, see .
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef GNSS_SDR_PCPS_ACQUISITION_FPGA_H_
+#define GNSS_SDR_PCPS_ACQUISITION_FPGA_H_
+
+#include "gnss_synchro.h"
+#include
+#include "fpga_acquisition.h"
+
+typedef struct
+{
+ /* pcps acquisition configuration */
+ unsigned int sampled_ms;
+ unsigned int doppler_max;
+ long freq;
+ long fs_in;
+ int samples_per_ms;
+ int samples_per_code;
+ std::string dump_filename;
+ unsigned int select_queue_Fpga;
+ std::string device_name;
+ unsigned int code_length;
+ lv_16sc_t *all_fft_codes; // memory that contains all the code ffts
+
+} pcpsconf_fpga_t;
+
+class pcps_acquisition_fpga;
+
+typedef boost::shared_ptr pcps_acquisition_fpga_sptr;
+
+pcps_acquisition_fpga_sptr
+pcps_make_acquisition(pcpsconf_fpga_t conf_);
+
+/*!
+ * \brief This class implements a Parallel Code Phase Search Acquisition that uses the FPGA.
+ *
+ * Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver",
+ * Algorithm 1, for a pseudocode description of this implementation.
+ */
+class pcps_acquisition_fpga : public gr::block
+{
+private:
+ friend pcps_acquisition_fpga_sptr
+
+ pcps_make_acquisition(pcpsconf_fpga_t conf_);
+
+ pcps_acquisition_fpga(pcpsconf_fpga_t conf_);
+
+ void send_negative_acquisition();
+
+ void send_positive_acquisition();
+
+ pcpsconf_fpga_t acq_parameters;
+ bool d_active;
+ float d_threshold;
+ float d_mag;
+ float d_input_power;
+ float d_test_statistics;
+ int d_state;
+ unsigned int d_channel;
+ unsigned int d_doppler_step;
+ unsigned int d_fft_size;
+ unsigned int d_num_doppler_bins;
+ unsigned long int d_sample_counter;
+ Gnss_Synchro* d_gnss_synchro;
+ std::shared_ptr acquisition_fpga;
+
+
+
+public:
+ ~pcps_acquisition_fpga();
+
+ /*!
+ * \brief Set acquisition/tracking common Gnss_Synchro object pointer
+ * to exchange synchronization data between acquisition and tracking blocks.
+ * \param p_gnss_synchro Satellite information shared by the processing blocks.
+ */
+ inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
+ {
+ d_gnss_synchro = p_gnss_synchro;
+ }
+
+ /*!
+ * \brief Returns the maximum peak of grid search.
+ */
+ inline unsigned int mag() const
+ {
+ return d_mag;
+ }
+
+ /*!
+ * \brief Initializes acquisition algorithm.
+ */
+ void init();
+
+ /*!
+ * \brief Sets local code for PCPS acquisition algorithm.
+ * \param code - Pointer to the PRN code.
+ */
+ void set_local_code();
+
+ /*!
+ * \brief If set to 1, ensures that acquisition starts at the
+ * first available sample.
+ * \param state - int=1 forces start of acquisition
+ */
+ void set_state(int state);
+
+ /*!
+ * \brief Starts acquisition algorithm, turning from standby mode to
+ * active mode
+ * \param active - bool that activates/deactivates the block.
+ */
+ void set_active(bool active);
+
+ /*!
+ * \brief Set acquisition channel unique ID
+ * \param channel - receiver channel.
+ */
+ inline void set_channel(unsigned int channel)
+ {
+ d_channel = channel;
+ }
+
+ /*!
+ * \brief Set statistics threshold of PCPS algorithm.
+ * \param threshold - Threshold for signal detection (check \ref Navitec2012,
+ * Algorithm 1, for a definition of this threshold).
+ */
+ inline void set_threshold(float threshold)
+ {
+ d_threshold = threshold;
+ }
+
+ /*!
+ * \brief Set maximum Doppler grid search
+ * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz].
+ */
+ inline void set_doppler_max(unsigned int doppler_max)
+ {
+ acq_parameters.doppler_max = doppler_max;
+ acquisition_fpga->set_doppler_max(doppler_max);
+ }
+
+ /*!
+ * \brief Set Doppler steps for the grid search
+ * \param doppler_step - Frequency bin of the search grid [Hz].
+ */
+ inline void set_doppler_step(unsigned int doppler_step)
+ {
+ d_doppler_step = doppler_step;
+ acquisition_fpga->set_doppler_step(doppler_step);
+ }
+
+ /*!
+ * \brief Parallel Code Phase Search Acquisition signal processing.
+ */
+ int general_work(int noutput_items, gr_vector_int& ninput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
+
+#endif /* GNSS_SDR_PCPS_ACQUISITION_FPGA_H_*/
diff --git a/src/algorithms/acquisition/libs/CMakeLists.txt b/src/algorithms/acquisition/libs/CMakeLists.txt
index 53feb9366..f4adf131c 100644
--- a/src/algorithms/acquisition/libs/CMakeLists.txt
+++ b/src/algorithms/acquisition/libs/CMakeLists.txt
@@ -18,7 +18,7 @@
set(ACQUISITION_LIB_SOURCES
- gps_fpga_acquisition_8sc.cc
+ fpga_acquisition.cc
)
include_directories(
diff --git a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc b/src/algorithms/acquisition/libs/fpga_acquisition.cc
similarity index 55%
rename from src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc
rename to src/algorithms/acquisition/libs/fpga_acquisition.cc
index 16280e1d4..213183ba5 100644
--- a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc
+++ b/src/algorithms/acquisition/libs/fpga_acquisition.cc
@@ -1,12 +1,12 @@
/*!
- * \file gps_fpga_acquisition_8sc.cc
+ * \file fpga_acquisition.cc
* \brief High optimized FPGA vector correlator class
* \authors
- * - Marc Majoral, 2017. mmajoral(at)cttc.cat
- *
+ * Marc Majoral, 2018. mmajoral(at)cttc.cat
+ *
*
- * Class that controls and executes a high optimized vector correlator
- * class in the FPGA
+ * Class that controls and executes a high optimized acquisition HW
+ * accelerator in the FPGA
*
* -------------------------------------------------------------------------
*
@@ -33,65 +33,46 @@
* -------------------------------------------------------------------------
*/
-#include "gps_fpga_acquisition_8sc.h"
+#include "fpga_acquisition.h"
#include "gps_sdr_signal_processing.h"
-#include
-// allocate memory dynamically
-#include
-
-// libraries used by DMA test code and GIPO test code
-#include
+// libraries used by the GIPO
#include
-#include
-#include
-
-// libraries used by DMA test code
-#include
-#include
-#include
-#include
-
-// libraries used by GPIO test code
-#include
-#include
#include
// logging
#include
-// volk
-#include
-
// GPS L1
#include "GPS_L1_CA.h"
#define PAGE_SIZE 0x10000
#define MAX_PHASE_STEP_RAD 0.999999999534339 // 1 - pow(2,-31);
-#define NUM_PRNs 32
-#define TEST_REGISTER_ACQ_WRITEVAL 0x55AA
+#define TEST_REG_SANITY_CHECK 0x55AA
-bool gps_fpga_acquisition_8sc::init()
+bool fpga_acquisition::init()
{
// configure the acquisition with the main initialization values
- gps_fpga_acquisition_8sc::configure_acquisition();
+ fpga_acquisition::configure_acquisition();
return true;
}
-bool gps_fpga_acquisition_8sc::set_local_code(unsigned int PRN)
+bool fpga_acquisition::set_local_code(unsigned int PRN)
{
// select the code with the chosen PRN
- gps_fpga_acquisition_8sc::fpga_configure_acquisition_local_code(
+ fpga_acquisition::fpga_configure_acquisition_local_code(
&d_all_fft_codes[d_nsamples_total * (PRN - 1)]);
return true;
}
-gps_fpga_acquisition_8sc::gps_fpga_acquisition_8sc(std::string device_name,
- unsigned int vector_length, unsigned int nsamples,
+fpga_acquisition::fpga_acquisition(std::string device_name,
+ unsigned int nsamples,
unsigned int doppler_max,
unsigned int nsamples_total, long fs_in, long freq,
- unsigned int sampled_ms, unsigned select_queue)
+ unsigned int sampled_ms, unsigned select_queue,
+ lv_16sc_t *all_fft_codes)
{
+ unsigned int vector_length = nsamples_total*sampled_ms;
// initial values
d_device_name = device_name;
d_freq = freq;
@@ -104,98 +85,49 @@ gps_fpga_acquisition_8sc::gps_fpga_acquisition_8sc(std::string device_name,
d_doppler_step = 0;
d_fd = 0; // driver descriptor
d_map_base = nullptr; // driver memory map
- // Direct FFT
- d_fft_if = new gr::fft::fft_complex(vector_length, true);
- // allocate memory to compute all the PRNs
- // and compute all the possible codes
- std::complex* code = new std::complex[nsamples_total]; // buffer for the local code
- gr_complex* d_fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
- d_all_fft_codes = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32
- float max; // temporary maxima search
- for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
- {
- gps_l1_ca_code_gen_complex_sampled(code, PRN, fs_in, 0); // generate PRN code
- // fill in zero padding
- for (int s=nsamples;sget_inbuf() + offset, code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer
- d_fft_if->execute(); // Run the FFT of local code
- volk_32fc_conjugate_32fc(d_fft_codes_padded, d_fft_if->get_outbuf(), nsamples_total); // conjugate values
- max = 0; // initialize maximum value
- for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima
- {
- if (std::abs(d_fft_codes_padded[i].real()) > max)
- {
- max = std::abs(d_fft_codes_padded[i].real());
- }
- if (std::abs(d_fft_codes_padded[i].imag()) > max)
- {
- max = std::abs(d_fft_codes_padded[i].imag());
- }
- }
- for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
- {
- d_all_fft_codes[i + nsamples_total * (PRN -1)] = lv_16sc_t(static_cast(d_fft_codes_padded[i].real() * (pow(2, 7) - 1) / max),
- static_cast(d_fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max));
+ d_all_fft_codes = all_fft_codes;
- }
- }
// open communication with HW accelerator
- //printf("opening device %s\n", d_device_name.c_str());
if ((d_fd = open(d_device_name.c_str(), O_RDWR | O_SYNC)) == -1)
{
LOG(WARNING) << "Cannot open deviceio" << d_device_name;
- //std::cout << "acquisition cannot open deviceio";
}
d_map_base = reinterpret_cast(mmap(NULL, PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, d_fd, 0));
+
if (d_map_base == reinterpret_cast(-1))
{
LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory";
- //std::cout << "acquisition : could not map the fpga registers to the driver" << std::endl;
}
+
// sanity check : check test register
- // we only nee to do this when the class is created
- // but the device is not opened yet when the class is create
- // because we need to open and close the device every time we run an acquisition
- // since the same device may be used by more than one class (gps acquisition, galileo
- // acquisition, etc ..)
- unsigned writeval = TEST_REGISTER_ACQ_WRITEVAL;
+ unsigned writeval = TEST_REG_SANITY_CHECK;
unsigned readval;
- readval = gps_fpga_acquisition_8sc::fpga_acquisition_test_register(writeval);
+ readval = fpga_acquisition::fpga_acquisition_test_register(writeval);
if (writeval != readval)
{
LOG(WARNING) << "Acquisition test register sanity check failed";
- //std:: cout << "Acquisition test register sanity check failed" << std::endl;
}
else
{
- //std::cout << "Acquisition test register sanity check success !" << std::endl;
LOG(INFO) << "Acquisition test register sanity check success !";
}
- gps_fpga_acquisition_8sc::reset_acquisition();
+ fpga_acquisition::reset_acquisition();
DLOG(INFO) << "Acquisition FPGA class created";
- // temporary buffers that we can delete
- delete[] code;
- delete d_fft_if;
- delete[] d_fft_codes_padded;
+
}
-gps_fpga_acquisition_8sc::~gps_fpga_acquisition_8sc()
+fpga_acquisition::~fpga_acquisition()
{
close_device();
- delete[] d_all_fft_codes;
}
-bool gps_fpga_acquisition_8sc::free()
+bool fpga_acquisition::free()
{
return true;
}
-unsigned gps_fpga_acquisition_8sc::fpga_acquisition_test_register(unsigned writeval)
+unsigned fpga_acquisition::fpga_acquisition_test_register(unsigned writeval)
{
unsigned readval;
// write value to test register
@@ -206,7 +138,7 @@ unsigned gps_fpga_acquisition_8sc::fpga_acquisition_test_register(unsigned write
return readval;
}
-void gps_fpga_acquisition_8sc::fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[])
+void fpga_acquisition::fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[])
{
unsigned short local_code;
unsigned int k, tmp, tmp2;
@@ -224,7 +156,7 @@ void gps_fpga_acquisition_8sc::fpga_configure_acquisition_local_code(lv_16sc_t f
}
}
-void gps_fpga_acquisition_8sc::run_acquisition(void)
+void fpga_acquisition::run_acquisition(void)
{
// enable interrupts
int reenable = 1;
@@ -243,7 +175,7 @@ void gps_fpga_acquisition_8sc::run_acquisition(void)
}
}
-void gps_fpga_acquisition_8sc::configure_acquisition()
+void fpga_acquisition::configure_acquisition()
{
d_map_base[0] = d_select_queue;
d_map_base[1] = d_vector_length;
@@ -251,7 +183,7 @@ void gps_fpga_acquisition_8sc::configure_acquisition()
d_map_base[5] = (int) log2((float) d_vector_length); // log2 FFTlength
}
-void gps_fpga_acquisition_8sc::set_phase_step(unsigned int doppler_index)
+void fpga_acquisition::set_phase_step(unsigned int doppler_index)
{
float phase_step_rad_real;
float phase_step_rad_int_temp;
@@ -274,7 +206,7 @@ void gps_fpga_acquisition_8sc::set_phase_step(unsigned int doppler_index)
d_map_base[3] = phase_step_rad_int;
}
-void gps_fpga_acquisition_8sc::read_acquisition_results(uint32_t* max_index,
+void fpga_acquisition::read_acquisition_results(uint32_t* max_index,
float* max_magnitude, unsigned *initial_sample, float *power_sum)
{
unsigned readval = 0;
@@ -288,18 +220,18 @@ void gps_fpga_acquisition_8sc::read_acquisition_results(uint32_t* max_index,
*max_index = readval;
}
-void gps_fpga_acquisition_8sc::block_samples()
+void fpga_acquisition::block_samples()
{
d_map_base[14] = 1; // block the samples
}
-void gps_fpga_acquisition_8sc::unblock_samples()
+void fpga_acquisition::unblock_samples()
{
d_map_base[14] = 0; // unblock the samples
}
-void gps_fpga_acquisition_8sc::close_device()
+void fpga_acquisition::close_device()
{
unsigned * aux = const_cast(d_map_base);
if (munmap(static_cast(aux), PAGE_SIZE) == -1)
@@ -309,7 +241,7 @@ void gps_fpga_acquisition_8sc::close_device()
close(d_fd);
}
-void gps_fpga_acquisition_8sc::reset_acquisition(void)
+void fpga_acquisition::reset_acquisition(void)
{
d_map_base[6] = 2; // writing a 2 to d_map_base[6] resets the multicorrelator
}
diff --git a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h b/src/algorithms/acquisition/libs/fpga_acquisition.h
similarity index 78%
rename from src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h
rename to src/algorithms/acquisition/libs/fpga_acquisition.h
index 609abf0d9..45cae5475 100644
--- a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h
+++ b/src/algorithms/acquisition/libs/fpga_acquisition.h
@@ -1,12 +1,12 @@
/*!
- * \file fpga_acquisition_8sc.h
- * \brief High optimized FPGA vector correlator class for lv_16sc_t (short int complex).
+ * \file fpga_acquisition.h
+ * \brief High optimized FPGA vector correlator class
* \authors
- * - Marc Majoral, 2017. mmajoral(at)cttc.cat
+ *
- Marc Majoral, 2018. mmajoral(at)cttc.cat
*
*
- * Class that controls and executes a high optimized vector correlator
- * class in the FPGA
+ * Class that controls and executes a high optimized acquisition HW
+ * accelerator in the FPGA
*
* -------------------------------------------------------------------------
*
@@ -33,26 +33,26 @@
* -------------------------------------------------------------------------
*/
-#ifndef GNSS_GPS_SDR_FPGA_ACQUISITION_8SC_H_
-#define GNSS_GPS_SDR_FPGA_ACQUISITION_8SC_H_
+#ifndef GNSS_SDR_FPGA_ACQUISITION_H_
+#define GNSS_SDR_FPGA_ACQUISITION_H_
#include
-#include
#include
/*!
* \brief Class that implements carrier wipe-off and correlators.
*/
-class gps_fpga_acquisition_8sc
+class fpga_acquisition
{
public:
- gps_fpga_acquisition_8sc(std::string device_name,
- unsigned int vector_length, unsigned int nsamples,
+ fpga_acquisition(std::string device_name,
+ unsigned int nsamples,
unsigned int doppler_max,
unsigned int nsamples_total, long fs_in, long freq,
- unsigned int sampled_ms, unsigned select_queue);
- ~gps_fpga_acquisition_8sc();bool init();bool set_local_code(
- unsigned int PRN); //int code_length_chips, const lv_16sc_t* local_code_in, float *shifts_chips);
+ unsigned int sampled_ms, unsigned select_queue,
+ lv_16sc_t *all_fft_codes);
+ ~fpga_acquisition();bool init();bool set_local_code(
+ unsigned int PRN);
bool free();
void run_acquisition(void);
void set_phase_step(unsigned int doppler_index);
@@ -60,7 +60,7 @@ public:
unsigned *initial_sample, float *power_sum);
void block_samples();
void unblock_samples();
- //void open_device();
+
/*!
* \brief Set maximum Doppler grid search
* \param doppler_max - Maximum Doppler shift considered in the grid search [Hz].
@@ -69,6 +69,7 @@ public:
{
d_doppler_max = doppler_max;
}
+
/*!
* \brief Set Doppler steps for the grid search
* \param doppler_step - Frequency bin of the search grid [Hz].
@@ -102,4 +103,4 @@ private:
void close_device();
};
-#endif /* GNSS_GPS_SDR_FPGA_MULTICORRELATOR_H_ */
+#endif /* GNSS_SDR_FPGA_ACQUISITION_H_ */