From dc4c7b95515bf25906b8ef90450f597a4f84cbff Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Fri, 2 Mar 2018 11:30:36 +0100 Subject: [PATCH 01/19] Adding AD9361 fpga signal source --- CMakeLists.txt | 1 + cmake/Modules/Findlibiio.cmake | 32 ++ .../signal_source/adapters/CMakeLists.txt | 24 ++ .../adapters/ad9361_fpga_signal_source.cc | 299 ++++++++++++++++++ .../adapters/ad9361_fpga_signal_source.h | 109 +++++++ src/core/receiver/CMakeLists.txt | 5 + src/core/receiver/gnss_block_factory.cc | 13 + 7 files changed, 483 insertions(+) create mode 100644 cmake/Modules/Findlibiio.cmake create mode 100644 src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc create mode 100644 src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dcd4d375..669c2ae43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal option(ENABLE_GN3S "Enable the use of the GN3S dongle as signal source (experimental)" OFF) option(ENABLE_PLUTOSDR "Enable the use of ADALM-PLUTO Evaluation Boards (Analog Devices Inc.), requires gr-iio" OFF) option(ENABLE_FMCOMMS2 "Enable the use of FMCOMMS4-EBZ + ZedBoard hardware, requires gr-iio" OFF) +option(ENABLE_AD9361 "Enable the use of AD9361 directo to FPGA hardware, requires gr-iio" OFF) # Performance analysis tools option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF) diff --git a/cmake/Modules/Findlibiio.cmake b/cmake/Modules/Findlibiio.cmake new file mode 100644 index 000000000..a708d7062 --- /dev/null +++ b/cmake/Modules/Findlibiio.cmake @@ -0,0 +1,32 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_LIBIIO libiio) + +FIND_PATH( + LIBIIO_INCLUDE_DIRS + NAMES gnuradio/iio/api.h + HINTS $ENV{LIBIIO_DIR}/include + ${PC_LIBIIO_INCLUDEDIR} + PATHS ${CMAKE_INSTALL_PREFIX}/include + /usr/local/include + /usr/include +) + +FIND_LIBRARY( + LIBIIO_LIBRARIES + NAMES libiio.so + HINTS $ENV{LIBIIO_DIR}/lib + ${PC_LIBIIO_LIBDIR} + PATHS ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 + /usr/lib/x86_64-linux-gnu +) + +message("find libiio:") +message(${LIBIIO_LIBRARIES}) +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBIIO DEFAULT_MSG LIBIIO_LIBRARIES LIBIIO_INCLUDE_DIRS) +MARK_AS_ADVANCED(LIBIIO_LIBRARIES LIBIIO_INCLUDE_DIRS) diff --git a/src/algorithms/signal_source/adapters/CMakeLists.txt b/src/algorithms/signal_source/adapters/CMakeLists.txt index 2fb8f4be8..ededc5dc7 100644 --- a/src/algorithms/signal_source/adapters/CMakeLists.txt +++ b/src/algorithms/signal_source/adapters/CMakeLists.txt @@ -35,6 +35,20 @@ if(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) endif(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) +if(ENABLE_AD9361) + find_package(libiio REQUIRED) + if(NOT LIBIIO_FOUND) + message(STATUS "gnuradio-iio not found, its installation is required.") + message(STATUS "Please build and install the following projects:") + message(STATUS " * libiio from https://github.com/analogdevicesinc/libiio") + message(STATUS " * libad9361-iio from https://github.com/analogdevicesinc/libad9361-iio") + message(STATUS " * gnuradio-iio from https://github.com/analogdevicesinc/gr-iio") + message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled") + endif(NOT LIBIIO_FOUND) + set(OPT_LIBRARIES ${OPT_LIBRARIES} ${LIBIIO_LIBRARIES}) + set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${LIBIIO_INCLUDE_DIRS}) +endif(ENABLE_AD9361) + if(ENABLE_PLUTOSDR) ############################################## @@ -55,6 +69,16 @@ if(ENABLE_FMCOMMS2) endif(IIO_FOUND) endif(ENABLE_FMCOMMS2) +if(ENABLE_AD9361) + ############################################### + # AD9361 DIRECT TO FPGA Hardware + ############################################### + if(LIBIIO_FOUND) + set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ad9361_fpga_signal_source.cc) + endif(LIBIIO_FOUND) +endif(ENABLE_AD9361) + + if(ENABLE_GN3S) ############################################## diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc new file mode 100644 index 000000000..3aaf74a79 --- /dev/null +++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc @@ -0,0 +1,299 @@ +/*! + * \file ad9361_fpga_signal_source.cc + * \brief signal source for Analog Devices front-end AD9361 connected directly to FPGA accelerators. + * This source implements only the AD9361 control. It is NOT compatible with conventional SDR acquisition and tracking blocks. + * Please use the fmcomms2 source if conventional SDR acquisition and tracking is selected in the configuration file. + * \author Javier Arribas, jarribas(at)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 . + * + * ------------------------------------------------------------------------- + */ + +#include "ad9361_fpga_signal_source.h" +#include "configuration_interface.h" +#include "GPS_L1_CA.h" +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + + +/* RX is input, TX is output */ +enum iodev { RX, TX }; + +/* common RX and TX streaming params */ +struct stream_cfg { + long long bw_hz; // Analog banwidth in Hz + long long fs_hz; // Baseband sample rate in Hz + long long lo_hz; // Local oscillator frequency in Hz + const char* rfport; // Port name +}; + + +using google::LogMessage; + + +/* static scratch mem for strings */ +static char tmpstr[64]; + +/* IIO structs required for streaming */ +static struct iio_context *ctx = NULL; +static struct iio_channel *rx0_i = NULL; +static struct iio_channel *rx0_q = NULL; + +/* check return value of attr_write function */ +static void errchk(int v, const char* what) { + if (v < 0) { fprintf(stderr, "Error %d writing to channel \"%s\"\nvalue may not be supported.\n", v, what); } +} + +/* write attribute: long long int */ +static void wr_ch_lli(struct iio_channel *chn, const char* what, long long val) +{ + errchk(iio_channel_attr_write_longlong(chn, what, val), what); +} + +/* write attribute: string */ +static void wr_ch_str(struct iio_channel *chn, const char* what, const char* str) +{ + errchk(iio_channel_attr_write(chn, what, str), what); +} + + +/* helper function generating channel names */ +static char* get_ch_name(const char* type, int id) +{ + snprintf(tmpstr, sizeof(tmpstr), "%s%d", type, id); + return tmpstr; +} + +/* returns ad9361 phy device */ +static struct iio_device* get_ad9361_phy(struct iio_context *ctx) +{ + struct iio_device *dev = iio_context_find_device(ctx, "ad9361-phy"); + return dev; +} + +/* finds AD9361 streaming IIO devices */ +static bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev) +{ + switch (d) { + case TX: *dev = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); return *dev != NULL; + case RX: *dev = iio_context_find_device(ctx, "cf-ad9361-lpc"); return *dev != NULL; + default: return false; + } +} + +/* finds AD9361 streaming IIO channels */ +static bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn) +{ + *chn = iio_device_find_channel(dev, get_ch_name("voltage", chid), d == TX); + if (!*chn) + *chn = iio_device_find_channel(dev, get_ch_name("altvoltage", chid), d == TX); + return *chn != NULL; +} + +/* finds AD9361 phy IIO configuration channel with id chid */ +static bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn) +{ + switch (d) { + case RX: *chn = iio_device_find_channel(get_ad9361_phy(ctx), get_ch_name("voltage", chid), false); return *chn != NULL; + case TX: *chn = iio_device_find_channel(get_ad9361_phy(ctx), get_ch_name("voltage", chid), true); return *chn != NULL; + default: return false; + } +} + +/* finds AD9361 local oscillator IIO configuration channels */ +static bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn) +{ + switch (d) { + // LO chan is always output, i.e. true + case RX: *chn = iio_device_find_channel(get_ad9361_phy(ctx), get_ch_name("altvoltage", 0), true); return *chn != NULL; + case TX: *chn = iio_device_find_channel(get_ad9361_phy(ctx), get_ch_name("altvoltage", 1), true); return *chn != NULL; + default: return false; + } +} + + +/* applies streaming configuration through IIO */ +bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid) +{ + struct iio_channel *chn = NULL; + + // Configure phy and lo channels + printf("* Acquiring AD9361 phy channel %d\n", chid); + if (!get_phy_chan(ctx, type, chid, &chn)) { return false; } + wr_ch_str(chn, "rf_port_select", cfg->rfport); + wr_ch_lli(chn, "rf_bandwidth", cfg->bw_hz); + wr_ch_lli(chn, "sampling_frequency", cfg->fs_hz); + + // Configure LO channel + printf("* Acquiring AD9361 %s lo channel\n", type == TX ? "TX" : "RX"); + if (!get_lo_chan(ctx, type, &chn)) { return false; } + wr_ch_lli(chn, "frequency", cfg->lo_hz); + return true; +} + + +Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configuration, + std::string role, unsigned int in_stream, unsigned int out_stream, + boost::shared_ptr queue) : + role_(role), in_stream_(in_stream), out_stream_(out_stream), + queue_(queue) +{ + std::string default_item_type = "gr_complex"; + std::string default_dump_file = "./data/signal_source.dat"; + uri_ = configuration->property(role + ".device_address", std::string("192.168.2.1")); + freq_ = configuration->property(role + ".freq", GPS_L1_FREQ_HZ); + sample_rate_ = configuration->property(role + ".sampling_frequency", 2600000); + bandwidth_ = configuration->property(role + ".bandwidth", 2000000); + rx1_en_ = configuration->property(role + ".rx1_enable", true); + rx2_en_ = configuration->property(role + ".rx2_enable", false); + buffer_size_ = configuration->property(role + ".buffer_size", 0xA0000); + quadrature_ = configuration->property(role + ".quadrature", true); + rf_dc_ = configuration->property(role + ".rf_dc", true); + bb_dc_ = configuration->property(role + ".bb_dc", true); + gain_mode_rx1_ = configuration->property(role + ".gain_mode_rx1", std::string("manual")); + gain_mode_rx2_ = configuration->property(role + ".gain_mode_rx2", std::string("manual")); + rf_gain_rx1_ = configuration->property(role + ".gain_rx1", 64.0); + rf_gain_rx2_ = configuration->property(role + ".gain_rx2", 64.0); + rf_port_select_ = configuration->property(role + ".rf_port_select", std::string("A_BALANCED")); + filter_file_ = configuration->property(role + ".filter_file", std::string("")); + filter_auto_ = configuration->property(role + ".filter_auto", true); + item_type_ = configuration->property(role + ".item_type", default_item_type); + samples_ = configuration->property(role + ".samples", 0); + dump_ = configuration->property(role + ".dump", false); + dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file); + + item_size_ = sizeof(gr_complex); + + std::cout << "device address: " << uri_ << std::endl; + std::cout << "LO frequency : " << freq_ << " Hz" << std::endl; + std::cout << "sample rate: " << sample_rate_ << " Hz" << std::endl; + + + // AD9361 Frontend IC device operation + + // Streaming devices + struct iio_device *rx; + + // RX stream config + // Stream configurations + struct stream_cfg rxcfg; + rxcfg.bw_hz = bandwidth_; // 2 MHz rf bandwidth + rxcfg.fs_hz = sample_rate_; // 2.5 MS/s rx sample rate + rxcfg.lo_hz = freq_; // 2.5 GHz rf frequency + rxcfg.rfport = rf_port_select_.c_str(); // port A (select for rf freq.) + + + std::cout<<"AD9361 Acquiring IIO context\n"; + ctx = iio_create_default_context(); + if (!ctx) + { + std::cout<<"No context\n"; + throw std::runtime_error("AD9361 IIO No context"); + } + + if (iio_context_get_devices_count(ctx) <= 0) + { + std::cout<<"No devices\n"; + throw std::runtime_error("AD9361 IIO No devices"); + } + + std::cout<<"* Acquiring AD9361 streaming devices\n"; + + if(!get_ad9361_stream_dev(ctx, RX, &rx)) + { + std::cout<<"No rx dev found\n"; + throw std::runtime_error("AD9361 IIO No rx dev found"); + }; + + std::cout<<"* Configuring AD9361 for streaming\n"; + if (!cfg_ad9361_streaming_ch(ctx, &rxcfg, RX, 0)) + { + std::cout<<"RX port 0 not found\n"; + throw std::runtime_error("AD9361 IIO RX port 0 not found"); + } + + std::cout<<"* Initializing AD9361 IIO streaming channels\n"; + if (!get_ad9361_stream_ch(ctx, RX, rx, 0, &rx0_i)) + { + std::cout<<"RX chan i not found\n"; + throw std::runtime_error("RX chan i not found"); + } + + if (!get_ad9361_stream_ch(ctx, RX, rx, 1, &rx0_q)) + { + std::cout<<"RX chan q not found\n"; + throw std::runtime_error("RX chan q not found"); + } + + std::cout<<"* Enabling IIO streaming channels\n"; + iio_channel_enable(rx0_i); + iio_channel_enable(rx0_q); + +} + + +Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource() +{ + /* cleanup and exit */ + std::cout<<"* AD9361 Disabling streaming channels\n"; + if (rx0_i) { iio_channel_disable(rx0_i); } + if (rx0_q) { iio_channel_disable(rx0_q); } + + std::cout<<"* AD9361 Destroying context\n"; + if (ctx) { iio_context_destroy(ctx); } +} + + +void Ad9361FpgaSignalSource::connect(gr::top_block_sptr top_block) +{ + DLOG(INFO) << "AD9361 FPGA source nothing to connect"; +} + + +void Ad9361FpgaSignalSource::disconnect(gr::top_block_sptr top_block) +{ + DLOG(INFO) << "AD9361 FPGA source nothing to disconnect"; +} + + +gr::basic_block_sptr Ad9361FpgaSignalSource::get_left_block() +{ + LOG(WARNING) << "Trying to get signal source left block."; + return gr::basic_block_sptr(); +} + + +gr::basic_block_sptr Ad9361FpgaSignalSource::get_right_block() +{ + LOG(WARNING) << "Trying to get AD9361 FPGA signal source right block."; + return gr::basic_block_sptr(); +} diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h new file mode 100644 index 000000000..ff6b796b7 --- /dev/null +++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h @@ -0,0 +1,109 @@ +/*! + * \file ad9361_fpga_signal_source.h + * \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. + * + * ------------------------------------------------------------------------- + * + * 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_AD9361_FPGA_SIGNAL_SOURCE_H_ +#define GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H_ + +#include "gnss_block_interface.h" + +#include +#include +#include + +class ConfigurationInterface; + +class Ad9361FpgaSignalSource: public GNSSBlockInterface +{ +public: + Ad9361FpgaSignalSource(ConfigurationInterface* configuration, + std::string role, unsigned int in_stream, + unsigned int out_stream, boost::shared_ptr queue); + + virtual ~Ad9361FpgaSignalSource(); + + inline std::string role() override + { + return role_; + } + + /*! + * \brief Returns "Ad9361_Fpga_Signal_Source" + */ + inline std::string implementation() override + { + return "Ad9361_Fpga_Signal_Source"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + +private: + std::string role_; + + // Front-end settings + std::string uri_;//device direction + unsigned long freq_; //frequency of local oscilator + unsigned long sample_rate_; + unsigned long bandwidth_; + unsigned long buffer_size_; //reception buffer + bool rx1_en_; + bool rx2_en_; + bool quadrature_; + bool rf_dc_; + bool bb_dc_; + std::string gain_mode_rx1_; + std::string gain_mode_rx2_; + double rf_gain_rx1_; + double rf_gain_rx2_; + std::string rf_port_select_; + std::string filter_file_; + bool filter_auto_; + + unsigned int in_stream_; + unsigned int out_stream_; + + std::string item_type_; + size_t item_size_; + long samples_; + bool dump_; + std::string dump_filename_; + + boost::shared_ptr queue_; +}; + +#endif /*GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H_*/ diff --git a/src/core/receiver/CMakeLists.txt b/src/core/receiver/CMakeLists.txt index 0e12422a6..c922cdf3d 100644 --- a/src/core/receiver/CMakeLists.txt +++ b/src/core/receiver/CMakeLists.txt @@ -90,6 +90,11 @@ if(ENABLE_FMCOMMS2) set(OPT_RECEIVER_INCLUDE_DIRS ${OPT_RECEIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) endif(ENABLE_FMCOMMS2) +if(ENABLE_AD9361) + add_definitions(-DAD9361_DRIVER=1) + set(OPT_RECEIVER_INCLUDE_DIRS ${OPT_RECEIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) +endif(ENABLE_AD9361) + if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" ) add_definitions( -DGR_GREATER_38=1 ) endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" ) diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 1ebab2595..e7d096fab 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -132,6 +132,10 @@ #include "fmcomms2_signal_source.h" #endif +#if AD9361_DRIVER +#include "ad9361_fpga_signal_source.h" +#endif + #if FLEXIBAND_DRIVER #include "flexiband_signal_source.h" #endif @@ -1080,6 +1084,15 @@ std::unique_ptr GNSSBlockFactory::GetBlock( } #endif +#if AD9361_DRIVER + else if (implementation.compare("Ad9361_Fpga_Signal_Source") == 0) + { + std::unique_ptr block_(new Ad9361FpgaSignalSource(configuration.get(), role, in_streams, + out_streams, queue)); + block = std::move(block_); + } +#endif + #if FLEXIBAND_DRIVER else if (implementation.compare("Flexiband_Signal_Source") == 0) { From 288dd481e776cf68f8147331b7396baaac8c143b Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Fri, 2 Mar 2018 12:23:10 +0100 Subject: [PATCH 02/19] Updating FPGA acquisition modules --- .../gps_l1_ca_pcps_acquisition_fpga.cc | 51 ++---- .../gps_pcps_acquisition_fpga_sc.cc | 65 +++---- .../gps_pcps_acquisition_fpga_sc.h | 18 +- .../libs/gps_fpga_acquisition_8sc.cc | 161 ++++++++---------- .../libs/gps_fpga_acquisition_8sc.h | 21 +-- 5 files changed, 126 insertions(+), 190 deletions(-) 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 4b373edb3..00ff2008c 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 @@ -32,12 +32,10 @@ */ #include "gps_l1_ca_pcps_acquisition_fpga.h" -#include #include #include #include "GPS_L1_CA.h" #include "configuration_interface.h" -#include "gnss_sdr_flags.h" using google::LogMessage; @@ -57,57 +55,46 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( unsigned int nsamples_total; unsigned int select_queue_Fpga; std::string device_name; - configuration_ = configuration; - std::string default_item_type = "cshort"; std::string default_dump_filename = "./data/acquisition.dat"; - DLOG(INFO) << "role " << role; - - item_type_ = configuration_->property(role + ".item_type", default_item_type); - - long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); - fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + 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); doppler_max_ = configuration_->property(role + ".doppler_max", 5000); - if (FLAGS_doppler_max != 0 ) doppler_max_ = FLAGS_doppler_max; - sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1); - + 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); - + 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); - + 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); - + 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); - + 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) { item_size_ = sizeof(lv_16sc_t); @@ -121,10 +108,8 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( } else { - LOG(WARNING) << "item_type configured to " << item_type_ << "but FPGA implementation only accepts cshort"; - throw std::invalid_argument( "Wrong input_type configuration. Should be cshort" ); + LOG(FATAL) << item_type_ << " FPGA only accepts chsort"; } - channel_ = 0; threshold_ = 0.0; doppler_step_ = 0; @@ -192,7 +177,6 @@ signed int GpsL1CaPcpsAcquisitionFpga::mag() void GpsL1CaPcpsAcquisitionFpga::init() { gps_acquisition_fpga_sc_->init(); - set_local_code(); } @@ -230,7 +214,6 @@ float GpsL1CaPcpsAcquisitionFpga::calculate_threshold(float pfa) double lambda = double(vector_length_); boost::math::exponential_distribution mydist(lambda); float threshold = static_cast(quantile(mydist, val)); - return threshold; } 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 index cc491f3c0..53b54686d 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc @@ -39,7 +39,10 @@ #include #include #include "control_message_factory.h" -#include "GPS_L1_CA.h" //GPS_TWO_PI +#include "GPS_L1_CA.h" + +#include + using google::LogMessage; void wait3(int seconds) @@ -74,12 +77,13 @@ gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_sc( unsigned int select_queue_Fpga, std::string device_name, bool dump, std::string dump_filename) : - gr::block("pcps_acquisition_fpga_sc", + //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_sample_counter = 0; // sample counter d_active = false; d_state = 0; d_samples_per_code = samples_per_code; @@ -94,16 +98,13 @@ gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_sc( 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, nsamples_total, fs_in, freq, sampled_ms, select_queue_Fpga); + (device_name, vector_length, d_fft_size, doppler_max, nsamples_total, fs_in, freq, sampled_ms, select_queue_Fpga); } @@ -113,7 +114,6 @@ gps_pcps_acquisition_fpga_sc::~gps_pcps_acquisition_fpga_sc() { d_dump_file.close(); } - acquisition_fpga_8sc->free(); } @@ -134,14 +134,11 @@ void gps_pcps_acquisition_fpga_sc::init() 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->open_device(); acquisition_fpga_8sc->init(); } @@ -167,34 +164,28 @@ void gps_pcps_acquisition_fpga_sc::set_state(int state) } + + 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; - acquisition_fpga_8sc->block_samples(); // block the samples to run the acquisition this is only necessary for the tests - + //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; - //float fft_normalization_factor = static_cast(d_fft_size) * static_cast(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: " @@ -207,26 +198,20 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) doppler_index++) { - doppler = -static_cast(d_doppler_max) - + d_doppler_step * 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 = @@ -234,14 +219,12 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) 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 @@ -250,19 +233,21 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) << 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 << " " @@ -274,10 +259,8 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) 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)); @@ -285,7 +268,6 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) 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 << " " @@ -297,25 +279,18 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) 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)); } - - acquisition_fpga_8sc->unblock_samples(); - - acquisition_fpga_8sc->close_device(); - DLOG(INFO) << "Done. Consumed 1 item."; } int gps_pcps_acquisition_fpga_sc::general_work(int noutput_items, - gr_vector_int &ninput_items, gr_vector_const_void_star &input_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 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 index 561609109..a8316c634 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h @@ -46,8 +46,8 @@ * ------------------------------------------------------------------------- */ -#ifndef GNSS_SDR_PCPS_ACQUISITION_FPGA_SC_H_ -#define GNSS_SDR_PCPS_ACQUISITION_FPGA_SC_H_ +#ifndef GNSS_SDR_GPS_PCPS_ACQUISITION_FPGA_SC_H_ +#define GNSS_SDR_GPS_PCPS_ACQUISITION_FPGA_SC_H_ #include #include @@ -57,6 +57,8 @@ #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; @@ -95,7 +97,6 @@ private: 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; @@ -105,15 +106,16 @@ private: 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; + 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: /*! @@ -155,6 +157,8 @@ public: * active mode * \param active - bool that activates/deactivates the block. */ + + void set_active(bool active); /*! @@ -212,4 +216,4 @@ public: }; -#endif /* GNSS_SDR_PCPS_ACQUISITION_SC_H_*/ +#endif /* GNSS_SDR_GPS_PCPS_ACQUISITION_SC_H_*/ diff --git a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc index ca80ee6ff..16280e1d4 100644 --- a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc +++ b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc @@ -60,8 +60,10 @@ // logging #include +// volk #include +// GPS L1 #include "GPS_L1_CA.h" #define PAGE_SIZE 0x10000 @@ -78,15 +80,15 @@ bool gps_fpga_acquisition_8sc::init() bool gps_fpga_acquisition_8sc::set_local_code(unsigned int PRN) { - // select the code with the chosen PRN gps_fpga_acquisition_8sc::fpga_configure_acquisition_local_code( - &d_all_fft_codes[d_vector_length * PRN]); + &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, + unsigned int doppler_max, unsigned int nsamples_total, long fs_in, long freq, unsigned int sampled_ms, unsigned select_queue) { @@ -97,48 +99,33 @@ gps_fpga_acquisition_8sc::gps_fpga_acquisition_8sc(std::string device_name, d_vector_length = vector_length; d_nsamples = nsamples; // number of samples not including padding d_select_queue = select_queue; - - d_doppler_max = 0; + d_nsamples_total = nsamples_total; + d_doppler_max = doppler_max; d_doppler_step = 0; d_fd = 0; // driver descriptor d_map_base = nullptr; // driver memory map - - // compute all the possible code ffts - // 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 - std::complex * code_total = new gr_complex[vector_length]; // buffer for the local code repeate every number of ms - - gr_complex* d_fft_codes_padded = static_cast(volk_gnsssdr_malloc(vector_length * sizeof(gr_complex), volk_gnsssdr_get_alignment())); - - d_all_fft_codes = new lv_16sc_t[vector_length * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32 - + 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 = 0; PRN < NUM_PRNs; PRN++) + for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) { gps_l1_ca_code_gen_complex_sampled(code, PRN, fs_in, 0); // generate PRN code - - for (unsigned int i = 0; i < sampled_ms; i++) + // fill in zero padding + for (int s=nsamples;sget_inbuf() + offset, code_total, sizeof(gr_complex) * vector_length); // copy to FFT buffer - + memcpy(d_fft_if->get_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(), vector_length); // conjugate values - + 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 < vector_length; i++) // search for maxima + for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima { if (std::abs(d_fft_codes_padded[i].real()) > max) { @@ -149,35 +136,65 @@ gps_fpga_acquisition_8sc::gps_fpga_acquisition_8sc(std::string device_name, max = std::abs(d_fft_codes_padded[i].imag()); } } - - for (unsigned int i = 0; i < vector_length; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs + 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 + vector_length * PRN] = lv_16sc_t(static_cast(d_fft_codes_padded[i].real() * (pow(2, 7) - 1) / max), + 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)); + } - + } + // 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 readval; + readval = gps_fpga_acquisition_8sc::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(); + DLOG(INFO) << "Acquisition FPGA class created"; // temporary buffers that we can delete delete[] code; - delete[] code_total; delete d_fft_if; delete[] d_fft_codes_padded; } - gps_fpga_acquisition_8sc::~gps_fpga_acquisition_8sc() { + close_device(); delete[] d_all_fft_codes; } - bool gps_fpga_acquisition_8sc::free() { return true; } - unsigned gps_fpga_acquisition_8sc::fpga_acquisition_test_register(unsigned writeval) { unsigned readval; @@ -189,31 +206,31 @@ 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[]) { - short int local_code; + unsigned short local_code; unsigned int k, tmp, tmp2; - + unsigned int fft_data; // clear memory address counter d_map_base[4] = 0x10000000; + // write local code for (k = 0; k < d_vector_length; k++) { tmp = fft_local_code[k].real(); tmp2 = fft_local_code[k].imag(); local_code = (tmp & 0xFF) | ((tmp2 * 256) & 0xFF00); // put together the real part and the imaginary part - d_map_base[4] = 0x0C000000 | (local_code & 0xFFFF); + fft_data = 0x0C000000 | (local_code & 0xFFFF); + d_map_base[4] = fft_data; } } - void gps_fpga_acquisition_8sc::run_acquisition(void) { // enable interrupts int reenable = 1; write(d_fd, reinterpret_cast(&reenable), sizeof(int)); - - d_map_base[5] = 0; // writing anything to reg 4 launches the acquisition process + // launch the acquisition process + d_map_base[6] = 1; // writing anything to reg 6 launches the acquisition process int irq_count; ssize_t nb; @@ -221,26 +238,24 @@ void gps_fpga_acquisition_8sc::run_acquisition(void) nb = read(d_fd, &irq_count, sizeof(irq_count)); if (nb != sizeof(irq_count)) { - printf("Tracking_module Read failed to retrieve 4 bytes!\n"); - printf("Tracking_module Interrupt number %d\n", irq_count); + printf("acquisition module Read failed to retrieve 4 bytes!\n"); + printf("acquisition module Interrupt number %d\n", irq_count); } } - void gps_fpga_acquisition_8sc::configure_acquisition() { d_map_base[0] = d_select_queue; d_map_base[1] = d_vector_length; d_map_base[2] = d_nsamples; + d_map_base[5] = (int) log2((float) d_vector_length); // log2 FFTlength } - void gps_fpga_acquisition_8sc::set_phase_step(unsigned int doppler_index) { float phase_step_rad_real; float phase_step_rad_int_temp; int32_t phase_step_rad_int; - int doppler = static_cast(-d_doppler_max) + d_doppler_step * doppler_index; float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_fs_in); // The doppler step can never be outside the range -pi to +pi, otherwise there would be aliasing @@ -250,22 +265,19 @@ void gps_fpga_acquisition_8sc::set_phase_step(unsigned int doppler_index) phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2); // avoid saturation of the fixed point representation in the fpga // (only the positive value can saturate due to the 2's complement representation) - if (phase_step_rad_real == 1.0) + if (phase_step_rad_real >= 1.0) { phase_step_rad_real = MAX_PHASE_STEP_RAD; } phase_step_rad_int_temp = phase_step_rad_real * 4; // * 2^2 phase_step_rad_int = (int32_t) (phase_step_rad_int_temp * (536870912)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings - d_map_base[3] = phase_step_rad_int; } - void gps_fpga_acquisition_8sc::read_acquisition_results(uint32_t* max_index, float* max_magnitude, unsigned *initial_sample, float *power_sum) { unsigned readval = 0; - readval = d_map_base[0]; readval = d_map_base[1]; *initial_sample = readval; readval = d_map_base[2]; @@ -276,7 +288,6 @@ void gps_fpga_acquisition_8sc::read_acquisition_results(uint32_t* max_index, *max_index = readval; } - void gps_fpga_acquisition_8sc::block_samples() { d_map_base[14] = 1; // block the samples @@ -288,44 +299,6 @@ void gps_fpga_acquisition_8sc::unblock_samples() d_map_base[14] = 0; // unblock the samples } - -void gps_fpga_acquisition_8sc::open_device() -{ - - if ((d_fd = open(d_device_name.c_str(), O_RDWR | O_SYNC)) == -1) - { - LOG(WARNING) << "Cannot open deviceio" << d_device_name; - } - - 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"; - } - - // 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 readval; - readval = gps_fpga_acquisition_8sc::fpga_acquisition_test_register(writeval); - - if (writeval != readval) - { - LOG(WARNING) << "Acquisition test register sanity check failed"; - } - else - { - LOG(INFO) << "Acquisition test register sanity check success !"; - } -} - - void gps_fpga_acquisition_8sc::close_device() { unsigned * aux = const_cast(d_map_base); @@ -336,3 +309,7 @@ void gps_fpga_acquisition_8sc::close_device() close(d_fd); } +void gps_fpga_acquisition_8sc::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/gps_fpga_acquisition_8sc.h index 4f48af3bc..609abf0d9 100644 --- a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h +++ b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h @@ -2,7 +2,7 @@ * \file fpga_acquisition_8sc.h * \brief High optimized FPGA vector correlator class for lv_16sc_t (short int complex). * \authors
    - *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat + *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat *
* * Class that controls and executes a high optimized vector correlator @@ -33,11 +33,10 @@ * ------------------------------------------------------------------------- */ -#ifndef GNSS_SDR_FPGA_ACQUISITION_8SC_H_ -#define GNSS_SDR_FPGA_ACQUISITION_8SC_H_ +#ifndef GNSS_GPS_SDR_FPGA_ACQUISITION_8SC_H_ +#define GNSS_GPS_SDR_FPGA_ACQUISITION_8SC_H_ #include - #include #include @@ -49,6 +48,7 @@ class gps_fpga_acquisition_8sc public: gps_fpga_acquisition_8sc(std::string device_name, unsigned int vector_length, 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( @@ -60,9 +60,7 @@ public: unsigned *initial_sample, float *power_sum); void block_samples(); void unblock_samples(); - void open_device(); - void close_device(); - + //void open_device(); /*! * \brief Set maximum Doppler grid search * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz]. @@ -71,7 +69,6 @@ public: { d_doppler_max = doppler_max; } - /*! * \brief Set Doppler steps for the grid search * \param doppler_step - Frequency bin of the search grid [Hz]. @@ -86,23 +83,23 @@ private: long d_freq; long d_fs_in; gr::fft::fft_complex* d_fft_if; // function used to run the fft of the local codes - // data related to the hardware module and the driver int d_fd; // driver descriptor volatile unsigned *d_map_base; // driver memory map lv_16sc_t *d_all_fft_codes; // memory that contains all the code ffts unsigned int d_vector_length; // number of samples incluing padding and number of ms + unsigned int d_nsamples_total; // number of samples including padding unsigned int d_nsamples; // number of samples not including padding unsigned int d_select_queue; // queue selection std::string d_device_name; // HW device name unsigned int d_doppler_max; // max doppler unsigned int d_doppler_step; // doppler step - // FPGA private functions unsigned fpga_acquisition_test_register(unsigned writeval); void fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[]); void configure_acquisition(); - + void reset_acquisition(void); + void close_device(); }; -#endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */ +#endif /* GNSS_GPS_SDR_FPGA_MULTICORRELATOR_H_ */ From c2fc4b9854536962ae7027106f59b766d43a72b3 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Fri, 2 Mar 2018 17:40:13 +0100 Subject: [PATCH 03/19] Updating GPS L1 FPGA tracking adapters --- .../tracking/adapters/CMakeLists.txt | 2 +- .../gps_l1_ca_dll_pll_c_aid_tracking_fpga.cc | 228 ----- .../gps_l1_ca_dll_pll_tracking_fpga.cc | 155 +++ ...ga.h => gps_l1_ca_dll_pll_tracking_fpga.h} | 38 +- .../tracking/gnuradio_blocks/CMakeLists.txt | 2 +- ...ps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc | 947 ------------------ ...gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.h | 185 ---- .../gps_l1_ca_dll_pll_tracking_fpga_sc.cc | 586 +++++++++++ .../gps_l1_ca_dll_pll_tracking_fpga_sc.h | 200 ++++ src/algorithms/tracking/libs/CMakeLists.txt | 2 + .../tracking/libs/fpga_multicorrelator_8sc.cc | 126 ++- .../tracking/libs/fpga_multicorrelator_8sc.h | 41 +- .../fpga_multicorrelator_real_codes_8sc.cc | 148 +++ .../fpga_multicorrelator_real_codes_8sc.h | 73 ++ src/core/receiver/gnss_block_factory.cc | 10 +- .../gps_l1_ca_dll_pll_tracking_test_fpga.cc | 11 +- 16 files changed, 1304 insertions(+), 1450 deletions(-) delete mode 100644 src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_c_aid_tracking_fpga.cc create mode 100644 src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc rename src/algorithms/tracking/adapters/{gps_l1_ca_dll_pll_c_aid_tracking_fpga.h => gps_l1_ca_dll_pll_tracking_fpga.h} (72%) delete mode 100644 src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc delete mode 100644 src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.h create mode 100644 src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc create mode 100644 src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h create mode 100644 src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.cc create mode 100644 src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.h diff --git a/src/algorithms/tracking/adapters/CMakeLists.txt b/src/algorithms/tracking/adapters/CMakeLists.txt index 437626d06..98fcfc99e 100644 --- a/src/algorithms/tracking/adapters/CMakeLists.txt +++ b/src/algorithms/tracking/adapters/CMakeLists.txt @@ -22,7 +22,7 @@ if(ENABLE_CUDA) endif(ENABLE_CUDA) if(ENABLE_FPGA) - SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_c_aid_tracking_fpga.cc) + SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_tracking_fpga.cc) endif(ENABLE_FPGA) set(TRACKING_ADAPTER_SOURCES diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_c_aid_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_c_aid_tracking_fpga.cc deleted file mode 100644 index 36d53d086..000000000 --- a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_c_aid_tracking_fpga.cc +++ /dev/null @@ -1,228 +0,0 @@ -/*! - * \file gps_l1_ca_dll_pll_c_aid_tracking_fpga.cc - * \brief Implementation of an adapter of a DLL+PLL tracking loop block - * for GPS L1 C/A to a TrackingInterface - * \author Marc Majoral, 2017. mmajoral(at)cttc.cat - * Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com - * Javier Arribas, 2011. jarribas(at)cttc.es - * - * Code DLL + carrier PLL according to the algorithms described in: - * 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 - * - * ------------------------------------------------------------------------- - * - * 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_l1_ca_dll_pll_c_aid_tracking_fpga.h" -#include -#include "GPS_L1_CA.h" -#include "configuration_interface.h" -#include "gnss_sdr_flags.h" - - -using google::LogMessage; - -GpsL1CaDllPllCAidTrackingFpga::GpsL1CaDllPllCAidTrackingFpga( - ConfigurationInterface* configuration, std::string role, - unsigned int in_streams, unsigned int out_streams) : - role_(role), in_streams_(in_streams), out_streams_(out_streams) -{ - DLOG(INFO) << "role " << role; - //################# CONFIGURATION PARAMETERS ######################## - int fs_in; - int vector_length; - int f_if; - bool dump; - std::string dump_filename; - std::string default_item_type = "cshort"; - float pll_bw_hz; - float pll_bw_narrow_hz; - float dll_bw_hz; - float dll_bw_narrow_hz; - float early_late_space_chips; - std::string device_name; - unsigned int device_base; - - item_type_ = configuration->property(role + ".item_type", default_item_type); - int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); - fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - f_if = configuration->property(role + ".if", 0); - dump = configuration->property(role + ".dump", false); - pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); - if(FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast(FLAGS_pll_bw_hz); - dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); - if(FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast(FLAGS_dll_bw_hz); - pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 20.0); - dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 2.0); - int extend_correlation_ms; - extend_correlation_ms = configuration->property(role + ".extend_correlation_ms", 1); - - early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); - std::string default_dump_filename = "./track_ch"; - dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); - std::string default_device_name = "/dev/uio"; - device_name = configuration->property(role + ".devicename", default_device_name); - device_base = configuration->property(role + ".device_base", 1); - vector_length = std::round(fs_in / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); - - //################# MAKE TRACKING GNURadio object ################### - - if (item_type_.compare("cshort") == 0) - { - item_size_ = sizeof(lv_16sc_t); - tracking_fpga_sc = gps_l1_ca_dll_pll_c_aid_make_tracking_fpga_sc( - f_if, fs_in, vector_length, dump, dump_filename, pll_bw_hz, - dll_bw_hz, pll_bw_narrow_hz, dll_bw_narrow_hz, - extend_correlation_ms, early_late_space_chips, device_name, - device_base); - DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; - } - else - { - - item_size_ = sizeof(lv_16sc_t); - // LOG(WARNING) << item_type_ << " unknown tracking item type"; - LOG(WARNING) << item_type_ - << " the tracking item type for the FPGA tracking test has to be cshort"; - } - - channel_ = 0; -} - - -GpsL1CaDllPllCAidTrackingFpga::~GpsL1CaDllPllCAidTrackingFpga() -{ - LOG(INFO) << "gspl1cadllpllcaidtrackingfpga destructor called"; -} - - -void GpsL1CaDllPllCAidTrackingFpga::start_tracking() -{ - if (item_type_.compare("cshort") == 0) - { - tracking_fpga_sc->start_tracking(); - } - else - { - // LOG(WARNING) << item_type_ << " unknown tracking item type"; - LOG(WARNING) << item_type_ - << " the tracking item type for the FPGA tracking test has to be cshort"; - } -} - - -/* - * Set tracking channel unique ID - */ -void GpsL1CaDllPllCAidTrackingFpga::set_channel(unsigned int channel) -{ - channel_ = channel; - - if (item_type_.compare("cshort") == 0) - { - tracking_fpga_sc->set_channel(channel); - } - else - { - // LOG(WARNING) << item_type_ << " unknown tracking item type"; - LOG(WARNING) << item_type_ - << " the tracking item type for the FPGA tracking test has to be cshort"; - } -} - - -void GpsL1CaDllPllCAidTrackingFpga::set_gnss_synchro( - Gnss_Synchro* p_gnss_synchro) -{ - if (item_type_.compare("cshort") == 0) - { - tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro); - } - else - { - // LOG(WARNING) << item_type_ << " unknown tracking item type"; - LOG(WARNING) << item_type_ - << " the tracking item type for the FPGA tracking test has to be cshort"; - } -} - - -void GpsL1CaDllPllCAidTrackingFpga::connect(gr::top_block_sptr top_block) -{ - if (top_block) - { /* top_block is not null */ - }; - //nothing to connect, now the tracking uses gr_sync_decimator -} - - -void GpsL1CaDllPllCAidTrackingFpga::disconnect(gr::top_block_sptr top_block) -{ - if (top_block) - { /* top_block is not null */ - }; - //nothing to disconnect, now the tracking uses gr_sync_decimator -} - - -// CONVERT TO SOURCE -gr::basic_block_sptr GpsL1CaDllPllCAidTrackingFpga::get_left_block() -{ - if (item_type_.compare("cshort") == 0) - { - return tracking_fpga_sc; - } - else - { - //LOG(WARNING) << item_type_ << " unknown tracking item type"; - LOG(WARNING) << item_type_ - << " the tracking item type for the FPGA tracking test has to be cshort"; - return nullptr; - } -} - - -gr::basic_block_sptr GpsL1CaDllPllCAidTrackingFpga::get_right_block() -{ - if (item_type_.compare("cshort") == 0) - { - return tracking_fpga_sc; - } - else - { - //LOG(WARNING) << item_type_ << " unknown tracking item type"; - LOG(WARNING) << item_type_ - << " the tracking item type for the FPGA tracking test has to be cshort"; - return nullptr; - } -} - - -void GpsL1CaDllPllCAidTrackingFpga::reset(void) -{ - tracking_fpga_sc->reset(); -} - diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc new file mode 100644 index 000000000..336e93eb8 --- /dev/null +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc @@ -0,0 +1,155 @@ +/*! + * \file gps_l1_ca_dll_pll_tracking.cc + * \brief Implementation of an adapter of a DLL+PLL tracking loop block + * for GPS L1 C/A to a TrackingInterface + * \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com + * Javier Arribas, 2011. jarribas(at)cttc.es + * + * Code DLL + carrier PLL according to the algorithms described in: + * 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 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (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_l1_ca_dll_pll_tracking_fpga.h" +#include +#include "GPS_L1_CA.h" +#include "configuration_interface.h" + + +using google::LogMessage; + +GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams) : + role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + DLOG(INFO) << "role " << role; + //################# CONFIGURATION PARAMETERS ######################## + int fs_in; + int vector_length; + int f_if; + bool dump; + std::string dump_filename; + std::string item_type; + //std::string default_item_type = "gr_complex"; + std::string default_item_type = "cshort"; + float pll_bw_hz; + float dll_bw_hz; + float early_late_space_chips; + item_type = configuration->property(role + ".item_type", default_item_type); + int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + std::string device_name; + unsigned int device_base; + std::string default_device_name = "/dev/uio"; + device_name = configuration->property(role + ".devicename", default_device_name); + device_base = configuration->property(role + ".device_base", 1); + fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + f_if = configuration->property(role + ".if", 0); + dump = configuration->property(role + ".dump", false); + pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); + dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); + early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); + std::string default_dump_filename = "./track_ch"; + dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); //unused! + vector_length = std::round(fs_in / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); + if (item_type.compare("cshort") == 0) + { + item_size_ = sizeof(lv_16sc_t); + tracking_fpga_sc = gps_l1_ca_dll_pll_make_tracking_fpga_sc( + f_if, fs_in, vector_length, dump, dump_filename, pll_bw_hz, + dll_bw_hz, early_late_space_chips, device_name, + device_base); + DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() + << ")"; + } + else + { + + item_size_ = sizeof(lv_16sc_t); + // LOG(WARNING) << item_type_ << " unknown tracking item type"; + LOG(WARNING) << item_type + << " the tracking item type for the FPGA tracking test has to be cshort"; + } + channel_ = 0; + DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; +} + +GpsL1CaDllPllTrackingFpga::~GpsL1CaDllPllTrackingFpga() +{} + +void GpsL1CaDllPllTrackingFpga::start_tracking() +{ + tracking_fpga_sc->start_tracking(); +} + +/* + * Set tracking channel unique ID + */ +void GpsL1CaDllPllTrackingFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + tracking_fpga_sc->set_channel(channel); +} + +void GpsL1CaDllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro); +} + +void GpsL1CaDllPllTrackingFpga::connect(gr::top_block_sptr top_block) +{ + if(top_block) { /* top_block is not null */}; + //nothing to connect, now the tracking uses gr_sync_decimator +} + + +void GpsL1CaDllPllTrackingFpga::disconnect(gr::top_block_sptr top_block) +{ + if(top_block) { /* top_block is not null */}; + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + + +gr::basic_block_sptr GpsL1CaDllPllTrackingFpga::get_left_block() +{ + return tracking_fpga_sc; +} + + +gr::basic_block_sptr GpsL1CaDllPllTrackingFpga::get_right_block() +{ + return tracking_fpga_sc; +} + + +void GpsL1CaDllPllTrackingFpga::reset(void) +{ + // tracking_fpga_sc->reset(); + +} diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_c_aid_tracking_fpga.h b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.h similarity index 72% rename from src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_c_aid_tracking_fpga.h rename to src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.h index c828f9c3d..f45e3f802 100644 --- a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_c_aid_tracking_fpga.h +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.h @@ -1,9 +1,8 @@ /*! - * \file gps_l1_ca_dll_pll_c_aid_tracking_fpga.h + * \file gps_l1_ca_dll_pll_tracking.h * \brief Interface of an adapter of a DLL+PLL tracking loop block * for GPS L1 C/A to a TrackingInterface - * \author Marc Majoral, 2017. mmajoral(at)cttc.cat - * Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com + * \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com * Javier Arribas, 2011. jarribas(at)cttc.es * * Code DLL + carrier PLL according to the algorithms described in: @@ -13,7 +12,7 @@ * * ------------------------------------------------------------------------- * - * 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 @@ -36,36 +35,38 @@ * ------------------------------------------------------------------------- */ -#ifndef GNSS_SDR_GPS_L1_CA_DLL_PLL_C_AID_TRACKING_FPGA__H_ -#define GNSS_SDR_GPS_L1_CA_DLL_PLL_C_AID_TRACKING_FPGA__H_ +#ifndef GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_H_ +#define GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_H_ #include #include "tracking_interface.h" -#include "gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.h" +#include "gps_l1_ca_dll_pll_tracking_fpga_sc.h" + class ConfigurationInterface; /*! * \brief This class implements a code DLL + carrier PLL tracking loop */ -class GpsL1CaDllPllCAidTrackingFpga : public TrackingInterface +class GpsL1CaDllPllTrackingFpga : public TrackingInterface { public: - GpsL1CaDllPllCAidTrackingFpga(ConfigurationInterface* configuration, - std::string role, unsigned int in_streams, + GpsL1CaDllPllTrackingFpga(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, unsigned int out_streams); - virtual ~GpsL1CaDllPllCAidTrackingFpga(); + virtual ~GpsL1CaDllPllTrackingFpga(); inline std::string role() override { return role_; } - //! Returns "GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga" + //! Returns "GPS_L1_CA_DLL_PLL_Tracking_Fpga" inline std::string implementation() override { - return "GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga"; + return "GPS_L1_CA_DLL_PLL_Tracking_Fpga"; } inline size_t item_size() override @@ -75,7 +76,6 @@ public: void connect(gr::top_block_sptr top_block) override; void disconnect(gr::top_block_sptr top_block) override; - // CONVERT TO SOURCE gr::basic_block_sptr get_left_block() override; gr::basic_block_sptr get_right_block() override; @@ -92,16 +92,16 @@ public: void start_tracking() override; - void reset(void); - + void reset(void); + private: - gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc_sptr tracking_fpga_sc; + //gps_l1_ca_dll_pll_tracking_cc_sptr tracking_; + gps_l1_ca_dll_pll_tracking_fpga_sc_sptr tracking_fpga_sc; size_t item_size_; - std::string item_type_; unsigned int channel_; std::string role_; unsigned int in_streams_; unsigned int out_streams_; }; -#endif // GNSS_SDR_GPS_L1_CA_DLL_PLL_C_AID_TRACKING_FPGA__H_ +#endif // GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_H_ diff --git a/src/algorithms/tracking/gnuradio_blocks/CMakeLists.txt b/src/algorithms/tracking/gnuradio_blocks/CMakeLists.txt index 4c4a2a550..b764548ef 100644 --- a/src/algorithms/tracking/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/tracking/gnuradio_blocks/CMakeLists.txt @@ -23,7 +23,7 @@ if(ENABLE_CUDA) endif(ENABLE_CUDA) if(ENABLE_FPGA) - set(OPT_TRACKING_BLOCKS ${OPT_TRACKING_BLOCKS} gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc) + set(OPT_TRACKING_BLOCKS ${OPT_TRACKING_BLOCKS} gps_l1_ca_dll_pll_tracking_fpga_sc.cc) endif(ENABLE_FPGA) set(TRACKING_GR_BLOCKS_SOURCES diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc deleted file mode 100644 index a8e0d0428..000000000 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc +++ /dev/null @@ -1,947 +0,0 @@ -/*! - * \file gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc - * \brief Implementation of a code DLL + carrier PLL tracking block - * \author Marc Majoral, 2017. mmajoral(at)cttc.cat - * Javier Arribas, 2015. jarribas(at)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 . - * - * ------------------------------------------------------------------------- - */ - -#include "gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.h" -#include "gnss_synchro.h" -#include "gps_sdr_signal_processing.h" -#include "tracking_discriminators.h" -#include "lock_detectors.h" -#include "GPS_L1_CA.h" -#include "gnss_sdr_flags.h" -#include "control_message_factory.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using google::LogMessage; - -gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc_sptr gps_l1_ca_dll_pll_c_aid_make_tracking_fpga_sc( - long if_freq, long fs_in, unsigned int vector_length, bool dump, - std::string dump_filename, float pll_bw_hz, float dll_bw_hz, - float pll_bw_narrow_hz, float dll_bw_narrow_hz, - int extend_correlation_ms, float early_late_space_chips, - std::string device_name, unsigned int device_base) -{ - return gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc_sptr( - new gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc(if_freq, fs_in, - vector_length, dump, dump_filename, pll_bw_hz, dll_bw_hz, - pll_bw_narrow_hz, dll_bw_narrow_hz, extend_correlation_ms, - early_late_space_chips, device_name, device_base)); -} - - -void gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::msg_handler_preamble_index( - pmt::pmt_t msg) -{ - DLOG(INFO) << "Extended correlation enabled for Tracking CH " - << d_channel << ": Satellite " - << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN); - if (d_enable_extended_integration == false) //avoid re-setting preamble indicator - { - d_preamble_timestamp_s = pmt::to_double(msg); - d_enable_extended_integration = true; - d_preamble_synchronized = false; - } -} - - -gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc( - long if_freq, long fs_in, unsigned int vector_length, bool dump, - std::string dump_filename, float pll_bw_hz, float dll_bw_hz, - float pll_bw_narrow_hz, float dll_bw_narrow_hz, - int extend_correlation_ms, float early_late_space_chips, - std::string device_name, unsigned int device_base) : - gr::block("gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc", - gr::io_signature::make(0, 0, sizeof(lv_16sc_t)), - gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) - -{ - // Telemetry bit synchronization message port input - this->message_port_register_in(pmt::mp("preamble_timestamp_s")); - this->set_msg_handler(pmt::mp("preamble_timestamp_s"), - boost::bind( - &gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::msg_handler_preamble_index, - this, _1)); - this->message_port_register_out(pmt::mp("events")); - // initialize internal vars - d_dump = dump; - d_if_freq = if_freq; - d_fs_in = fs_in; - d_vector_length = vector_length; - d_dump_filename = dump_filename; - d_correlation_length_samples = static_cast(d_vector_length); - - // Initialize tracking ========================================== - d_pll_bw_hz = pll_bw_hz; - d_dll_bw_hz = dll_bw_hz; - d_pll_bw_narrow_hz = pll_bw_narrow_hz; - d_dll_bw_narrow_hz = dll_bw_narrow_hz; - d_code_loop_filter.set_DLL_BW(d_dll_bw_hz); - d_carrier_loop_filter.set_params(10.0, d_pll_bw_hz, 2); - d_extend_correlation_ms = extend_correlation_ms; - - // --- DLL variables -------------------------------------------------------- - d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips) - - // Initialization of local code replica - // Get space for a vector with the C/A code replica sampled 1x/chip - d_ca_code = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS) * sizeof(gr_complex), volk_gnsssdr_get_alignment())); - d_ca_code_16sc = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS) * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment())); - - // correlator outputs (scalar) - d_n_correlator_taps = 3; // Early, Prompt, and Late - - d_correlator_outs_16sc = static_cast(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(lv_16sc_t), - volk_gnsssdr_get_alignment())); - - for (int n = 0; n < d_n_correlator_taps; n++) - { - d_correlator_outs_16sc[n] = lv_cmake(0, 0); - } - - d_local_code_shift_chips = static_cast(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(float), volk_gnsssdr_get_alignment())); - - // Set TAPs delay values [chips] - d_local_code_shift_chips[0] = -d_early_late_spc_chips; - d_local_code_shift_chips[1] = 0.0; - d_local_code_shift_chips[2] = d_early_late_spc_chips; - - // create multicorrelator class - multicorrelator_fpga_8sc = std::make_shared (d_n_correlator_taps, device_name, device_base); - - //--- Perform initializations ------------------------------ - // define initial code frequency basis of NCO - d_code_freq_chips = GPS_L1_CA_CODE_RATE_HZ; - // define residual code phase (in chips) - d_rem_code_phase_samples = 0.0; - // define residual carrier phase - d_rem_carrier_phase_rad = 0.0; - - // sample synchronization - d_sample_counter = 0; //(from trk to tlm) - d_acq_sample_stamp = 0; - d_enable_tracking = false; - d_pull_in = false; - - // CN0 estimation and lock detector buffers - d_cn0_estimation_counter = 0; - d_Prompt_buffer = new gr_complex[FLAGS_cn0_samples]; - d_carrier_lock_test = 1; - d_CN0_SNV_dB_Hz = 0; - d_carrier_lock_fail_counter = 0; - d_carrier_lock_threshold = FLAGS_carrier_lock_th; - - systemName["G"] = std::string("GPS"); - systemName["S"] = std::string("SBAS"); - - set_relative_rate(1.0 / static_cast(d_vector_length)); - - d_acquisition_gnss_synchro = 0; - d_channel = 0; - d_acq_code_phase_samples = 0.0; - d_acq_carrier_doppler_hz = 0.0; - d_carrier_doppler_hz = 0.0; - d_acc_carrier_phase_cycles = 0.0; - d_code_phase_samples = 0.0; - d_enable_extended_integration = false; - d_preamble_synchronized = false; - d_rem_code_phase_integer_samples = 0; - d_code_error_chips_Ti = 0.0; - d_pll_to_dll_assist_secs_Ti = 0.0; - d_rem_code_phase_chips = 0.0; - d_code_phase_step_chips = 0.0; - d_carrier_phase_step_rad = 0.0; - d_code_error_filt_chips_s = 0.0; - d_code_error_filt_chips_Ti = 0.0; - d_preamble_timestamp_s = 0.0; - d_carr_phase_error_secs_Ti = 0.0; - //set_min_output_buffer((long int)300); -} - - -void gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::start_tracking() -{ - /* - * correct the code phase according to the delay between acq and trk - */ - d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples; - d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz; - d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples; - - long int acq_trk_diff_samples; - double acq_trk_diff_seconds; - acq_trk_diff_samples = static_cast(d_sample_counter) - static_cast(d_acq_sample_stamp); - DLOG(INFO) << "Number of samples between Acquisition and Tracking =" << acq_trk_diff_samples; - acq_trk_diff_seconds = static_cast(acq_trk_diff_samples) / static_cast(d_fs_in); - // Doppler effect - // Fd=(C/(C+Vr))*F - double radial_velocity = (GPS_L1_FREQ_HZ + d_acq_carrier_doppler_hz) / GPS_L1_FREQ_HZ; - // new chip and prn sequence periods based on acq Doppler - double T_chip_mod_seconds; - double T_prn_mod_seconds; - double T_prn_mod_samples; - d_code_freq_chips = radial_velocity * GPS_L1_CA_CODE_RATE_HZ; - d_code_phase_step_chips = static_cast(d_code_freq_chips) / static_cast(d_fs_in); - T_chip_mod_seconds = 1.0 / d_code_freq_chips; - T_prn_mod_seconds = T_chip_mod_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS; - T_prn_mod_samples = T_prn_mod_seconds * static_cast(d_fs_in); - - d_correlation_length_samples = round(T_prn_mod_samples); - - double T_prn_true_seconds = GPS_L1_CA_CODE_LENGTH_CHIPS / GPS_L1_CA_CODE_RATE_HZ; - double T_prn_true_samples = T_prn_true_seconds * static_cast(d_fs_in); - double T_prn_diff_seconds = T_prn_true_seconds - T_prn_mod_seconds; - double N_prn_diff = acq_trk_diff_seconds / T_prn_true_seconds; - double corrected_acq_phase_samples, delay_correction_samples; - corrected_acq_phase_samples = fmod((d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * static_cast(d_fs_in)), T_prn_true_samples); - if (corrected_acq_phase_samples < 0) - { - corrected_acq_phase_samples = T_prn_mod_samples + corrected_acq_phase_samples; - } - delay_correction_samples = d_acq_code_phase_samples - corrected_acq_phase_samples; - - d_acq_code_phase_samples = corrected_acq_phase_samples; - - d_carrier_doppler_hz = d_acq_carrier_doppler_hz; - - d_carrier_phase_step_rad = GPS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); - - // DLL/PLL filter initialization - d_carrier_loop_filter.initialize(d_acq_carrier_doppler_hz); // The carrier loop filter implements the Doppler accumulator - d_code_loop_filter.initialize(); // initialize the code filter - - // generate local reference ALWAYS starting at chip 1 (1 sample per chip) - gps_l1_ca_code_gen_complex(d_ca_code, d_acquisition_gnss_synchro->PRN, 0); - volk_gnsssdr_32fc_convert_16ic(d_ca_code_16sc, d_ca_code, static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS)); - - multicorrelator_fpga_8sc->set_local_code_and_taps(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS), d_ca_code_16sc, d_local_code_shift_chips); - for (int n = 0; n < d_n_correlator_taps; n++) - { - d_correlator_outs_16sc[n] = lv_16sc_t(0, 0); - } - - d_carrier_lock_fail_counter = 0; - d_rem_code_phase_samples = 0.0; - d_rem_carrier_phase_rad = 0.0; - d_rem_code_phase_chips = 0.0; - d_acc_carrier_phase_cycles = 0.0; - d_pll_to_dll_assist_secs_Ti = 0.0; - d_code_phase_samples = d_acq_code_phase_samples; - - std::string sys_ = &d_acquisition_gnss_synchro->System; - sys = sys_.substr(0, 1); - - // DEBUG OUTPUT - std::cout << "Tracking start on channel " << d_channel << " for satellite " - << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) - << std::endl; - LOG(INFO) << "Starting tracking of satellite " - << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) - << " on channel " << d_channel; - - // enable tracking - d_pull_in = true; - d_enable_tracking = true; - d_enable_extended_integration = false; - d_preamble_synchronized = false; - - // lock the channel - multicorrelator_fpga_8sc->lock_channel(); - - LOG(INFO) << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz - << " Code Phase correction [samples]=" << delay_correction_samples - << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples; -} - - -gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::~gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc() -{ - if (d_dump_file.is_open()) - { - try - { - d_dump_file.close(); - } - catch(const std::exception & ex) - { - LOG(WARNING)<< "Exception in destructor " << ex.what(); - } - } - - if(d_dump) - { - if(d_channel == 0) - { - std::cout << "Writing .mat files ..."; - } - gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::save_matfile(); - if(d_channel == 0) - { - std::cout << " done." << std::endl; - } - } - - try - { - volk_gnsssdr_free(d_local_code_shift_chips); - volk_gnsssdr_free(d_ca_code); - volk_gnsssdr_free(d_ca_code_16sc); - volk_gnsssdr_free(d_correlator_outs_16sc); - delete[] d_Prompt_buffer; - multicorrelator_fpga_8sc->free(); - } - catch(const std::exception & ex) - { - LOG(WARNING) << "Exception in destructor " << ex.what(); - } -} - - -int gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::general_work( - int noutput_items __attribute__((unused)), - gr_vector_int &ninput_items __attribute__((unused)), - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - // samples offset - int samples_offset; - - // Block input data and block output stream pointers - Gnss_Synchro **out = reinterpret_cast(&output_items[0]); - - Gnss_Synchro current_synchro_data = Gnss_Synchro(); - - // process vars - double code_error_filt_secs_Ti = 0.0; - double CURRENT_INTEGRATION_TIME_S = 0.0; - double CORRECTED_INTEGRATION_TIME_S = 0.0; - - if (d_enable_tracking == true) - { - // Fill the acquisition data - current_synchro_data = *d_acquisition_gnss_synchro; - // Receiver signal alignment - if (d_pull_in == true) - { - double acq_trk_shif_correction_samples; - int acq_to_trk_delay_samples; - acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp; - acq_trk_shif_correction_samples = d_correlation_length_samples - fmod( static_cast(acq_to_trk_delay_samples), static_cast(d_correlation_length_samples)); - samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples); - current_synchro_data.Tracking_sample_counter = d_sample_counter + samples_offset; - d_sample_counter += samples_offset; // count for the processed samples - d_pull_in = false; - d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * samples_offset / GPS_TWO_PI; - current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_cycles * GPS_TWO_PI; - current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; - current_synchro_data.fs = d_fs_in; - *out[0] = current_synchro_data; - //consume_each(samples_offset); // shift input to perform alignment with local replica - multicorrelator_fpga_8sc->set_initial_sample(samples_offset); - - return 1; - } - - // ################# CARRIER WIPEOFF AND CORRELATORS ############################## - // perform carrier wipe-off and compute Early, Prompt and Late correlation - multicorrelator_fpga_8sc->set_output_vectors(d_correlator_outs_16sc); - - multicorrelator_fpga_8sc->Carrier_wipeoff_multicorrelator_resampler( - d_rem_carrier_phase_rad, d_carrier_phase_step_rad, - d_rem_code_phase_chips, d_code_phase_step_chips, - d_correlation_length_samples); - - // ####### coherent intergration extension - // keep the last symbols - d_E_history.push_back(d_correlator_outs_16sc[0]); // save early output - d_P_history.push_back(d_correlator_outs_16sc[1]); // save prompt output - d_L_history.push_back(d_correlator_outs_16sc[2]); // save late output - - if (static_cast(d_P_history.size()) > d_extend_correlation_ms) - { - d_E_history.pop_front(); - d_P_history.pop_front(); - d_L_history.pop_front(); - } - - bool enable_dll_pll; - if (d_enable_extended_integration == true) - { - long int symbol_diff = round(1000.0 * ((static_cast(d_sample_counter) + d_rem_code_phase_samples) / static_cast(d_fs_in) - d_preamble_timestamp_s)); - if (symbol_diff > 0 and symbol_diff % d_extend_correlation_ms == 0) - { - // compute coherent integration and enable tracking loop - // perform coherent integration using correlator output history - // std::cout<<"##### RESET COHERENT INTEGRATION ####"<PRN) - << " pll_bw = " << d_pll_bw_hz - << " [Hz], pll_narrow_bw = " - << d_pll_bw_narrow_hz << " [Hz]" - << std::endl << " dll_bw = " - << d_dll_bw_hz - << " [Hz], dll_narrow_bw = " - << d_dll_bw_narrow_hz << " [Hz]" - << std::endl; - } - // UPDATE INTEGRATION TIME - CURRENT_INTEGRATION_TIME_S = static_cast(d_extend_correlation_ms) * GPS_L1_CA_CODE_PERIOD; - enable_dll_pll = true; - } - else - { - if (d_preamble_synchronized == true) - { - // continue extended coherent correlation - // Compute the next buffer length based on the period of the PRN sequence and the code phase error estimation - double T_chip_seconds = 1.0 / d_code_freq_chips; - double T_prn_seconds = T_chip_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS; - double T_prn_samples = T_prn_seconds * static_cast(d_fs_in); - int K_prn_samples = round(T_prn_samples); - double K_T_prn_error_samples = K_prn_samples - T_prn_samples; - - d_rem_code_phase_samples = d_rem_code_phase_samples - K_T_prn_error_samples; - d_rem_code_phase_integer_samples = round(d_rem_code_phase_samples); // round to a discrete number of samples - d_correlation_length_samples = K_prn_samples + d_rem_code_phase_integer_samples; - d_rem_code_phase_samples = d_rem_code_phase_samples - d_rem_code_phase_integer_samples; - // code phase step (Code resampler phase increment per sample) [chips/sample] - d_code_phase_step_chips = d_code_freq_chips / static_cast(d_fs_in); - // remnant code phase [chips] - d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast(d_fs_in)); - d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + d_carrier_phase_step_rad * static_cast(d_correlation_length_samples), GPS_TWO_PI); - - // UPDATE ACCUMULATED CARRIER PHASE - CORRECTED_INTEGRATION_TIME_S = (static_cast(d_correlation_length_samples) / static_cast(d_fs_in)); - d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * d_correlation_length_samples / GPS_TWO_PI; - - // disable tracking loop and inform telemetry decoder - enable_dll_pll = false; - } - else - { - // perform basic (1ms) correlation - // UPDATE INTEGRATION TIME - CURRENT_INTEGRATION_TIME_S = static_cast(d_correlation_length_samples) / static_cast(d_fs_in); - enable_dll_pll = true; - } - } - } - else - { - // UPDATE INTEGRATION TIME - CURRENT_INTEGRATION_TIME_S = static_cast(d_correlation_length_samples) / static_cast(d_fs_in); - enable_dll_pll = true; - } - - if (enable_dll_pll == true) - { - // ################## PLL ########################################################## - // Update PLL discriminator [rads/Ti -> Secs/Ti] - d_carr_phase_error_secs_Ti = pll_cloop_two_quadrant_atan(std::complex(d_correlator_outs_16sc[1].real(), d_correlator_outs_16sc[1].imag())) / GPS_TWO_PI; //prompt output - - // Carrier discriminator filter - // NOTICE: The carrier loop filter includes the Carrier Doppler accumulator, as described in Kaplan - // Input [s/Ti] -> output [Hz] - d_carrier_doppler_hz = d_carrier_loop_filter.get_carrier_error(0.0, d_carr_phase_error_secs_Ti, CURRENT_INTEGRATION_TIME_S); - // PLL to DLL assistance [Secs/Ti] - d_pll_to_dll_assist_secs_Ti = (d_carrier_doppler_hz * CURRENT_INTEGRATION_TIME_S) / GPS_L1_FREQ_HZ; - // code Doppler frequency update - d_code_freq_chips = GPS_L1_CA_CODE_RATE_HZ + ((d_carrier_doppler_hz * GPS_L1_CA_CODE_RATE_HZ) / GPS_L1_FREQ_HZ); - - // ################## DLL ########################################################## - // DLL discriminator - d_code_error_chips_Ti = dll_nc_e_minus_l_normalized( - std::complex( - d_correlator_outs_16sc[0].real(), - d_correlator_outs_16sc[0].imag()), - std::complex( - d_correlator_outs_16sc[2].real(), - d_correlator_outs_16sc[2].imag())); // [chips/Ti] //early and late - // Code discriminator filter - d_code_error_filt_chips_s = d_code_loop_filter.get_code_nco(d_code_error_chips_Ti); // input [chips/Ti] -> output [chips/second] - d_code_error_filt_chips_Ti = d_code_error_filt_chips_s * CURRENT_INTEGRATION_TIME_S; - code_error_filt_secs_Ti = d_code_error_filt_chips_Ti / d_code_freq_chips; // [s/Ti] - - // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### - // keep alignment parameters for the next input buffer - // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation - double T_chip_seconds = 1.0 / d_code_freq_chips; - double T_prn_seconds = T_chip_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS; - double T_prn_samples = T_prn_seconds * static_cast(d_fs_in); - double K_prn_samples = round(T_prn_samples); - double K_T_prn_error_samples = K_prn_samples - T_prn_samples; - - d_rem_code_phase_samples = d_rem_code_phase_samples - K_T_prn_error_samples + code_error_filt_secs_Ti * static_cast(d_fs_in); //(code_error_filt_secs_Ti + d_pll_to_dll_assist_secs_Ti) * static_cast(d_fs_in); - d_rem_code_phase_integer_samples = round(d_rem_code_phase_samples); // round to a discrete number of samples - d_correlation_length_samples = K_prn_samples+ d_rem_code_phase_integer_samples; - d_rem_code_phase_samples = d_rem_code_phase_samples - d_rem_code_phase_integer_samples; - - //################### PLL COMMANDS ################################################# - //carrier phase step (NCO phase increment per sample) [rads/sample] - d_carrier_phase_step_rad = GPS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); - d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * d_correlation_length_samples / GPS_TWO_PI; - // UPDATE ACCUMULATED CARRIER PHASE - CORRECTED_INTEGRATION_TIME_S = (static_cast(d_correlation_length_samples) / static_cast(d_fs_in)); - //remnant carrier phase [rad] - d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + GPS_TWO_PI * d_carrier_doppler_hz * CORRECTED_INTEGRATION_TIME_S, GPS_TWO_PI); - - //################### DLL COMMANDS ################################################# - //code phase step (Code resampler phase increment per sample) [chips/sample] - d_code_phase_step_chips = d_code_freq_chips / static_cast(d_fs_in); - //remnant code phase [chips] - d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast(d_fs_in)); - - // ####### CN0 ESTIMATION AND LOCK DETECTORS ####################################### - if (d_cn0_estimation_counter < FLAGS_cn0_samples) - { - // fill buffer with prompt correlator output values - d_Prompt_buffer[d_cn0_estimation_counter] = lv_cmake(static_cast(d_correlator_outs_16sc[1].real()), - static_cast(d_correlator_outs_16sc[1].imag())); // prompt - d_cn0_estimation_counter++; - } - else - { - d_cn0_estimation_counter = 0; - // Code lock indicator - d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, FLAGS_cn0_samples, d_fs_in, GPS_L1_CA_CODE_LENGTH_CHIPS); - // Carrier lock indicator - d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, FLAGS_cn0_samples); - // Loss of lock detection - if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < FLAGS_cn0_min) - { - d_carrier_lock_fail_counter++; - } - else - { - if (d_carrier_lock_fail_counter > 0) - { - d_carrier_lock_fail_counter--; - } - } - if (d_carrier_lock_fail_counter > FLAGS_max_lock_fail) - { - std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; - LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; - this->message_port_pub(pmt::mp("events"), pmt::from_long(3)); //3 -> loss of lock - d_carrier_lock_fail_counter = 0; - d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine - multicorrelator_fpga_8sc->unlock_channel(); - } - } - // ########### Output the tracking data to navigation and PVT ########## - current_synchro_data.Prompt_I = static_cast((d_correlator_outs_16sc[1]).real()); - current_synchro_data.Prompt_Q = static_cast((d_correlator_outs_16sc[1]).imag()); - current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples; - current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; - current_synchro_data.Carrier_phase_rads = GPS_TWO_PI * d_acc_carrier_phase_cycles; - current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; - current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; - current_synchro_data.Flag_valid_symbol_output = true; - if (d_preamble_synchronized == true) - { - current_synchro_data.correlation_length_ms = d_extend_correlation_ms; - } - else - { - current_synchro_data.correlation_length_ms = 1; - } - } - else - { - current_synchro_data.Prompt_I = static_cast((d_correlator_outs_16sc[1]).real()); - current_synchro_data.Prompt_Q = static_cast((d_correlator_outs_16sc[1]).imag()); - current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples; - current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; - current_synchro_data.Carrier_phase_rads = GPS_TWO_PI * d_acc_carrier_phase_cycles; - current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; // todo: project the carrier doppler - current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; - } - } - else - { - for (int n = 0; n < d_n_correlator_taps; n++) - { - d_correlator_outs_16sc[n] = lv_cmake(0, 0); - } - - current_synchro_data.System = {'G'}; - current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples; - } - - current_synchro_data.fs = d_fs_in; - *out[0] = current_synchro_data; - - if (d_dump) - { - // MULTIPLEXED FILE RECORDING - Record results to file - float prompt_I; - float prompt_Q; - float tmp_E, tmp_P, tmp_L; - double tmp_double; - prompt_I = d_correlator_outs_16sc[1].real(); - prompt_Q = d_correlator_outs_16sc[1].imag(); - tmp_E = std::abs(std::complex(d_correlator_outs_16sc[0].real(), d_correlator_outs_16sc[0].imag())); - tmp_P = std::abs(std::complex(d_correlator_outs_16sc[1].real(), d_correlator_outs_16sc[1].imag())); - tmp_L = std::abs(std::complex(d_correlator_outs_16sc[2].real(), d_correlator_outs_16sc[2].imag())); - try - { - // EPR - d_dump_file.write(reinterpret_cast(&tmp_E), sizeof(float)); - d_dump_file.write(reinterpret_cast(&tmp_P), sizeof(float)); - d_dump_file.write(reinterpret_cast(&tmp_L), sizeof(float)); - // PROMPT I and Q (to analyze navigation symbols) - d_dump_file.write(reinterpret_cast(&prompt_I), sizeof(float)); - d_dump_file.write(reinterpret_cast(&prompt_Q), sizeof(float)); - // PRN start sample stamp - //tmp_float=(float)d_sample_counter; - d_dump_file.write(reinterpret_cast(&d_sample_counter), sizeof(unsigned long int)); - // accumulated carrier phase - d_dump_file.write(reinterpret_cast(&d_acc_carrier_phase_cycles), sizeof(double)); - - // carrier and code frequency - d_dump_file.write(reinterpret_cast(&d_carrier_doppler_hz), sizeof(double)); - d_dump_file.write(reinterpret_cast(&d_code_freq_chips), sizeof(double)); - - //PLL commands - d_dump_file.write(reinterpret_cast(&d_carr_phase_error_secs_Ti), sizeof(double)); - d_dump_file.write(reinterpret_cast(&d_carrier_doppler_hz), sizeof(double)); - - //DLL commands - d_dump_file.write(reinterpret_cast(&d_code_error_chips_Ti), sizeof(double)); - d_dump_file.write(reinterpret_cast(&d_code_error_filt_chips_Ti), sizeof(double)); - - // CN0 and carrier lock test - d_dump_file.write(reinterpret_cast(&d_CN0_SNV_dB_Hz), sizeof(double)); - d_dump_file.write(reinterpret_cast(&d_carrier_lock_test), sizeof(double)); - - // AUX vars (for debug purposes) - tmp_double = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S; - d_dump_file.write(reinterpret_cast(&tmp_double), sizeof(double)); - tmp_double = static_cast(d_sample_counter + d_correlation_length_samples); - d_dump_file.write(reinterpret_cast(&tmp_double), sizeof(double)); - - // PRN - unsigned int prn_ = d_acquisition_gnss_synchro->PRN; - d_dump_file.write(reinterpret_cast(&prn_), sizeof(unsigned int)); - } - catch (const std::ifstream::failure* e) - { - LOG(WARNING) << "Exception writing trk dump file " << e->what(); - } - } - - //consume_each(d_correlation_length_samples); // this is necessary in gr::block derivates - d_sample_counter += d_correlation_length_samples; //count for the processed samples - - if (d_enable_tracking) - { - return 1; - }else{ - return 0; - } -} - - -void gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::set_channel(unsigned int channel) -{ - d_channel = channel; - multicorrelator_fpga_8sc->set_channel(d_channel); - LOG(INFO) << "Tracking Channel set to " << d_channel; - // ############# ENABLE DATA FILE LOG ################# - if (d_dump == true) - { - if (d_dump_file.is_open() == false) - { - try - { - d_dump_filename.append(boost::lexical_cast(d_channel)); - d_dump_filename.append(".dat"); - d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit); - d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary); - LOG(INFO) << "Tracking dump enabled on channel " - << d_channel << " Log file: " - << d_dump_filename.c_str(); - } - catch (const std::ifstream::failure* e) - { - LOG(WARNING) << "channel " << d_channel - << " Exception opening trk dump file " - << e->what(); - } - } - } -} - - -int gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::save_matfile() -{ - // READ DUMP FILE - std::ifstream::pos_type size; - int number_of_double_vars = 11; - int number_of_float_vars = 5; - int epoch_size_bytes = sizeof(unsigned long int) + sizeof(double) * number_of_double_vars + - sizeof(float) * number_of_float_vars + sizeof(unsigned int); - std::ifstream dump_file; - dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit); - try - { - dump_file.open(d_dump_filename.c_str(), std::ios::binary | std::ios::ate); - } - catch(const std::ifstream::failure &e) - { - std::cerr << "Problem opening dump file:" << e.what() << std::endl; - return 1; - } - // count number of epochs and rewind - long int num_epoch = 0; - if (dump_file.is_open()) - { - size = dump_file.tellg(); - num_epoch = static_cast(size) / static_cast(epoch_size_bytes); - dump_file.seekg(0, std::ios::beg); - } - else - { - return 1; - } - float * abs_E = new float [num_epoch]; - float * abs_P = new float [num_epoch]; - float * abs_L = new float [num_epoch]; - float * Prompt_I = new float [num_epoch]; - float * Prompt_Q = new float [num_epoch]; - unsigned long int * PRN_start_sample_count = new unsigned long int [num_epoch]; - double * acc_carrier_phase_rad = new double [num_epoch]; - double * carrier_doppler_hz = new double [num_epoch]; - double * code_freq_chips = new double [num_epoch]; - double * carr_error_hz = new double [num_epoch]; - double * carr_error_filt_hz = new double [num_epoch]; - double * code_error_chips = new double [num_epoch]; - double * code_error_filt_chips = new double [num_epoch]; - double * CN0_SNV_dB_Hz = new double [num_epoch]; - double * carrier_lock_test = new double [num_epoch]; - double * aux1 = new double [num_epoch]; - double * aux2 = new double [num_epoch]; - unsigned int * PRN = new unsigned int [num_epoch]; - - try - { - if (dump_file.is_open()) - { - for(long int i = 0; i < num_epoch; i++) - { - dump_file.read(reinterpret_cast(&abs_E[i]), sizeof(float)); - dump_file.read(reinterpret_cast(&abs_P[i]), sizeof(float)); - dump_file.read(reinterpret_cast(&abs_L[i]), sizeof(float)); - dump_file.read(reinterpret_cast(&Prompt_I[i]), sizeof(float)); - dump_file.read(reinterpret_cast(&Prompt_Q[i]), sizeof(float)); - dump_file.read(reinterpret_cast(&PRN_start_sample_count[i]), sizeof(unsigned long int)); - dump_file.read(reinterpret_cast(&acc_carrier_phase_rad[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&carrier_doppler_hz[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&code_freq_chips[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&carr_error_hz[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&carr_error_filt_hz[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&code_error_chips[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&code_error_filt_chips[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&CN0_SNV_dB_Hz[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&carrier_lock_test[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&aux1[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&aux2[i]), sizeof(double)); - dump_file.read(reinterpret_cast(&PRN[i]), sizeof(unsigned int)); - } - } - dump_file.close(); - } - catch (const std::ifstream::failure &e) - { - std::cerr << "Problem reading dump file:" << e.what() << std::endl; - delete[] abs_E; - delete[] abs_P; - delete[] abs_L; - delete[] Prompt_I; - delete[] Prompt_Q; - delete[] PRN_start_sample_count; - delete[] acc_carrier_phase_rad; - delete[] carrier_doppler_hz; - delete[] code_freq_chips; - delete[] carr_error_hz; - delete[] carr_error_filt_hz; - delete[] code_error_chips; - delete[] code_error_filt_chips; - delete[] CN0_SNV_dB_Hz; - delete[] carrier_lock_test; - delete[] aux1; - delete[] aux2; - delete[] PRN; - return 1; - } - - // WRITE MAT FILE - mat_t *matfp; - matvar_t *matvar; - std::string filename = d_dump_filename; - filename.erase(filename.length() - 4, 4); - filename.append(".mat"); - matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT73); - if(reinterpret_cast(matfp) != NULL) - { - size_t dims[2] = {1, static_cast(num_epoch)}; - matvar = Mat_VarCreate("abs_E", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_E, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("abs_P", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_P, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("abs_L", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_L, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("Prompt_I", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, Prompt_I, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("Prompt_Q", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, Prompt_Q, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("PRN_start_sample_count", MAT_C_UINT64, MAT_T_UINT64, 2, dims, PRN_start_sample_count, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("acc_carrier_phase_rad", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, acc_carrier_phase_rad, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("carrier_doppler_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carrier_doppler_hz, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("code_freq_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_freq_chips, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("carr_error_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carr_error_hz, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("carr_error_filt_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carr_error_filt_hz, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("code_error_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_error_chips, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("code_error_filt_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_error_filt_chips, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("CN0_SNV_dB_Hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, CN0_SNV_dB_Hz, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("carrier_lock_test", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carrier_lock_test, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("aux1", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, aux1, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("aux2", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, aux2, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("PRN", MAT_C_UINT32, MAT_T_UINT32, 2, dims, PRN, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - } - Mat_Close(matfp); - delete[] abs_E; - delete[] abs_P; - delete[] abs_L; - delete[] Prompt_I; - delete[] Prompt_Q; - delete[] PRN_start_sample_count; - delete[] acc_carrier_phase_rad; - delete[] carrier_doppler_hz; - delete[] code_freq_chips; - delete[] carr_error_hz; - delete[] carr_error_filt_hz; - delete[] code_error_chips; - delete[] code_error_filt_chips; - delete[] CN0_SNV_dB_Hz; - delete[] carrier_lock_test; - delete[] aux1; - delete[] aux2; - delete[] PRN; - return 0; -} - -void gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::set_gnss_synchro( - Gnss_Synchro* p_gnss_synchro) -{ - d_acquisition_gnss_synchro = p_gnss_synchro; -} - - -void gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::reset(void) -{ - multicorrelator_fpga_8sc->unlock_channel(); -} diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.h b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.h deleted file mode 100644 index d1a3db6d5..000000000 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.h +++ /dev/null @@ -1,185 +0,0 @@ -/*! - * \file gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.h - * \brief Interface of a code DLL + carrier PLL tracking block - * \author Marc Majoral, 2017. mmajoral(at)cttc.cat - * Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com - * Javier Arribas, 2011. jarribas(at)cttc.es - * - * Code DLL + carrier PLL according to the algorithms described in: - * 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 - * - * ------------------------------------------------------------------------- - * - * 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_L1_CA_DLL_PLL_C_AID_TRACKING_FPGA_SC_H -#define GNSS_SDR_GPS_L1_CA_DLL_PLL_C_AID_TRACKING_FPGA_SC_H - -#include "gps_sdr_signal_processing.h" -#include "gnss_synchro.h" -#include "tracking_2nd_DLL_filter.h" -#include "tracking_FLL_PLL_filter.h" -#include "fpga_multicorrelator_8sc.h" -#include -#include -#include -#include -#include -#include -#include - -class gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc; - -typedef boost::shared_ptr gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc_sptr; - -gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc_sptr -gps_l1_ca_dll_pll_c_aid_make_tracking_fpga_sc(long if_freq, long fs_in, unsigned -int vector_length, bool dump, std::string dump_filename, float pll_bw_hz, - float dll_bw_hz, float pll_bw_narrow_hz, float dll_bw_narrow_hz, - int extend_correlation_ms, float early_late_space_chips, - std::string device_name, unsigned int device_base); - -/*! - * \brief This class implements a DLL + PLL tracking loop block - */ -class gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc : public gr::block -{ -public: - ~gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc(); - - void set_channel(unsigned int channel); - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); - void start_tracking(); - - int general_work(int noutput_items, gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - void reset(void); - -private: - friend gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc_sptr - gps_l1_ca_dll_pll_c_aid_make_tracking_fpga_sc(long if_freq, long fs_in, - unsigned - int vector_length, bool dump, std::string dump_filename, - float pll_bw_hz, float dll_bw_hz, float pll_bw_narrow_hz, - float dll_bw_narrow_hz, int extend_correlation_ms, - float early_late_space_chips, std::string device_name, - unsigned int device_base); - - gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc(long if_freq, long fs_in, unsigned - int vector_length, bool dump, std::string dump_filename, float pll_bw_hz, - float dll_bw_hz, float pll_bw_narrow_hz, float dll_bw_narrow_hz, - int extend_correlation_ms, float early_late_space_chips, - std::string device_name, unsigned int device_base); - - // tracking configuration vars - unsigned int d_vector_length;bool d_dump; - - Gnss_Synchro* d_acquisition_gnss_synchro; - unsigned int d_channel; - - long d_if_freq; - long d_fs_in; - - double d_early_late_spc_chips; - int d_n_correlator_taps; - - gr_complex* d_ca_code; - lv_16sc_t* d_ca_code_16sc; - float* d_local_code_shift_chips; - lv_16sc_t* d_correlator_outs_16sc; - //fpga_multicorrelator_8sc multicorrelator_fpga_8sc; - std::shared_ptr multicorrelator_fpga_8sc; - - // remaining code phase and carrier phase between tracking loops - double d_rem_code_phase_samples; - double d_rem_code_phase_chips; - double d_rem_carrier_phase_rad; - int d_rem_code_phase_integer_samples; - - // PLL and DLL filter library - Tracking_2nd_DLL_filter d_code_loop_filter; - Tracking_FLL_PLL_filter d_carrier_loop_filter; - - // acquisition - double d_acq_code_phase_samples; - double d_acq_carrier_doppler_hz; - - // tracking vars - float d_dll_bw_hz; - float d_pll_bw_hz; - float d_dll_bw_narrow_hz; - float d_pll_bw_narrow_hz; - double d_code_freq_chips; - double d_code_phase_step_chips; - double d_carrier_doppler_hz; - double d_carrier_phase_step_rad; - double d_acc_carrier_phase_cycles; - double d_code_phase_samples; - double d_pll_to_dll_assist_secs_Ti; - double d_carr_phase_error_secs_Ti; - double d_code_error_chips_Ti; - double d_preamble_timestamp_s; - int d_extend_correlation_ms;bool d_enable_extended_integration;bool d_preamble_synchronized; - double d_code_error_filt_chips_s; - double d_code_error_filt_chips_Ti; - void msg_handler_preamble_index(pmt::pmt_t msg); - - // symbol history to detect bit transition - std::deque d_E_history; - std::deque d_P_history; - std::deque d_L_history; - - //Integration period in samples - int d_correlation_length_samples; - - //processing samples counters - unsigned long int d_sample_counter; - unsigned long int d_acq_sample_stamp; - - // CN0 estimation and lock detector - int d_cn0_estimation_counter; - gr_complex* d_Prompt_buffer; - double d_carrier_lock_test; - double d_CN0_SNV_dB_Hz; - double d_carrier_lock_threshold; - int d_carrier_lock_fail_counter; - - // control vars - bool d_enable_tracking;bool d_pull_in; - - // file dump - std::string d_dump_filename; - std::ofstream d_dump_file; - - std::map systemName; - std::string sys; - - int save_matfile(); -}; - -#endif //GNSS_SDR_GPS_L1_CA_DLL_PLL_C_AID_TRACKING_FPGA_SC_H diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc new file mode 100644 index 000000000..a6ebb9bec --- /dev/null +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc @@ -0,0 +1,586 @@ +/*! + * \file gps_l1_ca_dll_pll_tracking_cc.cc + * \brief Implementation of a code DLL + carrier PLL tracking block + * \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com + * Javier Arribas, 2011. jarribas(at)cttc.es + * + * Code DLL + carrier PLL according to the algorithms described in: + * [1] 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 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (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_l1_ca_dll_pll_tracking_fpga_sc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "gps_sdr_signal_processing.h" +#include "tracking_discriminators.h" +#include "lock_detectors.h" +#include "GPS_L1_CA.h" +#include "control_message_factory.h" + + +/*! + * \todo Include in definition header file + */ +#define CN0_ESTIMATION_SAMPLES 20 +#define MINIMUM_VALID_CN0 25 +#define MAXIMUM_LOCK_FAIL_COUNTER 50 +#define CARRIER_LOCK_THRESHOLD 0.85 + + +using google::LogMessage; + +gps_l1_ca_dll_pll_tracking_fpga_sc_sptr +gps_l1_ca_dll_pll_make_tracking_fpga_sc( + long if_freq, + long fs_in, + unsigned int vector_length, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + std::string device_name, + unsigned int device_base) +{ + return gps_l1_ca_dll_pll_tracking_fpga_sc_sptr(new Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc(if_freq, + fs_in, vector_length, dump, dump_filename, pll_bw_hz, dll_bw_hz, early_late_space_chips, device_name, device_base)); +} + +Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc( + long if_freq, + long fs_in, + unsigned int vector_length, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + std::string device_name, + unsigned int device_base) : + gr::block("Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc", gr::io_signature::make(0, 0, sizeof(lv_16sc_t)), + gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) +{ + // Telemetry bit synchronization message port input + this->message_port_register_in(pmt::mp("preamble_timestamp_s")); + this->message_port_register_out(pmt::mp("events")); + + // initialize internal vars + d_dump = dump; + d_if_freq = if_freq; + d_fs_in = fs_in; + d_vector_length = vector_length; + d_dump_filename = dump_filename; + d_current_prn_length_samples = static_cast(d_vector_length); + d_correlation_length_samples = static_cast(d_vector_length); + + // Initialize tracking ========================================== + d_code_loop_filter.set_DLL_BW(dll_bw_hz); + d_carrier_loop_filter.set_PLL_BW(pll_bw_hz); + + //--- DLL variables -------------------------------------------------------- + d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips) + + // Initialization of local code replica + // Get space for a vector with the C/A code replica sampled 1x/chip + //d_ca_code = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS) * sizeof(float), volk_gnsssdr_get_alignment())); + //d_ca_code_16sc = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS) * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment())); + //d_ca_code_16sc = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS) * sizeof(int), volk_gnsssdr_get_alignment())); + + // correlator outputs (scalar) + d_n_correlator_taps = 3; // Early, Prompt, and Late + d_correlator_outs = static_cast(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + for (int n = 0; n < d_n_correlator_taps; n++) + { + d_correlator_outs[n] = gr_complex(0,0); + } + d_local_code_shift_chips = static_cast(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(float), volk_gnsssdr_get_alignment())); + + // Set TAPs delay values [chips] + d_local_code_shift_chips[0] = - d_early_late_spc_chips; + d_local_code_shift_chips[1] = 0.0; + d_local_code_shift_chips[2] = d_early_late_spc_chips; + + // create multicorrelator class + multicorrelator_fpga_8sc = std::make_shared (d_n_correlator_taps, device_name, device_base); + + //--- Perform initializations ------------------------------ + // define initial code frequency basis of NCO + d_code_freq_chips = GPS_L1_CA_CODE_RATE_HZ; + // define residual code phase (in chips) + d_rem_code_phase_samples = 0.0; + // define residual carrier phase + d_rem_carr_phase_rad = 0.0; + + // sample synchronization + d_sample_counter = 0; + d_acq_sample_stamp = 0; + + d_enable_tracking = false; + d_pull_in = false; + + // CN0 estimation and lock detector buffers + d_cn0_estimation_counter = 0; + d_Prompt_buffer = new gr_complex[CN0_ESTIMATION_SAMPLES]; + d_carrier_lock_test = 1; + d_CN0_SNV_dB_Hz = 0; + d_carrier_lock_fail_counter = 0; + d_carrier_lock_threshold = CARRIER_LOCK_THRESHOLD; + + systemName["G"] = std::string("GPS"); + systemName["S"] = std::string("SBAS"); + + d_acquisition_gnss_synchro = 0; + d_channel = 0; + d_acq_code_phase_samples = 0.0; + d_acq_carrier_doppler_hz = 0.0; + d_carrier_doppler_hz = 0.0; + d_acc_carrier_phase_rad = 0.0; + d_code_phase_samples = 0.0; + d_rem_code_phase_chips = 0.0; + d_code_phase_step_chips = 0.0; + d_carrier_phase_step_rad = 0.0; + + set_relative_rate(1.0 / static_cast(d_vector_length)); + + d_first_time = 1; + + + +} + +void Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::start_tracking() +{ + /* + * correct the code phase according to the delay between acq and trk + */ + + //printf("TRK : start tracking for satellite %d\n", d_acquisition_gnss_synchro->PRN); + d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples; + d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz; + d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples; + long int acq_trk_diff_samples; + double acq_trk_diff_seconds; + acq_trk_diff_samples = static_cast(d_sample_counter) - static_cast(d_acq_sample_stamp); //-d_vector_length; + DLOG(INFO) << "Number of samples between Acquisition and Tracking = " << acq_trk_diff_samples; + acq_trk_diff_seconds = static_cast(acq_trk_diff_samples) / static_cast(d_fs_in); + // Doppler effect + // Fd=(C/(C+Vr))*F + double radial_velocity = (GPS_L1_FREQ_HZ + d_acq_carrier_doppler_hz) / GPS_L1_FREQ_HZ; + // new chip and prn sequence periods based on acq Doppler + double T_chip_mod_seconds; + double T_prn_mod_seconds; + double T_prn_mod_samples; + d_code_freq_chips = radial_velocity * GPS_L1_CA_CODE_RATE_HZ; + d_code_phase_step_chips = static_cast(d_code_freq_chips) / static_cast(d_fs_in); + T_chip_mod_seconds = 1/d_code_freq_chips; + T_prn_mod_seconds = T_chip_mod_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS; + T_prn_mod_samples = T_prn_mod_seconds * static_cast(d_fs_in); + d_current_prn_length_samples = round(T_prn_mod_samples); + double T_prn_true_seconds = GPS_L1_CA_CODE_LENGTH_CHIPS / GPS_L1_CA_CODE_RATE_HZ; + double T_prn_true_samples = T_prn_true_seconds * static_cast(d_fs_in); + double T_prn_diff_seconds = T_prn_true_seconds - T_prn_mod_seconds; + double N_prn_diff = acq_trk_diff_seconds / T_prn_true_seconds; + double corrected_acq_phase_samples, delay_correction_samples; + corrected_acq_phase_samples = fmod((d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * static_cast(d_fs_in)), T_prn_true_samples); + if (corrected_acq_phase_samples < 0) + { + corrected_acq_phase_samples = T_prn_mod_samples + corrected_acq_phase_samples; + } + delay_correction_samples = d_acq_code_phase_samples - corrected_acq_phase_samples; + d_acq_code_phase_samples = corrected_acq_phase_samples; + d_carrier_doppler_hz = d_acq_carrier_doppler_hz; + d_carrier_phase_step_rad = GPS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); + // DLL/PLL filter initialization + d_carrier_loop_filter.initialize(); // initialize the carrier filter + d_code_loop_filter.initialize(); // initialize the code filter + // generate local reference ALWAYS starting at chip 1 (1 sample per chip) + //gps_l1_ca_code_gen_float(d_ca_code, d_acquisition_gnss_synchro->PRN, 0); + //gps_l1_ca_code_gen_int(d_ca_code_16sc, d_acquisition_gnss_synchro->PRN, 0); +/* for (int n = 0; n < static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS); n++) + { + d_ca_code_16sc[n] = d_ca_code[n]; + } */ + //multicorrelator_fpga_8sc->set_local_code_and_taps(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS), d_ca_code_16sc, d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN); + multicorrelator_fpga_8sc->set_local_code_and_taps(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS), d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN); + for (int n = 0; n < d_n_correlator_taps; n++) + { + d_correlator_outs[n] = gr_complex(0,0); + } + d_carrier_lock_fail_counter = 0; + d_rem_code_phase_samples = 0; + d_rem_carr_phase_rad = 0.0; + d_rem_code_phase_chips = 0.0; + d_acc_carrier_phase_rad = 0.0; + d_code_phase_samples = d_acq_code_phase_samples; + std::string sys_ = &d_acquisition_gnss_synchro->System; + sys = sys_.substr(0,1); + //std::cout << "Tracking of GPS L1 C/A signal started on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; + LOG(INFO) << "Starting tracking of satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " on channel " << d_channel; + // enable tracking + d_pull_in = true; + multicorrelator_fpga_8sc->lock_channel(); + d_enable_tracking = true; //do it in the end to avoid starting running tracking before finishing this function + LOG(INFO) << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz + << " Code Phase correction [samples]=" << delay_correction_samples + << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples; + d_first_time = 1; +} + +Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::~Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc() +{ + if (d_dump_file.is_open()) + { + try + { + d_dump_file.close(); + } + catch(const std::exception & ex) + { + LOG(WARNING) << "Exception in destructor " << ex.what(); + } + } + try + { + volk_gnsssdr_free(d_local_code_shift_chips); + volk_gnsssdr_free(d_correlator_outs); + //volk_gnsssdr_free(d_ca_code); + delete[] d_Prompt_buffer; + //multicorrelator_cpu.free(); + //volk_gnsssdr_free(d_ca_code_16sc); + multicorrelator_fpga_8sc->free(); + } + catch(const std::exception & ex) + { + LOG(WARNING) << "Exception in destructor " << ex.what(); + } +} + +int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)), + gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) +{ + + // debug + int secondary_sample_counter; + int counter_corr_0_in; + int counter_corr_0_out; + int sample_counter; + + // samples offset +// int samples_offset; + unsigned absolute_samples_offset; +// int kk2; + // process vars + double carr_error_hz = 0.0; + double carr_error_filt_hz = 0.0; + double code_error_chips = 0.0; + double code_error_filt_chips = 0.0; + + int next_prn_length_samples = d_current_prn_length_samples; +// int offset_prn_samples = 0; + + // Block input data and block output stream pointers + Gnss_Synchro **out = reinterpret_cast(&output_items[0]); + + // GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder + Gnss_Synchro current_synchro_data = Gnss_Synchro(); + + if (d_enable_tracking == true) + { + // Fill the acquisition data + current_synchro_data = *d_acquisition_gnss_synchro; + // Receiver signal alignment + if (d_pull_in == true) + { + d_pull_in = false; + unsigned counter_value = multicorrelator_fpga_8sc->read_sample_counter(); + unsigned num_frames = ceil((counter_value - current_synchro_data.Acq_samplestamp_samples - current_synchro_data.Acq_delay_samples)/d_correlation_length_samples); + absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; + multicorrelator_fpga_8sc->set_initial_sample(absolute_samples_offset); + d_sample_counter = absolute_samples_offset; + current_synchro_data.Tracking_sample_counter = absolute_samples_offset; + } + else + { + // continue as from the previous point + d_sample_counter = d_sample_counter_next; + } + d_sample_counter_next = d_sample_counter + d_current_prn_length_samples; + + // ################# CARRIER WIPEOFF AND CORRELATORS ############################## + // perform carrier wipe-off and compute Early, Prompt and Late correlation + multicorrelator_fpga_8sc->set_output_vectors(d_correlator_outs); + multicorrelator_fpga_8sc->Carrier_wipeoff_multicorrelator_resampler( + d_rem_carr_phase_rad, d_carrier_phase_step_rad, + d_rem_code_phase_chips, d_code_phase_step_chips, + d_current_prn_length_samples); + d_previous_sample_counter = d_debug_sample_counter; + d_previous_counter_corr_0_in = d_counter_corr_0_in; + d_previous_counter_corr_0_out = d_counter_corr_0_out; + multicorrelator_fpga_8sc->read_sample_counters(&sample_counter, &secondary_sample_counter, &counter_corr_0_in, &counter_corr_0_out); + d_debug_sample_counter = sample_counter; + d_counter_corr_0_in = counter_corr_0_in; + d_counter_corr_0_out = counter_corr_0_out; + d_counter_corr_0_in_inc = counter_corr_0_in - d_previous_counter_corr_0_in; + d_counter_corr_0_out_inc = counter_corr_0_out - d_previous_counter_corr_0_out; + d_sample_counter_inc = d_debug_sample_counter - d_previous_sample_counter; + + // ################## PLL ########################################################## + // PLL discriminator + // Update PLL discriminator [rads/Ti -> Secs/Ti] + carr_error_hz = pll_cloop_two_quadrant_atan(d_correlator_outs[1]) / GPS_TWO_PI; // prompt output + // Carrier discriminator filter + carr_error_filt_hz = d_carrier_loop_filter.get_carrier_nco(carr_error_hz); + // New carrier Doppler frequency estimation + d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_error_filt_hz; + // New code Doppler frequency estimation + d_code_freq_chips = GPS_L1_CA_CODE_RATE_HZ + ((d_carrier_doppler_hz * GPS_L1_CA_CODE_RATE_HZ) / GPS_L1_FREQ_HZ); + + // ################## DLL ########################################################## + // DLL discriminator + code_error_chips = dll_nc_e_minus_l_normalized(d_correlator_outs[0], d_correlator_outs[2]); // [chips/Ti] //early and late + // Code discriminator filter + code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips); // [chips/second] + double T_chip_seconds = 1.0 / static_cast(d_code_freq_chips); + double T_prn_seconds = T_chip_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS; + double code_error_filt_secs = (T_prn_seconds * code_error_filt_chips*T_chip_seconds); //[seconds] + + // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### + // keep alignment parameters for the next input buffer + // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation + double T_prn_samples = T_prn_seconds * static_cast(d_fs_in); + double K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * static_cast(d_fs_in); + next_prn_length_samples = round(K_blk_samples); +// offset_prn_samples = next_prn_length_samples - d_current_prn_length_samples; + + //################### PLL COMMANDS ################################################# + // carrier phase step (NCO phase increment per sample) [rads/sample] + d_carrier_phase_step_rad = GPS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); + // remnant carrier phase to prevent overflow in the code NCO + d_rem_carr_phase_rad = d_rem_carr_phase_rad + d_carrier_phase_step_rad * d_current_prn_length_samples; + d_rem_carr_phase_rad = fmod(d_rem_carr_phase_rad, GPS_TWO_PI); + // carrier phase accumulator + d_acc_carrier_phase_rad -= d_carrier_phase_step_rad * d_current_prn_length_samples; + + //################### DLL COMMANDS ################################################# + // code phase step (Code resampler phase increment per sample) [chips/sample] + d_code_phase_step_chips = d_code_freq_chips / static_cast(d_fs_in); + // remnant code phase [chips] + d_rem_code_phase_samples = K_blk_samples - next_prn_length_samples; // rounding error < 1 sample + d_rem_code_phase_chips = d_code_freq_chips * (d_rem_code_phase_samples / static_cast(d_fs_in)); + + // ####### CN0 ESTIMATION AND LOCK DETECTORS ###### + if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES) + { + // fill buffer with prompt correlator output values + d_Prompt_buffer[d_cn0_estimation_counter] = d_correlator_outs[1]; //prompt + d_cn0_estimation_counter++; + } + else + { + d_cn0_estimation_counter = 0; + // Code lock indicator + d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, GPS_L1_CA_CODE_LENGTH_CHIPS); + // Carrier lock indicator + d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); + // Loss of lock detection + if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) + { + d_carrier_lock_fail_counter++; + } + else + { + if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; + } + if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) + { + std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; + d_debug_loss_of_track = 1; + LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; + this->message_port_pub(pmt::mp("events"), pmt::from_long(3)); // 3 -> loss of lock + d_carrier_lock_fail_counter = 0; + d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine + multicorrelator_fpga_8sc->unlock_channel(); + + + } + } + + // ########### Output the tracking data to navigation and PVT ########## + current_synchro_data.Prompt_I = static_cast((d_correlator_outs[1]).real()); + current_synchro_data.Prompt_Q = static_cast((d_correlator_outs[1]).imag()); + current_synchro_data.Tracking_sample_counter = d_sample_counter + d_current_prn_length_samples; + current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; + current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; + current_synchro_data.Flag_valid_symbol_output = true; + current_synchro_data.correlation_length_ms = 1; + } + else + { + for (int n = 0; n < d_n_correlator_taps; n++) + { + d_correlator_outs[n] = gr_complex(0,0); + } + + current_synchro_data.Tracking_sample_counter =d_sample_counter + d_current_prn_length_samples; + current_synchro_data.System = {'G'}; + current_synchro_data.correlation_length_ms = 1; + } + + //assign the GNURadio block output data + current_synchro_data.fs = d_fs_in; + *out[0] = current_synchro_data; + if (d_enable_tracking == true) // in the FPGA case dump data only when tracking is enabled, otherwise the dumped data is useless + { + if(d_dump) + { + // MULTIPLEXED FILE RECORDING - Record results to file + float prompt_I; + float prompt_Q; + float tmp_E, tmp_P, tmp_L; + double tmp_double; + unsigned long int tmp_long; + prompt_I = d_correlator_outs[1].real(); + prompt_Q = d_correlator_outs[1].imag(); + tmp_E = std::abs(d_correlator_outs[0]); + tmp_P = std::abs(d_correlator_outs[1]); + tmp_L = std::abs(d_correlator_outs[2]); + try + { + // EPR + d_dump_file.write(reinterpret_cast(&tmp_E), sizeof(float)); + d_dump_file.write(reinterpret_cast(&tmp_P), sizeof(float)); + d_dump_file.write(reinterpret_cast(&tmp_L), sizeof(float)); + // PROMPT I and Q (to analyze navigation symbols) + d_dump_file.write(reinterpret_cast(&prompt_I), sizeof(float)); + d_dump_file.write(reinterpret_cast(&prompt_Q), sizeof(float)); + // PRN start sample stamp + tmp_long = d_sample_counter + d_current_prn_length_samples; + d_dump_file.write(reinterpret_cast(&tmp_long), sizeof(unsigned long int)); + // accumulated carrier phase + d_dump_file.write(reinterpret_cast(&d_acc_carrier_phase_rad), sizeof(double)); + + // carrier and code frequency + d_dump_file.write(reinterpret_cast(&d_carrier_doppler_hz), sizeof(double)); + d_dump_file.write(reinterpret_cast(&d_code_freq_chips), sizeof(double)); + + // PLL commands + d_dump_file.write(reinterpret_cast(&carr_error_hz), sizeof(double)); + d_dump_file.write(reinterpret_cast(&carr_error_filt_hz), sizeof(double)); + + // DLL commands + d_dump_file.write(reinterpret_cast(&code_error_chips), sizeof(double)); + d_dump_file.write(reinterpret_cast(&code_error_filt_chips), sizeof(double)); + + // CN0 and carrier lock test + d_dump_file.write(reinterpret_cast(&d_CN0_SNV_dB_Hz), sizeof(double)); + d_dump_file.write(reinterpret_cast(&d_carrier_lock_test), sizeof(double)); + + // AUX vars (for debug purposes) + tmp_double = d_rem_code_phase_samples; + d_dump_file.write(reinterpret_cast(&tmp_double), sizeof(double)); + tmp_double = static_cast(d_sample_counter); + d_dump_file.write(reinterpret_cast(&tmp_double), sizeof(double)); + + // PRN + unsigned int prn_ = d_acquisition_gnss_synchro->PRN; + d_dump_file.write(reinterpret_cast(&prn_), sizeof(unsigned int)); + + } + catch (const std::ifstream::failure &e) + { + LOG(WARNING) << "Exception writing trk dump file " << e.what(); + } + + + } + } + + + d_current_prn_length_samples = next_prn_length_samples; + d_sample_counter += d_current_prn_length_samples; // count for the processed samples + + if (d_enable_tracking == true) + { + return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + //return 0; // debug + } + else + { + return 0; + } + +} + + + +void Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::set_channel(unsigned int channel) +{ + d_channel = channel; + multicorrelator_fpga_8sc->set_channel(d_channel); + LOG(INFO) << "Tracking Channel set to " << d_channel; + + // ############# ENABLE DATA FILE LOG ################# + if (d_dump == true) + { + if (d_dump_file.is_open() == false) + { + try + { + d_dump_filename.append(boost::lexical_cast(d_channel)); + d_dump_filename.append(".dat"); + d_dump_file.exceptions (std::ifstream::failbit | std::ifstream::badbit); + d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary); + LOG(INFO) << "Tracking dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str(); + } + catch (const std::ifstream::failure &e) + { + LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what(); + } + } + } +} + + +void Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + d_acquisition_gnss_synchro = p_gnss_synchro; +} + +void Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::reset(void) +{ + multicorrelator_fpga_8sc->unlock_channel(); +} diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h new file mode 100644 index 000000000..c497c08f2 --- /dev/null +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h @@ -0,0 +1,200 @@ +/*! + * \file gps_l1_ca_dll_pll_tracking_cc.h + * \brief Interface of a code DLL + carrier PLL tracking block + * \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com + * Javier Arribas, 2011. jarribas(at)cttc.es + * Cillian O'Driscoll, 2017. cillian.odriscoll(at)gmail.com + * + * Code DLL + carrier PLL according to the algorithms described in: + * 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 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (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_L1_CA_DLL_PLL_TRACKING_FPGA_SC_H +#define GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_SC_H + +#include +#include +#include +#include +#include "gnss_synchro.h" +#include "tracking_2nd_DLL_filter.h" +#include "tracking_2nd_PLL_filter.h" +#include "fpga_multicorrelator_8sc.h" + +class Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc; + +typedef boost::shared_ptr + gps_l1_ca_dll_pll_tracking_fpga_sc_sptr; + +gps_l1_ca_dll_pll_tracking_fpga_sc_sptr +gps_l1_ca_dll_pll_make_tracking_fpga_sc(long if_freq, + long fs_in, unsigned + int vector_length, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + std::string device_name, + unsigned int device_base); + + + +/*! + * \brief This class implements a DLL + PLL tracking loop block + */ +class Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc: public gr::block +{ +public: + ~Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc(); + + void set_channel(unsigned int channel); + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); + void start_tracking(); + + int general_work (int noutput_items, gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + void reset(void); + +private: + friend gps_l1_ca_dll_pll_tracking_fpga_sc_sptr + gps_l1_ca_dll_pll_make_tracking_fpga_sc(long if_freq, + long fs_in, unsigned + int vector_length, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + std::string device_name, + unsigned int device_base); + + Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc(long if_freq, + long fs_in, unsigned + int vector_length, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + std::string device_name, + unsigned int device_base); + + // tracking configuration vars + unsigned int d_vector_length; + bool d_dump; + + Gnss_Synchro* d_acquisition_gnss_synchro; + unsigned int d_channel; + + long d_if_freq; + long d_fs_in; + + double d_early_late_spc_chips; + + // remaining code phase and carrier phase between tracking loops + double d_rem_code_phase_samples; + double d_rem_code_phase_chips; + double d_rem_carr_phase_rad; + + // PLL and DLL filter library + Tracking_2nd_DLL_filter d_code_loop_filter; + Tracking_2nd_PLL_filter d_carrier_loop_filter; + + // acquisition + double d_acq_code_phase_samples; + double d_acq_carrier_doppler_hz; + // correlator + int d_n_correlator_taps; + //float* d_ca_code; + //int* d_ca_code_16sc; + + float* d_local_code_shift_chips; + gr_complex* d_correlator_outs; + std::shared_ptr multicorrelator_fpga_8sc; + + // tracking vars + double d_code_freq_chips; + double d_code_phase_step_chips; + double d_carrier_doppler_hz; + double d_carrier_phase_step_rad; + double d_acc_carrier_phase_rad; + double d_code_phase_samples; + + //PRN period in samples + int d_current_prn_length_samples; + + //processing samples counters + unsigned long int d_sample_counter; + unsigned long int d_acq_sample_stamp; + + // CN0 estimation and lock detector + int d_cn0_estimation_counter; + gr_complex* d_Prompt_buffer; + double d_carrier_lock_test; + double d_CN0_SNV_dB_Hz; + double d_carrier_lock_threshold; + int d_carrier_lock_fail_counter; + + // control vars + bool d_enable_tracking; + bool d_pull_in; + + // file dump + std::string d_dump_filename; + std::ofstream d_dump_file; + + std::map systemName; + std::string sys; + + // extra + int d_correlation_length_samples; + unsigned long int d_sample_counter_next; + double d_rem_carrier_phase_rad; + + double d_K_blk_samples_previous; + int d_offset_sample_previous; + int d_first_time; + + int d_kk = 0; + int d_numsamples_debug = 990; + int d_previous_sample_counter = 0; + int d_debug_sample_counter = 0; + int d_previous_counter_corr_0_in = 0; + int d_previous_counter_corr_0_out = 0; + int d_counter_corr_0_in_inc = 0; + int d_counter_corr_0_out_inc = 0; + int d_counter_corr_0_in = 0; + int d_counter_corr_0_out = 0; + int d_sample_counter_inc = 0; + int d_debug_loss_of_track = 0; +}; + +#endif //GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_SC_H diff --git a/src/algorithms/tracking/libs/CMakeLists.txt b/src/algorithms/tracking/libs/CMakeLists.txt index 5c5ce7a2a..1cc68dabb 100644 --- a/src/algorithms/tracking/libs/CMakeLists.txt +++ b/src/algorithms/tracking/libs/CMakeLists.txt @@ -47,6 +47,7 @@ set(TRACKING_LIB_SOURCES if(ENABLE_FPGA) SET(TRACKING_LIB_SOURCES ${TRACKING_LIB_SOURCES} fpga_multicorrelator_8sc.cc) + SET(TRACKING_LIB_SOURCES ${TRACKING_LIB_SOURCES} fpga_multicorrelator_real_codes_8sc.cc) endif(ENABLE_FPGA) include_directories( @@ -54,6 +55,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/core/system_parameters ${CMAKE_SOURCE_DIR}/src/core/interfaces ${CMAKE_SOURCE_DIR}/src/core/receiver + ${CMAKE_SOURCE_DIR}/src/algorithms/libs ${VOLK_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS} diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc index cec90a8f3..dd6f208ce 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc @@ -35,6 +35,7 @@ */ #include "fpga_multicorrelator_8sc.h" + #include // FPGA stuff @@ -63,6 +64,12 @@ // string manipulation #include +// constants +#include "GPS_L1_CA.h" + +#include "gps_sdr_signal_processing.h" + +#define NUM_PRNs 32 #define PAGE_SIZE 0x10000 #define MAX_LENGTH_DEVICEIO_NAME 50 #define CODE_RESAMPLER_NUM_BITS_PRECISION 20 @@ -77,38 +84,39 @@ #define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000 #define TEST_REGISTER_TRACK_WRITEVAL 0x55AA +int fpga_multicorrelator_8sc::read_sample_counter() +{ + return d_map_base[7]; +} + void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset) { d_initial_sample_counter = samples_offset; + d_map_base[13] = d_initial_sample_counter; } - - + +//bool fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, +// const int* local_code_in, float *shifts_chips, int PRN) bool fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, - const lv_16sc_t* local_code_in, float *shifts_chips) + float *shifts_chips, int PRN) { - d_local_code_in = local_code_in; + //d_local_code_in = local_code_in; d_shifts_chips = shifts_chips; d_code_length_chips = code_length_chips; - - fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(); - + fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN); return true; } - -bool fpga_multicorrelator_8sc::set_output_vectors(lv_16sc_t* corr_out) +bool fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out) { // Save CPU pointers d_corr_out = corr_out; - return true; } - void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips) { d_rem_code_phase_chips = rem_code_phase_chips; - fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(); fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(); } @@ -120,32 +128,31 @@ bool fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( int signal_length_samples) { update_local_code(rem_code_phase_chips); - d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad; d_code_phase_step_chips = code_phase_step_chips; d_phase_step_rad = phase_step_rad; d_correlator_length_samples = signal_length_samples; - - fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(); - fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(); + +// if (first_time == 1) +// { + fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(); + fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(); +// first_time = 0; +// } + fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(); - int irq_count; ssize_t nb; - // wait for interrupt nb = read(d_device_descriptor, &irq_count, sizeof(irq_count)); if (nb != sizeof(irq_count)) { printf("Tracking_module Read failed to retrive 4 bytes!\n"); printf("Tracking_module Interrupt number %d\n", irq_count); } - fpga_multicorrelator_8sc::read_tracking_gps_results(); - return true; } - fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, std::string device_name, unsigned int device_base) { @@ -161,7 +168,7 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_initial_interp_counter = static_cast(volk_gnsssdr_malloc( n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); - d_local_code_in = nullptr; + //d_local_code_in = nullptr; d_shifts_chips = nullptr; d_corr_out = nullptr; d_code_length_chips = 0; @@ -172,22 +179,32 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_rem_carr_phase_rad_int = 0; d_phase_step_rad_int = 0; d_initial_sample_counter = 0; - d_channel = 0; d_correlator_length_samples = 0; + + // pre-compute all the codes + d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); + for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) + { + //gps_l1_ca_code_gen_int(&d_ca_codes[GPS_L1_CA_CODE_LENGTH_CHIPS*(PRN -1)], PRN, 0); + gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0); + } + DLOG(INFO) << "TRACKING FPGA CLASS CREATED"; + } fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc() { - close(d_device_descriptor); + delete[] d_ca_codes; + close_device(); } bool fpga_multicorrelator_8sc::free() { - // unlock the hardware - fpga_multicorrelator_8sc::unlock_channel(); // unlock the channel + // unlock the channel + fpga_multicorrelator_8sc::unlock_channel(); // free the FPGA dynamically created variables if (d_initial_index != nullptr) @@ -209,23 +226,19 @@ bool fpga_multicorrelator_8sc::free() void fpga_multicorrelator_8sc::set_channel(unsigned int channel) { char device_io_name[MAX_LENGTH_DEVICEIO_NAME]; // driver io name - d_channel = channel; // open the device corresponding to the assigned channel std::string mergedname; std::stringstream devicebasetemp; - int numdevice = d_device_base + d_channel; devicebasetemp << numdevice; mergedname = d_device_name + devicebasetemp.str(); strcpy(device_io_name, mergedname.c_str()); - printf("Opening Device Name : %s\n", device_io_name); if ((d_device_descriptor = open(device_io_name, O_RDWR | O_SYNC)) == -1) { LOG(WARNING) << "Cannot open deviceio" << device_io_name; } - d_map_base = reinterpret_cast(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0)); @@ -263,12 +276,11 @@ unsigned fpga_multicorrelator_8sc::fpga_acquisition_test_register( } -void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(void) +void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN) { int k, s; unsigned code_chip; unsigned select_fpga_correlator; - select_fpga_correlator = 0; for (s = 0; s < d_n_correlators; s++) @@ -276,7 +288,8 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(void) d_map_base[11] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER; for (k = 0; k < d_code_length_chips; k++) { - if (lv_creal(d_local_code_in[k]) == 1) + //if (d_local_code_in[k] == 1) + if (d_ca_codes[((int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)) + k] == 1) { code_chip = 1; } @@ -301,18 +314,16 @@ void fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(void) for (i = 0; i < d_n_correlators; i++) { - // initial index calculation temp_calculation = floor( - d_shifts_chips[i] + d_rem_code_phase_chips); + d_shifts_chips[i] - d_rem_code_phase_chips); + if (temp_calculation < 0) { temp_calculation = temp_calculation + d_code_length_chips; // % operator does not work as in Matlab with negative numbers } d_initial_index[i] = static_cast( (static_cast(temp_calculation)) % d_code_length_chips); - - // initial interpolator counter calculation - temp_calculation = fmod(d_shifts_chips[i] + d_rem_code_phase_chips, - 1.0); + temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips, + 1.0); if (temp_calculation < 0) { temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers @@ -339,7 +350,6 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void) float d_rem_carrier_phase_in_rad_temp; d_code_phase_step_chips_num = static_cast( roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips)); - if (d_rem_carrier_phase_in_rad > M_PI) { d_rem_carrier_phase_in_rad_temp = -2 * M_PI @@ -354,11 +364,9 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void) { d_rem_carrier_phase_in_rad_temp = d_rem_carrier_phase_in_rad; } - d_rem_carr_phase_rad_int = static_cast( roundf( (fabs(d_rem_carrier_phase_in_rad_temp) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC))); - if (d_rem_carrier_phase_in_rad_temp < 0) { d_rem_carr_phase_rad_int = -d_rem_carr_phase_rad_int; @@ -379,7 +387,6 @@ void fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(void) d_map_base[7] = d_correlator_length_samples - 1; d_map_base[9] = d_rem_carr_phase_rad_int; d_map_base[10] = d_phase_step_rad_int; - d_map_base[13] = d_initial_sample_counter; } @@ -389,7 +396,8 @@ void fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void) int reenable = 1; write(d_device_descriptor, reinterpret_cast(&reenable), sizeof(int)); - d_map_base[14] = 0; // writing anything to reg 14 launches the tracking + // writing 1 to reg 14 launches the tracking + d_map_base[14] = 1; } @@ -414,8 +422,7 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void) readval_imag = -2097152 + readval_imag; } readval_imag = readval_imag * 2; // the results are shifted two bits to the left due to the complex multiplier in the FPGA - - d_corr_out[k] = lv_cmake(readval_real, readval_imag); + d_corr_out[k] = gr_complex(readval_real,readval_imag); } } @@ -426,6 +433,20 @@ void fpga_multicorrelator_8sc::unlock_channel(void) d_map_base[12] = 1; // unlock the channel } +void fpga_multicorrelator_8sc::close_device() +{ + unsigned * aux = const_cast(d_map_base); + if (munmap(static_cast(aux), PAGE_SIZE) == -1) + { + printf("Failed to unmap memory uio\n"); + } +/* else + { + printf("memory uio unmapped\n"); + } */ + close(d_device_descriptor); +} + void fpga_multicorrelator_8sc::lock_channel(void) { @@ -433,3 +454,16 @@ void fpga_multicorrelator_8sc::lock_channel(void) d_map_base[12] = 0; // lock the channel } +void fpga_multicorrelator_8sc::read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out) +{ + *sample_counter = d_map_base[11]; + *secondary_sample_counter = d_map_base[8]; + *counter_corr_0_in = d_map_base[10]; + *counter_corr_0_out = d_map_base[9]; + +} + +void fpga_multicorrelator_8sc::reset_multicorrelator(void) +{ + d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator +} diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h index 801ae5332..0b726e121 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h @@ -37,6 +37,7 @@ #ifndef GNSS_SDR_FPGA_MULTICORRELATOR_8SC_H_ #define GNSS_SDR_FPGA_MULTICORRELATOR_8SC_H_ +#include #include #define MAX_LENGTH_DEVICEIO_NAME 50 @@ -49,22 +50,30 @@ class fpga_multicorrelator_8sc public: fpga_multicorrelator_8sc(int n_correlators, std::string device_name, unsigned int device_base); - ~fpga_multicorrelator_8sc();bool set_local_code_and_taps( - int code_length_chips, const lv_16sc_t* local_code_in, - float *shifts_chips);bool set_output_vectors(lv_16sc_t* corr_out); + ~fpga_multicorrelator_8sc(); + bool set_output_vectors(gr_complex* corr_out); +// bool set_local_code_and_taps( +// int code_length_chips, const int* local_code_in, +// float *shifts_chips, int PRN); + bool set_local_code_and_taps( + int code_length_chips, + float *shifts_chips, int PRN); + bool set_output_vectors(lv_16sc_t* corr_out); void update_local_code(float rem_code_phase_chips);bool Carrier_wipeoff_multicorrelator_resampler( float rem_carrier_phase_in_rad, float phase_step_rad, float rem_code_phase_chips, float code_phase_step_chips, int signal_length_samples);bool free(); - void set_channel(unsigned int channel); void set_initial_sample(int samples_offset); + int read_sample_counter(); void lock_channel(void); void unlock_channel(void); - + void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug + + private: - const lv_16sc_t *d_local_code_in; - lv_16sc_t *d_corr_out; + //const int *d_local_code_in; + gr_complex * d_corr_out; float *d_shifts_chips; int d_code_length_chips; int d_n_correlators; @@ -94,21 +103,23 @@ private: std::string d_device_name; unsigned int d_device_base; - // results - //int *d_readval_real; - //int *d_readval_imag; - // FPGA private functions + + int* d_ca_codes; + + // private functions unsigned fpga_acquisition_test_register(unsigned writeval); - void fpga_configure_tracking_gps_local_code(void); + void fpga_configure_tracking_gps_local_code(int PRN); void fpga_compute_code_shift_parameters(void); void fpga_configure_code_parameters_in_fpga(void); void fpga_compute_signal_parameters_in_fpga(void); void fpga_configure_signal_parameters_in_fpga(void); void fpga_launch_multicorrelator_fpga(void); void read_tracking_gps_results(void); - - //void unlock_channel(void); - + void reset_multicorrelator(void); + void close_device(void); + + // debug + //unsigned int first_time = 1; }; #endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */ diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.cc b/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.cc new file mode 100644 index 000000000..942cadaff --- /dev/null +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.cc @@ -0,0 +1,148 @@ +/*! + * \file fpga_multicorrelator_real_codes_8sc.cc + * \brief High optimized CPU vector multiTAP correlator class with real-valued local codes + * \authors
    + *
  • Javier Arribas, 2015. jarribas(at)cttc.es + *
  • Cillian O'Driscoll, 2017. cillian.odriscoll(at)gmail.com + *
+ * + * Class that implements a high optimized vector multiTAP correlator class for CPUs + * + * ------------------------------------------------------------------------- + * + * 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 "cpu_multicorrelator_real_codes.h" +#include "fpga_multicorrelator_real_codes_8sc.h" +#include +#include +#include + + +fpga_multicorrelator_real_codes_8sc::fpga_multicorrelator_real_codes_8sc() +{ + d_sig_in = nullptr; + d_local_code_in = nullptr; + d_shifts_chips = nullptr; + d_corr_out = nullptr; + d_local_codes_resampled = nullptr; + d_code_length_chips = 0; + d_n_correlators = 0; +} + + +fpga_multicorrelator_real_codes_8sc::~fpga_multicorrelator_real_codes_8sc() +{ + if(d_local_codes_resampled != nullptr) + { + fpga_multicorrelator_real_codes_8sc::free(); + } +} + + +bool fpga_multicorrelator_real_codes_8sc::init( + int max_signal_length_samples, + int n_correlators) +{ + // ALLOCATE MEMORY FOR INTERNAL vectors + size_t size = max_signal_length_samples * sizeof(float); + + d_local_codes_resampled = static_cast(volk_gnsssdr_malloc(n_correlators * sizeof(float*), volk_gnsssdr_get_alignment())); + for (int n = 0; n < n_correlators; n++) + { + d_local_codes_resampled[n] = static_cast(volk_gnsssdr_malloc(size, volk_gnsssdr_get_alignment())); + } + d_n_correlators = n_correlators; + return true; +} + + + +bool fpga_multicorrelator_real_codes_8sc::set_local_code_and_taps( + int code_length_chips, + const float* local_code_in, + float *shifts_chips) +{ + d_local_code_in = local_code_in; + d_shifts_chips = shifts_chips; + d_code_length_chips = code_length_chips; + return true; +} + + +bool fpga_multicorrelator_real_codes_8sc::set_input_output_vectors(std::complex* corr_out, const std::complex* sig_in) +{ + // Save CPU pointers + d_sig_in = sig_in; + d_corr_out = corr_out; + return true; +} + + +void fpga_multicorrelator_real_codes_8sc::update_local_code(int correlator_length_samples, float rem_code_phase_chips, float code_phase_step_chips) +{ + volk_gnsssdr_32f_xn_resampler_32f_xn(d_local_codes_resampled, + d_local_code_in, + rem_code_phase_chips, + code_phase_step_chips, + d_shifts_chips, + d_code_length_chips, + d_n_correlators, + correlator_length_samples); +} + + +bool fpga_multicorrelator_real_codes_8sc::Carrier_wipeoff_multicorrelator_resampler( + float rem_carrier_phase_in_rad, + float phase_step_rad, + float rem_code_phase_chips, + float code_phase_step_chips, + int signal_length_samples) +{ + update_local_code(signal_length_samples, rem_code_phase_chips, code_phase_step_chips); + // Regenerate phase at each call in order to avoid numerical issues + lv_32fc_t phase_offset_as_complex[1]; + phase_offset_as_complex[0] = lv_cmake(std::cos(rem_carrier_phase_in_rad), -std::sin(rem_carrier_phase_in_rad)); + // call VOLK_GNSSSDR kernel + volk_gnsssdr_32fc_32f_rotator_dot_prod_32fc_xn(d_corr_out, d_sig_in, std::exp(lv_32fc_t(0, - phase_step_rad)), phase_offset_as_complex, (const float**)d_local_codes_resampled, d_n_correlators, signal_length_samples); + return true; +} + + +bool fpga_multicorrelator_real_codes_8sc::free() +{ + // Free memory + if (d_local_codes_resampled != nullptr) + { + for (int n = 0; n < d_n_correlators; n++) + { + volk_gnsssdr_free(d_local_codes_resampled[n]); + } + volk_gnsssdr_free(d_local_codes_resampled); + d_local_codes_resampled = nullptr; + } + return true; +} + + diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.h b/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.h new file mode 100644 index 000000000..94d855ff8 --- /dev/null +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.h @@ -0,0 +1,73 @@ +/*! + * \file fpga_multicorrelator_real_codes_8sc.h + * \brief High optimized CPU vector multiTAP correlator class using real-valued local codes + * \authors
    + *
  • Javier Arribas, 2015. jarribas(at)cttc.es + *
  • Cillian O'Driscoll, 2017, cillian.odriscoll(at)gmail.com + *
+ * + * Class that implements a high optimized vector multiTAP correlator class for CPUs + * + * ------------------------------------------------------------------------- + * + * 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_CPU_MULTICORRELATOR_REAL_CODES_H_ +//#define GNSS_SDR_CPU_MULTICORRELATOR_REAL_CODES_H_ + +#ifndef GNSS_SDR_FPGA_MULTICORRELATOR_REAL_CODES_8SC_H_ +#define GNSS_SDR_FPGA_MULTICORRELATOR_REAL_CODES_8SC_H_ + + +#include + +/*! + * \brief Class that implements carrier wipe-off and correlators. + */ +class fpga_multicorrelator_real_codes_8sc +{ +public: + fpga_multicorrelator_real_codes_8sc(); + ~fpga_multicorrelator_real_codes_8sc(); + bool init(int max_signal_length_samples, int n_correlators); + bool set_local_code_and_taps(int code_length_chips, const float* local_code_in, float *shifts_chips); + bool set_input_output_vectors(std::complex* corr_out, const std::complex* sig_in); + void update_local_code(int correlator_length_samples, float rem_code_phase_chips, float code_phase_step_chips); + bool Carrier_wipeoff_multicorrelator_resampler(float rem_carrier_phase_in_rad, float phase_step_rad, float rem_code_phase_chips, float code_phase_step_chips, int signal_length_samples); + bool free(); + +private: + // Allocate the device input vectors + const std::complex *d_sig_in; + float **d_local_codes_resampled; + const float *d_local_code_in; + std::complex *d_corr_out; + float *d_shifts_chips; + int d_code_length_chips; + int d_n_correlators; +}; + + +#endif /* GNSS_SDR_FPGA_MULTICORRELATOR_REAL_CODES_8SC_H_ */ + diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index e7d096fab..d64dcb9a9 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -100,8 +100,8 @@ #include "rtklib_pvt.h" #if ENABLE_FPGA -#include "gps_l1_ca_dll_pll_c_aid_tracking_fpga.h" #include "gps_l1_ca_pcps_acquisition_fpga.h" +#include "gps_l1_ca_dll_pll_tracking_fpga.h" #endif #if OPENCL_BLOCKS @@ -1318,9 +1318,9 @@ std::unique_ptr GNSSBlockFactory::GetBlock( block = std::move(block_); } #if ENABLE_FPGA - else if (implementation.compare("GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga") == 0) + else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_Fpga") == 0) { - std::unique_ptr block_(new GpsL1CaDllPllCAidTrackingFpga(configuration.get(), role, in_streams, + std::unique_ptr block_(new GpsL1CaDllPllTrackingFpga(configuration.get(), role, in_streams, out_streams)); block = std::move(block_); } @@ -1607,9 +1607,9 @@ std::unique_ptr GNSSBlockFactory::GetTrkBlock( block = std::move(block_); } #if ENABLE_FPGA - else if (implementation.compare("GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga") == 0) + else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_Fpga") == 0) { - std::unique_ptr block_(new GpsL1CaDllPllCAidTrackingFpga(configuration.get(), role, in_streams, + std::unique_ptr block_(new GpsL1CaDllPllTrackingFpga(configuration.get(), role, in_streams, out_streams)); block = std::move(block_); } diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc index da2b3eb9c..91c611d2d 100644 --- a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc @@ -33,6 +33,7 @@ #include #include +#include #include #include #include // to test the FPGA we have to create a simultaneous task to send the samples using the DMA and stop the test @@ -53,7 +54,8 @@ #include "tracking_interface.h" #include "in_memory_configuration.h" #include "gnss_synchro.h" -#include "gps_l1_ca_dll_pll_c_aid_tracking_fpga.h" +//#include "gps_l1_ca_dll_pll_c_aid_tracking_fpga.h" +#include "gps_l1_ca_dll_pll_tracking_fpga.h" #include "tracking_true_obs_reader.h" #include "tracking_dump_reader.h" #include "signal_generator_flags.h" @@ -310,8 +312,10 @@ void GpsL1CADllPllTrackingTestFpga::configure_receiver() config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq)); // Set Tracking + //config->set_property("Tracking_1C.implementation", + // "GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga"); config->set_property("Tracking_1C.implementation", - "GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga"); + "GPS_L1_CA_DLL_PLL_Tracking_Fpga"); config->set_property("Tracking_1C.item_type", "cshort"); config->set_property("Tracking_1C.if", "0"); config->set_property("Tracking_1C.dump", "true"); @@ -467,7 +471,8 @@ TEST_F(GpsL1CADllPllTrackingTestFpga, ValidationOfResultsFpga) }) << "Failure opening true observables file"; top_block = gr::make_top_block("Tracking test"); - std::shared_ptr tracking = std::make_shared (config.get(), "Tracking_1C", 1, 1); + //std::shared_ptr tracking = std::make_shared (config.get(), "Tracking_1C", 1, 1); + std::shared_ptr tracking = std::make_shared (config.get(), "Tracking_1C", 1, 1); boost::shared_ptr msg_rx = GpsL1CADllPllTrackingTestFpga_msg_rx_make(); From 376de5807fd0fd7d044a15b2395d147258cae902 Mon Sep 17 00:00:00 2001 From: mmajoral Date: Tue, 20 Mar 2018 18:06:20 +0100 Subject: [PATCH 04/19] Added FPGA-related changes --- src/core/receiver/control_thread.cc | 7 ++++++ src/core/receiver/gnss_flowgraph.cc | 33 ++++++++++++++++++++++++++++- src/core/receiver/gnss_flowgraph.h | 2 ++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc index db3e3841b..15646a4d3 100644 --- a/src/core/receiver/control_thread.cc +++ b/src/core/receiver/control_thread.cc @@ -138,6 +138,13 @@ void ControlThread::run() keyboard_thread_ = boost::thread(&ControlThread::keyboard_listener, this); sysv_queue_thread_ = boost::thread(&ControlThread::sysv_queue_listener, this); + bool enable_FPGA = configuration_->property("Channel.enable_FPGA", false); + + if (enable_FPGA == true) + { + flowgraph_->start_acquisition_helper(); + } + // Main loop to read and process the control messages while (flowgraph_->running() && !stop_) { diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index e379220a5..b30c18c8d 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -107,6 +107,8 @@ void GNSSFlowgraph::connect() } for (int i = 0; i < sources_count_; i++) + { + if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false)==false) { try { @@ -120,9 +122,12 @@ void GNSSFlowgraph::connect() return; } } + } // Signal Source > Signal conditioner > for (unsigned int i = 0; i < sig_conditioner_.size(); i++) + { + if (configuration_->property(sig_conditioner_.at(i)->role() + ".enable_FPGA", false)==false) { try { @@ -136,6 +141,7 @@ void GNSSFlowgraph::connect() return; } } + } for (unsigned int i = 0; i < channels_count_; i++) { @@ -184,6 +190,10 @@ void GNSSFlowgraph::connect() for (int i = 0; i < sources_count_; i++) { + //FPGA Accelerators do not need signal sources or conditioners + //as the samples are feed directly to the FPGA fabric, so, if enabled, do not connect any source + if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false)==false) + { try { //TODO: Remove this array implementation and create generic multistream connector @@ -244,12 +254,17 @@ void GNSSFlowgraph::connect() return; } } + } DLOG(INFO) << "Signal source connected to signal conditioner"; // Signal conditioner (selected_signal_source) >> channels (i) (dependent of their associated SignalSource_ID) int selected_signal_conditioner_ID; for (unsigned int i = 0; i < channels_count_; i++) { + + bool FPGA_enabled = configuration_->property(sig_conditioner_.at(selected_signal_conditioner_ID)->role() + ".enable_FPGA", false); + if (FPGA_enabled == false) + { selected_signal_conditioner_ID = configuration_->property("Channel" + boost::lexical_cast(i) + ".RF_channel_ID", 0); try { @@ -265,7 +280,7 @@ void GNSSFlowgraph::connect() } DLOG(INFO) << "signal conditioner " << selected_signal_conditioner_ID << " connected to channel " << i; - + } // Signal Source > Signal conditioner >> Channels >> Observables try { @@ -285,7 +300,10 @@ void GNSSFlowgraph::connect() if (channels_state_[i] == 1) { + if (FPGA_enabled == false) + { channels_.at(i)->start_acquisition(); + } available_GNSS_signals_.pop_front(); LOG(INFO) << "Channel " << i << " assigned to " << channels_.at(i)->get_signal(); LOG(INFO) << "Channel " << i << " connected to observables and ready for acquisition"; @@ -295,11 +313,14 @@ void GNSSFlowgraph::connect() LOG(INFO) << "Channel " << i << " connected to observables in standby mode"; } //connect the sample counter to the channel 0 + if (FPGA_enabled == false) + { if (i == 0) { ch_out_sample_counter = gnss_sdr_make_sample_counter(); top_block_->connect(channels_.at(i)->get_right_block(), 0, ch_out_sample_counter, 0); } + } } /* @@ -326,6 +347,16 @@ void GNSSFlowgraph::connect() top_block_->dump(); } +void GNSSFlowgraph::start_acquisition_helper() +{ + for (unsigned int i = 0; i < channels_count_; i++) + { + if (channels_state_[i] == 1) + { + channels_.at(i)->start_acquisition(); + } + } +} void GNSSFlowgraph::wait() { diff --git a/src/core/receiver/gnss_flowgraph.h b/src/core/receiver/gnss_flowgraph.h index 615ee0dc4..a0f09e4bf 100644 --- a/src/core/receiver/gnss_flowgraph.h +++ b/src/core/receiver/gnss_flowgraph.h @@ -86,6 +86,8 @@ public: void wait(); + void start_acquisition_helper(); + /*! * \brief Applies an action to the flowgraph * From ec09016750f2634d9c8eb8d4e8de32f2d4e651d5 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Tue, 27 Mar 2018 14:24:07 +0200 Subject: [PATCH 05/19] Adding Local Oscillator generation for dual band operation using AD9361 FPGA source. Bug fix in FPGA flowgraph --- .../adapters/ad9361_fpga_signal_source.cc | 182 ++++++++++++++++++ .../adapters/ad9361_fpga_signal_source.h | 8 + .../signal_source/libs/ad9361_manager.cc | 166 ++++++++++++++++ .../signal_source/libs/ad9361_manager.h | 130 +++++++++++++ src/core/receiver/gnss_flowgraph.cc | 3 +- 5 files changed, 488 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/signal_source/libs/ad9361_manager.cc create mode 100644 src/algorithms/signal_source/libs/ad9361_manager.h diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc index 3aaf74a79..ff6860499 100644 --- a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc +++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc @@ -33,6 +33,7 @@ #include "ad9361_fpga_signal_source.h" #include "configuration_interface.h" #include "GPS_L1_CA.h" +#include "GPS_L2C.h" #include #include #include @@ -191,6 +192,13 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura dump_ = configuration->property(role + ".dump", false); dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file); + enable_dds_lo_=configuration->property(role + ".enable_dds_lo", false); + freq_rf_tx_hz_=configuration->property(role + ".freq_rf_tx_hz", GPS_L1_FREQ_HZ-GPS_L2_FREQ_HZ-1000); + freq_dds_tx_hz_=configuration->property(role + ".freq_dds_tx_hz", 1000); + 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", 0.0); + item_size_ = sizeof(gr_complex); std::cout << "device address: " << uri_ << std::endl; @@ -199,6 +207,8 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura // AD9361 Frontend IC device operation + int ret; + // Streaming devices struct iio_device *rx; @@ -258,6 +268,151 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura iio_channel_enable(rx0_i); iio_channel_enable(rx0_q); + + + struct iio_device *ad9361_phy; + ad9361_phy= iio_context_find_device(ctx, "ad9361-phy"); + ret=iio_device_attr_write(ad9361_phy,"trx_rate_governor","nominal"); + if (ret < 0) { + std::cout<<"Failed to set trx_rate_governor: "<. + * + * ------------------------------------------------------------------------- + */ +#include "ad9361_manager.h" +#include +#include //only for snprintf +#include +#include + +/* check return value of attr_write function */ +static void errchk(int v, const char* what) { + if (v < 0) + { + LOG(WARNING)<<"Error "<rfport); + wr_ch_lli(chn, "rf_bandwidth", cfg->bw_hz); + wr_ch_lli(chn, "sampling_frequency", cfg->fs_hz); + + // Configure LO channel + LOG(INFO)<<"* Acquiring AD9361 "<lo_hz); + return true; +} + + +static bool set_dds_cw_tone(struct iio_device *dac1, struct iio_channel *chn, double freq_hz, double scale_dbfs, double phase_deg) +{ + + //ENABLE DDS + int ret; + ret = iio_channel_attr_write_bool(iio_device_find_channel(dac1, "altvoltage0", true), "raw", true); + if (ret < 0) { + std::cout<<"Failed to toggle DDS: "<. + * + * ------------------------------------------------------------------------- + */ + +#ifndef __AD9361_MANAGER__ +#define __AD9361_MANAGER__ + + +#ifdef __APPLE__ +#include +#else +#include +#endif + + + +/* RX is input, TX is output */ +enum iodev { RX, TX }; + +/* common RX and TX streaming params */ +struct stream_cfg { + long long bw_hz; // Analog banwidth in Hz + long long fs_hz; // Baseband sample rate in Hz + long long lo_hz; // Local oscillator frequency in Hz + const char* rfport; // Port name +}; + + +enum dds_tone_type { + TX1_T1_I, + TX1_T2_I, + TX1_T1_Q, + TX1_T2_Q, + TX2_T1_I, + TX2_T2_I, + TX2_T1_Q, + TX2_T2_Q, + TX3_T1_I, + TX3_T2_I, + TX3_T1_Q, + TX3_T2_Q, + TX4_T1_I, + TX4_T2_I, + TX4_T1_Q, + TX4_T2_Q +}; + +enum dds_widget_type { + WIDGET_FREQUENCY, + WIDGET_SCALE, + WIDGET_PHASE +}; + +#define DDS_DISABLED 0 +#define DDS_ONE_TONE 1 +#define DDS_TWO_TONE 2 +#define DDS_INDEPDENT 3 +#define DDS_BUFFER 4 + + +/* static scratch mem for strings */ +static char tmpstr[64]; + +/* IIO structs required for streaming */ +static struct iio_context *ctx = NULL; +static struct iio_channel *rx0_i = NULL; +static struct iio_channel *rx0_q = NULL; + +/* check return value of attr_write function */ +static void errchk(int v, const char* what); + +/* write attribute: long long int */ +static void wr_ch_lli(struct iio_channel *chn, const char* what, long long val); + +/* write attribute: string */ +static void wr_ch_str(struct iio_channel *chn, const char* what, const char* str); + +/* helper function generating channel names */ +static char* get_ch_name(const char* type, int id); + +/* returns ad9361 phy device */ +static struct iio_device* get_ad9361_phy(struct iio_context *ctx); + +/* finds AD9361 streaming IIO devices */ +static bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev); + +/* finds AD9361 streaming IIO channels */ +static bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn); + +/* finds AD9361 phy IIO configuration channel with id chid */ +static bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn); + +/* finds AD9361 local oscillator IIO configuration channels */ +static bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn); + +/* applies streaming configuration through IIO */ +bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid); + + +static bool set_dds_cw_tone(struct iio_device *dac1, double freq_hz, double scale_dbfs, double phase_deg); + +#endif diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index b30c18c8d..8ba25be7f 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -262,7 +262,8 @@ void GNSSFlowgraph::connect() for (unsigned int i = 0; i < channels_count_; i++) { - bool FPGA_enabled = configuration_->property(sig_conditioner_.at(selected_signal_conditioner_ID)->role() + ".enable_FPGA", false); + bool FPGA_enabled = configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false); + if (FPGA_enabled == false) { selected_signal_conditioner_ID = configuration_->property("Channel" + boost::lexical_cast(i) + ".RF_channel_ID", 0); From 428a2eb1b5565e101e09a7514e8a53b0253cdf5e Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Tue, 27 Mar 2018 14:44:56 +0200 Subject: [PATCH 06/19] Removing unused files --- .../signal_source/libs/ad9361_manager.cc | 166 ------------------ .../signal_source/libs/ad9361_manager.h | 130 -------------- 2 files changed, 296 deletions(-) delete mode 100644 src/algorithms/signal_source/libs/ad9361_manager.cc delete mode 100644 src/algorithms/signal_source/libs/ad9361_manager.h diff --git a/src/algorithms/signal_source/libs/ad9361_manager.cc b/src/algorithms/signal_source/libs/ad9361_manager.cc deleted file mode 100644 index 370d3e531..000000000 --- a/src/algorithms/signal_source/libs/ad9361_manager.cc +++ /dev/null @@ -1,166 +0,0 @@ -/*! - * \file ad9361_manager.cc - * \brief An Analog Devices AD9361 front-end configuration library wrapper for configure some functions via iiod link. - * \author Javier Arribas, jarribas(at)cttc.es - * - * This file contains information taken from librtlsdr: - * http://git.osmocom.org/rtl-sdr/ - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2018 (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 "ad9361_manager.h" -#include -#include //only for snprintf -#include -#include - -/* check return value of attr_write function */ -static void errchk(int v, const char* what) { - if (v < 0) - { - LOG(WARNING)<<"Error "<rfport); - wr_ch_lli(chn, "rf_bandwidth", cfg->bw_hz); - wr_ch_lli(chn, "sampling_frequency", cfg->fs_hz); - - // Configure LO channel - LOG(INFO)<<"* Acquiring AD9361 "<lo_hz); - return true; -} - - -static bool set_dds_cw_tone(struct iio_device *dac1, struct iio_channel *chn, double freq_hz, double scale_dbfs, double phase_deg) -{ - - //ENABLE DDS - int ret; - ret = iio_channel_attr_write_bool(iio_device_find_channel(dac1, "altvoltage0", true), "raw", true); - if (ret < 0) { - std::cout<<"Failed to toggle DDS: "<. - * - * ------------------------------------------------------------------------- - */ - -#ifndef __AD9361_MANAGER__ -#define __AD9361_MANAGER__ - - -#ifdef __APPLE__ -#include -#else -#include -#endif - - - -/* RX is input, TX is output */ -enum iodev { RX, TX }; - -/* common RX and TX streaming params */ -struct stream_cfg { - long long bw_hz; // Analog banwidth in Hz - long long fs_hz; // Baseband sample rate in Hz - long long lo_hz; // Local oscillator frequency in Hz - const char* rfport; // Port name -}; - - -enum dds_tone_type { - TX1_T1_I, - TX1_T2_I, - TX1_T1_Q, - TX1_T2_Q, - TX2_T1_I, - TX2_T2_I, - TX2_T1_Q, - TX2_T2_Q, - TX3_T1_I, - TX3_T2_I, - TX3_T1_Q, - TX3_T2_Q, - TX4_T1_I, - TX4_T2_I, - TX4_T1_Q, - TX4_T2_Q -}; - -enum dds_widget_type { - WIDGET_FREQUENCY, - WIDGET_SCALE, - WIDGET_PHASE -}; - -#define DDS_DISABLED 0 -#define DDS_ONE_TONE 1 -#define DDS_TWO_TONE 2 -#define DDS_INDEPDENT 3 -#define DDS_BUFFER 4 - - -/* static scratch mem for strings */ -static char tmpstr[64]; - -/* IIO structs required for streaming */ -static struct iio_context *ctx = NULL; -static struct iio_channel *rx0_i = NULL; -static struct iio_channel *rx0_q = NULL; - -/* check return value of attr_write function */ -static void errchk(int v, const char* what); - -/* write attribute: long long int */ -static void wr_ch_lli(struct iio_channel *chn, const char* what, long long val); - -/* write attribute: string */ -static void wr_ch_str(struct iio_channel *chn, const char* what, const char* str); - -/* helper function generating channel names */ -static char* get_ch_name(const char* type, int id); - -/* returns ad9361 phy device */ -static struct iio_device* get_ad9361_phy(struct iio_context *ctx); - -/* finds AD9361 streaming IIO devices */ -static bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev); - -/* finds AD9361 streaming IIO channels */ -static bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn); - -/* finds AD9361 phy IIO configuration channel with id chid */ -static bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn); - -/* finds AD9361 local oscillator IIO configuration channels */ -static bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn); - -/* applies streaming configuration through IIO */ -bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid); - - -static bool set_dds_cw_tone(struct iio_device *dac1, double freq_hz, double scale_dbfs, double phase_deg); - -#endif From 982af827b4c973ec14aeb23cd7618750ec5a99d5 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Tue, 27 Mar 2018 19:00:25 +0200 Subject: [PATCH 07/19] Group all ad9361 configuration calls in one library --- .../adapters/ad9361_fpga_signal_source.cc | 371 +-------- .../signal_source/libs/CMakeLists.txt | 47 +- .../signal_source/libs/ad9361_manager.cc | 704 ++++++++++++++++++ .../signal_source/libs/ad9361_manager.h | 127 ++++ 4 files changed, 898 insertions(+), 351 deletions(-) create mode 100644 src/algorithms/signal_source/libs/ad9361_manager.cc create mode 100644 src/algorithms/signal_source/libs/ad9361_manager.h diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc index ff6860499..cf9130767 100644 --- a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc +++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc @@ -32,6 +32,7 @@ #include "ad9361_fpga_signal_source.h" #include "configuration_interface.h" +#include "ad9361_manager.h" #include "GPS_L1_CA.h" #include "GPS_L2C.h" #include @@ -45,123 +46,6 @@ #include #endif - -/* RX is input, TX is output */ -enum iodev { RX, TX }; - -/* common RX and TX streaming params */ -struct stream_cfg { - long long bw_hz; // Analog banwidth in Hz - long long fs_hz; // Baseband sample rate in Hz - long long lo_hz; // Local oscillator frequency in Hz - const char* rfport; // Port name -}; - - -using google::LogMessage; - - -/* static scratch mem for strings */ -static char tmpstr[64]; - -/* IIO structs required for streaming */ -static struct iio_context *ctx = NULL; -static struct iio_channel *rx0_i = NULL; -static struct iio_channel *rx0_q = NULL; - -/* check return value of attr_write function */ -static void errchk(int v, const char* what) { - if (v < 0) { fprintf(stderr, "Error %d writing to channel \"%s\"\nvalue may not be supported.\n", v, what); } -} - -/* write attribute: long long int */ -static void wr_ch_lli(struct iio_channel *chn, const char* what, long long val) -{ - errchk(iio_channel_attr_write_longlong(chn, what, val), what); -} - -/* write attribute: string */ -static void wr_ch_str(struct iio_channel *chn, const char* what, const char* str) -{ - errchk(iio_channel_attr_write(chn, what, str), what); -} - - -/* helper function generating channel names */ -static char* get_ch_name(const char* type, int id) -{ - snprintf(tmpstr, sizeof(tmpstr), "%s%d", type, id); - return tmpstr; -} - -/* returns ad9361 phy device */ -static struct iio_device* get_ad9361_phy(struct iio_context *ctx) -{ - struct iio_device *dev = iio_context_find_device(ctx, "ad9361-phy"); - return dev; -} - -/* finds AD9361 streaming IIO devices */ -static bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev) -{ - switch (d) { - case TX: *dev = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); return *dev != NULL; - case RX: *dev = iio_context_find_device(ctx, "cf-ad9361-lpc"); return *dev != NULL; - default: return false; - } -} - -/* finds AD9361 streaming IIO channels */ -static bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn) -{ - *chn = iio_device_find_channel(dev, get_ch_name("voltage", chid), d == TX); - if (!*chn) - *chn = iio_device_find_channel(dev, get_ch_name("altvoltage", chid), d == TX); - return *chn != NULL; -} - -/* finds AD9361 phy IIO configuration channel with id chid */ -static bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn) -{ - switch (d) { - case RX: *chn = iio_device_find_channel(get_ad9361_phy(ctx), get_ch_name("voltage", chid), false); return *chn != NULL; - case TX: *chn = iio_device_find_channel(get_ad9361_phy(ctx), get_ch_name("voltage", chid), true); return *chn != NULL; - default: return false; - } -} - -/* finds AD9361 local oscillator IIO configuration channels */ -static bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn) -{ - switch (d) { - // LO chan is always output, i.e. true - case RX: *chn = iio_device_find_channel(get_ad9361_phy(ctx), get_ch_name("altvoltage", 0), true); return *chn != NULL; - case TX: *chn = iio_device_find_channel(get_ad9361_phy(ctx), get_ch_name("altvoltage", 1), true); return *chn != NULL; - default: return false; - } -} - - -/* applies streaming configuration through IIO */ -bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid) -{ - struct iio_channel *chn = NULL; - - // Configure phy and lo channels - printf("* Acquiring AD9361 phy channel %d\n", chid); - if (!get_phy_chan(ctx, type, chid, &chn)) { return false; } - wr_ch_str(chn, "rf_port_select", cfg->rfport); - wr_ch_lli(chn, "rf_bandwidth", cfg->bw_hz); - wr_ch_lli(chn, "sampling_frequency", cfg->fs_hz); - - // Configure LO channel - printf("* Acquiring AD9361 %s lo channel\n", type == TX ? "TX" : "RX"); - if (!get_lo_chan(ctx, type, &chn)) { return false; } - wr_ch_lli(chn, "frequency", cfg->lo_hz); - return true; -} - - Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configuration, std::string role, unsigned int in_stream, unsigned int out_stream, boost::shared_ptr queue) : @@ -170,7 +54,6 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura { std::string default_item_type = "gr_complex"; std::string default_dump_file = "./data/signal_source.dat"; - uri_ = configuration->property(role + ".device_address", std::string("192.168.2.1")); freq_ = configuration->property(role + ".freq", GPS_L1_FREQ_HZ); sample_rate_ = configuration->property(role + ".sampling_frequency", 2600000); bandwidth_ = configuration->property(role + ".bandwidth", 2000000); @@ -205,212 +88,24 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura std::cout << "LO frequency : " << freq_ << " Hz" << std::endl; std::cout << "sample rate: " << sample_rate_ << " Hz" << std::endl; - - // AD9361 Frontend IC device operation - int ret; - - - // Streaming devices - struct iio_device *rx; - - // RX stream config - // Stream configurations - struct stream_cfg rxcfg; - rxcfg.bw_hz = bandwidth_; // 2 MHz rf bandwidth - rxcfg.fs_hz = sample_rate_; // 2.5 MS/s rx sample rate - rxcfg.lo_hz = freq_; // 2.5 GHz rf frequency - rxcfg.rfport = rf_port_select_.c_str(); // port A (select for rf freq.) - - - std::cout<<"AD9361 Acquiring IIO context\n"; - ctx = iio_create_default_context(); - if (!ctx) - { - std::cout<<"No context\n"; - throw std::runtime_error("AD9361 IIO No context"); - } - - if (iio_context_get_devices_count(ctx) <= 0) - { - std::cout<<"No devices\n"; - throw std::runtime_error("AD9361 IIO No devices"); - } - - std::cout<<"* Acquiring AD9361 streaming devices\n"; - - if(!get_ad9361_stream_dev(ctx, RX, &rx)) - { - std::cout<<"No rx dev found\n"; - throw std::runtime_error("AD9361 IIO No rx dev found"); - }; - - std::cout<<"* Configuring AD9361 for streaming\n"; - if (!cfg_ad9361_streaming_ch(ctx, &rxcfg, RX, 0)) - { - std::cout<<"RX port 0 not found\n"; - throw std::runtime_error("AD9361 IIO RX port 0 not found"); - } - - std::cout<<"* Initializing AD9361 IIO streaming channels\n"; - if (!get_ad9361_stream_ch(ctx, RX, rx, 0, &rx0_i)) - { - std::cout<<"RX chan i not found\n"; - throw std::runtime_error("RX chan i not found"); - } - - if (!get_ad9361_stream_ch(ctx, RX, rx, 1, &rx0_q)) - { - std::cout<<"RX chan q not found\n"; - throw std::runtime_error("RX chan q not found"); - } - - std::cout<<"* Enabling IIO streaming channels\n"; - iio_channel_enable(rx0_i); - iio_channel_enable(rx0_q); - - - - struct iio_device *ad9361_phy; - ad9361_phy= iio_context_find_device(ctx, "ad9361-phy"); - ret=iio_device_attr_write(ad9361_phy,"trx_rate_governor","nominal"); - if (ret < 0) { - std::cout<<"Failed to set trx_rate_governor: "<. # +if(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) + find_package(iio REQUIRED) + if(NOT IIO_FOUND) + message(STATUS "gnuradio-iio not found, its installation is required.") + message(STATUS "Please build and install the following projects:") + message(STATUS " * libiio from https://github.com/analogdevicesinc/libiio") + message(STATUS " * libad9361-iio from https://github.com/analogdevicesinc/libad9361-iio") + message(STATUS " * gnuradio-iio from https://github.com/analogdevicesinc/gr-iio") + message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled") + endif(NOT IIO_FOUND) + set(OPT_LIBRARIES ${OPT_LIBRARIES} ${IIO_LIBRARIES}) + set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) + +endif(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) + +if(ENABLE_FMCOMMS2 OR ENABLE_AD9361) + find_package(libiio REQUIRED) + if(NOT LIBIIO_FOUND) + message(STATUS "gnuradio-iio not found, its installation is required.") + message(STATUS "Please build and install the following projects:") + message(STATUS " * libiio from https://github.com/analogdevicesinc/libiio") + message(STATUS " * libad9361-iio from https://github.com/analogdevicesinc/libad9361-iio") + message(STATUS " * gnuradio-iio from https://github.com/analogdevicesinc/gr-iio") + message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled") + endif(NOT LIBIIO_FOUND) + set(OPT_LIBRARIES ${OPT_LIBRARIES} ${LIBIIO_LIBRARIES}) + set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${LIBIIO_INCLUDE_DIRS}) + + ############################################### + # FMCOMMS2 based SDR Hardware + ############################################### + if(IIO_FOUND) + set(OPT_SIGNAL_SOURCE_LIB_SOURCES ad9361_manager.cc) + endif(IIO_FOUND) + +endif(ENABLE_FMCOMMS2 OR ENABLE_AD9361) + set (SIGNAL_SOURCE_LIB_SOURCES rtl_tcp_commands.cc - rtl_tcp_dongle_info.cc) + rtl_tcp_dongle_info.cc + ${OPT_SIGNAL_SOURCE_LIB_SOURCES}) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${Boost_INCLUDE_DIRS} + ${OPT_DRIVER_INCLUDE_DIRS} ) + file(GLOB SIGNAL_SOURCE_LIB_HEADERS "*.h") list(SORT SIGNAL_SOURCE_LIB_HEADERS) add_library(signal_source_lib ${SIGNAL_SOURCE_LIB_SOURCES} ${SIGNAL_SOURCE_LIB_HEADERS}) -source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS}) \ No newline at end of file +source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS}) + +target_link_libraries(signal_source_lib ${OPT_LIBRARIES}) + diff --git a/src/algorithms/signal_source/libs/ad9361_manager.cc b/src/algorithms/signal_source/libs/ad9361_manager.cc new file mode 100644 index 000000000..66a95ee14 --- /dev/null +++ b/src/algorithms/signal_source/libs/ad9361_manager.cc @@ -0,0 +1,704 @@ +/*! + * \file ad9361_manager.cc + * \brief An Analog Devices AD9361 front-end configuration library wrapper for configure some functions via iiod link. + * \author Javier Arribas, jarribas(at)cttc.es + * + * This file contains information taken from librtlsdr: + * http://git.osmocom.org/rtl-sdr/ + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (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 "ad9361_manager.h" +#include +#include +#include +#include + +/* check return value of attr_write function */ +void errchk(int v, const char* what) { + if (v < 0) + { + LOG(WARNING)<<"Error "<rfport); + wr_ch_lli(chn, "rf_bandwidth", cfg->bw_hz); + wr_ch_lli(chn, "sampling_frequency", cfg->fs_hz); + + // Configure LO channel + //LOG(INFO)<<"* Acquiring AD9361 "<lo_hz); + return true; +} + + +bool config_ad9361_rx_local(unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_, + std::string rf_port_select_, + std::string gain_mode_rx1_, + std::string gain_mode_rx2_, + double rf_gain_rx1_, + double rf_gain_rx2_) + +{ + // RX stream config + // Stream configurations + struct stream_cfg rxcfg; + rxcfg.bw_hz = bandwidth_; // 2 MHz rf bandwidth + rxcfg.fs_hz = sample_rate_; // 2.5 MS/s rx sample rate + rxcfg.lo_hz = freq_; // 2.5 GHz rf frequency + rxcfg.rfport = rf_port_select_.c_str(); // port A (select for rf freq.) + + std::cout<<"AD9361 Acquiring IIO LOCAL context\n"; + struct iio_context *ctx; + // Streaming devices + struct iio_device *rx; + struct iio_channel *rx0_i; + struct iio_channel *rx0_q; + + ctx = iio_create_default_context(); + if (!ctx) + { + std::cout<<"No context\n"; + throw std::runtime_error("AD9361 IIO No context"); + } + + if (iio_context_get_devices_count(ctx) <= 0) + { + std::cout<<"No devices\n"; + throw std::runtime_error("AD9361 IIO No devices"); + } + + std::cout<<"* Acquiring AD9361 streaming devices\n"; + + if(!get_ad9361_stream_dev(ctx, RX, &rx)) + { + std::cout<<"No rx dev found\n"; + throw std::runtime_error("AD9361 IIO No rx dev found"); + }; + + std::cout<<"* Configuring AD9361 for streaming\n"; + if (!cfg_ad9361_streaming_ch(ctx, &rxcfg, RX, 0)) + { + std::cout<<"RX port 0 not found\n"; + throw std::runtime_error("AD9361 IIO RX port 0 not found"); + } + + std::cout<<"* Initializing AD9361 IIO streaming channels\n"; + if (!get_ad9361_stream_ch(ctx, RX, rx, 0, &rx0_i)) + { + std::cout<<"RX chan i not found\n"; + throw std::runtime_error("RX chan i not found"); + } + + if (!get_ad9361_stream_ch(ctx, RX, rx, 1, &rx0_q)) + { + std::cout<<"RX chan q not found\n"; + throw std::runtime_error("RX chan q not found"); + } + + std::cout<<"* Enabling IIO streaming channels\n"; + iio_channel_enable(rx0_i); + iio_channel_enable(rx0_q); + + struct iio_device *ad9361_phy; + ad9361_phy= iio_context_find_device(ctx, "ad9361-phy"); + int ret; + ret=iio_device_attr_write(ad9361_phy,"trx_rate_governor","nominal"); + if (ret < 0) { + std::cout<<"Failed to set trx_rate_governor: "<. + * + * ------------------------------------------------------------------------- + */ + +#ifndef __AD9361_MANAGER__ +#define __AD9361_MANAGER__ + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +/* RX is input, TX is output */ +enum iodev { RX, TX }; + +/* common RX and TX streaming params */ +struct stream_cfg { + long long bw_hz; // Analog banwidth in Hz + long long fs_hz; // Baseband sample rate in Hz + long long lo_hz; // Local oscillator frequency in Hz + const char* rfport; // Port name +}; + + +/* check return value of attr_write function */ +void errchk(int v, const char* what); + +/* write attribute: long long int */ +void wr_ch_lli(struct iio_channel *chn, const char* what, long long val); + +/* write attribute: string */ +void wr_ch_str(struct iio_channel *chn, const char* what, const char* str); + +/* helper function generating channel names */ +char* get_ch_name(const char* type, int id, char* tmpstr); + +/* returns ad9361 phy device */ +struct iio_device* get_ad9361_phy(struct iio_context *ctx); + +/* finds AD9361 streaming IIO devices */ +bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev); + +/* finds AD9361 streaming IIO channels */ +bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn); + +/* finds AD9361 phy IIO configuration channel with id chid */ +bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn); + +/* finds AD9361 local oscillator IIO configuration channels */ +bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn); + +/* applies streaming configuration through IIO */ +bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid); + + +bool config_ad9361_rx_local(unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_, + std::string rf_port_select_, + std::string gain_mode_rx1_, + std::string gain_mode_rx2_, + double rf_gain_rx1_, + double rf_gain_rx2_); + +bool config_ad9361_rx_remote(std::string remote_host, + unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_, + std::string rf_port_select_, + std::string gain_mode_rx1_, + std::string gain_mode_rx2_, + double rf_gain_rx1_, + double rf_gain_rx2_); + +bool config_ad9361_lo_local(unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_rf_tx_hz_, + double tx_attenuation_db_, + long long freq_dds_tx_hz_, + double scale_dds_dbfs_); + +bool config_ad9361_lo_remote(std::string remote_host, + unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_rf_tx_hz_, + double tx_attenuation_db_, + long long freq_dds_tx_hz_, + double scale_dds_dbfs_); + + +bool ad9361_disable_lo_remote(std::string remote_host); + +bool ad9361_disable_lo_local(); + + +#endif From e1635a735d997b525bb5797f21d4916c1b45d735 Mon Sep 17 00:00:00 2001 From: mmajoral Date: Thu, 5 Apr 2018 15:05:46 +0200 Subject: [PATCH 08/19] Added the class switch_FPGA, which controls the switch in the FPGA that connects the analog frontend and the DMA to the queues of the HW accelerators. Removed some unused variables in the tracking. --- .../adapters/ad9361_fpga_signal_source.cc | 6 + .../adapters/ad9361_fpga_signal_source.h | 3 + .../signal_source/libs/CMakeLists.txt | 4 + .../signal_source/libs/fpga_switch.cc | 136 ++++++++++++++++ .../signal_source/libs/fpga_switch.h | 61 ++++++++ .../gps_l1_ca_dll_pll_tracking_fpga_sc.cc | 27 +--- .../gps_l1_ca_dll_pll_tracking_fpga_sc.h | 2 - src/algorithms/tracking/libs/CMakeLists.txt | 1 - .../tracking/libs/fpga_multicorrelator_8sc.cc | 27 +--- .../tracking/libs/fpga_multicorrelator_8sc.h | 12 +- .../fpga_multicorrelator_real_codes_8sc.cc | 148 ------------------ .../fpga_multicorrelator_real_codes_8sc.h | 73 --------- 12 files changed, 231 insertions(+), 269 deletions(-) create mode 100644 src/algorithms/signal_source/libs/fpga_switch.cc create mode 100644 src/algorithms/signal_source/libs/fpga_switch.h delete mode 100644 src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.cc delete mode 100644 src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.h diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc index cf9130767..cba4e5439 100644 --- a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc +++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc @@ -108,6 +108,12 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura scale_dds_dbfs_); } + // turn switch to A/D position + std::string default_device_name = "/dev/uio13"; + std::string device_name = configuration->property(role + ".devicename", default_device_name); + int switch_position = configuration->property(role + ".switch_position", 0); + switch_fpga = std::make_shared (device_name); + switch_fpga->set_switch_position(switch_position); } diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h index 5371f7faf..6110a63c3 100644 --- a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h +++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h @@ -33,6 +33,7 @@ #define GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H_ #include "gnss_block_interface.h" +#include "fpga_switch.h" #include #include @@ -112,6 +113,8 @@ private: std::string dump_filename_; boost::shared_ptr queue_; + + std::shared_ptr switch_fpga; }; #endif /*GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H_*/ diff --git a/src/algorithms/signal_source/libs/CMakeLists.txt b/src/algorithms/signal_source/libs/CMakeLists.txt index 45131f918..5617be70a 100644 --- a/src/algorithms/signal_source/libs/CMakeLists.txt +++ b/src/algorithms/signal_source/libs/CMakeLists.txt @@ -58,6 +58,10 @@ set (SIGNAL_SOURCE_LIB_SOURCES rtl_tcp_dongle_info.cc ${OPT_SIGNAL_SOURCE_LIB_SOURCES}) +if(ENABLE_FPGA) + SET(SIGNAL_SOURCE_LIB_SOURCES ${SIGNAL_SOURCE_LIB_SOURCES} fpga_switch.cc) +endif(ENABLE_FPGA) + include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${Boost_INCLUDE_DIRS} diff --git a/src/algorithms/signal_source/libs/fpga_switch.cc b/src/algorithms/signal_source/libs/fpga_switch.cc new file mode 100644 index 000000000..e349a3c53 --- /dev/null +++ b/src/algorithms/signal_source/libs/fpga_switch.cc @@ -0,0 +1,136 @@ +/*! + * \file fpga_switch.cc + * \brief Switch that connects the HW accelerator queues to the analog front end or the DMA. + * \authors
    + *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat + *
  • Javier Arribas, 2015. jarribas(at)cttc.es + *
+ * + * Class that controls a switch in the FPGA + * + * + * ------------------------------------------------------------------------- + * + * 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 "fpga_switch.h" + +#include + +// FPGA stuff +#include + +// libraries used by DMA test code and GIPO test code +#include +#include +#include +#include + +// libraries used by DMA test code +#include +#include +#include +#include + +// libraries used by GPIO test code +#include +#include +#include + +// logging +#include + +// string manipulation +#include + +// constants +#define PAGE_SIZE 0x10000 +#define TEST_REGISTER_TRACK_WRITEVAL 0x55AA + +fpga_switch::fpga_switch(std::string device_name) +{ + if ((d_device_descriptor = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1) + { + LOG(WARNING) << "Cannot open deviceio" << device_name; + printf("switch memory successfully mapped\n"); + } + d_map_base = reinterpret_cast(mmap(NULL, PAGE_SIZE, + PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0)); + + if (d_map_base == reinterpret_cast(-1)) + { + LOG(WARNING) << "Cannot map the FPGA switch module into tracking memory"; + printf("could not map switch memory\n"); + } + + // sanity check : check test register + unsigned writeval = TEST_REGISTER_TRACK_WRITEVAL; + unsigned readval; + readval = fpga_switch::fpga_switch_test_register(writeval); + if (writeval != readval) + { + LOG(WARNING) << "Test register sanity check failed"; + } + else + { + LOG(INFO) << "Test register sanity check success !"; + } + + DLOG(INFO) << "Switch FPGA class created"; +} + +fpga_switch::~fpga_switch() +{ + close_device(); +} + +void fpga_switch::set_switch_position(int switch_position) +{ + d_map_base[0] = switch_position; +} + +unsigned fpga_switch::fpga_switch_test_register( + unsigned writeval) +{ + unsigned readval; + // write value to test register + d_map_base[3] = writeval; + // read value from test register + readval = d_map_base[3]; + // return read value + return readval; +} + +void fpga_switch::close_device() +{ + unsigned * aux = const_cast(d_map_base); + if (munmap(static_cast(aux), PAGE_SIZE) == -1) + { + printf("Failed to unmap memory uio\n"); + } + + close(d_device_descriptor); +} + + diff --git a/src/algorithms/signal_source/libs/fpga_switch.h b/src/algorithms/signal_source/libs/fpga_switch.h new file mode 100644 index 000000000..c3ce2fbba --- /dev/null +++ b/src/algorithms/signal_source/libs/fpga_switch.h @@ -0,0 +1,61 @@ +/*! + * \file fpga_switch.h + * \brief Switch that connects the HW accelerator queues to the analog front end or the DMA. + * \authors
    + *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat + *
  • Javier Arribas, 2016. jarribas(at)cttc.es + *
+ * + * Class that controls a switch in the FPGA + * + * + * ------------------------------------------------------------------------- + * + * 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_FPGA_SWITCH_H_ +#define GNSS_SDR_FPGA_SWITCH_H_ + +#include + +#define MAX_LENGTH_DEVICEIO_NAME 50 + +class fpga_switch +{ +public: + fpga_switch(std::string device_name); + ~fpga_switch(); + void set_switch_position(int switch_position); + +private: + int d_device_descriptor; // driver descriptor + volatile unsigned *d_map_base; // driver memory map + + // private functions + unsigned fpga_switch_test_register(unsigned writeval); + void close_device(void); + +}; + +#endif /* GNSS_SDR_FPGA_SWITCH_H_ */ diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc index a6ebb9bec..f346ff8bc 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc @@ -173,11 +173,6 @@ Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc( d_carrier_phase_step_rad = 0.0; set_relative_rate(1.0 / static_cast(d_vector_length)); - - d_first_time = 1; - - - } void Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::start_tracking() @@ -246,16 +241,14 @@ void Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::start_tracking() d_code_phase_samples = d_acq_code_phase_samples; std::string sys_ = &d_acquisition_gnss_synchro->System; sys = sys_.substr(0,1); - //std::cout << "Tracking of GPS L1 C/A signal started on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; + std::cout << "Tracking of GPS L1 C/A signal started on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; LOG(INFO) << "Starting tracking of satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " on channel " << d_channel; // enable tracking d_pull_in = true; - multicorrelator_fpga_8sc->lock_channel(); d_enable_tracking = true; //do it in the end to avoid starting running tracking before finishing this function LOG(INFO) << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz << " Code Phase correction [samples]=" << delay_correction_samples << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples; - d_first_time = 1; } Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::~Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc() @@ -275,10 +268,7 @@ Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::~Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc() { volk_gnsssdr_free(d_local_code_shift_chips); volk_gnsssdr_free(d_correlator_outs); - //volk_gnsssdr_free(d_ca_code); delete[] d_Prompt_buffer; - //multicorrelator_cpu.free(); - //volk_gnsssdr_free(d_ca_code_16sc); multicorrelator_fpga_8sc->free(); } catch(const std::exception & ex) @@ -297,8 +287,6 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib int counter_corr_0_out; int sample_counter; - // samples offset -// int samples_offset; unsigned absolute_samples_offset; // int kk2; // process vars @@ -308,7 +296,6 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib double code_error_filt_chips = 0.0; int next_prn_length_samples = d_current_prn_length_samples; -// int offset_prn_samples = 0; // Block input data and block output stream pointers Gnss_Synchro **out = reinterpret_cast(&output_items[0]); @@ -324,6 +311,7 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib if (d_pull_in == true) { d_pull_in = false; + multicorrelator_fpga_8sc->lock_channel(); unsigned counter_value = multicorrelator_fpga_8sc->read_sample_counter(); unsigned num_frames = ceil((counter_value - current_synchro_data.Acq_samplestamp_samples - current_synchro_data.Acq_delay_samples)/d_correlation_length_samples); absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; @@ -382,7 +370,6 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib double T_prn_samples = T_prn_seconds * static_cast(d_fs_in); double K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * static_cast(d_fs_in); next_prn_length_samples = round(K_blk_samples); -// offset_prn_samples = next_prn_length_samples - d_current_prn_length_samples; //################### PLL COMMANDS ################################################# // carrier phase step (NCO phase increment per sample) [rads/sample] @@ -426,15 +413,12 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) { std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; - d_debug_loss_of_track = 1; LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; this->message_port_pub(pmt::mp("events"), pmt::from_long(3)); // 3 -> loss of lock d_carrier_lock_fail_counter = 0; d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine multicorrelator_fpga_8sc->unlock_channel(); - - - } + } } // ########### Output the tracking data to navigation and PVT ########## @@ -535,14 +519,13 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib if (d_enable_tracking == true) { - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false - //return 0; // debug + return 1; } else { return 0; } - + } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h index c497c08f2..f7d2141c9 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h @@ -181,7 +181,6 @@ private: double d_K_blk_samples_previous; int d_offset_sample_previous; - int d_first_time; int d_kk = 0; int d_numsamples_debug = 990; @@ -194,7 +193,6 @@ private: int d_counter_corr_0_in = 0; int d_counter_corr_0_out = 0; int d_sample_counter_inc = 0; - int d_debug_loss_of_track = 0; }; #endif //GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_SC_H diff --git a/src/algorithms/tracking/libs/CMakeLists.txt b/src/algorithms/tracking/libs/CMakeLists.txt index 1cc68dabb..88c4eb2a5 100644 --- a/src/algorithms/tracking/libs/CMakeLists.txt +++ b/src/algorithms/tracking/libs/CMakeLists.txt @@ -47,7 +47,6 @@ set(TRACKING_LIB_SOURCES if(ENABLE_FPGA) SET(TRACKING_LIB_SOURCES ${TRACKING_LIB_SOURCES} fpga_multicorrelator_8sc.cc) - SET(TRACKING_LIB_SOURCES ${TRACKING_LIB_SOURCES} fpga_multicorrelator_real_codes_8sc.cc) endif(ENABLE_FPGA) include_directories( diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc index dd6f208ce..ce2275422 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc @@ -95,23 +95,18 @@ void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset) d_map_base[13] = d_initial_sample_counter; } -//bool fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, -// const int* local_code_in, float *shifts_chips, int PRN) -bool fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, +void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, float *shifts_chips, int PRN) { - //d_local_code_in = local_code_in; + d_shifts_chips = shifts_chips; d_code_length_chips = code_length_chips; fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN); - return true; } -bool fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out) +void fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out) { - // Save CPU pointers d_corr_out = corr_out; - return true; } void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips) @@ -122,24 +117,20 @@ void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips) } -bool fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( +void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( float rem_carrier_phase_in_rad, float phase_step_rad, float rem_code_phase_chips, float code_phase_step_chips, int signal_length_samples) { + + update_local_code(rem_code_phase_chips); d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad; d_code_phase_step_chips = code_phase_step_chips; d_phase_step_rad = phase_step_rad; d_correlator_length_samples = signal_length_samples; - -// if (first_time == 1) -// { - fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(); - fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(); -// first_time = 0; -// } - + fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(); + fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(); fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(); int irq_count; ssize_t nb; @@ -150,7 +141,6 @@ bool fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( printf("Tracking_module Interrupt number %d\n", irq_count); } fpga_multicorrelator_8sc::read_tracking_gps_results(); - return true; } fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, @@ -186,7 +176,6 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) { - //gps_l1_ca_code_gen_int(&d_ca_codes[GPS_L1_CA_CODE_LENGTH_CHIPS*(PRN -1)], PRN, 0); gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0); } DLOG(INFO) << "TRACKING FPGA CLASS CREATED"; diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h index 0b726e121..9bf44536e 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h @@ -51,15 +51,19 @@ public: fpga_multicorrelator_8sc(int n_correlators, std::string device_name, unsigned int device_base); ~fpga_multicorrelator_8sc(); - bool set_output_vectors(gr_complex* corr_out); + //bool set_output_vectors(gr_complex* corr_out); + void set_output_vectors(gr_complex* corr_out); // bool set_local_code_and_taps( // int code_length_chips, const int* local_code_in, // float *shifts_chips, int PRN); - bool set_local_code_and_taps( + //bool set_local_code_and_taps( + void set_local_code_and_taps( int code_length_chips, float *shifts_chips, int PRN); - bool set_output_vectors(lv_16sc_t* corr_out); - void update_local_code(float rem_code_phase_chips);bool Carrier_wipeoff_multicorrelator_resampler( + //bool set_output_vectors(lv_16sc_t* corr_out); + void update_local_code(float rem_code_phase_chips); + //bool Carrier_wipeoff_multicorrelator_resampler( + void Carrier_wipeoff_multicorrelator_resampler( float rem_carrier_phase_in_rad, float phase_step_rad, float rem_code_phase_chips, float code_phase_step_chips, int signal_length_samples);bool free(); diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.cc b/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.cc deleted file mode 100644 index 942cadaff..000000000 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.cc +++ /dev/null @@ -1,148 +0,0 @@ -/*! - * \file fpga_multicorrelator_real_codes_8sc.cc - * \brief High optimized CPU vector multiTAP correlator class with real-valued local codes - * \authors
    - *
  • Javier Arribas, 2015. jarribas(at)cttc.es - *
  • Cillian O'Driscoll, 2017. cillian.odriscoll(at)gmail.com - *
- * - * Class that implements a high optimized vector multiTAP correlator class for CPUs - * - * ------------------------------------------------------------------------- - * - * 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 "cpu_multicorrelator_real_codes.h" -#include "fpga_multicorrelator_real_codes_8sc.h" -#include -#include -#include - - -fpga_multicorrelator_real_codes_8sc::fpga_multicorrelator_real_codes_8sc() -{ - d_sig_in = nullptr; - d_local_code_in = nullptr; - d_shifts_chips = nullptr; - d_corr_out = nullptr; - d_local_codes_resampled = nullptr; - d_code_length_chips = 0; - d_n_correlators = 0; -} - - -fpga_multicorrelator_real_codes_8sc::~fpga_multicorrelator_real_codes_8sc() -{ - if(d_local_codes_resampled != nullptr) - { - fpga_multicorrelator_real_codes_8sc::free(); - } -} - - -bool fpga_multicorrelator_real_codes_8sc::init( - int max_signal_length_samples, - int n_correlators) -{ - // ALLOCATE MEMORY FOR INTERNAL vectors - size_t size = max_signal_length_samples * sizeof(float); - - d_local_codes_resampled = static_cast(volk_gnsssdr_malloc(n_correlators * sizeof(float*), volk_gnsssdr_get_alignment())); - for (int n = 0; n < n_correlators; n++) - { - d_local_codes_resampled[n] = static_cast(volk_gnsssdr_malloc(size, volk_gnsssdr_get_alignment())); - } - d_n_correlators = n_correlators; - return true; -} - - - -bool fpga_multicorrelator_real_codes_8sc::set_local_code_and_taps( - int code_length_chips, - const float* local_code_in, - float *shifts_chips) -{ - d_local_code_in = local_code_in; - d_shifts_chips = shifts_chips; - d_code_length_chips = code_length_chips; - return true; -} - - -bool fpga_multicorrelator_real_codes_8sc::set_input_output_vectors(std::complex* corr_out, const std::complex* sig_in) -{ - // Save CPU pointers - d_sig_in = sig_in; - d_corr_out = corr_out; - return true; -} - - -void fpga_multicorrelator_real_codes_8sc::update_local_code(int correlator_length_samples, float rem_code_phase_chips, float code_phase_step_chips) -{ - volk_gnsssdr_32f_xn_resampler_32f_xn(d_local_codes_resampled, - d_local_code_in, - rem_code_phase_chips, - code_phase_step_chips, - d_shifts_chips, - d_code_length_chips, - d_n_correlators, - correlator_length_samples); -} - - -bool fpga_multicorrelator_real_codes_8sc::Carrier_wipeoff_multicorrelator_resampler( - float rem_carrier_phase_in_rad, - float phase_step_rad, - float rem_code_phase_chips, - float code_phase_step_chips, - int signal_length_samples) -{ - update_local_code(signal_length_samples, rem_code_phase_chips, code_phase_step_chips); - // Regenerate phase at each call in order to avoid numerical issues - lv_32fc_t phase_offset_as_complex[1]; - phase_offset_as_complex[0] = lv_cmake(std::cos(rem_carrier_phase_in_rad), -std::sin(rem_carrier_phase_in_rad)); - // call VOLK_GNSSSDR kernel - volk_gnsssdr_32fc_32f_rotator_dot_prod_32fc_xn(d_corr_out, d_sig_in, std::exp(lv_32fc_t(0, - phase_step_rad)), phase_offset_as_complex, (const float**)d_local_codes_resampled, d_n_correlators, signal_length_samples); - return true; -} - - -bool fpga_multicorrelator_real_codes_8sc::free() -{ - // Free memory - if (d_local_codes_resampled != nullptr) - { - for (int n = 0; n < d_n_correlators; n++) - { - volk_gnsssdr_free(d_local_codes_resampled[n]); - } - volk_gnsssdr_free(d_local_codes_resampled); - d_local_codes_resampled = nullptr; - } - return true; -} - - diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.h b/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.h deleted file mode 100644 index 94d855ff8..000000000 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_real_codes_8sc.h +++ /dev/null @@ -1,73 +0,0 @@ -/*! - * \file fpga_multicorrelator_real_codes_8sc.h - * \brief High optimized CPU vector multiTAP correlator class using real-valued local codes - * \authors
    - *
  • Javier Arribas, 2015. jarribas(at)cttc.es - *
  • Cillian O'Driscoll, 2017, cillian.odriscoll(at)gmail.com - *
- * - * Class that implements a high optimized vector multiTAP correlator class for CPUs - * - * ------------------------------------------------------------------------- - * - * 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_CPU_MULTICORRELATOR_REAL_CODES_H_ -//#define GNSS_SDR_CPU_MULTICORRELATOR_REAL_CODES_H_ - -#ifndef GNSS_SDR_FPGA_MULTICORRELATOR_REAL_CODES_8SC_H_ -#define GNSS_SDR_FPGA_MULTICORRELATOR_REAL_CODES_8SC_H_ - - -#include - -/*! - * \brief Class that implements carrier wipe-off and correlators. - */ -class fpga_multicorrelator_real_codes_8sc -{ -public: - fpga_multicorrelator_real_codes_8sc(); - ~fpga_multicorrelator_real_codes_8sc(); - bool init(int max_signal_length_samples, int n_correlators); - bool set_local_code_and_taps(int code_length_chips, const float* local_code_in, float *shifts_chips); - bool set_input_output_vectors(std::complex* corr_out, const std::complex* sig_in); - void update_local_code(int correlator_length_samples, float rem_code_phase_chips, float code_phase_step_chips); - bool Carrier_wipeoff_multicorrelator_resampler(float rem_carrier_phase_in_rad, float phase_step_rad, float rem_code_phase_chips, float code_phase_step_chips, int signal_length_samples); - bool free(); - -private: - // Allocate the device input vectors - const std::complex *d_sig_in; - float **d_local_codes_resampled; - const float *d_local_code_in; - std::complex *d_corr_out; - float *d_shifts_chips; - int d_code_length_chips; - int d_n_correlators; -}; - - -#endif /* GNSS_SDR_FPGA_MULTICORRELATOR_REAL_CODES_8SC_H_ */ - From 2138c1340bfef2c698f0982fa5fb0335fb1860a0 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Thu, 12 Apr 2018 18:03:30 +0200 Subject: [PATCH 09/19] Removing debug code in trk FPGA accelerators --- .../gps_l1_ca_dll_pll_tracking_fpga_sc.cc | 17 ----------------- .../gps_l1_ca_dll_pll_tracking_fpga_sc.h | 11 ----------- 2 files changed, 28 deletions(-) diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc index f346ff8bc..b8a52b8c5 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc @@ -281,14 +281,7 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - // debug - int secondary_sample_counter; - int counter_corr_0_in; - int counter_corr_0_out; - int sample_counter; - unsigned absolute_samples_offset; -// int kk2; // process vars double carr_error_hz = 0.0; double carr_error_filt_hz = 0.0; @@ -333,16 +326,6 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib d_rem_carr_phase_rad, d_carrier_phase_step_rad, d_rem_code_phase_chips, d_code_phase_step_chips, d_current_prn_length_samples); - d_previous_sample_counter = d_debug_sample_counter; - d_previous_counter_corr_0_in = d_counter_corr_0_in; - d_previous_counter_corr_0_out = d_counter_corr_0_out; - multicorrelator_fpga_8sc->read_sample_counters(&sample_counter, &secondary_sample_counter, &counter_corr_0_in, &counter_corr_0_out); - d_debug_sample_counter = sample_counter; - d_counter_corr_0_in = counter_corr_0_in; - d_counter_corr_0_out = counter_corr_0_out; - d_counter_corr_0_in_inc = counter_corr_0_in - d_previous_counter_corr_0_in; - d_counter_corr_0_out_inc = counter_corr_0_out - d_previous_counter_corr_0_out; - d_sample_counter_inc = d_debug_sample_counter - d_previous_sample_counter; // ################## PLL ########################################################## // PLL discriminator diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h index f7d2141c9..161d87530 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.h @@ -182,17 +182,6 @@ private: double d_K_blk_samples_previous; int d_offset_sample_previous; - int d_kk = 0; - int d_numsamples_debug = 990; - int d_previous_sample_counter = 0; - int d_debug_sample_counter = 0; - int d_previous_counter_corr_0_in = 0; - int d_previous_counter_corr_0_out = 0; - int d_counter_corr_0_in_inc = 0; - int d_counter_corr_0_out_inc = 0; - int d_counter_corr_0_in = 0; - int d_counter_corr_0_out = 0; - int d_sample_counter_inc = 0; }; #endif //GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_SC_H From 2681ffab8175727a32f2f27a83dfb346f480ebe6 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Thu, 12 Apr 2018 18:46:55 +0200 Subject: [PATCH 10/19] Removing unused msg port --- .../gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc index b8a52b8c5..7f8a4233b 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc @@ -93,7 +93,6 @@ Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc( gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) { // Telemetry bit synchronization message port input - this->message_port_register_in(pmt::mp("preamble_timestamp_s")); this->message_port_register_out(pmt::mp("events")); // initialize internal vars From 1428630e79c32a4930f1f0dea72fc94bf71f8905 Mon Sep 17 00:00:00 2001 From: Antonio Ramos Date: Fri, 13 Apr 2018 15:27:14 +0200 Subject: [PATCH 11/19] Add RX time counter --- src/algorithms/libs/CMakeLists.txt | 67 ++-- src/algorithms/libs/gnss_sdr_time_counter.cc | 126 ++++++++ src/algorithms/libs/gnss_sdr_time_counter.h | 65 ++++ src/core/receiver/gnss_flowgraph.cc | 311 ++++++++++--------- src/core/receiver/gnss_flowgraph.h | 6 + 5 files changed, 412 insertions(+), 163 deletions(-) create mode 100644 src/algorithms/libs/gnss_sdr_time_counter.cc create mode 100644 src/algorithms/libs/gnss_sdr_time_counter.h diff --git a/src/algorithms/libs/CMakeLists.txt b/src/algorithms/libs/CMakeLists.txt index ac182801e..fd34bf693 100644 --- a/src/algorithms/libs/CMakeLists.txt +++ b/src/algorithms/libs/CMakeLists.txt @@ -18,27 +18,52 @@ add_subdirectory(rtklib) -set(GNSS_SPLIBS_SOURCES - gps_l2c_signal.cc - gps_l5_signal.cc - galileo_e1_signal_processing.cc - gnss_sdr_valve.cc - gnss_sdr_sample_counter.cc - gnss_signal_processing.cc - gps_sdr_signal_processing.cc - glonass_l1_signal_processing.cc - glonass_l2_signal_processing.cc - pass_through.cc - galileo_e5_signal_processing.cc - complex_byte_to_float_x2.cc - byte_x2_to_complex_byte.cc - cshort_to_float_x2.cc - short_x2_to_cshort.cc - complex_float_to_complex_byte.cc - conjugate_cc.cc - conjugate_sc.cc - conjugate_ic.cc -) +if(ENABLE_FPGA) + set(GNSS_SPLIBS_SOURCES + gps_l2c_signal.cc + gps_l5_signal.cc + galileo_e1_signal_processing.cc + gnss_sdr_valve.cc + gnss_sdr_sample_counter.cc + gnss_sdr_time_counter.cc + gnss_signal_processing.cc + gps_sdr_signal_processing.cc + glonass_l1_signal_processing.cc + glonass_l2_signal_processing.cc + pass_through.cc + galileo_e5_signal_processing.cc + complex_byte_to_float_x2.cc + byte_x2_to_complex_byte.cc + cshort_to_float_x2.cc + short_x2_to_cshort.cc + complex_float_to_complex_byte.cc + conjugate_cc.cc + conjugate_sc.cc + conjugate_ic.cc + ) +else(ENABLE_FPGA) + set(GNSS_SPLIBS_SOURCES + gps_l2c_signal.cc + gps_l5_signal.cc + galileo_e1_signal_processing.cc + gnss_sdr_valve.cc + gnss_sdr_sample_counter.cc + gnss_signal_processing.cc + gps_sdr_signal_processing.cc + glonass_l1_signal_processing.cc + glonass_l2_signal_processing.cc + pass_through.cc + galileo_e5_signal_processing.cc + complex_byte_to_float_x2.cc + byte_x2_to_complex_byte.cc + cshort_to_float_x2.cc + short_x2_to_cshort.cc + complex_float_to_complex_byte.cc + conjugate_cc.cc + conjugate_sc.cc + conjugate_ic.cc + ) +endif(ENABLE_FPGA) if(OPENCL_FOUND) set(GNSS_SPLIBS_SOURCES ${GNSS_SPLIBS_SOURCES} diff --git a/src/algorithms/libs/gnss_sdr_time_counter.cc b/src/algorithms/libs/gnss_sdr_time_counter.cc new file mode 100644 index 000000000..f94aadcab --- /dev/null +++ b/src/algorithms/libs/gnss_sdr_time_counter.cc @@ -0,0 +1,126 @@ +/*! + * \file gnss_sdr_time_counter.cc + * \brief Simple block to report the current receiver time based on the output of the tracking or telemetry blocks + * \author Antonio Ramos 2018. antonio.ramos(at)gmail.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (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 "gnss_sdr_time_counter.h" +#include "gnss_synchro.h" +#include +#include +#include +#include + +gnss_sdr_time_counter::gnss_sdr_time_counter() : gr::block("time_counter", + gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), + gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) +{ + set_max_noutput_items(1); + current_T_rx_ms = 0; + current_s = 0; + current_m = 0; + current_h = 0; + current_days = 0; + report_interval_ms = 1000; // default reporting 1 second + flag_m = false; + flag_h = false; + flag_days = false; +} + + +gnss_sdr_time_counter_sptr gnss_sdr_make_time_counter() +{ + gnss_sdr_time_counter_sptr counter_(new gnss_sdr_time_counter()); + return counter_; +} + + +int gnss_sdr_time_counter::general_work(int noutput_items __attribute__((unused)), + gr_vector_const_void_star &input_items __attribute__((unused)), + gr_vector_void_star &output_items) +{ + Gnss_Synchro *out = reinterpret_cast(output_items[0]); + const Gnss_Synchro *in = reinterpret_cast(input_items[0]); + out[0] = in[0]; + if ((current_T_rx_ms % report_interval_ms) == 0) + { + current_s++; + if ((current_s % 60) == 0) + { + current_s = 0; + current_m++; + flag_m = true; + if ((current_m % 60) == 0) + { + current_m = 0; + current_h++; + flag_h = true; + if ((current_h % 24) == 0) + { + current_h = 0; + current_days++; + flag_days = true; + } + } + } + + if (flag_days) + { + std::string day; + if (current_days == 1) + { + day = " day "; + } + else + { + day = " days "; + } + std::cout << "Current receiver time: " << current_days << day << current_h << " h " << current_m << " min " << current_s << " s" << std::endl; + } + else + { + if (flag_h) + { + std::cout << "Current receiver time: " << current_h << " h " << current_m << " min " << current_s << " s" << std::endl; + } + else + { + if (flag_m) + { + std::cout << "Current receiver time: " << current_m << " min " << current_s << " s" << std::endl; + } + else + { + std::cout << "Current receiver time: " << current_s << " s" << std::endl; + } + } + } + } + current_T_rx_ms++; + return 1; +} diff --git a/src/algorithms/libs/gnss_sdr_time_counter.h b/src/algorithms/libs/gnss_sdr_time_counter.h new file mode 100644 index 000000000..c0692252e --- /dev/null +++ b/src/algorithms/libs/gnss_sdr_time_counter.h @@ -0,0 +1,65 @@ +/*! + * \file gnss_sdr_time_counter.h + * \brief Simple block to report the current receiver time based on the output of the tracking or telemetry blocks + * \author Antonio Ramos 2018. antonio.ramosdet(at)gmail.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (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_TIME_COUNTER_H_ +#define GNSS_SDR_TIME_COUNTER_H_ + +#include +#include + + +class gnss_sdr_time_counter; + +typedef boost::shared_ptr gnss_sdr_time_counter_sptr; + +gnss_sdr_time_counter_sptr gnss_sdr_make_time_counter(); + +class gnss_sdr_time_counter : public gr::block +{ +private: + gnss_sdr_time_counter(); + long long int current_T_rx_ms; // Receiver time in ms since the beginning of the run + unsigned int current_s; // Receiver time in seconds, modulo 60 + bool flag_m; // True if the receiver has been running for at least 1 minute + unsigned int current_m; // Receiver time in minutes, modulo 60 + bool flag_h; // True if the receiver has been running for at least 1 hour + unsigned int current_h; // Receiver time in hours, modulo 24 + bool flag_days; // True if the receiver has been running for at least 1 day + unsigned int current_days; // Receiver time in days since the beginning of the run + int report_interval_ms; + +public: + friend gnss_sdr_time_counter_sptr gnss_sdr_make_time_counter(); + int general_work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /*GNSS_SDR_SAMPLE_COUNTER_H_*/ diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index 0c5a42f9c..67e9fc698 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -62,8 +62,6 @@ GNSSFlowgraph::GNSSFlowgraph(std::shared_ptr configurati GNSSFlowgraph::~GNSSFlowgraph() {} - - void GNSSFlowgraph::start() { if (running_) @@ -108,41 +106,41 @@ void GNSSFlowgraph::connect() } for (int i = 0; i < sources_count_; i++) - { - if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false)==false) { - try + if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false) == false) { - sig_source_.at(i)->connect(top_block_); - } - catch (const std::exception& e) - { - LOG(INFO) << "Can't connect signal source block " << i << " internally"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; + try + { + sig_source_.at(i)->connect(top_block_); + } + catch (const std::exception& e) + { + LOG(INFO) << "Can't connect signal source block " << i << " internally"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; + } } } - } // Signal Source > Signal conditioner > for (unsigned int i = 0; i < sig_conditioner_.size(); i++) - { - if (configuration_->property(sig_conditioner_.at(i)->role() + ".enable_FPGA", false)==false) { - try + if (configuration_->property(sig_conditioner_.at(i)->role() + ".enable_FPGA", false) == false) { - sig_conditioner_.at(i)->connect(top_block_); - } - catch (const std::exception& e) - { - LOG(INFO) << "Can't connect signal conditioner block " << i << " internally"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; + try + { + sig_conditioner_.at(i)->connect(top_block_); + } + catch (const std::exception& e) + { + LOG(INFO) << "Can't connect signal conditioner block " << i << " internally"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; + } } } - } for (unsigned int i = 0; i < channels_count_; i++) { @@ -191,144 +189,173 @@ void GNSSFlowgraph::connect() for (int i = 0; i < sources_count_; i++) { - //FPGA Accelerators do not need signal sources or conditioners - //as the samples are feed directly to the FPGA fabric, so, if enabled, do not connect any source - if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false)==false) - { - try + //FPGA Accelerators do not need signal sources or conditioners + //as the samples are feed directly to the FPGA fabric, so, if enabled, do not connect any source + if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false) == false) { - //TODO: Remove this array implementation and create generic multistream connector - //(if a signal source has more than 1 stream, then connect it to the multistream signal conditioner) - if (sig_source_.at(i)->implementation().compare("Raw_Array_Signal_Source") == 0) + try { - //Multichannel Array - std::cout << "ARRAY MODE" << std::endl; - for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++) + //TODO: Remove this array implementation and create generic multistream connector + //(if a signal source has more than 1 stream, then connect it to the multistream signal conditioner) + if (sig_source_.at(i)->implementation().compare("Raw_Array_Signal_Source") == 0) { - std::cout << "connecting ch " << j << std::endl; - top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j); - } - } - else - { - //TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. - //Include GetRFChannels in the interface to avoid read config parameters here - //read the number of RF channels for each front-end - RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1); - - for (int j = 0; j < RF_Channels; j++) - { - //Connect the multichannel signal source to multiple signal conditioners - // GNURADIO max_streams=-1 means infinite ports! - LOG(INFO) << "sig_source_.at(i)->get_right_block()->output_signature()->max_streams()=" << sig_source_.at(i)->get_right_block()->output_signature()->max_streams(); - LOG(INFO) << "sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()=" << sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->max_streams(); - - if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1) + //Multichannel Array + std::cout << "ARRAY MODE" << std::endl; + for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++) { - LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j; - top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); + std::cout << "connecting ch " << j << std::endl; + top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j); } - else + } + else + { + //TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. + //Include GetRFChannels in the interface to avoid read config parameters here + //read the number of RF channels for each front-end + RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1); + + for (int j = 0; j < RF_Channels; j++) { - if (j == 0) + //Connect the multichannel signal source to multiple signal conditioners + // GNURADIO max_streams=-1 means infinite ports! + LOG(INFO) << "sig_source_.at(i)->get_right_block()->output_signature()->max_streams()=" << sig_source_.at(i)->get_right_block()->output_signature()->max_streams(); + LOG(INFO) << "sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()=" << sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->max_streams(); + + if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1) { - // RF_channel 0 backward compatibility with single channel sources - LOG(INFO) << "connecting sig_source_ " << i << " stream " << 0 << " to conditioner " << j; - top_block_->connect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); + LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j; + top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); } else { - // Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call) - LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j; - top_block_->connect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); + if (j == 0) + { + // RF_channel 0 backward compatibility with single channel sources + LOG(INFO) << "connecting sig_source_ " << i << " stream " << 0 << " to conditioner " << j; + top_block_->connect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); + } + else + { + // Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call) + LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j; + top_block_->connect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); + } } + signal_conditioner_ID++; } - signal_conditioner_ID++; } } + catch (const std::exception& e) + { + LOG(WARNING) << "Can't connect signal source " << i << " to signal conditioner " << i; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; + } + } + } + DLOG(INFO) << "Signal source connected to signal conditioner"; + bool FPGA_enabled = configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false); + +#if ENABLE_FPGA + + if (FPGA_enabled == false) + { + //connect the signal source to sample counter + //connect the sample counter to Observables + try + { + double fs = static_cast(configuration_->property("GNSS-SDR.internal_fs_sps", 0)); + if (fs == 0.0) + { + LOG(WARNING) << "Set GNSS-SDR.internal_fs_sps in configuration file"; + std::cout << "Set GNSS-SDR.internal_fs_sps in configuration file" << std::endl; + throw(std::invalid_argument("Set GNSS-SDR.internal_fs_sps in configuration")); + } + ch_out_sample_counter = gnss_sdr_make_sample_counter(fs, sig_conditioner_.at(0)->get_right_block()->output_signature()->sizeof_stream_item(0)); + top_block_->connect(sig_conditioner_.at(0)->get_right_block(), 0, ch_out_sample_counter, 0); + top_block_->connect(ch_out_sample_counter, 0, observables_->get_left_block(), channels_count_); //extra port for the sample counter pulse } catch (const std::exception& e) { - LOG(WARNING) << "Can't connect signal source " << i << " to signal conditioner " << i; + LOG(WARNING) << "Can't connect sample counter"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; + } + } + else + { + //create a software-defined 1kHz gnss_synchro pulse for the observables block + try + { + //null source + null_source_ = gr::blocks::null_source::make(sizeof(Gnss_Synchro)); + //throttle 1kHz + throttle_ = gr::blocks::throttle::make(sizeof(Gnss_Synchro), 1000); // 1000 samples per second (1kHz) + time_counter_ = gnss_sdr_make_time_counter(); + top_block_->connect(null_source_, 0, throttle_, 0); + top_block_->connect(throttle_, 0, time_counter_, 0); + top_block_->connect(time_counter_, 0, observables_->get_left_block(), channels_count_); + } + catch (const std::exception& e) + { + LOG(WARNING) << "Can't connect sample counter"; LOG(ERROR) << e.what(); top_block_->disconnect_all(); return; } } - } - DLOG(INFO) << "Signal source connected to signal conditioner"; - bool FPGA_enabled = configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false); +#else - if (FPGA_enabled==false) - { - //connect the signal source to sample counter - //connect the sample counter to Observables - try - { - double fs = static_cast(configuration_->property("GNSS-SDR.internal_fs_sps", 0)); - if (fs == 0.0) - { - LOG(WARNING) << "Set GNSS-SDR.internal_fs_sps in configuration file"; - std::cout << "Set GNSS-SDR.internal_fs_sps in configuration file" << std::endl; - throw(std::invalid_argument("Set GNSS-SDR.internal_fs_sps in configuration")); - } - ch_out_sample_counter = gnss_sdr_make_sample_counter(fs, sig_conditioner_.at(0)->get_right_block()->output_signature()->sizeof_stream_item(0)); - top_block_->connect(sig_conditioner_.at(0)->get_right_block(), 0, ch_out_sample_counter, 0); - top_block_->connect(ch_out_sample_counter, 0, observables_->get_left_block(), channels_count_); //extra port for the sample counter pulse - } - catch (const std::exception& e) - { - LOG(WARNING) << "Can't connect sample counter"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; - } - }else{ - //create a software-defined 1kHz gnss_synchro pulse for the observables block - try - { - //null source - null_source_= gr::blocks::null_source::make(sizeof(Gnss_Synchro)); - //throttle 1kHz - throttle_ = gr::blocks::throttle::make(sizeof(Gnss_Synchro),1000);// 1000 samples per second (1kHz) - top_block_->connect(null_source_, 0, throttle_, 0); - top_block_->connect(throttle_, 0, observables_->get_left_block(), channels_count_); //extra port for the sample counter pulse + //connect the signal source to sample counter + //connect the sample counter to Observables + try + { + double fs = static_cast(configuration_->property("GNSS-SDR.internal_fs_sps", 0)); + if (fs == 0.0) + { + LOG(WARNING) << "Set GNSS-SDR.internal_fs_sps in configuration file"; + std::cout << "Set GNSS-SDR.internal_fs_sps in configuration file" << std::endl; + throw(std::invalid_argument("Set GNSS-SDR.internal_fs_sps in configuration")); + } + ch_out_sample_counter = gnss_sdr_make_sample_counter(fs, sig_conditioner_.at(0)->get_right_block()->output_signature()->sizeof_stream_item(0)); + top_block_->connect(sig_conditioner_.at(0)->get_right_block(), 0, ch_out_sample_counter, 0); + top_block_->connect(ch_out_sample_counter, 0, observables_->get_left_block(), channels_count_); //extra port for the sample counter pulse + } + catch (const std::exception& e) + { + LOG(WARNING) << "Can't connect sample counter"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; + } - } - catch (const std::exception& e) - { - LOG(WARNING) << "Can't connect sample counter"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; - } - } +#endif // Signal conditioner (selected_signal_source) >> channels (i) (dependent of their associated SignalSource_ID) int selected_signal_conditioner_ID; for (unsigned int i = 0; i < channels_count_; i++) { - - - if (FPGA_enabled == false) - { - selected_signal_conditioner_ID = configuration_->property("Channel" + boost::lexical_cast(i) + ".RF_channel_ID", 0); - try + if (FPGA_enabled == false) { - top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, - channels_.at(i)->get_left_block(), 0); - } - catch (const std::exception& e) - { - LOG(WARNING) << "Can't connect signal conditioner " << selected_signal_conditioner_ID << " to channel " << i; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; - } + selected_signal_conditioner_ID = configuration_->property("Channel" + boost::lexical_cast(i) + ".RF_channel_ID", 0); + try + { + top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, + channels_.at(i)->get_left_block(), 0); + } + catch (const std::exception& e) + { + LOG(WARNING) << "Can't connect signal conditioner " << selected_signal_conditioner_ID << " to channel " << i; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; + } - DLOG(INFO) << "signal conditioner " << selected_signal_conditioner_ID << " connected to channel " << i; - } + DLOG(INFO) << "signal conditioner " << selected_signal_conditioner_ID << " connected to channel " << i; + } // Signal Source > Signal conditioner >> Channels >> Observables try { @@ -348,10 +375,10 @@ void GNSSFlowgraph::connect() if (channels_state_[i] == 1) { - if (FPGA_enabled == false) - { - channels_.at(i)->start_acquisition(); - } + if (FPGA_enabled == false) + { + channels_.at(i)->start_acquisition(); + } available_GNSS_signals_.pop_front(); LOG(INFO) << "Channel " << i << " assigned to " << channels_.at(i)->get_signal(); LOG(INFO) << "Channel " << i << " connected to observables and ready for acquisition"; @@ -491,12 +518,12 @@ void GNSSFlowgraph::set_configuration(std::shared_ptr co void GNSSFlowgraph::start_acquisition_helper() { for (unsigned int i = 0; i < channels_count_; i++) - { - if (channels_state_[i] == 1) - { - channels_.at(i)->start_acquisition(); - } - } + { + if (channels_state_[i] == 1) + { + channels_.at(i)->start_acquisition(); + } + } } void GNSSFlowgraph::init() diff --git a/src/core/receiver/gnss_flowgraph.h b/src/core/receiver/gnss_flowgraph.h index 84a426920..d2d95dc29 100644 --- a/src/core/receiver/gnss_flowgraph.h +++ b/src/core/receiver/gnss_flowgraph.h @@ -49,6 +49,9 @@ #include #include +#if ENABLE_FPGA +#include "gnss_sdr_time_counter.h" +#endif class GNSSBlockInterface; class ChannelInterface; @@ -144,6 +147,9 @@ private: std::vector> channels_; gnss_sdr_sample_counter_sptr ch_out_sample_counter; +#if ENABLE_FPGA + gnss_sdr_time_counter_sptr time_counter_; +#endif gr::blocks::null_source::sptr null_source_; gr::blocks::throttle::sptr throttle_; gr::top_block_sptr top_block_; From ab534e77911275f86370663bdb72c0b88a06c423 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 13 Apr 2018 18:31:35 +0200 Subject: [PATCH 12/19] Fix build bug --- src/algorithms/signal_source/libs/CMakeLists.txt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/algorithms/signal_source/libs/CMakeLists.txt b/src/algorithms/signal_source/libs/CMakeLists.txt index 5617be70a..10fdd0d4c 100644 --- a/src/algorithms/signal_source/libs/CMakeLists.txt +++ b/src/algorithms/signal_source/libs/CMakeLists.txt @@ -53,13 +53,12 @@ if(ENABLE_FMCOMMS2 OR ENABLE_AD9361) endif(ENABLE_FMCOMMS2 OR ENABLE_AD9361) -set (SIGNAL_SOURCE_LIB_SOURCES - rtl_tcp_commands.cc - rtl_tcp_dongle_info.cc - ${OPT_SIGNAL_SOURCE_LIB_SOURCES}) +if(ENABLE_AD9361) + set(OPT_SIGNAL_SOURCE_LIB_SOURCES ad9361_manager.cc) +endif(ENABLE_AD9361) if(ENABLE_FPGA) - SET(SIGNAL_SOURCE_LIB_SOURCES ${SIGNAL_SOURCE_LIB_SOURCES} fpga_switch.cc) + SET(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_switch.cc) endif(ENABLE_FPGA) include_directories( @@ -68,6 +67,10 @@ include_directories( ${OPT_DRIVER_INCLUDE_DIRS} ) +set (SIGNAL_SOURCE_LIB_SOURCES + rtl_tcp_commands.cc + rtl_tcp_dongle_info.cc + ${OPT_SIGNAL_SOURCE_LIB_SOURCES}) file(GLOB SIGNAL_SOURCE_LIB_HEADERS "*.h") list(SORT SIGNAL_SOURCE_LIB_HEADERS) From 6a3770c7629e2cd92f9d3694ec7262e0453e5ece Mon Sep 17 00:00:00 2001 From: mmajoral Date: Thu, 19 Apr 2018 12:09:08 +0200 Subject: [PATCH 13/19] - set output vectors is only done in the class constructor, no need to do it continuously - no need to multiply by two the results of the multicorrelator HW accelerators --- .../gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc | 3 ++- src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc index 7f8a4233b..069b426db 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_fpga_sc.cc @@ -172,6 +172,8 @@ Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc( d_carrier_phase_step_rad = 0.0; set_relative_rate(1.0 / static_cast(d_vector_length)); + + multicorrelator_fpga_8sc->set_output_vectors(d_correlator_outs); } void Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::start_tracking() @@ -320,7 +322,6 @@ int Gps_L1_Ca_Dll_Pll_Tracking_fpga_sc::general_work (int noutput_items __attrib // ################# CARRIER WIPEOFF AND CORRELATORS ############################## // perform carrier wipe-off and compute Early, Prompt and Late correlation - multicorrelator_fpga_8sc->set_output_vectors(d_correlator_outs); multicorrelator_fpga_8sc->Carrier_wipeoff_multicorrelator_resampler( d_rem_carr_phase_rad, d_carrier_phase_step_rad, d_rem_code_phase_chips, d_code_phase_step_chips, diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc index dba1da094..9c9e6af0b 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc @@ -403,14 +403,12 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void) { readval_real = -2097152 + readval_real; } - readval_real = readval_real * 2; // the results are shifted two bits to the left due to the complex multiplier in the FPGA readval_imag = d_map_base[1 + d_n_correlators + k]; if (readval_imag >= 1048576) // 0x100000 (21 bits two's complement) { readval_imag = -2097152 + readval_imag; } - readval_imag = readval_imag * 2; // the results are shifted two bits to the left due to the complex multiplier in the FPGA d_corr_out[k] = gr_complex(readval_real,readval_imag); } } From 512bf3f4cf9d0925953520d664f1266c25263293 Mon Sep 17 00:00:00 2001 From: mmajoral Date: Fri, 27 Apr 2018 20:00:50 +0200 Subject: [PATCH 14/19] Created a generic gnuradio block acquisition class for the FPGA. --- .../gps_l1_ca_pcps_acquisition_fpga.cc | 236 +++++++------- .../gps_l1_ca_pcps_acquisition_fpga.h | 41 +-- .../gnuradio_blocks/CMakeLists.txt | 2 +- .../gps_pcps_acquisition_fpga_sc.cc | 298 ------------------ .../gps_pcps_acquisition_fpga_sc.h | 219 ------------- .../gnuradio_blocks/pcps_acquisition_fpga.cc | 247 +++++++++++++++ .../gnuradio_blocks/pcps_acquisition_fpga.h | 216 +++++++++++++ .../acquisition/libs/CMakeLists.txt | 2 +- ...acquisition_8sc.cc => fpga_acquisition.cc} | 140 +++----- ...a_acquisition_8sc.h => fpga_acquisition.h} | 33 +- 10 files changed, 655 insertions(+), 779 deletions(-) delete mode 100644 src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc delete mode 100644 src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h create mode 100644 src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc create mode 100644 src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h rename src/algorithms/acquisition/libs/{gps_fpga_acquisition_8sc.cc => fpga_acquisition.cc} (55%) rename src/algorithms/acquisition/libs/{gps_fpga_acquisition_8sc.h => fpga_acquisition.h} (78%) 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). - *
    - *
  1. Compute the input signal power estimation - *
  2. Doppler serial search loop - *
  3. Perform the FFT-based circular convolution (parallel time search) - *
  4. Record the maximum peak and the associated synchronization parameters - *
  5. Compute the test statistics and compare to the threshold - *
  6. 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). + *
    + *
  1. Compute the input signal power estimation + *
  2. Doppler serial search loop + *
  3. Perform the FFT-based circular convolution (parallel time search) + *
  4. Record the maximum peak and the associated synchronization parameters + *
  5. Compute the test statistics and compare to the threshold + *
  6. 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_ */ From 627848458eb3ec65a15184b6b5adf61b3f41f03f Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 29 Apr 2018 19:23:46 +0200 Subject: [PATCH 15/19] Remove unused variable --- src/core/receiver/gnss_flowgraph.cc | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index 3303d15b6..532aaaf15 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -772,15 +772,6 @@ void GNSSFlowgraph::set_signals_list() // Set a sequential list of GNSS satellites std::set::const_iterator available_gnss_prn_iter; - // Read GNSS systems and signals - unsigned int total_channels = configuration_->property("Channels_1C.count", 0) + - configuration_->property("Channels_1B.count", 0) + - configuration_->property("Channels_1G.count", 0) + - configuration_->property("Channels_2S.count", 0) + - configuration_->property("Channels_2G.count", 0) + - configuration_->property("Channels_5X.count", 0) + - configuration_->property("Channels_L5.count", 0); - // Create the lists of GNSS satellites std::set available_gps_prn = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, From 4433c0c6bea86801c857a7503425a88c2341388a Mon Sep 17 00:00:00 2001 From: mmajoral Date: Mon, 30 Apr 2018 11:59:56 +0200 Subject: [PATCH 16/19] Minor code cleaning. --- .../gps_l1_ca_pcps_acquisition_fpga.cc | 40 +++++++++---------- .../gps_l1_ca_pcps_acquisition_fpga.h | 9 +---- .../gnuradio_blocks/pcps_acquisition_fpga.cc | 13 +++--- .../gnuradio_blocks/pcps_acquisition_fpga.h | 7 +--- .../acquisition/libs/fpga_acquisition.cc | 37 +++++++++++------ 5 files changed, 52 insertions(+), 54 deletions(-) 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 f585fdbc0..455fac062 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,4 +1,3 @@ - /*! * \file gps_l1_ca_pcps_acquisition_fpga.cc * \brief Adapts a PCPS acquisition block to an FPGA AcquisitionInterface @@ -59,21 +58,21 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( DLOG(INFO) << "role " << role; 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_; + long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + acq_parameters.fs_in = fs_in; + long ifreq = configuration_->property(role + ".if", 0); + acq_parameters.freq = ifreq; doppler_max_ = configuration_->property(role + ".doppler_max", 5000); 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))); + unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1); + acq_parameters.sampled_ms = sampled_ms; + unsigned int 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_)); + float nbits = ceilf(log2f((float) code_length)); unsigned int nsamples_total = pow(2, nbits); - vector_length_ = nsamples_total * sampled_ms_; + unsigned int 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"; @@ -85,20 +84,18 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( // 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 + gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT + // 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 + 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 + gps_l1_ca_code_gen_complex_sampled(code, PRN, fs_in, 0); // generate PRN code // fill in zero padding - for (int s=code_length_;s(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), + 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 + + acq_parameters.all_fft_codes = d_all_fft_codes_; + // temporary buffers that we can delete delete[] code; delete fft_if; @@ -144,8 +143,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( GpsL1CaPcpsAcquisitionFpga::~GpsL1CaPcpsAcquisitionFpga() { - //delete[] code_; - delete[] d_all_fft_codes; + delete[] d_all_fft_codes_; } 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 d65e677e7..642e9bf8e 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 @@ -37,10 +37,10 @@ #ifndef GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ #define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ +#include #include "acquisition_interface.h" #include "gnss_synchro.h" #include "pcps_acquisition_fpga.h" -#include class ConfigurationInterface; @@ -137,19 +137,14 @@ public: private: ConfigurationInterface* configuration_; pcps_acquisition_fpga_sptr acquisition_fpga_; - unsigned int vector_length_; - unsigned int code_length_; unsigned int channel_; unsigned int doppler_max_; unsigned int doppler_step_; - 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 + lv_16sc_t *d_all_fft_codes_; // memory that contains all the code ffts }; diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc index 4f21ffa7a..6a337925e 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc @@ -38,11 +38,10 @@ * ------------------------------------------------------------------------- */ -#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 +#include "pcps_acquisition_fpga.h" using google::LogMessage; @@ -175,12 +174,10 @@ void pcps_acquisition_fpga::set_active(bool 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 @@ -208,9 +205,9 @@ void pcps_acquisition_fpga::set_active(bool active) { 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); + input_power_all = d_input_power / (d_fft_size - 1); + input_power_computed = (d_input_power - d_mag) / (d_fft_size - 1); + d_input_power = (d_input_power - d_mag) / (d_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); diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h index d140f538c..3014a278a 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h @@ -56,9 +56,10 @@ #ifndef GNSS_SDR_PCPS_ACQUISITION_FPGA_H_ #define GNSS_SDR_PCPS_ACQUISITION_FPGA_H_ -#include "gnss_synchro.h" + #include #include "fpga_acquisition.h" +#include "gnss_synchro.h" typedef struct { @@ -69,10 +70,8 @@ typedef struct 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; @@ -118,8 +117,6 @@ private: Gnss_Synchro* d_gnss_synchro; std::shared_ptr acquisition_fpga; - - public: ~pcps_acquisition_fpga(); diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.cc b/src/algorithms/acquisition/libs/fpga_acquisition.cc index 213183ba5..82f22e050 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.cc +++ b/src/algorithms/acquisition/libs/fpga_acquisition.cc @@ -33,9 +33,6 @@ * ------------------------------------------------------------------------- */ -#include "fpga_acquisition.h" -#include "gps_sdr_signal_processing.h" - // libraries used by the GIPO #include #include @@ -46,9 +43,23 @@ // GPS L1 #include "GPS_L1_CA.h" -#define PAGE_SIZE 0x10000 -#define MAX_PHASE_STEP_RAD 0.999999999534339 // 1 - pow(2,-31); -#define TEST_REG_SANITY_CHECK 0x55AA +#include "fpga_acquisition.h" +#include "gps_sdr_signal_processing.h" + +#define PAGE_SIZE 0x10000 // default page size for the multicorrelator memory map +#define MAX_PHASE_STEP_RAD 0.999999999534339 // 1 - pow(2,-31); +#define RESET_ACQUISITION 2 // command to reset the multicorrelator +#define LAUNCH_ACQUISITION 1 // command to launch the multicorrelator +#define TEST_REG_SANITY_CHECK 0x55AA // value to check the presence of the test register (to detect the hw) +#define LOCAL_CODE_CLEAR_MEM 0x10000000 // command to clear the internal memory of the multicorrelator +#define MEM_LOCAL_CODE_WR_ENABLE 0x0C000000 // command to enable the ENA and WR pins of the internal memory of the multicorrelator +#define POW_2_2 4 // 2^2 (used for the conversion of floating point numbers to integers) +#define POW_2_29 536870912 // 2^29 (used for the conversion of floating point numbers to integers) +#define SELECT_LSB 0x00FF // value to select the least significant byte +#define SELECT_MSB 0XFF00 // value to select the most significant byte +#define SELECT_16_BITS 0xFFFF // value to select 16 bits +#define SHL_8_BITS 256 // value used to shift a value 8 bits to the left + bool fpga_acquisition::init() { @@ -144,14 +155,14 @@ void fpga_acquisition::fpga_configure_acquisition_local_code(lv_16sc_t fft_local unsigned int k, tmp, tmp2; unsigned int fft_data; // clear memory address counter - d_map_base[4] = 0x10000000; + d_map_base[4] = LOCAL_CODE_CLEAR_MEM; // write local code for (k = 0; k < d_vector_length; k++) { tmp = fft_local_code[k].real(); tmp2 = fft_local_code[k].imag(); - local_code = (tmp & 0xFF) | ((tmp2 * 256) & 0xFF00); // put together the real part and the imaginary part - fft_data = 0x0C000000 | (local_code & 0xFFFF); + local_code = (tmp & SELECT_LSB) | ((tmp2 * SHL_8_BITS) & SELECT_MSB); // put together the real part and the imaginary part + fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_16_BITS); d_map_base[4] = fft_data; } } @@ -162,7 +173,7 @@ void fpga_acquisition::run_acquisition(void) int reenable = 1; write(d_fd, reinterpret_cast(&reenable), sizeof(int)); // launch the acquisition process - d_map_base[6] = 1; // writing anything to reg 6 launches the acquisition process + d_map_base[6] = LAUNCH_ACQUISITION; // writing anything to reg 6 launches the acquisition process int irq_count; ssize_t nb; @@ -201,8 +212,8 @@ void fpga_acquisition::set_phase_step(unsigned int doppler_index) { phase_step_rad_real = MAX_PHASE_STEP_RAD; } - phase_step_rad_int_temp = phase_step_rad_real * 4; // * 2^2 - phase_step_rad_int = (int32_t) (phase_step_rad_int_temp * (536870912)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings + phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2 + phase_step_rad_int = (int32_t) (phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings d_map_base[3] = phase_step_rad_int; } @@ -243,5 +254,5 @@ void fpga_acquisition::close_device() void fpga_acquisition::reset_acquisition(void) { - d_map_base[6] = 2; // writing a 2 to d_map_base[6] resets the multicorrelator + d_map_base[6] = RESET_ACQUISITION; // writing a 2 to d_map_base[6] resets the multicorrelator } From bd8133020183b8790e3221da6093b6d9ef224656 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Mon, 30 Apr 2018 19:53:20 +0200 Subject: [PATCH 17/19] Apply code formatting --- src/algorithms/libs/CMakeLists.txt | 146 ++++++------- .../signal_source/libs/CMakeLists.txt | 7 +- .../signal_source/libs/fpga_switch.cc | 17 +- .../signal_source/libs/fpga_switch.h | 9 +- .../tracking/libs/fpga_multicorrelator_8sc.cc | 143 ++++++------ .../tracking/libs/fpga_multicorrelator_8sc.h | 48 ++-- .../gps_l1_ca_dll_pll_tracking_test_fpga.cc | 206 +++++++++--------- 7 files changed, 281 insertions(+), 295 deletions(-) diff --git a/src/algorithms/libs/CMakeLists.txt b/src/algorithms/libs/CMakeLists.txt index fd34bf693..6a3924e19 100644 --- a/src/algorithms/libs/CMakeLists.txt +++ b/src/algorithms/libs/CMakeLists.txt @@ -19,81 +19,81 @@ add_subdirectory(rtklib) if(ENABLE_FPGA) - set(GNSS_SPLIBS_SOURCES - gps_l2c_signal.cc - gps_l5_signal.cc - galileo_e1_signal_processing.cc - gnss_sdr_valve.cc - gnss_sdr_sample_counter.cc - gnss_sdr_time_counter.cc - gnss_signal_processing.cc - gps_sdr_signal_processing.cc - glonass_l1_signal_processing.cc - glonass_l2_signal_processing.cc - pass_through.cc - galileo_e5_signal_processing.cc - complex_byte_to_float_x2.cc - byte_x2_to_complex_byte.cc - cshort_to_float_x2.cc - short_x2_to_cshort.cc - complex_float_to_complex_byte.cc - conjugate_cc.cc - conjugate_sc.cc - conjugate_ic.cc + set(GNSS_SPLIBS_SOURCES + gps_l2c_signal.cc + gps_l5_signal.cc + galileo_e1_signal_processing.cc + gnss_sdr_valve.cc + gnss_sdr_sample_counter.cc + gnss_sdr_time_counter.cc + gnss_signal_processing.cc + gps_sdr_signal_processing.cc + glonass_l1_signal_processing.cc + glonass_l2_signal_processing.cc + pass_through.cc + galileo_e5_signal_processing.cc + complex_byte_to_float_x2.cc + byte_x2_to_complex_byte.cc + cshort_to_float_x2.cc + short_x2_to_cshort.cc + complex_float_to_complex_byte.cc + conjugate_cc.cc + conjugate_sc.cc + conjugate_ic.cc ) else(ENABLE_FPGA) set(GNSS_SPLIBS_SOURCES - gps_l2c_signal.cc - gps_l5_signal.cc - galileo_e1_signal_processing.cc - gnss_sdr_valve.cc - gnss_sdr_sample_counter.cc - gnss_signal_processing.cc - gps_sdr_signal_processing.cc - glonass_l1_signal_processing.cc - glonass_l2_signal_processing.cc - pass_through.cc - galileo_e5_signal_processing.cc - complex_byte_to_float_x2.cc - byte_x2_to_complex_byte.cc - cshort_to_float_x2.cc - short_x2_to_cshort.cc - complex_float_to_complex_byte.cc - conjugate_cc.cc - conjugate_sc.cc - conjugate_ic.cc - ) + gps_l2c_signal.cc + gps_l5_signal.cc + galileo_e1_signal_processing.cc + gnss_sdr_valve.cc + gnss_sdr_sample_counter.cc + gnss_signal_processing.cc + gps_sdr_signal_processing.cc + glonass_l1_signal_processing.cc + glonass_l2_signal_processing.cc + pass_through.cc + galileo_e5_signal_processing.cc + complex_byte_to_float_x2.cc + byte_x2_to_complex_byte.cc + cshort_to_float_x2.cc + short_x2_to_cshort.cc + complex_float_to_complex_byte.cc + conjugate_cc.cc + conjugate_sc.cc + conjugate_ic.cc + ) endif(ENABLE_FPGA) if(OPENCL_FOUND) - set(GNSS_SPLIBS_SOURCES ${GNSS_SPLIBS_SOURCES} - opencl/fft_execute.cc # Needs OpenCL - opencl/fft_setup.cc # Needs OpenCL - opencl/fft_kernelstring.cc # Needs OpenCL - ) + set(GNSS_SPLIBS_SOURCES ${GNSS_SPLIBS_SOURCES} + opencl/fft_execute.cc # Needs OpenCL + opencl/fft_setup.cc # Needs OpenCL + opencl/fft_kernelstring.cc # Needs OpenCL + ) endif(OPENCL_FOUND) include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR}/src/core/system_parameters - ${CMAKE_SOURCE_DIR}/src/core/receiver - ${CMAKE_SOURCE_DIR}/src/core/interfaces - ${Boost_INCLUDE_DIRS} - ${GLOG_INCLUDE_DIRS} - ${GFlags_INCLUDE_DIRS} - ${GNURADIO_RUNTIME_INCLUDE_DIRS} - ${GNURADIO_BLOCKS_INCLUDE_DIRS} - ${VOLK_INCLUDE_DIRS} - ${VOLK_GNSSSDR_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/src/core/system_parameters + ${CMAKE_SOURCE_DIR}/src/core/receiver + ${CMAKE_SOURCE_DIR}/src/core/interfaces + ${Boost_INCLUDE_DIRS} + ${GLOG_INCLUDE_DIRS} + ${GFlags_INCLUDE_DIRS} + ${GNURADIO_RUNTIME_INCLUDE_DIRS} + ${GNURADIO_BLOCKS_INCLUDE_DIRS} + ${VOLK_INCLUDE_DIRS} + ${VOLK_GNSSSDR_INCLUDE_DIRS} ) if(OPENCL_FOUND) - include_directories( ${OPENCL_INCLUDE_DIRS} ) - if(OS_IS_MACOSX) - set(OPT_LIBRARIES ${OPT_LIBRARIES} "-framework OpenCL") - else(OS_IS_MACOSX) - set(OPT_LIBRARIES ${OPT_LIBRARIES} ${OPENCL_LIBRARIES}) - endif(OS_IS_MACOSX) + include_directories( ${OPENCL_INCLUDE_DIRS} ) + if(OS_IS_MACOSX) + set(OPT_LIBRARIES ${OPT_LIBRARIES} "-framework OpenCL") + else(OS_IS_MACOSX) + set(OPT_LIBRARIES ${OPT_LIBRARIES} ${OPENCL_LIBRARIES}) + endif(OS_IS_MACOSX) endif(OPENCL_FOUND) add_definitions(-DGNSSSDR_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}") @@ -105,18 +105,18 @@ add_library(gnss_sp_libs ${GNSS_SPLIBS_SOURCES} ${GNSS_SPLIBS_HEADERS}) source_group(Headers FILES ${GNSS_SPLIBS_HEADERS}) target_link_libraries(gnss_sp_libs ${GNURADIO_RUNTIME_LIBRARIES} - ${VOLK_LIBRARIES} ${ORC_LIBRARIES} - ${VOLK_GNSSSDR_LIBRARIES} ${ORC_LIBRARIES} - ${GFlags_LIBS} - ${GNURADIO_BLOCKS_LIBRARIES} - ${GNURADIO_FFT_LIBRARIES} - ${GNURADIO_FILTER_LIBRARIES} - ${OPT_LIBRARIES} - gnss_rx + ${VOLK_LIBRARIES} ${ORC_LIBRARIES} + ${VOLK_GNSSSDR_LIBRARIES} ${ORC_LIBRARIES} + ${GFlags_LIBS} + ${GNURADIO_BLOCKS_LIBRARIES} + ${GNURADIO_FFT_LIBRARIES} + ${GNURADIO_FILTER_LIBRARIES} + ${OPT_LIBRARIES} + gnss_rx ) if(NOT VOLK_GNSSSDR_FOUND) - add_dependencies(gnss_sp_libs volk_gnsssdr_module) + add_dependencies(gnss_sp_libs volk_gnsssdr_module) endif(NOT VOLK_GNSSSDR_FOUND) if(${GFLAGS_GREATER_20}) @@ -125,4 +125,4 @@ endif(${GFLAGS_GREATER_20}) add_library(gnss_sdr_flags gnss_sdr_flags.cc gnss_sdr_flags.h) source_group(Headers FILES gnss_sdr_flags.h) -target_link_libraries(gnss_sdr_flags ${GFlags_LIBS}) \ No newline at end of file +target_link_libraries(gnss_sdr_flags ${GFlags_LIBS}) diff --git a/src/algorithms/signal_source/libs/CMakeLists.txt b/src/algorithms/signal_source/libs/CMakeLists.txt index 10fdd0d4c..c8f676b49 100644 --- a/src/algorithms/signal_source/libs/CMakeLists.txt +++ b/src/algorithms/signal_source/libs/CMakeLists.txt @@ -28,7 +28,7 @@ if(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) endif(NOT IIO_FOUND) set(OPT_LIBRARIES ${OPT_LIBRARIES} ${IIO_LIBRARIES}) set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) - + endif(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) if(ENABLE_FMCOMMS2 OR ENABLE_AD9361) @@ -43,14 +43,14 @@ if(ENABLE_FMCOMMS2 OR ENABLE_AD9361) endif(NOT LIBIIO_FOUND) set(OPT_LIBRARIES ${OPT_LIBRARIES} ${LIBIIO_LIBRARIES}) set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${LIBIIO_INCLUDE_DIRS}) - + ############################################### # FMCOMMS2 based SDR Hardware ############################################### if(IIO_FOUND) set(OPT_SIGNAL_SOURCE_LIB_SOURCES ad9361_manager.cc) endif(IIO_FOUND) - + endif(ENABLE_FMCOMMS2 OR ENABLE_AD9361) if(ENABLE_AD9361) @@ -78,4 +78,3 @@ add_library(signal_source_lib ${SIGNAL_SOURCE_LIB_SOURCES} ${SIGNAL_SOURCE_LIB_H source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS}) target_link_libraries(signal_source_lib ${OPT_LIBRARIES}) - diff --git a/src/algorithms/signal_source/libs/fpga_switch.cc b/src/algorithms/signal_source/libs/fpga_switch.cc index e349a3c53..aae7da979 100644 --- a/src/algorithms/signal_source/libs/fpga_switch.cc +++ b/src/algorithms/signal_source/libs/fpga_switch.cc @@ -35,7 +35,6 @@ */ #include "fpga_switch.h" - #include // FPGA stuff @@ -76,9 +75,9 @@ fpga_switch::fpga_switch(std::string device_name) printf("switch memory successfully mapped\n"); } d_map_base = reinterpret_cast(mmap(NULL, PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0)); + PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0)); - if (d_map_base == reinterpret_cast(-1)) + if (d_map_base == reinterpret_cast(-1)) { LOG(WARNING) << "Cannot map the FPGA switch module into tracking memory"; printf("could not map switch memory\n"); @@ -100,18 +99,21 @@ fpga_switch::fpga_switch(std::string device_name) DLOG(INFO) << "Switch FPGA class created"; } + fpga_switch::~fpga_switch() { close_device(); } + void fpga_switch::set_switch_position(int switch_position) { d_map_base[0] = switch_position; } + unsigned fpga_switch::fpga_switch_test_register( - unsigned writeval) + unsigned writeval) { unsigned readval; // write value to test register @@ -122,15 +124,14 @@ unsigned fpga_switch::fpga_switch_test_register( return readval; } + void fpga_switch::close_device() { - unsigned * aux = const_cast(d_map_base); - if (munmap(static_cast(aux), PAGE_SIZE) == -1) + unsigned *aux = const_cast(d_map_base); + if (munmap(static_cast(aux), PAGE_SIZE) == -1) { printf("Failed to unmap memory uio\n"); } close(d_device_descriptor); } - - diff --git a/src/algorithms/signal_source/libs/fpga_switch.h b/src/algorithms/signal_source/libs/fpga_switch.h index c3ce2fbba..395aff425 100644 --- a/src/algorithms/signal_source/libs/fpga_switch.h +++ b/src/algorithms/signal_source/libs/fpga_switch.h @@ -47,15 +47,14 @@ public: fpga_switch(std::string device_name); ~fpga_switch(); void set_switch_position(int switch_position); - + private: - int d_device_descriptor; // driver descriptor - volatile unsigned *d_map_base; // driver memory map + int d_device_descriptor; // driver descriptor + volatile unsigned *d_map_base; // driver memory map // private functions unsigned fpga_switch_test_register(unsigned writeval); - void close_device(void); - + void close_device(void); }; #endif /* GNSS_SDR_FPGA_SWITCH_H_ */ diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc index 9c9e6af0b..737e414d9 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc @@ -35,9 +35,7 @@ */ #include "fpga_multicorrelator_8sc.h" - #include - // FPGA stuff #include @@ -65,7 +63,7 @@ #include // constants -#include "GPS_L1_CA.h" +#include "GPS_L1_CA.h" #include "gps_sdr_signal_processing.h" @@ -75,7 +73,7 @@ #define CODE_RESAMPLER_NUM_BITS_PRECISION 20 #define CODE_PHASE_STEP_CHIPS_NUM_NBITS CODE_RESAMPLER_NUM_BITS_PRECISION #define pwrtwo(x) (1 << (x)) -#define MAX_CODE_RESAMPLER_COUNTER pwrtwo(CODE_PHASE_STEP_CHIPS_NUM_NBITS) // 2^CODE_PHASE_STEP_CHIPS_NUM_NBITS +#define MAX_CODE_RESAMPLER_COUNTER pwrtwo(CODE_PHASE_STEP_CHIPS_NUM_NBITS) // 2^CODE_PHASE_STEP_CHIPS_NUM_NBITS #define PHASE_CARR_NBITS 32 #define PHASE_CARR_NBITS_INT 1 #define PHASE_CARR_NBITS_FRAC PHASE_CARR_NBITS - PHASE_CARR_NBITS_INT @@ -86,7 +84,7 @@ int fpga_multicorrelator_8sc::read_sample_counter() { - return d_map_base[7]; + return d_map_base[7]; } void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset) @@ -94,17 +92,16 @@ void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset) d_initial_sample_counter = samples_offset; d_map_base[13] = d_initial_sample_counter; } - -void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, - float *shifts_chips, int PRN) -{ +void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, + float *shifts_chips, int PRN) +{ d_shifts_chips = shifts_chips; d_code_length_chips = code_length_chips; fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN); } -void fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out) +void fpga_multicorrelator_8sc::set_output_vectors(gr_complex *corr_out) { d_corr_out = corr_out; } @@ -116,21 +113,18 @@ void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips) fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(); } - void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( - float rem_carrier_phase_in_rad, float phase_step_rad, - float rem_code_phase_chips, float code_phase_step_chips, - int signal_length_samples) + float rem_carrier_phase_in_rad, float phase_step_rad, + float rem_code_phase_chips, float code_phase_step_chips, + int signal_length_samples) { - - update_local_code(rem_code_phase_chips); d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad; d_code_phase_step_chips = code_phase_step_chips; d_phase_step_rad = phase_step_rad; d_correlator_length_samples = signal_length_samples; - fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(); - fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(); + fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(); + fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(); fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(); int irq_count; ssize_t nb; @@ -143,8 +137,9 @@ void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( fpga_multicorrelator_8sc::read_tracking_gps_results(); } + fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, - std::string device_name, unsigned int device_base) + std::string device_name, unsigned int device_base) { d_n_correlators = n_correlators; d_device_name = device_name; @@ -153,10 +148,10 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_map_base = nullptr; // instantiate variable length vectors - d_initial_index = static_cast(volk_gnsssdr_malloc( - n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); - d_initial_interp_counter = static_cast(volk_gnsssdr_malloc( - n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); + d_initial_index = static_cast(volk_gnsssdr_malloc( + n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); + d_initial_interp_counter = static_cast(volk_gnsssdr_malloc( + n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); //d_local_code_in = nullptr; d_shifts_chips = nullptr; @@ -171,21 +166,20 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_initial_sample_counter = 0; d_channel = 0; d_correlator_length_samples = 0; - + // pre-compute all the codes - d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); + d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS * NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) - { - gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0); - } + { + gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0); + } DLOG(INFO) << "TRACKING FPGA CLASS CREATED"; - } fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc() { - delete[] d_ca_codes; + delete[] d_ca_codes; close_device(); } @@ -193,7 +187,7 @@ fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc() bool fpga_multicorrelator_8sc::free() { // unlock the channel - fpga_multicorrelator_8sc::unlock_channel(); + fpga_multicorrelator_8sc::unlock_channel(); // free the FPGA dynamically created variables if (d_initial_index != nullptr) @@ -214,7 +208,7 @@ bool fpga_multicorrelator_8sc::free() void fpga_multicorrelator_8sc::set_channel(unsigned int channel) { - char device_io_name[MAX_LENGTH_DEVICEIO_NAME]; // driver io name + char device_io_name[MAX_LENGTH_DEVICEIO_NAME]; // driver io name d_channel = channel; // open the device corresponding to the assigned channel @@ -229,12 +223,12 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel) LOG(WARNING) << "Cannot open deviceio" << device_io_name; } d_map_base = reinterpret_cast(mmap(NULL, PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0)); + PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0)); - if (d_map_base == reinterpret_cast(-1)) + if (d_map_base == reinterpret_cast(-1)) { LOG(WARNING) << "Cannot map the FPGA tracking module " - << d_channel << "into user memory"; + << d_channel << "into user memory"; } // sanity check : check test register @@ -253,7 +247,7 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel) unsigned fpga_multicorrelator_8sc::fpga_acquisition_test_register( - unsigned writeval) + unsigned writeval) { unsigned readval; // write value to test register @@ -287,11 +281,9 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN) code_chip = 0; } // copy the local code to the FPGA memory one by one - d_map_base[11] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY - | code_chip | select_fpga_correlator; + d_map_base[11] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | code_chip | select_fpga_correlator; } - select_fpga_correlator = select_fpga_correlator - + LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT; + select_fpga_correlator = select_fpga_correlator + LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT; } } @@ -304,20 +296,20 @@ void fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(void) for (i = 0; i < d_n_correlators; i++) { temp_calculation = floor( - d_shifts_chips[i] - d_rem_code_phase_chips); - + d_shifts_chips[i] - d_rem_code_phase_chips); + if (temp_calculation < 0) { - temp_calculation = temp_calculation + d_code_length_chips; // % operator does not work as in Matlab with negative numbers + temp_calculation = temp_calculation + d_code_length_chips; // % operator does not work as in Matlab with negative numbers } - d_initial_index[i] = static_cast( (static_cast(temp_calculation)) % d_code_length_chips); + d_initial_index[i] = static_cast((static_cast(temp_calculation)) % d_code_length_chips); temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips, - 1.0); + 1.0); if (temp_calculation < 0) { - temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers + temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers } - d_initial_interp_counter[i] = static_cast( floor( MAX_CODE_RESAMPLER_COUNTER * temp_calculation)); + d_initial_interp_counter[i] = static_cast(floor(MAX_CODE_RESAMPLER_COUNTER * temp_calculation)); } } @@ -330,7 +322,7 @@ void fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void) d_map_base[1 + i] = d_initial_index[i]; d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i]; } - d_map_base[8] = d_code_length_chips - 1; // number of samples - 1 + d_map_base[8] = d_code_length_chips - 1; // number of samples - 1 } @@ -338,30 +330,27 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void) { float d_rem_carrier_phase_in_rad_temp; - d_code_phase_step_chips_num = static_cast( roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips)); + d_code_phase_step_chips_num = static_cast(roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips)); if (d_rem_carrier_phase_in_rad > M_PI) { - d_rem_carrier_phase_in_rad_temp = -2 * M_PI - + d_rem_carrier_phase_in_rad; + d_rem_carrier_phase_in_rad_temp = -2 * M_PI + d_rem_carrier_phase_in_rad; } else if (d_rem_carrier_phase_in_rad < -M_PI) { - d_rem_carrier_phase_in_rad_temp = 2 * M_PI - + d_rem_carrier_phase_in_rad; + d_rem_carrier_phase_in_rad_temp = 2 * M_PI + d_rem_carrier_phase_in_rad; } else { d_rem_carrier_phase_in_rad_temp = d_rem_carrier_phase_in_rad; } - d_rem_carr_phase_rad_int = static_cast( roundf( - (fabs(d_rem_carrier_phase_in_rad_temp) / M_PI) - * pow(2, PHASE_CARR_NBITS_FRAC))); + d_rem_carr_phase_rad_int = static_cast(roundf( + (fabs(d_rem_carrier_phase_in_rad_temp) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC))); if (d_rem_carrier_phase_in_rad_temp < 0) { d_rem_carr_phase_rad_int = -d_rem_carr_phase_rad_int; } - d_phase_step_rad_int = static_cast( roundf( - (fabs(d_phase_step_rad) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC))); // the FPGA accepts a range for the phase step between -pi and +pi + d_phase_step_rad_int = static_cast(roundf( + (fabs(d_phase_step_rad) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC))); // the FPGA accepts a range for the phase step between -pi and +pi if (d_phase_step_rad < 0) { @@ -383,10 +372,10 @@ void fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void) { // enable interrupts int reenable = 1; - write(d_device_descriptor, reinterpret_cast(&reenable), sizeof(int)); + write(d_device_descriptor, reinterpret_cast(&reenable), sizeof(int)); - // writing 1 to reg 14 launches the tracking - d_map_base[14] = 1; + // writing 1 to reg 14 launches the tracking + d_map_base[14] = 1; } @@ -399,17 +388,17 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void) for (k = 0; k < d_n_correlators; k++) { readval_real = d_map_base[1 + k]; - if (readval_real >= 1048576) // 0x100000 (21 bits two's complement) + if (readval_real >= 1048576) // 0x100000 (21 bits two's complement) { readval_real = -2097152 + readval_real; } readval_imag = d_map_base[1 + d_n_correlators + k]; - if (readval_imag >= 1048576) // 0x100000 (21 bits two's complement) + if (readval_imag >= 1048576) // 0x100000 (21 bits two's complement) { readval_imag = -2097152 + readval_imag; } - d_corr_out[k] = gr_complex(readval_real,readval_imag); + d_corr_out[k] = gr_complex(readval_real, readval_imag); } } @@ -417,40 +406,42 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void) void fpga_multicorrelator_8sc::unlock_channel(void) { // unlock the channel to let the next samples go through - d_map_base[12] = 1; // unlock the channel + d_map_base[12] = 1; // unlock the channel } + void fpga_multicorrelator_8sc::close_device() { - unsigned * aux = const_cast(d_map_base); - if (munmap(static_cast(aux), PAGE_SIZE) == -1) + unsigned *aux = const_cast(d_map_base); + if (munmap(static_cast(aux), PAGE_SIZE) == -1) { printf("Failed to unmap memory uio\n"); } -/* else + /* else { printf("memory uio unmapped\n"); } */ close(d_device_descriptor); } - + void fpga_multicorrelator_8sc::lock_channel(void) { // lock the channel for processing - d_map_base[12] = 0; // lock the channel + d_map_base[12] = 0; // lock the channel } + void fpga_multicorrelator_8sc::read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out) { - *sample_counter = d_map_base[11]; - *secondary_sample_counter = d_map_base[8]; - *counter_corr_0_in = d_map_base[10]; - *counter_corr_0_out = d_map_base[9]; - + *sample_counter = d_map_base[11]; + *secondary_sample_counter = d_map_base[8]; + *counter_corr_0_in = d_map_base[10]; + *counter_corr_0_out = d_map_base[9]; } + void fpga_multicorrelator_8sc::reset_multicorrelator(void) { - d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator + d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator } diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h index 9bf44536e..1eceb1936 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h @@ -49,46 +49,46 @@ class fpga_multicorrelator_8sc { public: fpga_multicorrelator_8sc(int n_correlators, std::string device_name, - unsigned int device_base); + unsigned int device_base); ~fpga_multicorrelator_8sc(); - //bool set_output_vectors(gr_complex* corr_out); - void set_output_vectors(gr_complex* corr_out); -// bool set_local_code_and_taps( -// int code_length_chips, const int* local_code_in, -// float *shifts_chips, int PRN); + //bool set_output_vectors(gr_complex* corr_out); + void set_output_vectors(gr_complex *corr_out); + // bool set_local_code_and_taps( + // int code_length_chips, const int* local_code_in, + // float *shifts_chips, int PRN); //bool set_local_code_and_taps( void set_local_code_and_taps( - int code_length_chips, - float *shifts_chips, int PRN); + int code_length_chips, + float *shifts_chips, int PRN); //bool set_output_vectors(lv_16sc_t* corr_out); void update_local_code(float rem_code_phase_chips); //bool Carrier_wipeoff_multicorrelator_resampler( void Carrier_wipeoff_multicorrelator_resampler( - float rem_carrier_phase_in_rad, float phase_step_rad, - float rem_code_phase_chips, float code_phase_step_chips, - int signal_length_samples);bool free(); + float rem_carrier_phase_in_rad, float phase_step_rad, + float rem_code_phase_chips, float code_phase_step_chips, + int signal_length_samples); + bool free(); void set_channel(unsigned int channel); void set_initial_sample(int samples_offset); int read_sample_counter(); void lock_channel(void); void unlock_channel(void); - void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug - - + void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug + private: //const int *d_local_code_in; - gr_complex * d_corr_out; + gr_complex *d_corr_out; float *d_shifts_chips; int d_code_length_chips; int d_n_correlators; // data related to the hardware module and the driver - int d_device_descriptor; // driver descriptor - volatile unsigned *d_map_base; // driver memory map + int d_device_descriptor; // driver descriptor + volatile unsigned *d_map_base; // driver memory map // configuration data received from the interface - unsigned int d_channel; // channel number - unsigned d_ncorrelators; // number of correlators + unsigned int d_channel; // channel number + unsigned d_ncorrelators; // number of correlators unsigned d_correlator_length_samples; float d_rem_code_phase_chips; float d_code_phase_step_chips; @@ -107,8 +107,7 @@ private: std::string d_device_name; unsigned int d_device_base; - - int* d_ca_codes; + int *d_ca_codes; // private functions unsigned fpga_acquisition_test_register(unsigned writeval); @@ -119,11 +118,8 @@ private: void fpga_configure_signal_parameters_in_fpga(void); void fpga_launch_multicorrelator_fpga(void); void read_tracking_gps_results(void); - void reset_multicorrelator(void); - void close_device(void); - - // debug - //unsigned int first_time = 1; + void reset_multicorrelator(void); + void close_device(void); }; #endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */ diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc index 91c611d2d..797f2c3d9 100644 --- a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc @@ -36,8 +36,8 @@ #include #include #include -#include // to test the FPGA we have to create a simultaneous task to send the samples using the DMA and stop the test -#include // FPGA read input file +#include // to test the FPGA we have to create a simultaneous task to send the samples using the DMA and stop the test +#include // FPGA read input file #include #include #include @@ -61,17 +61,17 @@ #include "signal_generator_flags.h" #include "interleaved_byte_to_complex_short.h" -#define DMA_TRACK_TRANSFER_SIZE 2046 // DMA transfer size for tracking -#define MIN_SAMPLES_REMAINING 20000 // number of remaining samples in the DMA that causes the CPU to stop the flowgraph (it has to be a bit alrger than 2x max packet size) -#define FIVE_SECONDS 5000000 // five seconds in microseconds +#define DMA_TRACK_TRANSFER_SIZE 2046 // DMA transfer size for tracking +#define MIN_SAMPLES_REMAINING 20000 // number of remaining samples in the DMA that causes the CPU to stop the flowgraph (it has to be a bit alrger than 2x max packet size) +#define FIVE_SECONDS 5000000 // five seconds in microseconds void send_tracking_gps_input_samples(FILE *rx_signal_file, - int num_remaining_samples, gr::top_block_sptr top_block) + int num_remaining_samples, gr::top_block_sptr top_block) { - int num_samples_transferred = 0; // number of samples that have been transferred to the DMA so far - static int flowgraph_stopped = 0; // flag to indicate if the flowgraph is stopped already - char *buffer_DMA; // temporary buffer to store the samples to be sent to the DMA - int dma_descr; // DMA descriptor + int num_samples_transferred = 0; // number of samples that have been transferred to the DMA so far + static int flowgraph_stopped = 0; // flag to indicate if the flowgraph is stopped already + char *buffer_DMA; // temporary buffer to store the samples to be sent to the DMA + int dma_descr; // DMA descriptor dma_descr = open("/dev/loop_tx", O_WRONLY); if (dma_descr < 0) { @@ -79,7 +79,7 @@ void send_tracking_gps_input_samples(FILE *rx_signal_file, exit(1); } - buffer_DMA = (char *) malloc(DMA_TRACK_TRANSFER_SIZE); + buffer_DMA = (char *)malloc(DMA_TRACK_TRANSFER_SIZE); if (!buffer_DMA) { fprintf(stderr, "Memory error!"); @@ -98,8 +98,7 @@ void send_tracking_gps_input_samples(FILE *rx_signal_file, } if (num_remaining_samples > DMA_TRACK_TRANSFER_SIZE) { - - fread(buffer_DMA, DMA_TRACK_TRANSFER_SIZE, 1,rx_signal_file); + fread(buffer_DMA, DMA_TRACK_TRANSFER_SIZE, 1, rx_signal_file); assert(DMA_TRACK_TRANSFER_SIZE == write(dma_descr, &buffer_DMA[0], DMA_TRACK_TRANSFER_SIZE)); num_remaining_samples = num_remaining_samples - DMA_TRACK_TRANSFER_SIZE; @@ -121,11 +120,11 @@ void send_tracking_gps_input_samples(FILE *rx_signal_file, // thread that sends the samples to the FPGA -void thread(gr::top_block_sptr top_block, const char * file_name) +void thread(gr::top_block_sptr top_block, const char *file_name) { // file descriptor - FILE *rx_signal_file; // file descriptor - int file_length; // length of the file containing the received samples + FILE *rx_signal_file; // file descriptor + int file_length; // length of the file containing the received samples rx_signal_file = fopen(file_name, "rb"); if (!rx_signal_file) @@ -137,7 +136,7 @@ void thread(gr::top_block_sptr top_block, const char * file_name) file_length = ftell(rx_signal_file); fseek(rx_signal_file, 0, SEEK_SET); - usleep(FIVE_SECONDS); // wait for some time to give time to the other thread to program the device + usleep(FIVE_SECONDS); // wait for some time to give time to the other thread to program the device //send_tracking_gps_input_samples(dma_descr, rx_signal_file, file_length); send_tracking_gps_input_samples(rx_signal_file, file_length, top_block); @@ -163,14 +162,14 @@ private: public: int rx_message; - ~GpsL1CADllPllTrackingTestFpga_msg_rx(); //!< Default destructor + ~GpsL1CADllPllTrackingTestFpga_msg_rx(); //!< Default destructor }; GpsL1CADllPllTrackingTestFpga_msg_rx_sptr GpsL1CADllPllTrackingTestFpga_msg_rx_make() { return GpsL1CADllPllTrackingTestFpga_msg_rx_sptr( - new GpsL1CADllPllTrackingTestFpga_msg_rx()); + new GpsL1CADllPllTrackingTestFpga_msg_rx()); } @@ -181,7 +180,7 @@ void GpsL1CADllPllTrackingTestFpga_msg_rx::msg_handler_events(pmt::pmt_t msg) long int message = pmt::to_long(msg); rx_message = message; } - catch (boost::bad_any_cast& e) + catch (boost::bad_any_cast &e) { LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; rx_message = 0; @@ -189,22 +188,22 @@ void GpsL1CADllPllTrackingTestFpga_msg_rx::msg_handler_events(pmt::pmt_t msg) } -GpsL1CADllPllTrackingTestFpga_msg_rx::GpsL1CADllPllTrackingTestFpga_msg_rx() : - gr::block("GpsL1CADllPllTrackingTestFpga_msg_rx", - gr::io_signature::make(0, 0, 0), - gr::io_signature::make(0, 0, 0)) +GpsL1CADllPllTrackingTestFpga_msg_rx::GpsL1CADllPllTrackingTestFpga_msg_rx() : gr::block("GpsL1CADllPllTrackingTestFpga_msg_rx", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) { this->message_port_register_in(pmt::mp("events")); this->set_msg_handler(pmt::mp("events"), - boost::bind( - &GpsL1CADllPllTrackingTestFpga_msg_rx::msg_handler_events, - this, _1)); + boost::bind( + &GpsL1CADllPllTrackingTestFpga_msg_rx::msg_handler_events, + this, _1)); rx_message = 0; } GpsL1CADllPllTrackingTestFpga_msg_rx::~GpsL1CADllPllTrackingTestFpga_msg_rx() -{} +{ +} // ########################################################### @@ -226,12 +225,12 @@ public: int configure_generator(); int generate_signal(); - void check_results_doppler(arma::vec & true_time_s, arma::vec & true_value, - arma::vec & meas_time_s, arma::vec & meas_value); - void check_results_acc_carrier_phase(arma::vec & true_time_s, - arma::vec & true_value, arma::vec & meas_time_s, arma::vec & meas_value); - void check_results_codephase(arma::vec & true_time_s, arma::vec & true_value, - arma::vec & meas_time_s, arma::vec & meas_value); + void check_results_doppler(arma::vec &true_time_s, arma::vec &true_value, + arma::vec &meas_time_s, arma::vec &meas_value); + void check_results_acc_carrier_phase(arma::vec &true_time_s, + arma::vec &true_value, arma::vec &meas_time_s, arma::vec &meas_value); + void check_results_codephase(arma::vec &true_time_s, arma::vec &true_value, + arma::vec &meas_time_s, arma::vec &meas_value); GpsL1CADllPllTrackingTestFpga() { @@ -263,16 +262,15 @@ int GpsL1CADllPllTrackingTestFpga::configure_generator() p1 = std::string("-rinex_nav_file=") + FLAGS_rinex_nav_file; if (FLAGS_dynamic_position.empty()) { - p2 = std::string("-static_position=") + FLAGS_static_position - + std::string(",") + std::to_string(FLAGS_duration * 10); + p2 = std::string("-static_position=") + FLAGS_static_position + std::string(",") + std::to_string(FLAGS_duration * 10); } else { p2 = std::string("-obs_pos_file=") + std::string(FLAGS_dynamic_position); } - p3 = std::string("-rinex_obs_file=") + FLAGS_filename_rinex_obs; // RINEX 2.10 observation file output - p4 = std::string("-sig_out_file=") + FLAGS_filename_raw_data; // Baseband signal output file. Will be stored in int8_t IQ multiplexed samples - p5 = std::string("-sampling_freq=") + std::to_string(baseband_sampling_freq); //Baseband sampling frequency [MSps] + p3 = std::string("-rinex_obs_file=") + FLAGS_filename_rinex_obs; // RINEX 2.10 observation file output + p4 = std::string("-sig_out_file=") + FLAGS_filename_raw_data; // Baseband signal output file. Will be stored in int8_t IQ multiplexed samples + p5 = std::string("-sampling_freq=") + std::to_string(baseband_sampling_freq); //Baseband sampling frequency [MSps] return 0; } @@ -281,8 +279,8 @@ int GpsL1CADllPllTrackingTestFpga::generate_signal() { int child_status; - char * const parmList[] = { &generator_binary[0], &generator_binary[0], &p1[0], &p2[0], &p3[0], - &p4[0], &p5[0], NULL }; + char *const parmList[] = {&generator_binary[0], &generator_binary[0], &p1[0], &p2[0], &p3[0], + &p4[0], &p5[0], NULL}; int pid; if ((pid = fork()) == -1) @@ -310,12 +308,12 @@ void GpsL1CADllPllTrackingTestFpga::configure_receiver() gnss_synchro.PRN = FLAGS_test_satellite_PRN; config->set_property("GNSS-SDR.internal_fs_sps", - std::to_string(baseband_sampling_freq)); + std::to_string(baseband_sampling_freq)); // Set Tracking //config->set_property("Tracking_1C.implementation", // "GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga"); config->set_property("Tracking_1C.implementation", - "GPS_L1_CA_DLL_PLL_Tracking_Fpga"); + "GPS_L1_CA_DLL_PLL_Tracking_Fpga"); config->set_property("Tracking_1C.item_type", "cshort"); config->set_property("Tracking_1C.if", "0"); config->set_property("Tracking_1C.dump", "true"); @@ -328,8 +326,8 @@ void GpsL1CADllPllTrackingTestFpga::configure_receiver() } -void GpsL1CADllPllTrackingTestFpga::check_results_doppler(arma::vec & true_time_s, - arma::vec & true_value, arma::vec & meas_time_s, arma::vec & meas_value) +void GpsL1CADllPllTrackingTestFpga::check_results_doppler(arma::vec &true_time_s, + arma::vec &true_value, arma::vec &meas_time_s, arma::vec &meas_value) { //1. True value interpolation to match the measurement times arma::vec true_value_interp; @@ -362,13 +360,13 @@ void GpsL1CADllPllTrackingTestFpga::check_results_doppler(arma::vec & true_time_ << ", mean=" << error_mean << ", stdev=" << sqrt(error_var) << " (max,min)=" << max_error << "," << min_error << " [Hz]" << std::endl; - std::cout.precision (ss); + std::cout.precision(ss); } void GpsL1CADllPllTrackingTestFpga::check_results_acc_carrier_phase( - arma::vec & true_time_s, arma::vec & true_value, arma::vec & meas_time_s, - arma::vec & meas_value) + arma::vec &true_time_s, arma::vec &true_value, arma::vec &meas_time_s, + arma::vec &meas_value) { //1. True value interpolation to match the measurement times arma::vec true_value_interp; @@ -401,13 +399,13 @@ void GpsL1CADllPllTrackingTestFpga::check_results_acc_carrier_phase( << ", mean=" << error_mean << ", stdev=" << sqrt(error_var) << " (max,min)=" << max_error << "," << min_error << " [Hz]" << std::endl; - std::cout.precision (ss); + std::cout.precision(ss); } void GpsL1CADllPllTrackingTestFpga::check_results_codephase( - arma::vec & true_time_s, arma::vec & true_value, arma::vec & meas_time_s, - arma::vec & meas_value) + arma::vec &true_time_s, arma::vec &true_value, arma::vec &meas_time_s, + arma::vec &meas_value) { //1. True value interpolation to match the measurement times arma::vec true_value_interp; @@ -439,7 +437,7 @@ void GpsL1CADllPllTrackingTestFpga::check_results_codephase( << ", mean=" << error_mean << ", stdev=" << sqrt(error_var) << " (max,min)=" << max_error << "," << min_error << " [Chips]" << std::endl; - std::cout.precision (ss); + std::cout.precision(ss); } @@ -463,27 +461,29 @@ TEST_F(GpsL1CADllPllTrackingTestFpga, ValidationOfResultsFpga) true_obs_file.append(std::to_string(test_satellite_PRN)); true_obs_file.append(".dat"); ASSERT_NO_THROW( + { + if (true_obs_data.open_obs_file(true_obs_file) == false) { - if (true_obs_data.open_obs_file(true_obs_file) == false) - { - throw std::exception(); - }; - }) << "Failure opening true observables file"; + throw std::exception(); + }; + }) + << "Failure opening true observables file"; top_block = gr::make_top_block("Tracking test"); //std::shared_ptr tracking = std::make_shared (config.get(), "Tracking_1C", 1, 1); - std::shared_ptr tracking = std::make_shared (config.get(), "Tracking_1C", 1, 1); + std::shared_ptr tracking = std::make_shared(config.get(), "Tracking_1C", 1, 1); boost::shared_ptr msg_rx = GpsL1CADllPllTrackingTestFpga_msg_rx_make(); // load acquisition data based on the first epoch of the true observations ASSERT_NO_THROW( + { + if (true_obs_data.read_binary_obs() == false) { - if (true_obs_data.read_binary_obs() == false) - { - throw std::exception(); - }; - }) << "Failure reading true observables file"; + throw std::exception(); + }; + }) + << "Failure reading true observables file"; //restart the epoch counter true_obs_data.restart(); @@ -492,52 +492,54 @@ TEST_F(GpsL1CADllPllTrackingTestFpga, ValidationOfResultsFpga) << " Initial code delay [Chips]=" << true_obs_data.prn_delay_chips << std::endl; - gnss_synchro.Acq_delay_samples = (GPS_L1_CA_CODE_LENGTH_CHIPS - - true_obs_data.prn_delay_chips / GPS_L1_CA_CODE_LENGTH_CHIPS) - * baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD; + gnss_synchro.Acq_delay_samples = (GPS_L1_CA_CODE_LENGTH_CHIPS - true_obs_data.prn_delay_chips / GPS_L1_CA_CODE_LENGTH_CHIPS) * baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD; gnss_synchro.Acq_doppler_hz = true_obs_data.doppler_l1_hz; gnss_synchro.Acq_samplestamp_samples = 0; ASSERT_NO_THROW( - { - tracking->set_channel(gnss_synchro.Channel_ID); - }) << "Failure setting channel."; + { + tracking->set_channel(gnss_synchro.Channel_ID); + }) + << "Failure setting channel."; ASSERT_NO_THROW( - { - tracking->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro."; + { + tracking->set_gnss_synchro(&gnss_synchro); + }) + << "Failure setting gnss_synchro."; ASSERT_NO_THROW( - { - tracking->connect(top_block); - }) << "Failure connecting tracking to the top_block."; + { + tracking->connect(top_block); + }) + << "Failure connecting tracking to the top_block."; ASSERT_NO_THROW( - { - gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro)); - top_block->connect(tracking->get_right_block(), 0, sink, 0); - top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); - }) << "Failure connecting the blocks of tracking test."; + { + gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro)); + top_block->connect(tracking->get_right_block(), 0, sink, 0); + top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + }) + << "Failure connecting the blocks of tracking test."; tracking->start_tracking(); // assemble again the file name in a null terminated string (not available by default in the main program flow) std::string file = "./" + filename_raw_data; - const char * file_name = file.c_str(); + const char *file_name = file.c_str(); // start thread that sends the DMA samples to the FPGA - boost::thread t - { thread, top_block, file_name }; + boost::thread t{thread, top_block, file_name}; EXPECT_NO_THROW( - { - start = std::chrono::system_clock::now(); - top_block->run(); // Start threads and wait - tracking->reset();// unlock the channel - end = std::chrono::system_clock::now(); - elapsed_seconds = end - start; - }) << "Failure running the top_block."; + { + start = std::chrono::system_clock::now(); + top_block->run(); // Start threads and wait + tracking->reset(); // unlock the channel + end = std::chrono::system_clock::now(); + elapsed_seconds = end - start; + }) + << "Failure running the top_block."; // wait until child thread terminates t.join(); @@ -567,12 +569,13 @@ TEST_F(GpsL1CADllPllTrackingTestFpga, ValidationOfResultsFpga) //load the measured values tracking_dump_reader trk_dump; ASSERT_NO_THROW( + { + if (trk_dump.open_obs_file(std::string("./tracking_ch_0.dat")) == false) { - if (trk_dump.open_obs_file(std::string("./tracking_ch_0.dat")) == false) - { - throw std::exception(); - }; - }) << "Failure opening tracking dump file"; + throw std::exception(); + }; + }) + << "Failure opening tracking dump file"; nepoch = trk_dump.num_epochs(); std::cout << "Measured observation epochs=" << nepoch << std::endl; @@ -585,14 +588,11 @@ TEST_F(GpsL1CADllPllTrackingTestFpga, ValidationOfResultsFpga) epoch_counter = 0; while (trk_dump.read_binary_obs()) { - trk_timestamp_s(epoch_counter) = static_cast(trk_dump.PRN_start_sample_count) - / static_cast(baseband_sampling_freq); + trk_timestamp_s(epoch_counter) = static_cast(trk_dump.PRN_start_sample_count) / static_cast(baseband_sampling_freq); trk_acc_carrier_phase_cycles(epoch_counter) = trk_dump.acc_carrier_phase_rad / GPS_TWO_PI; trk_Doppler_Hz(epoch_counter) = trk_dump.carrier_doppler_hz; - double delay_chips = GPS_L1_CA_CODE_LENGTH_CHIPS - GPS_L1_CA_CODE_LENGTH_CHIPS - * (fmod( (static_cast(trk_dump.PRN_start_sample_count) + trk_dump.aux1) - / static_cast(baseband_sampling_freq), 1.0e-3) / 1.0e-3); + double delay_chips = GPS_L1_CA_CODE_LENGTH_CHIPS - GPS_L1_CA_CODE_LENGTH_CHIPS * (fmod((static_cast(trk_dump.PRN_start_sample_count) + trk_dump.aux1) / static_cast(baseband_sampling_freq), 1.0e-3) / 1.0e-3); trk_prn_delay_chips(epoch_counter) = delay_chips; epoch_counter++; @@ -600,7 +600,7 @@ TEST_F(GpsL1CADllPllTrackingTestFpga, ValidationOfResultsFpga) //Align initial measurements and cut the tracking pull-in transitory double pull_in_offset_s = 1.0; - arma::uvec initial_meas_point = arma::find( trk_timestamp_s >= (true_timestamp_s(0) + pull_in_offset_s), 1, "first"); + arma::uvec initial_meas_point = arma::find(trk_timestamp_s >= (true_timestamp_s(0) + pull_in_offset_s), 1, "first"); trk_timestamp_s = trk_timestamp_s.subvec(initial_meas_point(0), trk_timestamp_s.size() - 1); trk_acc_carrier_phase_cycles = trk_acc_carrier_phase_cycles.subvec(initial_meas_point(0), trk_acc_carrier_phase_cycles.size() - 1); @@ -610,8 +610,8 @@ TEST_F(GpsL1CADllPllTrackingTestFpga, ValidationOfResultsFpga) check_results_doppler(true_timestamp_s, true_Doppler_Hz, trk_timestamp_s, trk_Doppler_Hz); check_results_codephase(true_timestamp_s, true_prn_delay_chips, trk_timestamp_s, trk_prn_delay_chips); check_results_acc_carrier_phase(true_timestamp_s, - true_acc_carrier_phase_cycles, trk_timestamp_s, - trk_acc_carrier_phase_cycles); + true_acc_carrier_phase_cycles, trk_timestamp_s, + trk_acc_carrier_phase_cycles); std::cout << "Signal tracking completed in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; } From faf27fff220469a64337af8d9031fbcb71a19332 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Mon, 30 Apr 2018 20:15:00 +0200 Subject: [PATCH 18/19] Apply code formatting --- .../gps_l1_ca_pcps_acquisition_fpga.cc | 49 ++++++------- .../gps_l1_ca_pcps_acquisition_fpga.h | 6 +- src/algorithms/libs/CMakeLists.txt | 68 +++++++++---------- 3 files changed, 61 insertions(+), 62 deletions(-) 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 455fac062..da4cd4483 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 @@ -33,15 +33,17 @@ * * ------------------------------------------------------------------------- */ -#include + +#include "configuration_interface.h" +#include "gnss_sdr_flags.h" +#include "gps_l1_ca_pcps_acquisition_fpga.h" +#include "gps_sdr_signal_processing.h" +#include "GPS_L1_CA.h" #include #include #include -#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" +#include + #define NUM_PRNs 32 @@ -70,10 +72,10 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( unsigned int 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)); + float nbits = ceilf(log2f((float)code_length)); unsigned int nsamples_total = pow(2, nbits); unsigned int vector_length = nsamples_total * sampled_ms; - unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga",0); + 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); @@ -84,27 +86,27 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( // 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) - gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT + gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT // 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 + 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 + 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 + 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 + memcpy(fft_if->get_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) { @@ -115,13 +117,12 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( 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 + 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))); - + 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 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 642e9bf8e..53ab4af1d 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 @@ -37,11 +37,10 @@ #ifndef GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ #define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ -#include #include "acquisition_interface.h" #include "gnss_synchro.h" #include "pcps_acquisition_fpga.h" - +#include class ConfigurationInterface; @@ -144,8 +143,7 @@ private: 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 - + lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts }; #endif /* GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ */ diff --git a/src/algorithms/libs/CMakeLists.txt b/src/algorithms/libs/CMakeLists.txt index 6a3924e19..775ac6358 100644 --- a/src/algorithms/libs/CMakeLists.txt +++ b/src/algorithms/libs/CMakeLists.txt @@ -42,7 +42,7 @@ if(ENABLE_FPGA) conjugate_ic.cc ) else(ENABLE_FPGA) - set(GNSS_SPLIBS_SOURCES + set(GNSS_SPLIBS_SOURCES gps_l2c_signal.cc gps_l5_signal.cc galileo_e1_signal_processing.cc @@ -62,38 +62,38 @@ else(ENABLE_FPGA) conjugate_cc.cc conjugate_sc.cc conjugate_ic.cc - ) + ) endif(ENABLE_FPGA) if(OPENCL_FOUND) - set(GNSS_SPLIBS_SOURCES ${GNSS_SPLIBS_SOURCES} - opencl/fft_execute.cc # Needs OpenCL - opencl/fft_setup.cc # Needs OpenCL - opencl/fft_kernelstring.cc # Needs OpenCL - ) + set(GNSS_SPLIBS_SOURCES ${GNSS_SPLIBS_SOURCES} + opencl/fft_execute.cc # Needs OpenCL + opencl/fft_setup.cc # Needs OpenCL + opencl/fft_kernelstring.cc # Needs OpenCL + ) endif(OPENCL_FOUND) include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR}/src/core/system_parameters - ${CMAKE_SOURCE_DIR}/src/core/receiver - ${CMAKE_SOURCE_DIR}/src/core/interfaces - ${Boost_INCLUDE_DIRS} - ${GLOG_INCLUDE_DIRS} - ${GFlags_INCLUDE_DIRS} - ${GNURADIO_RUNTIME_INCLUDE_DIRS} - ${GNURADIO_BLOCKS_INCLUDE_DIRS} - ${VOLK_INCLUDE_DIRS} - ${VOLK_GNSSSDR_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/src/core/system_parameters + ${CMAKE_SOURCE_DIR}/src/core/receiver + ${CMAKE_SOURCE_DIR}/src/core/interfaces + ${Boost_INCLUDE_DIRS} + ${GLOG_INCLUDE_DIRS} + ${GFlags_INCLUDE_DIRS} + ${GNURADIO_RUNTIME_INCLUDE_DIRS} + ${GNURADIO_BLOCKS_INCLUDE_DIRS} + ${VOLK_INCLUDE_DIRS} + ${VOLK_GNSSSDR_INCLUDE_DIRS} ) if(OPENCL_FOUND) - include_directories( ${OPENCL_INCLUDE_DIRS} ) - if(OS_IS_MACOSX) - set(OPT_LIBRARIES ${OPT_LIBRARIES} "-framework OpenCL") - else(OS_IS_MACOSX) - set(OPT_LIBRARIES ${OPT_LIBRARIES} ${OPENCL_LIBRARIES}) - endif(OS_IS_MACOSX) + include_directories( ${OPENCL_INCLUDE_DIRS} ) + if(OS_IS_MACOSX) + set(OPT_LIBRARIES ${OPT_LIBRARIES} "-framework OpenCL") + else(OS_IS_MACOSX) + set(OPT_LIBRARIES ${OPT_LIBRARIES} ${OPENCL_LIBRARIES}) + endif(OS_IS_MACOSX) endif(OPENCL_FOUND) add_definitions(-DGNSSSDR_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}") @@ -105,22 +105,22 @@ add_library(gnss_sp_libs ${GNSS_SPLIBS_SOURCES} ${GNSS_SPLIBS_HEADERS}) source_group(Headers FILES ${GNSS_SPLIBS_HEADERS}) target_link_libraries(gnss_sp_libs ${GNURADIO_RUNTIME_LIBRARIES} - ${VOLK_LIBRARIES} ${ORC_LIBRARIES} - ${VOLK_GNSSSDR_LIBRARIES} ${ORC_LIBRARIES} - ${GFlags_LIBS} - ${GNURADIO_BLOCKS_LIBRARIES} - ${GNURADIO_FFT_LIBRARIES} - ${GNURADIO_FILTER_LIBRARIES} - ${OPT_LIBRARIES} - gnss_rx + ${VOLK_LIBRARIES} ${ORC_LIBRARIES} + ${VOLK_GNSSSDR_LIBRARIES} ${ORC_LIBRARIES} + ${GFlags_LIBS} + ${GNURADIO_BLOCKS_LIBRARIES} + ${GNURADIO_FFT_LIBRARIES} + ${GNURADIO_FILTER_LIBRARIES} + ${OPT_LIBRARIES} + gnss_rx ) if(NOT VOLK_GNSSSDR_FOUND) - add_dependencies(gnss_sp_libs volk_gnsssdr_module) + add_dependencies(gnss_sp_libs volk_gnsssdr_module) endif(NOT VOLK_GNSSSDR_FOUND) if(${GFLAGS_GREATER_20}) - add_definitions(-DGFLAGS_GREATER_2_0=1) + add_definitions(-DGFLAGS_GREATER_2_0=1) endif(${GFLAGS_GREATER_20}) add_library(gnss_sdr_flags gnss_sdr_flags.cc gnss_sdr_flags.h) From 0494d9b5a8945a3a45533f4b45b7f4d341da7f19 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Mon, 30 Apr 2018 20:58:53 +0200 Subject: [PATCH 19/19] Avoid claah between volk and volk_gnsssdr defines --- .../gps_l1_ca_pcps_acquisition_fpga.cc | 1 - .../gps_l1_ca_pcps_acquisition_fpga.h | 1 + .../gnuradio_blocks/pcps_acquisition_fpga.h | 4 +- .../acquisition/libs/fpga_acquisition.cc | 107 ++++++++++-------- .../acquisition/libs/fpga_acquisition.h | 45 ++++---- 5 files changed, 83 insertions(+), 75 deletions(-) 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 da4cd4483..d9ef75ae3 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 @@ -40,7 +40,6 @@ #include "gps_sdr_signal_processing.h" #include "GPS_L1_CA.h" #include -#include #include #include 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 53ab4af1d..f070e8818 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 @@ -40,6 +40,7 @@ #include "acquisition_interface.h" #include "gnss_synchro.h" #include "pcps_acquisition_fpga.h" +#include #include class ConfigurationInterface; diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h index 3014a278a..e758904e3 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h @@ -57,9 +57,9 @@ #define GNSS_SDR_PCPS_ACQUISITION_FPGA_H_ -#include #include "fpga_acquisition.h" #include "gnss_synchro.h" +#include typedef struct { @@ -72,7 +72,7 @@ typedef struct int samples_per_code; unsigned int select_queue_Fpga; std::string device_name; - lv_16sc_t *all_fft_codes; // memory that contains all the code ffts + lv_16sc_t* all_fft_codes; // memory that contains all the code ffts } pcpsconf_fpga_t; diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.cc b/src/algorithms/acquisition/libs/fpga_acquisition.cc index 82f22e050..81995faab 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.cc +++ b/src/algorithms/acquisition/libs/fpga_acquisition.cc @@ -33,32 +33,27 @@ * ------------------------------------------------------------------------- */ -// libraries used by the GIPO -#include -#include - -// logging -#include - -// GPS L1 -#include "GPS_L1_CA.h" - #include "fpga_acquisition.h" +#include "GPS_L1_CA.h" #include "gps_sdr_signal_processing.h" +#include +#include // libraries used by the GIPO +#include // libraries used by the GIPO -#define PAGE_SIZE 0x10000 // default page size for the multicorrelator memory map -#define MAX_PHASE_STEP_RAD 0.999999999534339 // 1 - pow(2,-31); -#define RESET_ACQUISITION 2 // command to reset the multicorrelator -#define LAUNCH_ACQUISITION 1 // command to launch the multicorrelator -#define TEST_REG_SANITY_CHECK 0x55AA // value to check the presence of the test register (to detect the hw) -#define LOCAL_CODE_CLEAR_MEM 0x10000000 // command to clear the internal memory of the multicorrelator -#define MEM_LOCAL_CODE_WR_ENABLE 0x0C000000 // command to enable the ENA and WR pins of the internal memory of the multicorrelator -#define POW_2_2 4 // 2^2 (used for the conversion of floating point numbers to integers) -#define POW_2_29 536870912 // 2^29 (used for the conversion of floating point numbers to integers) -#define SELECT_LSB 0x00FF // value to select the least significant byte -#define SELECT_MSB 0XFF00 // value to select the most significant byte -#define SELECT_16_BITS 0xFFFF // value to select 16 bits -#define SHL_8_BITS 256 // value used to shift a value 8 bits to the left + +#define PAGE_SIZE 0x10000 // default page size for the multicorrelator memory map +#define MAX_PHASE_STEP_RAD 0.999999999534339 // 1 - pow(2,-31); +#define RESET_ACQUISITION 2 // command to reset the multicorrelator +#define LAUNCH_ACQUISITION 1 // command to launch the multicorrelator +#define TEST_REG_SANITY_CHECK 0x55AA // value to check the presence of the test register (to detect the hw) +#define LOCAL_CODE_CLEAR_MEM 0x10000000 // command to clear the internal memory of the multicorrelator +#define MEM_LOCAL_CODE_WR_ENABLE 0x0C000000 // command to enable the ENA and WR pins of the internal memory of the multicorrelator +#define POW_2_2 4 // 2^2 (used for the conversion of floating point numbers to integers) +#define POW_2_29 536870912 // 2^29 (used for the conversion of floating point numbers to integers) +#define SELECT_LSB 0x00FF // value to select the least significant byte +#define SELECT_MSB 0XFF00 // value to select the most significant byte +#define SELECT_16_BITS 0xFFFF // value to select 16 bits +#define SHL_8_BITS 256 // value used to shift a value 8 bits to the left bool fpga_acquisition::init() @@ -68,34 +63,36 @@ bool fpga_acquisition::init() return true; } + bool fpga_acquisition::set_local_code(unsigned int PRN) { // select the code with the chosen PRN fpga_acquisition::fpga_configure_acquisition_local_code( - &d_all_fft_codes[d_nsamples_total * (PRN - 1)]); + &d_all_fft_codes[d_nsamples_total * (PRN - 1)]); return true; } + 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, - lv_16sc_t *all_fft_codes) + unsigned int nsamples, + unsigned int doppler_max, + unsigned int nsamples_total, long fs_in, long freq, + unsigned int sampled_ms, unsigned select_queue, + lv_16sc_t *all_fft_codes) { - unsigned int vector_length = nsamples_total*sampled_ms; + unsigned int vector_length = nsamples_total * sampled_ms; // initial values d_device_name = device_name; d_freq = freq; d_fs_in = fs_in; d_vector_length = vector_length; - d_nsamples = nsamples; // number of samples not including padding + d_nsamples = nsamples; // number of samples not including padding d_select_queue = select_queue; d_nsamples_total = nsamples_total; d_doppler_max = doppler_max; d_doppler_step = 0; - d_fd = 0; // driver descriptor - d_map_base = nullptr; // driver memory map + d_fd = 0; // driver descriptor + d_map_base = nullptr; // driver memory map d_all_fft_codes = all_fft_codes; // open communication with HW accelerator @@ -104,9 +101,9 @@ fpga_acquisition::fpga_acquisition(std::string device_name, LOG(WARNING) << "Cannot open deviceio" << d_device_name; } d_map_base = reinterpret_cast(mmap(NULL, PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_SHARED, d_fd, 0)); + PROT_READ | PROT_WRITE, MAP_SHARED, d_fd, 0)); - if (d_map_base == reinterpret_cast(-1)) + if (d_map_base == reinterpret_cast(-1)) { LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory"; } @@ -121,23 +118,25 @@ fpga_acquisition::fpga_acquisition(std::string device_name, } else { - LOG(INFO) << "Acquisition test register sanity check success !"; + LOG(INFO) << "Acquisition test register sanity check success!"; } fpga_acquisition::reset_acquisition(); DLOG(INFO) << "Acquisition FPGA class created"; - } + fpga_acquisition::~fpga_acquisition() { close_device(); } + bool fpga_acquisition::free() { return true; } + unsigned fpga_acquisition::fpga_acquisition_test_register(unsigned writeval) { unsigned readval; @@ -149,6 +148,7 @@ unsigned fpga_acquisition::fpga_acquisition_test_register(unsigned writeval) return readval; } + void fpga_acquisition::fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[]) { unsigned short local_code; @@ -161,19 +161,20 @@ void fpga_acquisition::fpga_configure_acquisition_local_code(lv_16sc_t fft_local { tmp = fft_local_code[k].real(); tmp2 = fft_local_code[k].imag(); - local_code = (tmp & SELECT_LSB) | ((tmp2 * SHL_8_BITS) & SELECT_MSB); // put together the real part and the imaginary part + local_code = (tmp & SELECT_LSB) | ((tmp2 * SHL_8_BITS) & SELECT_MSB); // put together the real part and the imaginary part fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_16_BITS); d_map_base[4] = fft_data; } } + void fpga_acquisition::run_acquisition(void) { // enable interrupts int reenable = 1; - write(d_fd, reinterpret_cast(&reenable), sizeof(int)); + write(d_fd, reinterpret_cast(&reenable), sizeof(int)); // launch the acquisition process - d_map_base[6] = LAUNCH_ACQUISITION; // writing anything to reg 6 launches the acquisition process + d_map_base[6] = LAUNCH_ACQUISITION; // writing anything to reg 6 launches the acquisition process int irq_count; ssize_t nb; @@ -186,14 +187,16 @@ void fpga_acquisition::run_acquisition(void) } } + void fpga_acquisition::configure_acquisition() { d_map_base[0] = d_select_queue; d_map_base[1] = d_vector_length; d_map_base[2] = d_nsamples; - d_map_base[5] = (int) log2((float) d_vector_length); // log2 FFTlength + d_map_base[5] = (int)log2((float)d_vector_length); // log2 FFTlength } + void fpga_acquisition::set_phase_step(unsigned int doppler_index) { float phase_step_rad_real; @@ -212,13 +215,14 @@ void fpga_acquisition::set_phase_step(unsigned int doppler_index) { phase_step_rad_real = MAX_PHASE_STEP_RAD; } - phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2 - phase_step_rad_int = (int32_t) (phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings + phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2 + phase_step_rad_int = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings d_map_base[3] = phase_step_rad_int; } -void fpga_acquisition::read_acquisition_results(uint32_t* max_index, - float* max_magnitude, unsigned *initial_sample, float *power_sum) + +void fpga_acquisition::read_acquisition_results(uint32_t *max_index, + float *max_magnitude, unsigned *initial_sample, float *power_sum) { unsigned readval = 0; readval = d_map_base[1]; @@ -231,28 +235,31 @@ void fpga_acquisition::read_acquisition_results(uint32_t* max_index, *max_index = readval; } + void fpga_acquisition::block_samples() { - d_map_base[14] = 1; // block the samples + d_map_base[14] = 1; // block the samples } void fpga_acquisition::unblock_samples() { - d_map_base[14] = 0; // unblock the samples + d_map_base[14] = 0; // unblock the samples } + void fpga_acquisition::close_device() { - unsigned * aux = const_cast(d_map_base); - if (munmap(static_cast(aux), PAGE_SIZE) == -1) + unsigned *aux = const_cast(d_map_base); + if (munmap(static_cast(aux), PAGE_SIZE) == -1) { printf("Failed to unmap memory uio\n"); } close(d_fd); } + void fpga_acquisition::reset_acquisition(void) { - d_map_base[6] = RESET_ACQUISITION; // writing a 2 to d_map_base[6] resets the multicorrelator + d_map_base[6] = RESET_ACQUISITION; // writing a 2 to d_map_base[6] resets the multicorrelator } diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.h b/src/algorithms/acquisition/libs/fpga_acquisition.h index 45cae5475..00641e1cd 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.h +++ b/src/algorithms/acquisition/libs/fpga_acquisition.h @@ -36,8 +36,8 @@ #ifndef GNSS_SDR_FPGA_ACQUISITION_H_ #define GNSS_SDR_FPGA_ACQUISITION_H_ -#include #include +#include /*! * \brief Class that implements carrier wipe-off and correlators. @@ -46,18 +46,20 @@ class fpga_acquisition { public: 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, - lv_16sc_t *all_fft_codes); - ~fpga_acquisition();bool init();bool set_local_code( - unsigned int PRN); + unsigned int nsamples, + unsigned int doppler_max, + unsigned int nsamples_total, long fs_in, long freq, + 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); - void read_acquisition_results(uint32_t* max_index, float* max_magnitude, - unsigned *initial_sample, float *power_sum); + void read_acquisition_results(uint32_t *max_index, float *max_magnitude, + unsigned *initial_sample, float *power_sum); void block_samples(); void unblock_samples(); @@ -80,21 +82,20 @@ public: } private: - long d_freq; long d_fs_in; - gr::fft::fft_complex* d_fft_if; // function used to run the fft of the local codes + gr::fft::fft_complex *d_fft_if; // function used to run the fft of the local codes // data related to the hardware module and the driver - int d_fd; // driver descriptor - volatile unsigned *d_map_base; // driver memory map - lv_16sc_t *d_all_fft_codes; // memory that contains all the code ffts - unsigned int d_vector_length; // number of samples incluing padding and number of ms - unsigned int d_nsamples_total; // number of samples including padding - unsigned int d_nsamples; // number of samples not including padding - unsigned int d_select_queue; // queue selection - std::string d_device_name; // HW device name - unsigned int d_doppler_max; // max doppler - unsigned int d_doppler_step; // doppler step + int d_fd; // driver descriptor + volatile unsigned *d_map_base; // driver memory map + lv_16sc_t *d_all_fft_codes; // memory that contains all the code ffts + unsigned int d_vector_length; // number of samples incluing padding and number of ms + unsigned int d_nsamples_total; // number of samples including padding + unsigned int d_nsamples; // number of samples not including padding + unsigned int d_select_queue; // queue selection + std::string d_device_name; // HW device name + unsigned int d_doppler_max; // max doppler + unsigned int d_doppler_step; // doppler step // FPGA private functions unsigned fpga_acquisition_test_register(unsigned writeval); void fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[]);