mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 15:23:04 +00:00 
			
		
		
		
	Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into vtl_experimental
This commit is contained in:
		| @@ -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}" | ||||
|   | ||||
| @@ -125,6 +125,7 @@ if(ENABLE_FPGA) | ||||
|     target_link_libraries(acquisition_adapters | ||||
|         PRIVATE | ||||
|             algorithms_libs | ||||
|             core_libs | ||||
|             Gnuradio::fft | ||||
|             Volk::volk | ||||
|             Volkgnsssdr::volkgnsssdr | ||||
|   | ||||
| @@ -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))); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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))); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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)); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
| ######################################################################## | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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(); }); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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,13 +64,12 @@ 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) + | ||||
|     num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) + | ||||
|                            configuration->property("Channels_2S.count", 0) + | ||||
|                            configuration->property("Channels_L5.count", 0); | ||||
|  | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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_; | ||||
|   | ||||
| @@ -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,17 +61,16 @@ 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) + | ||||
|     num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) + | ||||
|                            configuration->property("Channels_2S.count", 0) + | ||||
|                            configuration->property("Channels_1B.count", 0); | ||||
|  | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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_; | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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_; | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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_; | ||||
|   | ||||
| @@ -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,13 +66,12 @@ 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) + | ||||
|     num_prev_assigned_ch = configuration->property("Channels_1C.count", 0) + | ||||
|                            configuration->property("Channels_2S.count", 0); | ||||
|  | ||||
|     // ################# PRE-COMPUTE ALL THE CODES ################# | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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_; | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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'; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
|  | ||||
| @@ -64,7 +66,6 @@ private: | ||||
|     void wait_for_interrupt(void); | ||||
|  | ||||
|     volatile uint32_t *map_base;  // driver memory map | ||||
|     std::string device_name = "/dev/uio2";  // HW device name | ||||
|  | ||||
|     double fs; | ||||
|     uint64_t sample_counter; | ||||
|   | ||||
							
								
								
									
										213
									
								
								src/core/libs/uio_fpga.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								src/core/libs/uio_fpga.cc
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										47
									
								
								src/core/libs/uio_fpga.h
									
									
									
									
									
										Normal 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 | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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); | ||||
| }; | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Javier Arribas
					Javier Arribas