1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-01-18 21:23:02 +00:00

Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into vtl_experimental

This commit is contained in:
Javier Arribas 2020-12-01 12:51:34 +01:00
commit bb256c0650
45 changed files with 756 additions and 201 deletions

View File

@ -329,7 +329,7 @@ set(GNSSSDR_GTEST_LOCAL_VERSION "1.10.0")
set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "master")
set(GNSSSDR_GPSTK_LOCAL_VERSION "3.0.0")
set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.18")
set(GNSSSDR_PUGIXML_LOCAL_VERSION "1.10")
set(GNSSSDR_PUGIXML_LOCAL_VERSION "1.11")
set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "3.14.0")
set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.5.2")
set(GNSSSDR_MATHJAX_EXTERNAL_VERSION "2.7.7")
@ -1133,6 +1133,9 @@ if(NOT VOLKGNSSSDR_FOUND)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(SUPPORTED_CPU_FEATURES_ARCH TRUE)
endif()
if(${CMAKE_INSTALL_LIBDIR} MATCHES lib64)
set(VOLK_GNSSSDR_LIB_SUFFIX 64)
endif()
if(CMAKE_VERSION VERSION_LESS 3.2)
ExternalProject_Add(volk_gnsssdr_module
PREFIX ${CMAKE_BINARY_DIR}/volk_gnsssdr_module
@ -1140,6 +1143,7 @@ if(NOT VOLKGNSSSDR_FOUND)
BINARY_DIR ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/build
CMAKE_ARGS ${VOLK_GNSSSDR_CMAKE_ARGS}
-DCMAKE_BUILD_TYPE=$<$<CONFIG:None>:None>$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>$<$<CONFIG:RelWithDebInfo>:RelWithDebInfo>$<$<CONFIG:MinSizeRel>:MinSizeRel>$<$<CONFIG:NoOptWithASM>:NoOptWithASM>$<$<CONFIG:Coverage>:Coverage>$<$<CONFIG:O2WithASM>:O2WithASM>$<$<CONFIG:O3WithASM>:O3WithASM>$<$<CONFIG:ASAN>:ASAN>
-DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
DOWNLOAD_COMMAND ""
UPDATE_COMMAND ""
PATCH_COMMAND ""
@ -1154,11 +1158,12 @@ if(NOT VOLKGNSSSDR_FOUND)
BINARY_DIR ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/build
CMAKE_ARGS ${VOLK_GNSSSDR_CMAKE_ARGS}
-DCMAKE_BUILD_TYPE=$<$<CONFIG:None>:None>$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>$<$<CONFIG:RelWithDebInfo>:RelWithDebInfo>$<$<CONFIG:MinSizeRel>:MinSizeRel>$<$<CONFIG:NoOptWithASM>:NoOptWithASM>$<$<CONFIG:Coverage>:Coverage>$<$<CONFIG:O2WithASM>:O2WithASM>$<$<CONFIG:O3WithASM>:O3WithASM>$<$<CONFIG:ASAN>:ASAN>
-DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
DOWNLOAD_COMMAND ""
UPDATE_COMMAND ""
PATCH_COMMAND ""
BUILD_COMMAND ${VOLK_GNSSSDR_BUILD_COMMAND} volk_gnsssdr_profile
BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib/${CMAKE_FIND_LIBRARY_PREFIXES}volk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX}
BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib${VOLK_GNSSSDR_LIB_SUFFIX}/${CMAKE_FIND_LIBRARY_PREFIXES}volk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX}
${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/bin/volk_gnsssdr_profile
${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/${CMAKE_INSTALL_LIBDIR}/${CMAKE_FIND_LIBRARY_PREFIXES}cpu_features${CMAKE_STATIC_LIBRARY_SUFFIX}
INSTALL_DIR ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install
@ -1170,11 +1175,12 @@ if(NOT VOLKGNSSSDR_FOUND)
BINARY_DIR ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/build
CMAKE_ARGS ${VOLK_GNSSSDR_CMAKE_ARGS}
-DCMAKE_BUILD_TYPE=$<$<CONFIG:None>:None>$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>$<$<CONFIG:RelWithDebInfo>:RelWithDebInfo>$<$<CONFIG:MinSizeRel>:MinSizeRel>$<$<CONFIG:NoOptWithASM>:NoOptWithASM>$<$<CONFIG:Coverage>:Coverage>$<$<CONFIG:O2WithASM>:O2WithASM>$<$<CONFIG:O3WithASM>:O3WithASM>$<$<CONFIG:ASAN>:ASAN>
-DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
DOWNLOAD_COMMAND ""
UPDATE_COMMAND ""
PATCH_COMMAND ""
BUILD_COMMAND ${VOLK_GNSSSDR_BUILD_COMMAND} volk_gnsssdr_profile
BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib/${CMAKE_FIND_LIBRARY_PREFIXES}volk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX}
BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib${VOLK_GNSSSDR_LIB_SUFFIX}/${CMAKE_FIND_LIBRARY_PREFIXES}volk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX}
${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/bin/volk_gnsssdr_profile
INSTALL_DIR ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install
)
@ -1187,7 +1193,7 @@ if(NOT VOLKGNSSSDR_FOUND)
endif()
add_library(volk_gnsssdr UNKNOWN IMPORTED)
set_property(TARGET volk_gnsssdr PROPERTY IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib/libvolk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET volk_gnsssdr PROPERTY IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib${VOLK_GNSSSDR_LIB_SUFFIX}/libvolk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX})
set(VOLK_GNSSSDR_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/volk_gnsssdr_module/build/include/;${CMAKE_SOURCE_DIR}/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/include;${ORC_INCLUDE_DIRS}")
set(VOLK_GNSSSDR_LIBRARIES volk_gnsssdr ${ORC_LIBRARIES})
@ -1197,7 +1203,7 @@ if(NOT VOLKGNSSSDR_FOUND)
add_dependencies(Volkgnsssdr::volkgnsssdr volk_gnsssdr_module)
set_target_properties(Volkgnsssdr::volkgnsssdr PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib/libvolk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX}"
IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib${VOLK_GNSSSDR_LIB_SUFFIX}/libvolk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX}"
INCLUDE_DIRECTORIES "${VOLK_GNSSSDR_INCLUDE_DIRS}"
INTERFACE_INCLUDE_DIRECTORIES "${VOLK_GNSSSDR_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${VOLK_GNSSSDR_LIBRARIES}"

View File

@ -125,6 +125,7 @@ if(ENABLE_FPGA)
target_link_libraries(acquisition_adapters
PRIVATE
algorithms_libs
core_libs
Gnuradio::fft
Volk::volk
Volkgnsssdr::volkgnsssdr

View File

@ -24,6 +24,7 @@
#include "galileo_e1_signal_replica.h"
#include "gnss_sdr_flags.h"
#include "gnss_sdr_make_unique.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -77,11 +78,18 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
float nbits = ceilf(log2f(static_cast<float>(code_length) * 2.0F));
uint32_t nsamples_total = pow(2, nbits);
uint32_t 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;
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the acquisition
if (find_uio_dev_file_name(device_io_name, acquisition_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << acquisition_device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GALILEO_E1_CODE_CHIP_RATE_CPS) * static_cast<float>(fs_in)));

View File

@ -183,6 +183,8 @@ public:
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
const std::string acquisition_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -24,6 +24,7 @@
#include "galileo_e5_signal_replica.h"
#include "gnss_sdr_flags.h"
#include "gnss_sdr_make_unique.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -80,11 +81,18 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 1);
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_code = nsamples_total;
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the acquisition
if (find_uio_dev_file_name(device_io_name, acquisition_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << acquisition_device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GALILEO_E5A_CODE_CHIP_RATE_CPS) * static_cast<float>(fs_in)));
// compute all the GALILEO E5 PRN Codes (this is done only once in the class constructor in order to avoid re-computing the PRN codes every time

View File

@ -191,6 +191,8 @@ public:
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
const std::string acquisition_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -24,6 +24,7 @@
#include "configuration_interface.h"
#include "galileo_e5_signal_replica.h"
#include "gnss_sdr_flags.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -79,11 +80,18 @@ GalileoE5bPcpsAcquisitionFpga::GalileoE5bPcpsAcquisitionFpga(const Configuration
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 1);
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_code = nsamples_total;
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the acquisition
if (find_uio_dev_file_name(device_io_name, acquisition_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << acquisition_device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GALILEO_E5B_CODE_CHIP_RATE_CPS) * static_cast<float>(fs_in)));
// compute all the GALILEO E5b PRN Codes (this is done only once in the class constructor in order to avoid re-computing the PRN codes every time

View File

@ -190,6 +190,8 @@ public:
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
const std::string acquisition_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -27,6 +27,7 @@
#include "gnss_sdr_flags.h"
#include "gnss_sdr_make_unique.h"
#include "gps_sdr_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h>
#include <gnuradio/gr_complex.h> // for gr_complex
@ -72,9 +73,17 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
uint32_t nsamples_total = pow(2, nbits);
uint32_t 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;
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the acquisition
if (find_uio_dev_file_name(device_io_name, acquisition_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << acquisition_device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil(GPS_L1_CA_CHIP_PERIOD_S * static_cast<float>(fs_in)));

View File

@ -187,6 +187,8 @@ public:
private:
static const uint32_t NUM_PRNs = 32;
const std::string acquisition_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -27,6 +27,7 @@
#include "gnss_sdr_make_unique.h"
#include "gnss_synchro.h"
#include "gps_l2c_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -70,11 +71,18 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
unsigned int nsamples_total = pow(2, nbits);
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_code = nsamples_total;
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the acquisition
if (find_uio_dev_file_name(device_io_name, acquisition_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << acquisition_device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.downsampling_factor = configuration->property(role + ".downsampling_factor", 1.0);
acq_parameters.total_block_exp = configuration->property(role + ".total_block_exp", 14);
acq_parameters.excludelimit = static_cast<uint32_t>(std::round(static_cast<double>(fs_in_) / GPS_L2_M_CODE_RATE_CPS));

View File

@ -151,6 +151,8 @@ public:
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
const std::string acquisition_device_name = "acquisition_S00_AXI"; // UIO device name
static const uint32_t NUM_PRNs = 32;
static const uint32_t QUANT_BITS_LOCAL_CODE = 16;
static const uint32_t SELECT_LSBits = 0x0000FFFF; // Select the 10 LSbits out of a 20-bit word

View File

@ -27,6 +27,7 @@
#include "gnss_sdr_flags.h"
#include "gnss_sdr_make_unique.h"
#include "gps_l5_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -76,11 +77,18 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 1);
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_code = nsamples_total;
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the acquisition
if (find_uio_dev_file_name(device_io_name, acquisition_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << acquisition_device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GPS_L5I_CODE_RATE_CPS) * static_cast<float>(fs_in)));
// compute all the GPS L5 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time

View File

@ -187,6 +187,8 @@ public:
private:
static const uint32_t NUM_PRNs = 32;
const std::string acquisition_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -341,6 +341,14 @@ if(DOXYGEN_FOUND)
endif()
########################################################################
# Detect /lib versus /lib64
########################################################################
if(${CMAKE_INSTALL_LIBDIR} MATCHES lib64)
set(LIB_SUFFIX 64)
endif()
########################################################################
# Setup the package config file
########################################################################

View File

@ -146,6 +146,13 @@ target_include_directories(signal_source_adapters
${CMAKE_SOURCE_DIR}/src/core/interfaces
)
if(ENABLE_FPGA OR ENABLE_AD9361)
target_link_libraries(signal_source_adapters
PRIVATE
core_libs
)
endif()
target_link_libraries(signal_source_adapters
PUBLIC
Boost::headers

View File

@ -28,6 +28,7 @@
#include "ad9361_manager.h"
#include "configuration_interface.h"
#include "gnss_sdr_flags.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <iio.h>
#include <algorithm> // for max
@ -90,9 +91,16 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
rf_shutdown_ = configuration->property(role + ".rf_shutdown", FLAGS_rf_shutdown);
// turn switch to A/D position
const std::string default_device_name("/dev/uio1");
const std::string device_name = configuration->property(role + ".devicename", default_device_name);
// Switch UIO device file
std::string device_io_name;
// find the uio device file corresponding to the switch.
if (find_uio_dev_file_name(device_io_name, switch_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << switch_device_name << std::endl;
throw std::exception();
}
switch_position = configuration->property(role + ".switch_position", 0);
if (switch_position != 0 && switch_position != 2)
{
@ -101,7 +109,7 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
switch_position = 0;
}
switch_fpga = std::make_shared<Fpga_Switch>(device_name);
switch_fpga = std::make_shared<Fpga_Switch>(device_io_name);
switch_fpga->set_switch_position(switch_position);
item_size_ = sizeof(gr_complex);
@ -293,11 +301,22 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
enable_dynamic_bit_selection_ = configuration->property(role + ".enable_dynamic_bit_selection", true);
if (enable_dynamic_bit_selection_)
{
const std::string dynamic_bit_selection_default_device_name1("/dev/uio48");
std::string device_name1 = configuration->property(role + ".dyn_bits_sel_devicename", dynamic_bit_selection_default_device_name1);
const std::string dynamic_bit_selection_default_device_name2("/dev/uio49");
std::string device_name2 = configuration->property(role + ".dyn_bits_sel_devicename", dynamic_bit_selection_default_device_name2);
dynamic_bit_selection_fpga = std::make_shared<Fpga_dynamic_bit_selection>(device_name1, device_name2);
std::string device_io_name_dyn_bit_sel_0, device_io_name_dyn_bit_sel_1;
// find the uio device file corresponding to the dynamic bit selector 0 module.
if (find_uio_dev_file_name(device_io_name_dyn_bit_sel_0, dyn_bit_sel_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << dyn_bit_sel_device_name << std::endl;
throw std::exception();
}
// find the uio device file corresponding to the dynamic bit selector 1 module.
if (find_uio_dev_file_name(device_io_name_dyn_bit_sel_1, dyn_bit_sel_device_name, 1) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << dyn_bit_sel_device_name << std::endl;
throw std::exception();
}
dynamic_bit_selection_fpga = std::make_shared<Fpga_dynamic_bit_selection>(device_io_name_dyn_bit_sel_0, device_io_name_dyn_bit_sel_1);
thread_dynamic_bit_selection = std::thread([&] { run_dynamic_bit_selection_process(); });
}

View File

@ -50,7 +50,7 @@ public:
~Ad9361FpgaSignalSource();
void start();
void start() override;
inline std::string role() override
{
@ -76,6 +76,9 @@ public:
gr::basic_block_sptr get_right_block() override;
private:
const std::string switch_device_name = "AXIS_Switch_v1_0_0"; // Switch UIO device name
const std::string dyn_bit_sel_device_name = "dynamic_bits_selector"; // Switch UIO device name
// perform dynamic bit selection every 500 ms by default
static const uint32_t Gain_control_period_ms = 500;

View File

@ -111,6 +111,13 @@ target_include_directories(tracking_adapters
${CMAKE_SOURCE_DIR}/src/core/interfaces
)
if(ENABLE_FPGA)
target_link_libraries(tracking_adapters
PRIVATE
core_libs
)
endif()
if(ENABLE_CUDA)
if(CMAKE_VERSION VERSION_GREATER 3.11)
target_include_directories(tracking_adapters

View File

@ -30,6 +30,7 @@
#include "dll_pll_conf_fpga.h"
#include "galileo_e1_signal_replica.h"
#include "gnss_sdr_flags.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <volk_gnsssdr/volk_gnsssdr_alloc.h>
#include <array>
@ -63,15 +64,14 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
const std::array<char, 3> sig_{'1', 'B', '\0'};
std::memcpy(trk_params_fpga.signal, sig_.data(), 3);
// FPGA configuration parameters
// obtain the number of the first uio device corresponding to a HW accelerator in the FPGA
// that can be assigned to the tracking of the E1 signal
trk_params_fpga.dev_file_num = configuration->property(role + ".dev_file_num", 15);
// UIO device file
device_name = configuration->property(role + ".devicename", default_device_name);
// compute the number of tracking channels that have already been instantiated. The order in which
// GNSS-SDR instantiates the tracking channels i L1, L2, L5, E1, E5a
trk_params_fpga.num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_2S.count", 0) +
configuration->property("Channels_L5.count", 0);
num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_2S.count", 0) +
configuration->property("Channels_L5.count", 0);
// ################# PRE-COMPUTE ALL THE CODES #################
uint32_t code_samples_per_chip = 2;
@ -184,7 +184,16 @@ void GalileoE1DllPllVemlTrackingFpga::start_tracking()
void GalileoE1DllPllVemlTrackingFpga::set_channel(unsigned int channel)
{
channel_ = channel;
tracking_fpga_sc->set_channel(channel);
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the tracking multicorrelator
if (find_uio_dev_file_name(device_io_name, device_name, channel - num_prev_assigned_ch) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
tracking_fpga_sc->set_channel(channel, device_io_name);
}

View File

@ -126,11 +126,16 @@ public:
void stop_tracking() override;
private:
const std::string default_device_name = "multicorrelator_resampler_5_1_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const int32_t LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY = 0x0C000000; // flag that enables WE (Write Enable) of the local code FPGA
static const int32_t LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT = 0x20000000; // flag that selects the writing of the pilot code in the FPGA (as opposed to the data code)
std::string device_name;
uint32_t num_prev_assigned_ch;
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
uint32_t channel_;
std::string role_;

View File

@ -25,6 +25,7 @@
#include "dll_pll_conf_fpga.h"
#include "galileo_e5_signal_replica.h"
#include "gnss_sdr_flags.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <volk_gnsssdr/volk_gnsssdr_alloc.h>
#include <array>
@ -60,19 +61,18 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
d_data_codes = nullptr;
// FPGA configuration parameters
// obtain the number of the first uio device corresponding to a HW accelerator in the FPGA
// that can be assigned to the tracking of the E5a signal
trk_params_fpga.dev_file_num = configuration->property(role + ".dev_file_num", 27);
// UIO device file
device_name = configuration->property(role + ".devicename", default_device_name);
// compute the number of tracking channels that have already been instantiated. The order in which
// GNSS-SDR instantiates the tracking channels i L1, L2, L5, E1, E5a
// However E5a can use the same tracking HW accelerators as L5 (but not simultaneously).
// Therefore for the proper assignment of the FPGA tracking device file numbers to the E5a tracking channels,
// the number of channels that have already been assigned to L5 must not be substracted to this channel number,
// so they are not counted here.
trk_params_fpga.num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_2S.count", 0) +
configuration->property("Channels_1B.count", 0);
num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_2S.count", 0) +
configuration->property("Channels_1B.count", 0);
// ################# PRE-COMPUTE ALL THE CODES #################
uint32_t code_samples_per_chip = 1;
@ -207,7 +207,16 @@ void GalileoE5aDllPllTrackingFpga::stop_tracking()
void GalileoE5aDllPllTrackingFpga::set_channel(unsigned int channel)
{
channel_ = channel;
tracking_fpga_sc->set_channel(channel);
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the tracking multicorrelator
if (find_uio_dev_file_name(device_io_name, device_name, channel - num_prev_assigned_ch) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
tracking_fpga_sc->set_channel(channel, device_io_name);
}

View File

@ -119,11 +119,15 @@ public:
void stop_tracking() override;
private:
const std::string default_device_name = "multicorrelator_resampler_3_1_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const int32_t LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY = 0x0C000000; // flag that enables WE (Write Enable) of the local code FPGA
static const int32_t LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT = 0x20000000; // flag that selects the writing of the pilot code in the FPGA (as opposed to the data code)
std::string device_name;
uint32_t num_prev_assigned_ch;
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
uint32_t channel_;

View File

@ -30,6 +30,7 @@
#include "dll_pll_conf_fpga.h"
#include "gnss_sdr_flags.h"
#include "gps_sdr_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <array>
@ -68,13 +69,12 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
const std::array<char, 3> sig_{'1', 'C', '\0'};
std::memcpy(trk_params_fpga.signal, sig_.data(), 3);
// FPGA configuration parameters
// obtain the number of the first uio device corresponding to a HW accelerator in the FPGA
// that can be assigned to the tracking of the L1 signal
trk_params_fpga.dev_file_num = configuration->property(role + ".dev_file_num", 3);
// UIO device file
device_name = configuration->property(role + ".devicename", default_device_name);
// compute the number of tracking channels that have already been instantiated. The order in which
// GNSS-SDR instantiates the tracking channels i L1, l2, L5, E1, E5a
trk_params_fpga.num_prev_assigned_ch = 0;
num_prev_assigned_ch = 0;
// ################# PRE-COMPUTE ALL THE CODES #################
d_ca_codes = static_cast<int32_t*>(volk_gnsssdr_malloc(static_cast<int32_t>(GPS_L1_CA_CODE_LENGTH_CHIPS * NUM_PRNs) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
@ -153,7 +153,17 @@ void GpsL1CaDllPllTrackingFpga::stop_tracking()
void GpsL1CaDllPllTrackingFpga::set_channel(unsigned int channel)
{
channel_ = channel;
tracking_fpga_sc->set_channel(channel);
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the tracking multicorrelator
if (find_uio_dev_file_name(device_io_name, device_name, channel - num_prev_assigned_ch) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
tracking_fpga_sc->set_channel(channel, device_io_name);
}

View File

@ -124,12 +124,16 @@ public:
void stop_tracking() override;
private:
const std::string default_device_name = "multicorrelator_resampler_S00_AXI"; // UIO device name
static const uint32_t NUM_PRNs = 32; // total number of PRNs
static const int32_t GPS_CA_BIT_DURATION_MS = 20;
// the following flag is FPGA-specific and they are using arrange the values of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const int32_t LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY = 0x0C000000; // flag that enables WE (Write Enable) of the local code FPGA
std::string device_name;
uint32_t num_prev_assigned_ch;
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
uint32_t channel_;

View File

@ -32,6 +32,7 @@
#include "gnss_sdr_flags.h"
#include "gnss_synchro.h"
#include "gps_l2c_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <volk_gnsssdr/volk_gnsssdr_alloc.h>
#include <array>
@ -66,12 +67,12 @@ GpsL2MDllPllTrackingFpga::GpsL2MDllPllTrackingFpga(
const std::array<char, 3> sig_{'2', 'S', '\0'};
std::memcpy(trk_params_fpga.signal, sig_.data(), 3);
// FPGA configuration parameters
// obtain the number of the first uio device file that is assigned to the FPGA L2 tracking multicorrelator HW accelerators
trk_params_fpga.dev_file_num = configuration->property(role + ".dev_file_num", 27);
// UIO device file
device_name = configuration->property(role + ".devicename", default_device_name);
// compute the number of tracking channels that have already been instantiated. The order in which
// GNSS-SDR instantiates the tracking channels i L1, L2, L5, E1, E5a
trk_params_fpga.num_prev_assigned_ch = configuration->property("Channels_1C.count", 0);
num_prev_assigned_ch = configuration->property("Channels_1C.count", 0);
volk_gnsssdr::vector<float> ca_codes_f(static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS), 0.0);
// ################# PRE-COMPUTE ALL THE CODES #################
@ -130,7 +131,17 @@ void GpsL2MDllPllTrackingFpga::stop_tracking()
void GpsL2MDllPllTrackingFpga::set_channel(unsigned int channel)
{
channel_ = channel;
tracking_fpga_sc->set_channel(channel);
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the tracking multicorrelator
if (find_uio_dev_file_name(device_io_name, device_name, channel - num_prev_assigned_ch) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
tracking_fpga_sc->set_channel(channel, device_io_name);
}

View File

@ -95,6 +95,11 @@ public:
void stop_tracking() override;
private:
const std::string default_device_name = "multicorrelator_resampler_S00_AXI"; // UIO device name
std::string device_name;
uint32_t num_prev_assigned_ch;
static const uint32_t NUM_PRNs = 32;
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
unsigned int channel_;

View File

@ -32,6 +32,7 @@
#include "dll_pll_conf_fpga.h"
#include "gnss_sdr_flags.h"
#include "gps_l5_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <volk_gnsssdr/volk_gnsssdr_alloc.h>
#include <array>
@ -65,14 +66,13 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
const std::array<char, 3> sig_{'L', '5', '\0'};
std::memcpy(trk_params_fpga.signal, sig_.data(), 3);
// FPGA configuration parameters
// obtain the number of the first uio device corresponding to a HW accelerator in the FPGA
// that can be assigned to the tracking of the L5 signal
trk_params_fpga.dev_file_num = configuration->property(role + ".dev_file_num", 27);
// UIO device file
device_name = configuration->property(role + ".devicename", default_device_name);
// compute the number of tracking channels that have already been instantiated. The order in which
// GNSS-SDR instantiates the tracking channels i L1, L2, L5, E1, E5a
trk_params_fpga.num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_2S.count", 0);
num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_2S.count", 0);
// ################# PRE-COMPUTE ALL THE CODES #################
uint32_t code_samples_per_chip = 1;
@ -215,7 +215,17 @@ void GpsL5DllPllTrackingFpga::stop_tracking()
void GpsL5DllPllTrackingFpga::set_channel(unsigned int channel)
{
channel_ = channel;
tracking_fpga_sc->set_channel(channel);
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the tracking multicorrelator
if (find_uio_dev_file_name(device_io_name, device_name, channel - num_prev_assigned_ch) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
tracking_fpga_sc->set_channel(channel, device_io_name);
}

View File

@ -125,6 +125,8 @@ public:
void stop_tracking() override;
private:
const std::string default_device_name = "multicorrelator_resampler_3_1_AXI"; // UIO device name
static const uint32_t NUM_PRNs = 32; // total number of PRNs
// the following flags are FPGA-specific and they are using arrange the values of the local code in the way the FPGA
@ -132,6 +134,9 @@ private:
static const int32_t LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY = 0x0C000000; // flag that enables WE (Write Enable) of the local code FPGA
static const int32_t LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT = 0x20000000; // flag that selects the writing of the pilot code in the FPGA (as opposed to the data code)
std::string device_name;
uint32_t num_prev_assigned_ch;
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
uint32_t channel_;
std::string role_;

View File

@ -466,12 +466,9 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga &
}
}
// create multicorrelator class
const std::string device_name = d_trk_parameters.device_name;
const uint32_t dev_file_num = d_trk_parameters.dev_file_num;
const uint32_t num_prev_assigned_ch = d_trk_parameters.num_prev_assigned_ch;
int32_t *ca_codes = d_trk_parameters.ca_codes;
int32_t *data_codes = d_trk_parameters.data_codes;
d_multicorrelator_fpga = std::make_shared<Fpga_Multicorrelator_8sc>(d_n_correlator_taps, device_name, dev_file_num, num_prev_assigned_ch, ca_codes, data_codes, d_code_length_chips, d_trk_parameters.track_pilot, d_code_samples_per_chip);
d_multicorrelator_fpga = std::make_shared<Fpga_Multicorrelator_8sc>(d_n_correlator_taps, ca_codes, data_codes, d_code_length_chips, d_trk_parameters.track_pilot, d_code_samples_per_chip);
d_multicorrelator_fpga->set_output_vectors(d_correlator_outs.data(), d_Prompt_Data.data());
d_sample_counter_next = 0ULL;
@ -1313,12 +1310,12 @@ int32_t dll_pll_veml_tracking_fpga::save_matfile() const
}
void dll_pll_veml_tracking_fpga::set_channel(uint32_t channel)
void dll_pll_veml_tracking_fpga::set_channel(uint32_t channel, std::string device_io_name)
{
gr::thread::scoped_lock l(d_setlock);
d_channel = channel;
d_multicorrelator_fpga->set_channel(d_channel);
d_multicorrelator_fpga->open_channel(device_io_name, channel);
LOG(INFO) << "Tracking Channel set to " << d_channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump)

View File

@ -69,7 +69,7 @@ public:
/*!
* \brief Set the channel number and configure some multicorrelator parameters
*/
void set_channel(uint32_t channel);
void set_channel(uint32_t channel, std::string device_io_name);
/*!
* \brief This function is used with two purposes:

View File

@ -75,8 +75,6 @@ Dll_Pll_Conf_Fpga::Dll_Pll_Conf_Fpga()
signal[1] = 'C';
signal[2] = '\0';
device_name = "/dev/uio";
dev_file_num = 3;
num_prev_assigned_ch = 0;
code_length_chips = 0U;
code_samples_per_chip = 0U;
ca_codes = nullptr;

View File

@ -68,8 +68,6 @@ public:
uint32_t bit_synchronization_time_limit_s;
uint32_t vector_length;
uint32_t smoother_length;
uint32_t dev_file_num;
uint32_t num_prev_assigned_ch;
uint32_t code_length_chips;
uint32_t code_samples_per_chip;
uint32_t extend_fpga_integration_periods;

View File

@ -50,9 +50,6 @@ const float PHASE_CARR_MAX_DIV_PI = 683565275.5764316; // 2^(31)/pi
const float TWO_PI = 6.283185307179586;
Fpga_Multicorrelator_8sc::Fpga_Multicorrelator_8sc(int32_t n_correlators,
const std::string &device_name,
uint32_t dev_file_num,
uint32_t num_prev_assigned_ch,
int32_t *ca_codes,
int32_t *data_codes,
uint32_t code_length_chips,
@ -60,10 +57,6 @@ Fpga_Multicorrelator_8sc::Fpga_Multicorrelator_8sc(int32_t n_correlators,
uint32_t code_samples_per_chip)
{
d_n_correlators = n_correlators;
d_device_name = device_name;
d_dev_file_num = dev_file_num;
d_num_prev_assigned_ch = num_prev_assigned_ch;
d_track_pilot = track_pilot;
d_device_descriptor = 0;
d_map_base = nullptr;
@ -91,7 +84,6 @@ Fpga_Multicorrelator_8sc::Fpga_Multicorrelator_8sc(int32_t 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;
d_code_phase_step_chips_num = 0;
d_code_length_chips = code_length_chips;
@ -203,28 +195,11 @@ bool Fpga_Multicorrelator_8sc::free()
}
void Fpga_Multicorrelator_8sc::set_channel(uint32_t channel)
void Fpga_Multicorrelator_8sc::open_channel(std::string device_io_name, uint32_t 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;
uint32_t numdevice = d_dev_file_num + d_channel - d_num_prev_assigned_ch;
devicebasetemp << numdevice;
mergedname = d_device_name + devicebasetemp.str();
if (mergedname.size() > max_length_deviceio_name)
{
mergedname = mergedname.substr(0, max_length_deviceio_name);
}
mergedname.copy(device_io_name, mergedname.size() + 1);
device_io_name[mergedname.size()] = '\0';
std::cout << "trk device_io_name = " << device_io_name << '\n';
if ((d_device_descriptor = open(device_io_name, O_RDWR | O_SYNC)) == -1)
if ((d_device_descriptor = open(device_io_name.c_str(), O_RDWR | O_SYNC)) == -1)
{
LOG(WARNING) << "Cannot open deviceio" << device_io_name;
std::cout << "Cannot open deviceio" << device_io_name << '\n';
@ -235,7 +210,7 @@ void Fpga_Multicorrelator_8sc::set_channel(uint32_t channel)
if (d_map_base == reinterpret_cast<void *>(-1))
{
LOG(WARNING) << "Cannot map the FPGA tracking module "
<< d_channel << "into user memory";
<< channel << "into user memory";
std::cout << "Cannot map deviceio" << device_io_name << '\n';
}

View File

@ -47,9 +47,6 @@ public:
* \brief Constructor
*/
Fpga_Multicorrelator_8sc(int32_t n_correlators,
const std::string &device_name,
uint32_t dev_file_num,
uint32_t num_prev_assigned_ch,
int32_t *ca_codes,
int32_t *data_codes,
uint32_t code_length_chips,
@ -95,9 +92,9 @@ public:
bool free();
/*!
* \brief Set channel number and open the FPGA device driver
* \brief Open the FPGA device driver
*/
void set_channel(uint32_t channel);
void open_channel(std::string device_io_name, uint32_t channel);
/*!
* \brief Set the initial sample number where the tracking process begins
@ -193,7 +190,6 @@ private:
static const uint32_t enable_secondary_code = 2; // bit 1 of drop_samples_reg_addr
static const uint32_t init_secondary_code_addresses = 4; // bit 2 of drop_samples_reg_addr
static const uint32_t page_size = 0x10000;
static const uint32_t max_length_deviceio_name = 50;
static const uint32_t max_code_resampler_counter = 1 << 31; // 2^(number of bits of precision of the code resampler)
static const uint32_t local_code_fpga_clear_address_counter = 0x10000000;
static const uint32_t test_register_track_writeval = 0x55AA;
@ -237,7 +233,6 @@ private:
volatile uint32_t *d_map_base; // driver memory map
// configuration data received from the interface
uint32_t d_channel; // channel number
uint32_t d_correlator_length_samples;
uint32_t d_code_samples_per_chip;
@ -247,11 +242,6 @@ private:
int32_t d_phase_step_rad_int;
int32_t d_carrier_phase_rate_step_rad_int;
// driver
std::string d_device_name;
uint32_t d_dev_file_num;
uint32_t d_num_prev_assigned_ch;
// PRN codes
int32_t *d_ca_codes;
int32_t *d_data_codes;

View File

@ -44,6 +44,17 @@ if(ENABLE_FPGA)
)
endif()
if(ENABLE_FPGA OR ENABLE_AD9361)
set(CORE_LIBS_SOURCES
${CORE_LIBS_SOURCES}
uio_fpga.cc
)
set(CORE_LIBS_HEADERS
${CORE_LIBS_HEADERS}
uio_fpga.h
)
endif()
list(SORT CORE_LIBS_HEADERS)
list(SORT CORE_LIBS_SOURCES)
@ -114,6 +125,18 @@ if(USE_BOOST_BIND_PLACEHOLDERS)
)
endif()
if(ENABLE_FPGA OR ENABLE_AD9361)
if(FILESYSTEM_FOUND)
target_compile_definitions(core_libs PRIVATE -DHAS_STD_FILESYSTEM=1)
if(find_experimental)
target_compile_definitions(core_libs PRIVATE -DHAS_STD_FILESYSTEM_EXPERIMENTAL=1)
endif()
target_link_libraries(core_libs PRIVATE std::filesystem)
else()
target_link_libraries(core_libs PRIVATE Boost::filesystem Boost::system)
endif()
endif()
if(ENABLE_CLANG_TIDY)
if(CLANG_TIDY_EXE)
set_target_properties(core_libs

View File

@ -21,6 +21,7 @@
#include "gnss_sdr_fpga_sample_counter.h"
#include "gnss_synchro.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/io_signature.h>
#include <pmt/pmt.h> // for from_double
@ -132,11 +133,20 @@ void gnss_sdr_fpga_sample_counter::configure_samples_per_output(uint32_t interva
void gnss_sdr_fpga_sample_counter::open_device()
{
// open communication with HW accelerator
if ((fd = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1)
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the sample counter module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
LOG(WARNING) << "Cannot open deviceio" << device_name;
std::cout << "Counter-Intr: cannot open deviceio" << device_name << '\n';
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
// open communication with HW accelerator
if ((fd = open(device_io_name.c_str(), O_RDWR | O_SYNC)) == -1)
{
LOG(WARNING) << "Cannot open deviceio" << device_io_name;
std::cout << "Counter-Intr: cannot open deviceio" << device_io_name << '\n';
}
map_base = reinterpret_cast<volatile uint32_t *>(mmap(nullptr, page_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
@ -144,7 +154,7 @@ void gnss_sdr_fpga_sample_counter::open_device()
if (map_base == reinterpret_cast<void *>(-1))
{
LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory";
std::cout << "Counter-Intr: cannot map deviceio" << device_name << '\n';
std::cout << "Counter-Intr: cannot map deviceio" << device_io_name << '\n';
}
// sanity check : check test register

View File

@ -50,6 +50,8 @@ public:
gr_vector_void_star &output_items);
private:
const std::string device_name = "counter"; // UIO device name
static const uint32_t page_size = 0x10000; // default page size for the multicorrelator memory map
static const uint32_t test_reg_sanity_check = 0x55AA; // value to check the presence of the test register (to detect the hw)
@ -63,8 +65,7 @@ private:
bool stop();
void wait_for_interrupt(void);
volatile uint32_t *map_base; // driver memory map
std::string device_name = "/dev/uio2"; // HW device name
volatile uint32_t *map_base; // driver memory map
double fs;
uint64_t sample_counter;

213
src/core/libs/uio_fpga.cc Normal file
View File

@ -0,0 +1,213 @@
/*!
* \file uio_fpga.cc
* \brief This library contains functions to determine the uio device driver
* file that corresponds to a hardware accelerator device name in the FPGA.
* \author Marc Majoral, 2020. mmajoral(at)cttc.es
*
* -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2020 (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.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "uio_fpga.h"
#include <algorithm> // sort
#include <cstdlib> // atoi, size_t
#include <fstream> // ifstream
#include <iostream> // cout
#include <locale> // isdigit
#include <sstream> // std::stringstream
#include <vector>
#if HAS_STD_FILESYSTEM
#if HAS_STD_FILESYSTEM_EXPERIMENTAL
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <filesystem>
namespace fs = std::filesystem;
#endif
#else
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
namespace fs = boost::filesystem;
#endif
int32_t get_uio_num(std::string uio_name)
{
size_t i = 0;
// search first digit
for (; i < uio_name.length(); i++)
{
if (isdigit(uio_name[i])) break;
}
// remove the first chars, which aren't digits
std::string uio_num = uio_name.substr(i, uio_name.length() - i);
// convert the remaining text to an integer
return atoi(uio_num.c_str());
}
void get_uio_name(uint32_t uio_num, std::string &uio_name)
{
std::stringstream filename;
filename << uio_dir << uio_filename << uio_num << uio_subdir_name;
std::ifstream infile;
infile.open(filename.str());
if (infile.is_open())
{
std::getline(infile, uio_name);
if (infile.bad())
{
std::cout << "Could not read the FPGA uio device information file\n";
throw std::exception();
}
infile.close();
}
else
{
std::cout << "Could not open the FPGA uio device information file\n";
throw std::exception();
}
}
int my_strverscmp(const char *s1, const char *s2)
{
// from https://code.woboq.org/userspace/glibc/string/strverscmp.c.html
const uint8_t S_N = 0x0;
const uint8_t S_I = 0x3;
const uint8_t S_F = 0x6;
const uint8_t S_Z = 0x9;
const int8_t CMP = 2;
const int8_t LEN = 3;
const unsigned char *p1 = (const unsigned char *)s1;
const unsigned char *p2 = (const unsigned char *)s2;
/* Symbol(s) 0 [1-9] others
Transition (10) 0 (01) d (00) x */
static const uint8_t next_state[] =
{
/* state x d 0 */
/* S_N */ S_N, S_I, S_Z,
/* S_I */ S_N, S_I, S_I,
/* S_F */ S_N, S_F, S_F,
/* S_Z */ S_N, S_F, S_Z};
static const int8_t result_type[] =
{
/* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
/* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
/* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN,
/* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
/* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP};
if (p1 == p2)
{
return 0;
}
unsigned char c1 = *p1++;
unsigned char c2 = *p2++;
/* Hint: '0' is a digit too. */
int state = S_N + ((c1 == '0') + (isdigit(c1) != 0));
int diff;
while ((diff = c1 - c2) == 0)
{
if (c1 == '\0')
{
return diff;
}
state = next_state[state];
c1 = *p1++;
c2 = *p2++;
state += (c1 == '0') + (isdigit(c1) != 0);
}
state = result_type[state * 3 + (((c2 == '0') + (isdigit(c2) != 0)))];
switch (state)
{
case CMP:
return diff;
case LEN:
while (isdigit(*p1++))
{
if (!isdigit(*p2++))
{
return 1;
}
}
return isdigit(*p2) ? -1 : diff;
default:
return state;
}
}
bool sort_directories(fs::directory_entry a, fs::directory_entry b)
{
int cmp = my_strverscmp(a.path().string().c_str(), b.path().string().c_str());
return (cmp < 0);
}
int32_t find_uio_num(const std::string &device_name, uint32_t device_num)
{
int32_t uio_num;
uint32_t uio_count = 0;
// search for the requested device driver
fs::path path(uio_dir);
std::vector<fs::directory_entry> dirs;
for (auto &p : fs::directory_iterator(path))
{
dirs.push_back(p);
}
std::sort(dirs.begin(), dirs.end(), sort_directories);
for (auto &p : dirs)
{
// get the uio number corresponding to directory entry n
uio_num = get_uio_num(p.path().string());
if (uio_num >= 0) // valid uio number
{
std::string nametemp;
get_uio_name(uio_num, nametemp);
if (device_name.compare(nametemp) == 0)
{
if (uio_count == device_num)
{
return uio_num;
}
else
{
uio_count++;
}
}
}
}
return -1; // uio number not found
}
int32_t find_uio_dev_file_name(std::string &device_file_name, const std::string &device_name, uint32_t device_num)
{
int32_t uio_num = find_uio_num(device_name, device_num);
if (uio_num >= 0)
{
std::stringstream device_file_name_tmp;
device_file_name_tmp << "/dev/uio" << uio_num;
device_file_name = device_file_name_tmp.str();
return 0;
}
return -1;
}

47
src/core/libs/uio_fpga.h Normal file
View File

@ -0,0 +1,47 @@
/*!
* \file uio_fpga.h
* \brief This library contains functions to determine the uio device driver
* file that corresponds to a hardware accelerator device name in the FPGA.
* \author Marc Majoral, 2020. mmajoral(at)cttc.es
*
* -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2020 (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.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_UIO_FPGA_H
#define GNSS_SDR_UIO_FPGA_H
#include <cstdint>
#include <string>
/** \addtogroup Core
* \{ */
/** \addtogroup Core_Receiver_Library
* \{ */
const std::string uio_dir("/sys/class/uio/");
const std::string uio_filename("uio");
const std::string uio_subdir_name("/name");
/*!
* \brief This function finds the uio device driver device file name out of the
* device name and the device number.
*/
int32_t find_uio_dev_file_name(std::string &device_file_name,
const std::string &device_name,
uint32_t device_num);
/** \} */
/** \} */
#endif // GNSS_SDR_UIO_FPGA_H

View File

@ -149,41 +149,65 @@ double Beidou_Dnav_Ephemeris::satellitePosition(double transmitTime)
}
// Compute the true anomaly
const double tmp_Y = sqrt(1.0 - d_eccentricity * d_eccentricity) * sin(E);
const double tmp_X = cos(E) - d_eccentricity;
const double sek = sin(E);
const double cek = cos(E);
const double OneMinusecosE = 1.0 - d_eccentricity * cek;
const double ekdot = n / OneMinusecosE;
// Compute the true anomaly
const double sq1e2 = sqrt(1.0 - d_eccentricity * d_eccentricity);
const double tmp_Y = sq1e2 * sek;
const double tmp_X = cek - d_eccentricity;
const double nu = atan2(tmp_Y, tmp_X);
// Compute angle phi (argument of Latitude)
double phi = nu + d_OMEGA;
const double phi = nu + d_OMEGA;
double pkdot = sq1e2 * ekdot / OneMinusecosE;
// Reduce phi to between 0 and 2*pi rad
phi = fmod((phi), (2.0 * GNSS_PI));
// phi = fmod((phi), (2.0 * GNSS_PI));
const double s2pk = sin(2.0 * phi);
const double c2pk = cos(2.0 * phi);
// Correct argument of latitude
const double u = phi + d_Cuc * cos(2.0 * phi) + d_Cus * sin(2.0 * phi);
const double u = phi + d_Cuc * c2pk + d_Cus * s2pk;
const double cuk = cos(u);
const double suk = sin(u);
const double ukdot = pkdot * (1.0 + 2.0 * (d_Cus * c2pk - d_Cuc * s2pk));
// Correct radius
const double r = a * (1.0 - d_eccentricity * cos(E)) + d_Crc * cos(2.0 * phi) + d_Crs * sin(2.0 * phi);
const double r = a * (1.0 - d_eccentricity * cek) + d_Crc * c2pk + d_Crs * s2pk;
const double rkdot = a * d_eccentricity * sek * ekdot + 2.0 * pkdot * (d_Crs * c2pk - d_Crc * s2pk);
// Correct inclination
const double i = d_i_0 + d_IDOT * tk + d_Cic * cos(2.0 * phi) + d_Cis * sin(2.0 * phi);
const double i = d_i_0 + d_IDOT * tk + d_Cic * c2pk + d_Cis * s2pk;
const double sik = sin(i);
const double cik = cos(i);
const double ikdot = d_IDOT + 2.0 * pkdot * (d_Cis * c2pk - d_Cic * s2pk);
// Compute the angle between the ascending node and the Greenwich meridian
double Omega = d_OMEGA0 + (d_OMEGA_DOT - BEIDOU_OMEGA_EARTH_DOT) * tk - BEIDOU_OMEGA_EARTH_DOT * d_Toe;
// Reduce to between 0 and 2*pi rad
Omega = fmod((Omega + 2.0 * GNSS_PI), (2.0 * GNSS_PI));
const double Omega = d_OMEGA0 + (d_OMEGA_DOT - BEIDOU_OMEGA_EARTH_DOT) * tk - BEIDOU_OMEGA_EARTH_DOT * d_Toe;
const double sok = sin(Omega);
const double cok = cos(Omega);
// --- Compute satellite coordinates in Earth-fixed coordinates
d_satpos_X = cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega);
d_satpos_Y = cos(u) * r * sin(Omega) + sin(u) * r * cos(i) * cos(Omega);
d_satpos_Z = sin(u) * r * sin(i);
const double xprime = r * cuk;
const double yprime = r * suk;
d_satpos_X = xprime * cok - yprime * cik * sok;
d_satpos_Y = xprime * sok + yprime * cik * cok;
d_satpos_Z = yprime * sik;
// Satellite's velocity. Can be useful for Vector Tracking loops
const double Omega_dot = d_OMEGA_DOT - BEIDOU_OMEGA_EARTH_DOT;
d_satvel_X = -Omega_dot * (cos(u) * r + sin(u) * r * cos(i)) + d_satpos_X * cos(Omega) - d_satpos_Y * cos(i) * sin(Omega);
d_satvel_Y = Omega_dot * (cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega)) + d_satpos_X * sin(Omega) + d_satpos_Y * cos(i) * cos(Omega);
d_satvel_Z = d_satpos_Y * sin(i);
const double xpkdot = rkdot * cuk - yprime * ukdot;
const double ypkdot = rkdot * suk + xprime * ukdot;
const double tmp = ypkdot * cik - d_satpos_Z * ikdot;
d_satvel_X = -Omega_dot * d_satpos_Y + xpkdot * cok - tmp * sok;
d_satvel_Y = Omega_dot * d_satpos_X + xpkdot * sok + tmp * cok;
d_satvel_Z = yprime * cik * ikdot + ypkdot * sik;
// Time from ephemeris reference clock
tk = check_t(transmitTime - d_Toc);
@ -191,7 +215,7 @@ double Beidou_Dnav_Ephemeris::satellitePosition(double transmitTime)
double dtr_s = d_A_f0 + d_A_f1 * tk + d_A_f2 * tk * tk;
/* relativity correction */
dtr_s -= 2.0 * sqrt(BEIDOU_GM * a) * d_eccentricity * sin(E) / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S);
dtr_s -= 2.0 * sqrt(BEIDOU_GM * a) * d_eccentricity * sek / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S);
return dtr_s;
}

View File

@ -78,7 +78,7 @@ double Galileo_Ephemeris::sv_clock_relativistic_term(double transmitTime) // Sa
// Time from ephemeris reference epoch
// t = WN_5*86400*7 + TOW_5; //WN_5*86400*7 are the second from the origin of the Galileo time
const double tk = transmitTime - t0e_1;
const double tk = check_t(transmitTime - static_cast<double>(t0e_1));
// Corrected mean motion
const double n = n0 + delta_n_3;
@ -87,7 +87,7 @@ double Galileo_Ephemeris::sv_clock_relativistic_term(double transmitTime) // Sa
double M = M0_1 + n * tk;
// Reduce mean anomaly to between 0 and 2pi
M = fmod((M + 2 * GNSS_PI), (2 * GNSS_PI));
M = fmod((M + 2.0 * GNSS_PI), (2.0 * GNSS_PI));
// Initial guess of eccentric anomaly
double E = M;
@ -99,7 +99,7 @@ double Galileo_Ephemeris::sv_clock_relativistic_term(double transmitTime) // Sa
{
E_old = E;
E = M + e_1 * sin(E);
dE = fmod(E - E_old, 2 * GNSS_PI);
dE = fmod(E - E_old, 2.0 * GNSS_PI);
if (fabs(dE) < 1e-12)
{
// Necessary precision is reached, exit from the loop
@ -127,7 +127,7 @@ void Galileo_Ephemeris::satellitePosition(double transmitTime)
const double n0 = sqrt(GALILEO_GM / (a * a * a));
// Time from ephemeris reference epoch
const double tk = transmitTime - t0e_1;
const double tk = check_t(transmitTime - static_cast<double>(t0e_1));
// Corrected mean motion
const double n = n0 + delta_n_3;
@ -136,7 +136,7 @@ void Galileo_Ephemeris::satellitePosition(double transmitTime)
double M = M0_1 + n * tk;
// Reduce mean anomaly to between 0 and 2pi
M = fmod((M + 2 * GNSS_PI), (2 * GNSS_PI));
M = fmod((M + 2.0 * GNSS_PI), (2.0 * GNSS_PI));
// Initial guess of eccentric anomaly
double E = M;
@ -148,7 +148,7 @@ void Galileo_Ephemeris::satellitePosition(double transmitTime)
{
E_old = E;
E = M + e_1 * sin(E);
dE = fmod(E - E_old, 2 * GNSS_PI);
dE = fmod(E - E_old, 2.0 * GNSS_PI);
if (fabs(dE) < 1e-12)
{
// Necessary precision is reached, exit from the loop
@ -156,40 +156,80 @@ void Galileo_Ephemeris::satellitePosition(double transmitTime)
}
}
const double sek = sin(E);
const double cek = cos(E);
const double OneMinusecosE = 1.0 - e_1 * cek;
const double sq1e2 = sqrt(1.0 - e_1 * e_1);
const double ekdot = n / OneMinusecosE;
// Compute the true anomaly
const double tmp_Y = sqrt(1.0 - e_1 * e_1) * sin(E);
const double tmp_X = cos(E) - e_1;
const double tmp_Y = sq1e2 * sek;
const double tmp_X = cek - e_1;
const double nu = atan2(tmp_Y, tmp_X);
// Compute angle phi (argument of Latitude)
double phi = nu + omega_2;
// Reduce phi to between 0 and 2*pi rad
phi = fmod((phi), (2 * GNSS_PI));
phi = fmod((phi), (2.0 * GNSS_PI));
const double s2pk = sin(2.0 * phi);
const double c2pk = cos(2.0 * phi);
const double pkdot = sq1e2 * ekdot / OneMinusecosE;
// Correct argument of latitude
const double u = phi + C_uc_3 * cos(2 * phi) + C_us_3 * sin(2 * phi);
const double u = phi + C_uc_3 * c2pk + C_us_3 * s2pk;
const double suk = sin(u);
const double cuk = cos(u);
const double ukdot = pkdot * (1.0 + 2.0 * (C_us_3 * c2pk - C_uc_3 * s2pk));
// Correct radius
const double r = a * (1 - e_1 * cos(E)) + C_rc_3 * cos(2 * phi) + C_rs_3 * sin(2 * phi);
const double r = a * OneMinusecosE + C_rc_3 * c2pk + C_rs_3 * s2pk;
const double rkdot = a * e_1 * sek * ekdot + 2.0 * pkdot * (C_rs_3 * c2pk - C_rc_3 * s2pk);
// Correct inclination
const double i = i_0_2 + iDot_2 * tk + C_ic_4 * cos(2 * phi) + C_is_4 * sin(2 * phi);
const double i = i_0_2 + iDot_2 * tk + C_ic_4 * c2pk + C_is_4 * s2pk;
const double sik = sin(i);
const double cik = cos(i);
const double ikdot = iDot_2 + 2.0 * pkdot * (C_is_4 * c2pk - C_ic_4 * s2pk);
// Compute the angle between the ascending node and the Greenwich meridian
double Omega = OMEGA_0_2 + (OMEGA_dot_3 - GNSS_OMEGA_EARTH_DOT) * tk - GNSS_OMEGA_EARTH_DOT * t0e_1;
const double Omega_dot = OMEGA_dot_3 - GNSS_OMEGA_EARTH_DOT;
double Omega = OMEGA_0_2 + Omega_dot * tk - GNSS_OMEGA_EARTH_DOT * static_cast<double>(t0e_1);
// Reduce to between 0 and 2*pi rad
Omega = fmod((Omega + 2 * GNSS_PI), (2 * GNSS_PI));
Omega = fmod((Omega + 2.0 * GNSS_PI), (2.0 * GNSS_PI));
const double sok = sin(Omega);
const double cok = cos(Omega);
// --- Compute satellite coordinates in Earth-fixed coordinates
d_satpos_X = cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega);
d_satpos_Y = cos(u) * r * sin(Omega) + sin(u) * r * cos(i) * cos(Omega); // ********NOTE: in GALILEO ICD this expression is not correct because it has minus (- sin(u) * r * cos(i) * cos(Omega)) instead of plus
d_satpos_Z = sin(u) * r * sin(i);
const double xprime = r * cuk;
const double yprime = r * suk;
d_satpos_X = xprime * cok - yprime * cik * sok;
d_satpos_Y = xprime * sok + yprime * cik * cok; // ********NOTE: in GALILEO ICD this expression is not correct because it has minus (- sin(u) * r * cos(i) * cos(Omega)) instead of plus
d_satpos_Z = yprime * sik;
// Satellite's velocity. Can be useful for Vector Tracking loops
const double Omega_dot = OMEGA_dot_3 - GNSS_OMEGA_EARTH_DOT;
d_satvel_X = -Omega_dot * (cos(u) * r + sin(u) * r * cos(i)) + d_satpos_X * cos(Omega) - d_satpos_Y * cos(i) * sin(Omega);
d_satvel_Y = Omega_dot * (cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega)) + d_satpos_X * sin(Omega) + d_satpos_Y * cos(i) * cos(Omega);
d_satvel_Z = d_satpos_Y * sin(i);
const double xpkdot = rkdot * cuk - yprime * ukdot;
const double ypkdot = rkdot * suk + xprime * ukdot;
const double tmp = ypkdot * cik - d_satpos_Z * ikdot;
d_satvel_X = -Omega_dot * d_satpos_Y + xpkdot * cok - tmp * sok;
d_satvel_Y = Omega_dot * d_satpos_X + xpkdot * sok + tmp * cok;
d_satvel_Z = yprime * cik * ikdot + ypkdot * sik;
}
double Galileo_Ephemeris::check_t(double time)
{
const double half_week = 302400.0; // seconds
double corrTime = time;
if (time > half_week)
{
corrTime = time - 2.0 * half_week;
}
else if (time < -half_week)
{
corrTime = time + 2.0 * half_week;
}
return corrTime;
}

View File

@ -162,6 +162,15 @@ public:
archive& BOOST_SERIALIZATION_NVP(flag_all_ephemeris);
}
private:
/*
* Accounts for the beginning or end of week crossover
*
* \param[in] - time in seconds
* \param[out] - corrected time, in seconds
*/
double check_t(double time);
};

View File

@ -148,43 +148,66 @@ double Gps_CNAV_Ephemeris::satellitePosition(double transmitTime)
}
}
const double sek = sin(E);
const double cek = cos(E);
const double OneMinusecosE = 1.0 - d_e_eccentricity * cek;
const double ekdot = n / OneMinusecosE;
// Compute the true anomaly
const double tmp_Y = sqrt(1.0 - d_e_eccentricity * d_e_eccentricity) * sin(E);
const double tmp_X = cos(E) - d_e_eccentricity;
const double sq1e2 = sqrt(1.0 - d_e_eccentricity * d_e_eccentricity);
const double tmp_Y = sq1e2 * sek;
const double tmp_X = cek - d_e_eccentricity;
const double nu = atan2(tmp_Y, tmp_X);
// Compute angle phi (argument of Latitude)
const double phi = nu + d_OMEGA;
double pkdot = sq1e2 * ekdot / OneMinusecosE;
// Reduce phi to between 0 and 2*pi rad
// phi = fmod((phi), (2*GNSS_PI));
// phi = fmod((phi), (2.0 * GNSS_PI));
const double s2pk = sin(2.0 * phi);
const double c2pk = cos(2.0 * phi);
// Correct argument of latitude
const double u = phi + d_Cuc * cos(2 * phi) + d_Cus * sin(2 * phi);
const double u = phi + d_Cuc * c2pk + d_Cus * s2pk;
const double cuk = cos(u);
const double suk = sin(u);
const double ukdot = pkdot * (1.0 + 2.0 * (d_Cus * c2pk - d_Cuc * s2pk));
// Correct radius
const double r = a * (1 - d_e_eccentricity * cos(E)) + d_Crc * cos(2 * phi) + d_Crs * sin(2 * phi);
const double r = a * (1.0 - d_e_eccentricity * cek) + d_Crc * c2pk + d_Crs * s2pk;
const double rkdot = a * d_e_eccentricity * sek * ekdot + 2.0 * pkdot * (d_Crs * c2pk - d_Crc * s2pk);
// Correct inclination
const double i = d_i_0 + d_IDOT * tk + d_Cic * cos(2 * phi) + d_Cis * sin(2 * phi);
const double i = d_i_0 + d_IDOT * tk + d_Cic * c2pk + d_Cis * s2pk;
const double sik = sin(i);
const double cik = cos(i);
const double ikdot = d_IDOT + 2.0 * pkdot * (d_Cis * c2pk - d_Cic * s2pk);
// Compute the angle between the ascending node and the Greenwich meridian
const double d_OMEGA_DOT = OMEGA_DOT_REF * GNSS_PI + d_DELTA_OMEGA_DOT;
const double Omega = d_OMEGA0 + (d_OMEGA_DOT - GNSS_OMEGA_EARTH_DOT) * tk - GNSS_OMEGA_EARTH_DOT * d_Toe1;
const double sok = sin(Omega);
const double cok = cos(Omega);
// Reduce to between 0 and 2*pi rad
// Omega = fmod((Omega + 2*GNSS_PI), (2*GNSS_PI));
// --- Compute satellite coordinates in Earth-fixed coordinates
d_satpos_X = cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega);
d_satpos_Y = cos(u) * r * sin(Omega) + sin(u) * r * cos(i) * cos(Omega);
d_satpos_Z = sin(u) * r * sin(i);
// Compute satellite coordinates in Earth-fixed coordinates
const double xprime = r * cuk;
const double yprime = r * suk;
d_satpos_X = xprime * cok - yprime * cik * sok;
d_satpos_Y = xprime * sok + yprime * cik * cok;
d_satpos_Z = yprime * sik;
// Satellite's velocity. Can be useful for Vector Tracking loops
const double Omega_dot = d_OMEGA_DOT - GNSS_OMEGA_EARTH_DOT;
d_satvel_X = -Omega_dot * (cos(u) * r + sin(u) * r * cos(i)) + d_satpos_X * cos(Omega) - d_satpos_Y * cos(i) * sin(Omega);
d_satvel_Y = Omega_dot * (cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega)) + d_satpos_X * sin(Omega) + d_satpos_Y * cos(i) * cos(Omega);
d_satvel_Z = d_satpos_Y * sin(i);
const double xpkdot = rkdot * cuk - yprime * ukdot;
const double ypkdot = rkdot * suk + xprime * ukdot;
const double tmp = ypkdot * cik - d_satpos_Z * ikdot;
d_satvel_X = -Omega_dot * d_satpos_Y + xpkdot * cok - tmp * sok;
d_satvel_Y = Omega_dot * d_satpos_X + xpkdot * sok + tmp * cok;
d_satvel_Z = yprime * cik * ikdot + ypkdot * sik;
// Time from ephemeris reference clock
tk = check_t(transmitTime - d_Toc);
@ -192,7 +215,7 @@ double Gps_CNAV_Ephemeris::satellitePosition(double transmitTime)
double dtr_s = d_A_f0 + d_A_f1 * tk + d_A_f2 * tk * tk;
/* relativity correction */
dtr_s -= 2.0 * sqrt(GPS_GM * a) * d_e_eccentricity * sin(E) / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S);
dtr_s -= 2.0 * sqrt(GPS_GM * a) * d_e_eccentricity * sek / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S);
return dtr_s;
}

View File

@ -155,42 +155,65 @@ double Gps_Ephemeris::satellitePosition(double transmitTime)
}
}
const double sek = sin(E);
const double cek = cos(E);
const double OneMinusecosE = 1.0 - d_e_eccentricity * cek;
const double ekdot = n / OneMinusecosE;
// Compute the true anomaly
const double tmp_Y = sqrt(1.0 - d_e_eccentricity * d_e_eccentricity) * sin(E);
const double tmp_X = cos(E) - d_e_eccentricity;
const double sq1e2 = sqrt(1.0 - d_e_eccentricity * d_e_eccentricity);
const double tmp_Y = sq1e2 * sek;
const double tmp_X = cek - d_e_eccentricity;
const double nu = atan2(tmp_Y, tmp_X);
// Compute angle phi (argument of Latitude)
const double phi = nu + d_OMEGA;
double pkdot = sq1e2 * ekdot / OneMinusecosE;
// Reduce phi to between 0 and 2*pi rad
// phi = fmod((phi), (2.0 * GNSS_PI));
const double s2pk = sin(2.0 * phi);
const double c2pk = cos(2.0 * phi);
// Correct argument of latitude
const double u = phi + d_Cuc * cos(2.0 * phi) + d_Cus * sin(2.0 * phi);
const double u = phi + d_Cuc * c2pk + d_Cus * s2pk;
const double cuk = cos(u);
const double suk = sin(u);
const double ukdot = pkdot * (1.0 + 2.0 * (d_Cus * c2pk - d_Cuc * s2pk));
// Correct radius
const double r = a * (1.0 - d_e_eccentricity * cos(E)) + d_Crc * cos(2.0 * phi) + d_Crs * sin(2.0 * phi);
const double r = a * (1.0 - d_e_eccentricity * cek) + d_Crc * c2pk + d_Crs * s2pk;
const double rkdot = a * d_e_eccentricity * sek * ekdot + 2.0 * pkdot * (d_Crs * c2pk - d_Crc * s2pk);
// Correct inclination
const double i = d_i_0 + d_IDOT * tk + d_Cic * cos(2.0 * phi) + d_Cis * sin(2.0 * phi);
const double i = d_i_0 + d_IDOT * tk + d_Cic * c2pk + d_Cis * s2pk;
const double sik = sin(i);
const double cik = cos(i);
const double ikdot = d_IDOT + 2.0 * pkdot * (d_Cis * c2pk - d_Cic * s2pk);
// Compute the angle between the ascending node and the Greenwich meridian
const double Omega = d_OMEGA0 + (d_OMEGA_DOT - GNSS_OMEGA_EARTH_DOT) * tk - GNSS_OMEGA_EARTH_DOT * d_Toe;
// Reduce to between 0 and 2*pi rad
// Omega = fmod((Omega + 2.0 * GNSS_PI), (2.0 * GNSS_PI));
const double sok = sin(Omega);
const double cok = cos(Omega);
// --- Compute satellite coordinates in Earth-fixed coordinates
d_satpos_X = cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega);
d_satpos_Y = cos(u) * r * sin(Omega) + sin(u) * r * cos(i) * cos(Omega);
d_satpos_Z = sin(u) * r * sin(i);
const double xprime = r * cuk;
const double yprime = r * suk;
d_satpos_X = xprime * cok - yprime * cik * sok;
d_satpos_Y = xprime * sok + yprime * cik * cok;
d_satpos_Z = yprime * sik;
// Satellite's velocity. Can be useful for Vector Tracking loops
const double Omega_dot = d_OMEGA_DOT - GNSS_OMEGA_EARTH_DOT;
d_satvel_X = -Omega_dot * (cos(u) * r + sin(u) * r * cos(i)) + d_satpos_X * cos(Omega) - d_satpos_Y * cos(i) * sin(Omega);
d_satvel_Y = Omega_dot * (cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega)) + d_satpos_X * sin(Omega) + d_satpos_Y * cos(i) * cos(Omega);
d_satvel_Z = d_satpos_Y * sin(i);
const double xpkdot = rkdot * cuk - yprime * ukdot;
const double ypkdot = rkdot * suk + xprime * ukdot;
const double tmp = ypkdot * cik - d_satpos_Z * ikdot;
d_satvel_X = -Omega_dot * d_satpos_Y + xpkdot * cok - tmp * sok;
d_satvel_Y = Omega_dot * d_satpos_X + xpkdot * sok + tmp * cok;
d_satvel_Z = yprime * cik * ikdot + ypkdot * sik;
// Time from ephemeris reference clock
tk = check_t(transmitTime - d_Toc);
@ -198,7 +221,7 @@ double Gps_Ephemeris::satellitePosition(double transmitTime)
double dtr_s = d_A_f0 + d_A_f1 * tk + d_A_f2 * tk * tk;
/* relativity correction */
dtr_s -= 2.0 * sqrt(GPS_GM * a) * d_e_eccentricity * sin(E) / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S);
dtr_s -= 2.0 * sqrt(GPS_GM * a) * d_e_eccentricity * sek / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S);
return dtr_s;
}