diff --git a/.gitignore b/.gitignore index 4a50387fa..4afd17279 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,3 @@ HAS_* gnss_sdr_pvt.nmea build-debug/ build-release/ - diff --git a/AUTHORS b/AUTHORS index ad0660662..7df41ed17 100644 --- a/AUTHORS +++ b/AUTHORS @@ -64,6 +64,7 @@ Marc Sales marcsales92@gmail.com Contributor Piyush Gupta piyush04111999@gmail.com Contributor Rodrigo Muñoz rodrigo.munoz@proteinlab.cl Contributor Stefan van der Linden spvdlinden@gmail.com Contributor +Víctor Castillo-Agüero victorcastilloaguero@gmail.com Contributor Will Silberman wsilberm@google.com Contributor Carlos Paniego carpanie@hotmail.com Artwork diff --git a/CITATION.cff b/CITATION.cff index 0f11b55f1..4bf27081f 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -34,6 +34,11 @@ authors: email: mara.branzanti@gmail.com family-names: Branzanti given-names: Mara + - alias: castle055 + affiliation: "Instituto Nacional de Técnica Aeroespacial" + email: victorcastilloaguero@gmail.com + family-names: "Castillo-Agüero" + given-names: Víctor - alias: acebrianjuan email: acebrianjuan@gmail.com family-names: "Cebrián-Juan" diff --git a/CMakeLists.txt b/CMakeLists.txt index c10936ca1..39132e9cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,8 @@ option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal option(ENABLE_ZMQ "Enable GNU Radio ZeroMQ Messaging, requires gr-zeromq" ON) +option(ENABLE_ION "Enable ION GNSS-SDR Metadata Standard signal source" OFF) + # Performance analysis tools option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF) @@ -358,12 +360,12 @@ set(GNSSSDR_ARMADILLO_LOCAL_VERSION "14.0.x") set(GNSSSDR_GFLAGS_LOCAL_VERSION "2.2.2") set(GNSSSDR_GLOG_LOCAL_VERSION "0.7.1") set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.27") -set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "27.3") +set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "28.0") set(GNSSSDR_PUGIXML_LOCAL_VERSION "1.14") set(GNSSSDR_GTEST_LOCAL_VERSION "1.15.2") set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "origin/master") set(GNSSSDR_GNSSTK_LOCAL_VERSION "14.3.0") -set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.8.5") +set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.9.0") set(GNSSSDR_MATHJAX_EXTERNAL_VERSION "2.7.7") set(GNSSSDR_ABSL_LOCAL_VERSION "origin/master") # live at head (see https://abseil.io/about/releases) @@ -3252,7 +3254,7 @@ set_package_properties(LIBIIO PROPERTIES PURPOSE "Used for communication with the AD9361 chipset." TYPE OPTIONAL ) -if(ENABLE_AD9361 OR ENABLE_FMCOMMS2) +if(ENABLE_AD9361 OR ENABLE_FMCOMMS2 OR ENABLE_PLUTOSDR) if(NOT LIBIIO_FOUND) message(STATUS "libiio not found, its installation is required.") message(STATUS "Please build and install the following projects:") @@ -3270,6 +3272,161 @@ if(ENABLE_AD9361 OR ENABLE_FMCOMMS2) endif() +################################################################################ +# ION GNSS-SDR Metadata Standard https://sdr.ion.org/ (OPTIONAL) +################################################################################ +if(CMAKE_VERSION VERSION_LESS 3.14) + set(ENABLE_ION OFF) # FetchContent_MakeAvailable is available from CMake 3.14 +endif() +if(ENABLE_ION) + include(FetchContent) + set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) + FetchContent_Declare( + gnss_metadata_standard + GIT_REPOSITORY https://github.com/IonMetadataWorkingGroup/GNSS-Metadata-Standard + GIT_TAG 220d116e10db5e403e21b77a1fa25aa35feda198 + SOURCE_DIR ${GNSSSDR_BINARY_DIR}/thirdparty/gnss-metadata-standard + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${GNSSSDR_BINARY_DIR}/gnss-metadata-standard + BINARY_DIR ${GNSSSDR_BINARY_DIR}/gnss-metadata-standard + ) + FetchContent_MakeAvailable(gnss_metadata_standard) + + if(NOT TARGET ION::ion) + add_library(ION::ion STATIC IMPORTED) + add_dependencies(ION::ion gnss_metadata_standard) + if(CMAKE_GENERATOR STREQUAL "Xcode") + set_target_properties(ION::ion PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION_DEBUG "${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX}" + IMPORTED_LOCATION_RELEASE "${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/Release/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX}" + IMPORTED_LOCATION_RELWITHDEBINFO "${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/RelWithDebInfo/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX}" + IMPORTED_LOCATION_MINSIZEREL "${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/MinSizeRel/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX}" + INTERFACE_INCLUDE_DIRECTORIES "${GNSSSDR_BINARY_DIR}/thirdparty/gnss-metadata-standard/source/api/inc" + ) + set_property(TARGET ION::ion APPEND PROPERTY + INTERFACE_LINK_LIBRARIES + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/Release/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/Release/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/RelWithDebInfo/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/RelWithDebInfo/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/MinSizeRel/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/MinSizeRel/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/RelWithDebInfo/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/RelWithDebInfo/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/RelWithDebInfo/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/RelWithDebInfo/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + "$<$:${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/Debug/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}>" + ) + else() + set_target_properties(ION::ion PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION "${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX}" + INTERFACE_INCLUDE_DIRECTORIES "${GNSSSDR_BINARY_DIR}/thirdparty/gnss-metadata-standard/source/api/inc" + INTERFACE_LINK_LIBRARIES "${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/GnssMetadata/${CMAKE_FIND_LIBRARY_PREFIXES}api${CMAKE_STATIC_LIBRARY_SUFFIX};${GNSSSDR_BINARY_DIR}/gnss-metadata-standard/source/api/lib/tinyxml2/${CMAKE_FIND_LIBRARY_PREFIXES}xml${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + endif() + endif() +endif() + + +##################################################################### +# Check signal sources related to FPGA only. +##################################################################### +if(ENABLE_MAX2771 AND NOT ENABLE_FPGA) + message(STATUS "The SPIdev driver is enabled, but the FPGA is not enabled. The FPGA is required when using the SPIdev driver.") + if(ENABLE_PACKAGING) + set(ENABLE_MAX2771 OFF) + else() + message(FATAL_ERROR "ENABLE_MAX2771 can only be set when ENABLE_FPGA is also set.") + endif() +endif() +if(ENABLE_DMA_PROXY AND NOT ENABLE_FPGA) + message(STATUS "The DMA Proxy driver is enabled, but the FPGA is not enabled. The FPGA is required when using the DMA Proxy driver.") + if(ENABLE_PACKAGING) + set(ENABLE_DMA_PROXY OFF) + else() + message(FATAL_ERROR "ENABLE_DMA_PROXY can only be set when ENABLE_FPGA is also set.") + endif() +endif() + + + +##################################################################### +# spidev driver - OPTIONAL +# Linux kernel driver that provides user-space access to Serial +# Peripheral Interface) +##################################################################### +if(ENABLE_MAX2771) + if(DEFINED ENV{SDKTARGETSYSROOT}) + set(TARGET_ROOTFS_PATH $ENV{SDKTARGETSYSROOT}) + else() + set(TARGET_ROOTFS_PATH "") + endif() + find_program(STRINGS_EXECUTABLE strings) + if(NOT STRINGS_EXECUTABLE) + message(STATUS "The 'strings' command could not be found. See https://www.gnu.org/software/binutils/") + message(STATUS " You can try to install it by typing:") + if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|kFreeBSD|GNU") + if(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "Red Hat") + message(STATUS " sudo yum install binutils") + elseif(${LINUX_DISTRIBUTION} MATCHES "openSUSE") + message(STATUS " sudo zypper install binutils") + else() + message(STATUS " sudo apt-get install binutils") + endif() + endif() + message(FATAL_ERROR "Binutils are required to build GNSS-SDR for SoC FPGA devices using the MAX2771 option.") + endif() + set(DTB_FILE "${TARGET_ROOTFS_PATH}/boot/devicetree/system-top.dtb") + if(EXISTS "${DTB_FILE}") + message(STATUS "Found DTB file: ${DTB_FILE}") + # Run the strings command and grep for "spidev" + execute_process( + COMMAND ${STRINGS_EXECUTABLE} ${DTB_FILE} + COMMAND grep "spidev" + OUTPUT_VARIABLE GREP_OUTPUT + RESULT_VARIABLE GREP_RESULT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(GREP_RESULT EQUAL 0) + message(STATUS "Found spidev-compatible peripheral in ${DTB_FILE}.") + else() + message(STATUS "SPIdev driver not found, its installation is required.") + if(ENABLE_PACKAGING) + set(ENABLE_MAX2771 OFF) + else() + message(FATAL_ERROR "SPIdev driver is required for building gnss-sdr with -DENABLE_MAX2271=ON.") + endif() + endif() + else() + message(FATAL_ERROR "The device tree (DTB) file ${DTB_FILE} cannot be found.") + endif() +endif() + + + +##################################################################### +# DMA Proxy driver - OPTIONAL +# Simplified and efficient interface for user-space applications +# to leverage DMA capabilities for Xilinx FPGA and SoC systems +##################################################################### +if(ENABLE_DMA_PROXY) + if(DEFINED ENV{SDKTARGETSYSROOT}) + set(TARGET_ROOTFS_PATH $ENV{SDKTARGETSYSROOT}) + else() + set(TARGET_ROOTFS_PATH "") + endif() + set(DMA_PROXY_FILE "${TARGET_ROOTFS_PATH}/lib/modules/5.10.0-xilinx-v2021.2/extra/dma-proxy.ko") + if(EXISTS "${DMA_PROXY_FILE}") + message(STATUS "Found dma-proxy.ko file: ${DMA_PROXY_FILE}") + else() + if(ENABLE_PACKAGING) + set(ENABLE_DMA_PROXY OFF) + else() + message(FATAL_ERROR "DMA Proxy driver is required for building gnss-sdr with -DENABLE_DMA_PROXY=ON.") + endif() + endif() +endif() + + ##################################################################### # Check signal sources related to FPGA only. @@ -3573,23 +3730,24 @@ add_subdirectory(src) add_feature_info(ENABLE_UHD ENABLE_UHD "Enables UHD_Signal_Source for using RF front-ends from the USRP family. Requires gr-uhd.") add_feature_info(ENABLE_OSMOSDR ENABLE_OSMOSDR "Enables Osmosdr_Signal_Source and RtlTcp_Signal_Source for using RF front-ends compatible with the OsmoSDR driver. Requires gr-osmosdr.") add_feature_info(ENABLE_LIMESDR ENABLE_LIMESDR "Enables Limesdr_Signal_Source. Requires gr-limesdr.") -add_feature_info(ENABLE_FMCOMMS2 ENABLE_FMCOMMS2 "Enables Fmcomms2_Signal_Source for FMCOMMS2/3/4 devices. Requires gr-iio and libad9361-dev.") -add_feature_info(ENABLE_PLUTOSDR ENABLE_PLUTOSDR "Enables Plutosdr_Signal_Source for using ADALM-PLUTO boards. Requires gr-iio.") -add_feature_info(ENABLE_AD9361 ENABLE_AD9361 "Enables Ad9361_Fpga_Signal_Source for devices with the AD9361 chipset. Requires libiio and libad9361-dev.") -add_feature_info(ENABLE_MAX2771 ENABLE_MAX2771 "Enables FPGA_MAX2771_EVKIT_Signal_Source for devices with the MAX2771 chipset. Requires the spidev driver") -add_feature_info(ENABLE_DMA_PROXY ENABLE_DMA_PROXY "Enables DMA Signal_Source. Requires the DMA Proxy driver") -add_feature_info(ENABLE_AD936X_SDR ENABLE_AD936X_SDR "Enables Ad936x_Iio_Signal_Source to access AD936X front-ends using libiio. Requires libiio and libad9361-dev.") +add_feature_info(ENABLE_FMCOMMS2 ENABLE_FMCOMMS2 "Enables Fmcomms2_Signal_Source for FMCOMMS2/3/4 devices. Requires libiio, libad9361-dev, and gr-iio.") +add_feature_info(ENABLE_PLUTOSDR ENABLE_PLUTOSDR "Enables Plutosdr_Signal_Source and Ad936x_Custom_Signal_Source for using ADALM-PLUTO boards. Requires libiio, libad9361-dev, and gr-iio.") +add_feature_info(ENABLE_AD936X_SDR ENABLE_AD936X_SDR "Enables Ad936x_Custom_Signal_Source for using ADALM-PLUTO boards with custom firmware. Requires libiio and libad9361-dev.") +add_feature_info(ENABLE_FPGA ENABLE_FPGA "Enables building of processing blocks for FPGA offloading.") +add_feature_info(ENABLE_AD9361 ENABLE_AD9361 "Enables ADRV9361_Z7035_Signal_Source_FPGA and the FMCOMMS5_Signal_Source_FPGA for FPGA SoC devices with the AD9361 chipset. Requires libiio, libad9361-dev, and -DENABLE_FPGA=ON.") +add_feature_info(ENABLE_MAX2771 ENABLE_MAX2771 "Enables FPGA_MAX2771_EVKIT_Signal_Source for FPGA SoC devices with the with the MAX2771 chipset. Requires the spidev driver and -DENABLE_FPGA=ON.") +add_feature_info(ENABLE_DMA_PROXY ENABLE_DMA_PROXY "Enables DMA_Signal_Source_FPGA for file post-processing in FPGA SoC devices. Requires the DMA Proxy driver and -DENABLE_FPGA=ON.") add_feature_info(ENABLE_RAW_UDP ENABLE_RAW_UDP "Enables Custom_UDP_Signal_Source for custom UDP packet sample source. Requires libpcap.") add_feature_info(ENABLE_FLEXIBAND ENABLE_FLEXIBAND "Enables Flexiband_Signal_Source for using Teleorbit's Flexiband RF front-end. Requires gr-teleorbit.") add_feature_info(ENABLE_ARRAY ENABLE_ARRAY "Enables Raw_Array_Signal_Source and Array_Signal_Conditioner for using CTTC's antenna array. Requires gr-dbfcttc.") add_feature_info(ENABLE_ZMQ ENABLE_ZMQ "Enables ZMQ_Signal_Source for GNU Radio ZeroMQ messages. Requires gr-zeromq.") +add_feature_info(ENABLE_ION ENABLE_ION "Enables ION_GSMS_Signal_Source for the ION Metadata Standard.") add_feature_info(ENABLE_GPERFTOOLS ENABLE_GPERFTOOLS "Enables performance analysis. Requires Gperftools.") add_feature_info(ENABLE_GPROF ENABLE_GPROF "Enables performance analysis with 'gprof'.") add_feature_info(ENABLE_CLANG_TIDY ENABLE_CLANG_TIDY "Runs clang-tidy along with the compiler. Requires Clang.") add_feature_info(ENABLE_PROFILING ENABLE_PROFILING "Runs volk_gnsssdr_profile at the end of the building.") add_feature_info(ENABLE_OPENCL ENABLE_OPENCL "Enables GPS_L1_CA_PCPS_OpenCl_Acquisition (experimental). Requires OpenCL.") add_feature_info(ENABLE_CUDA ENABLE_CUDA "Enables GPS_L1_CA_DLL_PLL_Tracking_GPU (experimental). Requires CUDA.") -add_feature_info(ENABLE_FPGA ENABLE_FPGA "Enables building of processing blocks for FPGA offloading.") add_feature_info(ENABLE_ARMA_NO_DEBUG ENABLE_ARMA_NO_DEBUG "Enables passing the ARMA_NO_DEBUG macro to Armadillo, hence disabling bound checking.") add_feature_info(ENABLE_PACKAGING ENABLE_PACKAGING "Enables software packaging.") add_feature_info(ENABLE_OWN_GLOG ENABLE_OWN_GLOG "Forces the downloading and building of Google glog.") diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3963e0b20..327b26a8d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -41,6 +41,11 @@ All notable changes to GNSS-SDR will be documented in this file. - `-DENABLE_DMA_PROXY`: Checks if the DMA proxy driver is installed for controlling the DMA in the FPGA and enables its usage. +- Add the `ION_GSMS_Signal_Source`, which is able to process raw data files + described with the + [ION GNSS Software Defined Receiver Metadata Standard](https://sdr.ion.org/). + It requires the `-DENABLE_ION=ON` building configuration option. + ### Improvements in Portability: - Fix building against google-glog 0.7.x. diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h index 42b4e55b1..c800d0c32 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h @@ -227,11 +227,11 @@ #endif // defined(CPU_FEATURES_ARCH_X86) #if defined(CPU_FEATURES_ARCH_ANY_ARM) -#if defined(__ARM_NEON__) +#if defined(__ARM_NEON) #define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1 #else #define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0 -#endif // defined(__ARM_NEON__) +#endif // defined(__ARM_NEON) #endif // defined(CPU_FEATURES_ARCH_ANY_ARM) #if defined(CPU_FEATURES_ARCH_MIPS) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h index a8cb0d41a..41108b6ec 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h @@ -182,6 +182,31 @@ typedef struct int smef16f16 : 1; // FP16 to FP16 outer product. int mops : 1; // Standardized memory operations. int hbc : 1; // Hinted conditional branches. + int sveb16b16 : 1; // Non-widening BFloat16 to BFloat16 arithmetic for SVE2 + // and SME2. + int lrcpc3 : 1; // Load-Acquire RCpc instructions version 3. + int lse128 : 1; // 128-bit Atomics. + int fpmr : 1; // Floating-point Mode Register. + int lut : 1; // Lookup table instructions with 2-bit and 4-bit indices. + int faminmax : 1; // Maximum and minimum absolute value instructions. + int f8cvt : 1; // FP scaling instructions and FP8 convert instructions. + int f8fma : 1; // FP8 to single-precision and half-precision + // multiply-accumulate instructions. + int f8dp4 : 1; // FP8 to single-precision 4-way dot product FDOT (4-way) + // instructions. + int f8dp2 : 1; // FP8 to half-precision 2-way dot product FDOT (2-way) + // instructions. + int f8e4m3 : 1; // Arm FP8 E4M3 format. + int f8e5m2 : 1; // Arm FP8 E5M2 format. + int smelutv2 : 1; // SME2 lookup table LUTI4 and MOVT instructions. + int smef8f16 : 1; // SME2 F8F16 instructions. + int smef8f32 : 1; // SME2 F8F32 instructions. + int smesf8fma : 1; // SVE2 FP8 to single-precision and half-precision + // multiply-accumulate instructions. + int smesf8dp4 : 1; // SVE2 FP8 to single-precision 4-way dot product FDOT + // (4-way) instructions. + int smesf8dp2 : 1; // SVE2 FP8 to half-precision 2-way dot product FDOT + // (2-way) instructions. // Make sure to update Aarch64FeaturesEnum below if you add a field here. } Aarch64Features; @@ -280,6 +305,24 @@ typedef enum AARCH64_SME_F16F16, AARCH64_MOPS, AARCH64_HBC, + AARCH64_SVE_B16B16, + AARCH64_LRCPC3, + AARCH64_LSE128, + AARCH64_FPMR, + AARCH64_LUT, + AARCH64_FAMINMAX, + AARCH64_F8CVT, + AARCH64_F8FMA, + AARCH64_F8DP4, + AARCH64_F8DP2, + AARCH64_F8E4M3, + AARCH64_F8E5M2, + AARCH64_SME_LUTV2, + AARCH64_SME_F8F16, + AARCH64_SME_F8F32, + AARCH64_SME_SF8FMA, + AARCH64_SME_SF8DP4, + AARCH64_SME_SF8DP2, AARCH64_LAST_, } Aarch64FeaturesEnum; diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h index 63baa1fff..3f500f606 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h @@ -94,6 +94,24 @@ CPU_FEATURES_START_CPP_NAMESPACE #define AARCH64_HWCAP2_SME_F16F16 (1UL << 42) #define AARCH64_HWCAP2_MOPS (1UL << 43) #define AARCH64_HWCAP2_HBC (1UL << 44) +#define AARCH64_HWCAP2_SVE_B16B16 (1UL << 45) +#define AARCH64_HWCAP2_LRCPC3 (1UL << 46) +#define AARCH64_HWCAP2_LSE128 (1UL << 47) +#define AARCH64_HWCAP2_FPMR (1UL << 48) +#define AARCH64_HWCAP2_LUT (1UL << 49) +#define AARCH64_HWCAP2_FAMINMAX (1UL << 50) +#define AARCH64_HWCAP2_F8CVT (1UL << 51) +#define AARCH64_HWCAP2_F8FMA (1UL << 52) +#define AARCH64_HWCAP2_F8DP4 (1UL << 53) +#define AARCH64_HWCAP2_F8DP2 (1UL << 54) +#define AARCH64_HWCAP2_F8E4M3 (1UL << 55) +#define AARCH64_HWCAP2_F8E5M2 (1UL << 56) +#define AARCH64_HWCAP2_SME_LUTV2 (1UL << 57) +#define AARCH64_HWCAP2_SME_F8F16 (1UL << 58) +#define AARCH64_HWCAP2_SME_F8F32 (1UL << 59) +#define AARCH64_HWCAP2_SME_SF8FMA (1UL << 60) +#define AARCH64_HWCAP2_SME_SF8DP4 (1UL << 61) +#define AARCH64_HWCAP2_SME_SF8DP2 (1UL << 62) // http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h #define ARM_HWCAP_SWP (1UL << 0) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/impl_aarch64__base_implementation.inl b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/impl_aarch64__base_implementation.inl index 14be5a726..d0057ee10 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/impl_aarch64__base_implementation.inl +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/impl_aarch64__base_implementation.inl @@ -103,7 +103,28 @@ LINE(AARCH64_SME_F16F16, smef16f16, "smef16f16", 0, \ AARCH64_HWCAP2_SME_F16F16) \ LINE(AARCH64_MOPS, mops, "mops", 0, AARCH64_HWCAP2_MOPS) \ - LINE(AARCH64_HBC, hbc, "hbc", 0, AARCH64_HWCAP2_HBC) + LINE(AARCH64_HBC, hbc, "hbc", 0, AARCH64_HWCAP2_HBC) \ + LINE(AARCH64_SVE_B16B16, sveb16b16, "sveb16b16", 0, \ + AARCH64_HWCAP2_SVE_B16B16) \ + LINE(AARCH64_LRCPC3, lrcpc3, "lrcpc3", 0, AARCH64_HWCAP2_LRCPC3) \ + LINE(AARCH64_LSE128, lse128, "lse128", 0, AARCH64_HWCAP2_LSE128) \ + LINE(AARCH64_FPMR, fpmr, "fpmr", 0, AARCH64_HWCAP2_FPMR) \ + LINE(AARCH64_LUT, lut, "lut", 0, AARCH64_HWCAP2_LUT) \ + LINE(AARCH64_FAMINMAX, faminmax, "faminmax", 0, AARCH64_HWCAP2_FAMINMAX) \ + LINE(AARCH64_F8CVT, f8cvt, "f8cvt", 0, AARCH64_HWCAP2_F8CVT) \ + LINE(AARCH64_F8FMA, f8fma, "f8fma", 0, AARCH64_HWCAP2_F8FMA) \ + LINE(AARCH64_F8DP4, f8dp4, "f8dp4", 0, AARCH64_HWCAP2_F8DP4) \ + LINE(AARCH64_F8DP2, f8dp2, "f8dp2", 0, AARCH64_HWCAP2_F8DP2) \ + LINE(AARCH64_F8E4M3, f8e4m3, "f8e4m3", 0, AARCH64_HWCAP2_F8E4M3) \ + LINE(AARCH64_F8E5M2, f8e5m2, "f8e5m2", 0, AARCH64_HWCAP2_F8E5M2) \ + LINE(AARCH64_SME_LUTV2, smelutv2, "smelutv1", 0, AARCH64_HWCAP2_SME_LUTV2) \ + LINE(AARCH64_SME_F8F16, smef8f16, "smef8f16", 0, AARCH64_HWCAP2_SME_F8F16) \ + LINE(AARCH64_SME_F8F32, smef8f32, "smef8f32", 0, AARCH64_HWCAP2_SME_F8F32) \ + LINE(AARCH64_SME_SF8FMA, smesf8fma, "smesf8fma", 0, \ + AARCH64_HWCAP2_SME_SF8FMA) \ + LINE(AARCH64_SME_SF8DP4, smesf8dp4, "smesf8dp4", 0, \ + AARCH64_HWCAP2_SME_SF8DP4) \ + LINE(AARCH64_SME_SF8DP2, smesf8dp2, "smesf8dp2", 0, AARCH64_HWCAP2_SME_SF8DP2) #define INTROSPECTION_PREFIX Aarch64 #define INTROSPECTION_ENUM_PREFIX AARCH64 #include "define_introspection_and_hwcaps.inl" \ No newline at end of file diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc index fc8abf8fe..e69c5ef78 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc @@ -326,6 +326,24 @@ CPU revision : 3)"); EXPECT_FALSE(info.features.smef16f16); EXPECT_FALSE(info.features.mops); EXPECT_FALSE(info.features.hbc); + EXPECT_FALSE(info.features.sveb16b16); + EXPECT_FALSE(info.features.lrcpc3); + EXPECT_FALSE(info.features.lse128); + EXPECT_FALSE(info.features.fpmr); + EXPECT_FALSE(info.features.lut); + EXPECT_FALSE(info.features.faminmax); + EXPECT_FALSE(info.features.f8cvt); + EXPECT_FALSE(info.features.f8fma); + EXPECT_FALSE(info.features.f8dp4); + EXPECT_FALSE(info.features.f8dp2); + EXPECT_FALSE(info.features.f8e4m3); + EXPECT_FALSE(info.features.f8e5m2); + EXPECT_FALSE(info.features.smelutv2); + EXPECT_FALSE(info.features.smef8f16); + EXPECT_FALSE(info.features.smef8f32); + EXPECT_FALSE(info.features.smesf8fma); + EXPECT_FALSE(info.features.smesf8dp4); + EXPECT_FALSE(info.features.smesf8dp2); } #elif defined(CPU_FEATURES_OS_MACOS) TEST_F(CpuidAarch64Test, FromDarwinSysctlFromName) diff --git a/src/algorithms/signal_source/adapters/CMakeLists.txt b/src/algorithms/signal_source/adapters/CMakeLists.txt index 0aa745101..48e18e5f3 100644 --- a/src/algorithms/signal_source/adapters/CMakeLists.txt +++ b/src/algorithms/signal_source/adapters/CMakeLists.txt @@ -25,6 +25,14 @@ if(ENABLE_PLUTOSDR) set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_custom_signal_source.h) endif() +if(ENABLE_AD936X_SDR AND NOT ENABLE_PLUTOSDR) + ############################################## + # CUSTOM AD936X IIO SOURCE + ############################################## + set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ad936x_custom_signal_source.cc) + set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_custom_signal_source.h) +endif() + if(ENABLE_FMCOMMS2) ############################################### # FMCOMMS2 based SDR Hardware @@ -103,6 +111,11 @@ if(ENABLE_ZMQ) list(APPEND OPT_DRIVER_HEADERS zmq_signal_source.h) endif() +if(ENABLE_ION) + list(APPEND OPT_DRIVER_SOURCES ion_gsms_signal_source.cc) + list(APPEND OPT_DRIVER_HEADERS ion_gsms_signal_source.h) +endif() + set(SIGNAL_SOURCE_ADAPTER_SOURCES signal_source_base.cc file_source_base.cc @@ -169,7 +182,7 @@ target_include_directories(signal_source_adapters ${GNSSSDR_SOURCE_DIR}/src/core/interfaces ) -if(ENABLE_FPGA OR ENABLE_AD9361) +if(ENABLE_FPGA OR ENABLE_AD9361 OR ENABLE_ION) target_link_libraries(signal_source_adapters PUBLIC signal_source_libs @@ -239,14 +252,14 @@ if(ENABLE_LIMESDR AND GRLIMESDR_FOUND) ) endif() -if(ENABLE_AD9361 AND LIBIIO_FOUND) +if(LIBIIO_FOUND) target_link_libraries(signal_source_adapters PRIVATE Iio::iio ) endif() -if(ENABLE_AD9361 OR ENABLE_FMCOMMS2 OR ENABLE_PLUTOSDR) +if(ENABLE_AD9361 OR ENABLE_FMCOMMS2 OR ENABLE_PLUTOSDR OR ENABLE_AD936X_SDR) if(LIBAD9361_VERSION) if(LIBAD9361_VERSION VERSION_GREATER 0.1) target_compile_definitions(signal_source_adapters diff --git a/src/algorithms/signal_source/adapters/ad936x_custom_signal_source.cc b/src/algorithms/signal_source/adapters/ad936x_custom_signal_source.cc index b93dc9344..b824a250d 100644 --- a/src/algorithms/signal_source/adapters/ad936x_custom_signal_source.cc +++ b/src/algorithms/signal_source/adapters/ad936x_custom_signal_source.cc @@ -76,8 +76,11 @@ Ad936xCustomSignalSource::Ad936xCustomSignalSource(const ConfigurationInterface* item_size_ = sizeof(gr_complex); // 1. Make the driver instance bool customsamplesize = false; - if (ssize_ != 12 or spattern_ == true) customsamplesize = true; // custom FPGA DMA firmware - if (ssize_ == 12) // default original FPGA DMA firmware + if (ssize_ != 12 || spattern_ == true) + { + customsamplesize = true; // custom FPGA DMA firmware + } + if (ssize_ == 12) // default original FPGA DMA firmware { ssize_ = 16; // set to 16 bits and do not try to change sample size } @@ -153,8 +156,14 @@ Ad936xCustomSignalSource::Ad936xCustomSignalSource(const ConfigurationInterface* for (int n = 0; n < n_channels; n++) { - if (n == 0) inverted_spectrum_vec.push_back(inverted_spectrum_ch0_); - if (n == 1) inverted_spectrum_vec.push_back(inverted_spectrum_ch1_); + if (n == 0) + { + inverted_spectrum_vec.push_back(inverted_spectrum_ch0_); + } + if (n == 1) + { + inverted_spectrum_vec.push_back(inverted_spectrum_ch1_); + } } for (int n = 0; n < n_channels; n++) diff --git a/src/algorithms/signal_source/adapters/adrv9361_z7035_signal_source_fpga.cc b/src/algorithms/signal_source/adapters/adrv9361_z7035_signal_source_fpga.cc index 9d29e2de2..897dd7777 100644 --- a/src/algorithms/signal_source/adapters/adrv9361_z7035_signal_source_fpga.cc +++ b/src/algorithms/signal_source/adapters/adrv9361_z7035_signal_source_fpga.cc @@ -1,6 +1,6 @@ /*! * \file adrv9361_z7035_signal_source_fpga.cc - * \brief signal source for the Analog Devices ADRV9361-Z7035 evaluation board + * \brief Signal source for the Analog Devices ADRV9361-Z7035 evaluation board * directly connected to the FPGA accelerators. * This source implements only the AD9361 control. It is NOT compatible with * conventional SDR acquisition and tracking blocks. @@ -51,14 +51,14 @@ Adrv9361z7035SignalSourceFPGA::Adrv9361z7035SignalSourceFPGA(const Configuration gain_mode_rx1_(configuration->property(role + ".gain_mode_rx1", default_gain_mode)), gain_mode_rx2_(configuration->property(role + ".gain_mode_rx2", default_gain_mode)), rf_port_select_(configuration->property(role + ".rf_port_select", default_rf_port_select)), + filter_source_(configuration->property(role + ".filter_source", std::string("Off"))), filter_filename_(configuration->property(role + ".filter_filename", filter_file_)), rf_gain_rx1_(configuration->property(role + ".gain_rx1", default_manual_gain_rx1)), rf_gain_rx2_(configuration->property(role + ".gain_rx2", default_manual_gain_rx2)), scale_dds_dbfs_(configuration->property(role + ".scale_dds_dbfs", -3.0)), phase_dds_deg_(configuration->property(role + ".phase_dds_deg", 0.0)), tx_attenuation_db_(configuration->property(role + ".tx_attenuation_db", default_tx_attenuation_db)), - freq0_(configuration->property(role + ".freq", 0)), - freq1_(configuration->property(role + ".freq1", static_cast(GPS_L5_FREQ_HZ))), + freq0_(configuration->property(role + ".freq", GPS_L5_FREQ_HZ)), sample_rate_(configuration->property(role + ".sampling_frequency", default_bandwidth)), bandwidth_(configuration->property(role + ".bandwidth", default_bandwidth)), freq_dds_tx_hz_(configuration->property(role + ".freq_dds_tx_hz", uint64_t(10000))), @@ -70,7 +70,6 @@ Adrv9361z7035SignalSourceFPGA::Adrv9361z7035SignalSourceFPGA(const Configuration out_stream_(out_stream), item_size_(sizeof(int8_t)), enable_dds_lo_(configuration->property(role + ".enable_dds_lo", false)), - filter_auto_(configuration->property(role + ".filter_auto", false)), quadrature_(configuration->property(role + ".quadrature", true)), rf_dc_(configuration->property(role + ".rf_dc", true)), bb_dc_(configuration->property(role + ".bb_dc", true)), @@ -98,15 +97,6 @@ Adrv9361z7035SignalSourceFPGA::Adrv9361z7035SignalSourceFPGA(const Configuration freq0_ = configuration->property(role + ".freq0", static_cast(GPS_L1_FREQ_HZ)); } - if (filter_auto_) - { - filter_source_ = configuration->property(role + ".filter_source", std::string("Auto")); - } - else - { - filter_source_ = configuration->property(role + ".filter_source", std::string("Off")); - } - switch_fpga = std::make_shared(); switch_fpga->set_switch_position(switch_to_real_time_mode); @@ -190,12 +180,15 @@ Adrv9361z7035SignalSourceFPGA::Adrv9361z7035SignalSourceFPGA(const Configuration } std::cout << "LO frequency : " << freq0_ << " Hz\n"; + + uint64_t freq1 = 0; // The local oscillator frequency of the ADRV9361-B is not used when using the ADRV9361-Z7035 board. + try { config_ad9361_rx_local(bandwidth_, sample_rate_, freq0_, - freq1_, + freq1, rf_port_select_, rx1_enable_, rx2_enable_, @@ -257,7 +250,6 @@ Adrv9361z7035SignalSourceFPGA::Adrv9361z7035SignalSourceFPGA(const Configuration buffer_monitor_fpga = std::make_shared(num_freq_bands, dump_, dump_filename); thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); }); - // dynamic bits selection if (enable_dynamic_bit_selection_) { @@ -278,15 +270,23 @@ Adrv9361z7035SignalSourceFPGA::Adrv9361z7035SignalSourceFPGA(const Configuration Adrv9361z7035SignalSourceFPGA::~Adrv9361z7035SignalSourceFPGA() { - /* cleanup and exit */ - + // cleanup and exit if (rf_shutdown_) { std::cout << "* AD9361 Disabling RX streaming channels\n"; - if (!disable_ad9361_rx_local()) + try { - LOG(WARNING) << "Problem shutting down the AD9361 RX channels"; + if (!disable_ad9361_rx_local()) + { + LOG(WARNING) << "Problem shutting down the AD9361 RX channels"; + } } + catch (const std::exception &e) + { + LOG(WARNING) << "Problem shutting down the AD9361 RX channels: " << e.what(); + std::cerr << "Problem shutting down the AD9361 RX channels: " << e.what() << '\n'; + } + if (enable_dds_lo_) { try @@ -301,24 +301,27 @@ Adrv9361z7035SignalSourceFPGA::~Adrv9361z7035SignalSourceFPGA() } // disable buffer overflow checking and buffer monitoring - std::unique_lock lock_buffer_monitor(buffer_monitor_mutex); - enable_ovf_check_buffer_monitor_active_ = false; - lock_buffer_monitor.unlock(); + { + std::lock_guard lock_buffer_monitor(buffer_monitor_mutex); + enable_ovf_check_buffer_monitor_active_ = false; + } if (thread_buffer_monitor.joinable()) { thread_buffer_monitor.join(); } - - std::unique_lock lock_dyn_bit_sel(dynamic_bit_selection_mutex); - bool bit_selection_enabled = enable_dynamic_bit_selection_; - lock_dyn_bit_sel.unlock(); + bool bit_selection_enabled = false; + { + std::lock_guard lock_dyn_bit_sel(dynamic_bit_selection_mutex); + bit_selection_enabled = enable_dynamic_bit_selection_; + } if (bit_selection_enabled == true) { - std::unique_lock lock(dynamic_bit_selection_mutex); - enable_dynamic_bit_selection_ = false; - lock.unlock(); + { + std::lock_guard lock(dynamic_bit_selection_mutex); + enable_dynamic_bit_selection_ = false; + } if (thread_dynamic_bit_selection.joinable()) { @@ -337,12 +340,11 @@ void Adrv9361z7035SignalSourceFPGA::run_dynamic_bit_selection_process() // setting the bit selection to the top bits dynamic_bit_selection_fpga->bit_selection(); std::this_thread::sleep_for(std::chrono::milliseconds(Gain_control_period_ms)); - std::unique_lock lock(dynamic_bit_selection_mutex); + std::lock_guard lock(dynamic_bit_selection_mutex); if (enable_dynamic_bit_selection_ == false) { dynamic_bit_selection_active = false; } - lock.unlock(); } } @@ -357,12 +359,11 @@ void Adrv9361z7035SignalSourceFPGA::run_buffer_monitor_process() { buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status(); std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms)); - std::unique_lock lock(buffer_monitor_mutex); + std::lock_guard lock(buffer_monitor_mutex); if (enable_ovf_check_buffer_monitor_active_ == false) { enable_ovf_check_buffer_monitor_active = false; } - lock.unlock(); } } diff --git a/src/algorithms/signal_source/adapters/adrv9361_z7035_signal_source_fpga.h b/src/algorithms/signal_source/adapters/adrv9361_z7035_signal_source_fpga.h index 5e7e8b7e4..286cde2d5 100644 --- a/src/algorithms/signal_source/adapters/adrv9361_z7035_signal_source_fpga.h +++ b/src/algorithms/signal_source/adapters/adrv9361_z7035_signal_source_fpga.h @@ -1,6 +1,6 @@ /*! * \file adrv9361_z7035_signal_source_fpga.h - * \brief signal source for the Analog Devices ADRV9361-Z7035 evaluation board + * \brief Signal source for the Analog Devices ADRV9361-Z7035 evaluation board * directly connected to the FPGA accelerators. * This source implements only the AD9361 control. It is NOT compatible with * conventional SDR acquisition and tracking blocks. @@ -23,7 +23,6 @@ #include "concurrent_queue.h" #include "fpga_buffer_monitor.h" -#include "fpga_dma-proxy.h" #include "fpga_dynamic_bit_selection.h" #include "fpga_switch.h" #include "gnss_block_interface.h" @@ -78,13 +77,14 @@ private: const uint32_t buffer_monitor_period_ms = 1000; // buffer overflow and buffer monitoring initial delay const uint32_t buffer_monitoring_initial_delay_ms = 2000; - // sample block size when running in post-processing mode - const int sample_block_size = 16384; const int32_t switch_to_real_time_mode = 2; void run_dynamic_bit_selection_process(); void run_buffer_monitor_process(); + mutable std::mutex dynamic_bit_selection_mutex; + mutable std::mutex buffer_monitor_mutex; + std::thread thread_dynamic_bit_selection; std::thread thread_buffer_monitor; @@ -92,9 +92,6 @@ private: std::shared_ptr dynamic_bit_selection_fpga; std::shared_ptr buffer_monitor_fpga; - std::mutex dynamic_bit_selection_mutex; - std::mutex buffer_monitor_mutex; - std::string gain_mode_rx1_; std::string gain_mode_rx2_; std::string rf_port_select_; @@ -109,7 +106,6 @@ private: double tx_attenuation_db_; uint64_t freq0_; // frequency of local oscillator for ADRV9361-A 0 - uint64_t freq1_; // frequency of local oscillator for ADRV9361-B (if present) uint64_t sample_rate_; uint64_t bandwidth_; uint64_t freq_dds_tx_hz_; @@ -124,7 +120,6 @@ private: size_t item_size_; bool enable_dds_lo_; - bool filter_auto_; bool quadrature_; bool rf_dc_; bool bb_dc_; diff --git a/src/algorithms/signal_source/adapters/fmcomms5_signal_source_fpga.cc b/src/algorithms/signal_source/adapters/fmcomms5_signal_source_fpga.cc index d8c5a65c0..f52c67425 100644 --- a/src/algorithms/signal_source/adapters/fmcomms5_signal_source_fpga.cc +++ b/src/algorithms/signal_source/adapters/fmcomms5_signal_source_fpga.cc @@ -1,6 +1,6 @@ /*! * \file fmcomms5_signal_source_fpga.cc - * \brief signal source for the Analog Devices FMCOMMS5 directly connected + * \brief Signal source for the Analog Devices FMCOMMS5 directly connected * to the FPGA accelerators. * This source implements only the AD9361 control. It is NOT compatible with * conventional SDR acquisition and tracking blocks. @@ -51,6 +51,7 @@ Fmcomms5SignalSourceFPGA::Fmcomms5SignalSourceFPGA(const ConfigurationInterface gain_mode_rx1_(configuration->property(role + ".gain_mode_rx1", default_gain_mode)), gain_mode_rx2_(configuration->property(role + ".gain_mode_rx2", default_gain_mode)), rf_port_select_(configuration->property(role + ".rf_port_select", default_rf_port_select)), + filter_source_(configuration->property(role + ".filter_source", std::string("Off"))), filter_filename_(configuration->property(role + ".filter_filename", filter_file_)), rf_gain_rx1_(configuration->property(role + ".gain_rx1", default_manual_gain_rx1)), rf_gain_rx2_(configuration->property(role + ".gain_rx2", default_manual_gain_rx2)), @@ -63,7 +64,6 @@ Fmcomms5SignalSourceFPGA::Fmcomms5SignalSourceFPGA(const ConfigurationInterface in_stream_(in_stream), out_stream_(out_stream), item_size_(sizeof(int8_t)), - filter_auto_(configuration->property(role + ".filter_auto", false)), quadrature_(configuration->property(role + ".quadrature", true)), rf_dc_(configuration->property(role + ".rf_dc", true)), bb_dc_(configuration->property(role + ".bb_dc", true)), @@ -86,15 +86,6 @@ Fmcomms5SignalSourceFPGA::Fmcomms5SignalSourceFPGA(const ConfigurationInterface const uint32_t num_freq_bands = ((enable_rx1_band == true) and (enable_rx2_band == true)) ? 2 : 1; - if (filter_auto_) - { - filter_source_ = configuration->property(role + ".filter_source", std::string("Auto")); - } - else - { - filter_source_ = configuration->property(role + ".filter_source", std::string("Off")); - } - switch_fpga = std::make_shared(); switch_fpga->set_switch_position(switch_to_real_time_mode); @@ -217,7 +208,6 @@ Fmcomms5SignalSourceFPGA::Fmcomms5SignalSourceFPGA(const ConfigurationInterface buffer_monitor_fpga = std::make_shared(num_freq_bands, dump_, dump_filename); thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); }); - // dynamic bits selection if (enable_dynamic_bit_selection_) { @@ -238,36 +228,45 @@ Fmcomms5SignalSourceFPGA::Fmcomms5SignalSourceFPGA(const ConfigurationInterface Fmcomms5SignalSourceFPGA::~Fmcomms5SignalSourceFPGA() { - /* cleanup and exit */ - + // cleanup and exit if (rf_shutdown_) { std::cout << "* Disabling RX streaming channels\n"; - if (!disable_ad9361_rx_local()) + try { - LOG(WARNING) << "Problem shutting down the AD9361 RX channels"; + if (!disable_ad9361_rx_local()) + { + LOG(WARNING) << "Problem shutting down the AD9361 RX channels"; + } + } + catch (const std::exception &e) + { + std::cerr << "Problem shutting down the AD9361 RX channels: " << e.what() << '\n'; } } // disable buffer overflow checking and buffer monitoring - std::unique_lock lock_buffer_monitor(buffer_monitor_mutex); - enable_ovf_check_buffer_monitor_active_ = false; - lock_buffer_monitor.unlock(); + { + std::lock_guard lock_buffer_monitor(buffer_monitor_mutex); + enable_ovf_check_buffer_monitor_active_ = false; + } if (thread_buffer_monitor.joinable()) { thread_buffer_monitor.join(); } - - std::unique_lock lock_dyn_bit_sel(dynamic_bit_selection_mutex); - bool bit_selection_enabled = enable_dynamic_bit_selection_; - lock_dyn_bit_sel.unlock(); + bool bit_selection_enabled = false; + { + std::lock_guard lock_dyn_bit_sel(dynamic_bit_selection_mutex); + bit_selection_enabled = enable_dynamic_bit_selection_; + } if (bit_selection_enabled == true) { - std::unique_lock lock(dynamic_bit_selection_mutex); - enable_dynamic_bit_selection_ = false; - lock.unlock(); + { + std::lock_guard lock(dynamic_bit_selection_mutex); + enable_dynamic_bit_selection_ = false; + } if (thread_dynamic_bit_selection.joinable()) { @@ -286,12 +285,11 @@ void Fmcomms5SignalSourceFPGA::run_dynamic_bit_selection_process() // setting the bit selection to the top bits dynamic_bit_selection_fpga->bit_selection(); std::this_thread::sleep_for(std::chrono::milliseconds(Gain_control_period_ms)); - std::unique_lock lock(dynamic_bit_selection_mutex); + std::lock_guard lock(dynamic_bit_selection_mutex); if (enable_dynamic_bit_selection_ == false) { dynamic_bit_selection_active = false; } - lock.unlock(); } } @@ -306,12 +304,11 @@ void Fmcomms5SignalSourceFPGA::run_buffer_monitor_process() { buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status(); std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms)); - std::unique_lock lock(buffer_monitor_mutex); + std::lock_guard lock(buffer_monitor_mutex); if (enable_ovf_check_buffer_monitor_active_ == false) { enable_ovf_check_buffer_monitor_active = false; } - lock.unlock(); } } diff --git a/src/algorithms/signal_source/adapters/fmcomms5_signal_source_fpga.h b/src/algorithms/signal_source/adapters/fmcomms5_signal_source_fpga.h index 1bdcf4e6f..fbb10bf67 100644 --- a/src/algorithms/signal_source/adapters/fmcomms5_signal_source_fpga.h +++ b/src/algorithms/signal_source/adapters/fmcomms5_signal_source_fpga.h @@ -1,6 +1,6 @@ /*! * \file fmcomms5_signal_source_fpga.h - * \brief signal source for the Analog Devices FMCOMMS5 directly connected + * \brief Signal source for the Analog Devices FMCOMMS5 directly connected * to the FPGA accelerators. * This source implements only the AD9361 control. It is NOT compatible with * conventional SDR acquisition and tracking blocks. @@ -23,7 +23,6 @@ #include "concurrent_queue.h" #include "fpga_buffer_monitor.h" -#include "fpga_dma-proxy.h" #include "fpga_dynamic_bit_selection.h" #include "fpga_switch.h" #include "gnss_block_interface.h" @@ -67,7 +66,6 @@ private: const std::string default_dump_filename = std::string("FPGA_buffer_monitor_dump.dat"); const std::string default_rf_port_select = std::string("A_BALANCED"); const std::string default_gain_mode = std::string("slow_attack"); - const double default_tx_attenuation_db = -10.0; const double default_manual_gain_rx1 = 64.0; const double default_manual_gain_rx2 = 64.0; const uint64_t default_bandwidth = 12500000; @@ -78,13 +76,14 @@ private: const uint32_t buffer_monitor_period_ms = 1000; // buffer overflow and buffer monitoring initial delay const uint32_t buffer_monitoring_initial_delay_ms = 2000; - // sample block size when running in post-processing mode - const int sample_block_size = 16384; const int32_t switch_to_real_time_mode = 2; void run_dynamic_bit_selection_process(); void run_buffer_monitor_process(); + mutable std::mutex dynamic_bit_selection_mutex; + mutable std::mutex buffer_monitor_mutex; + std::thread thread_dynamic_bit_selection; std::thread thread_buffer_monitor; @@ -92,9 +91,6 @@ private: std::shared_ptr dynamic_bit_selection_fpga; std::shared_ptr buffer_monitor_fpga; - std::mutex dynamic_bit_selection_mutex; - std::mutex buffer_monitor_mutex; - std::string gain_mode_rx1_; std::string gain_mode_rx2_; std::string rf_port_select_; @@ -117,7 +113,6 @@ private: size_t item_size_; - bool filter_auto_; bool quadrature_; bool rf_dc_; bool bb_dc_; diff --git a/src/algorithms/signal_source/adapters/ion_gsms_signal_source.cc b/src/algorithms/signal_source/adapters/ion_gsms_signal_source.cc new file mode 100644 index 000000000..00f2be229 --- /dev/null +++ b/src/algorithms/signal_source/adapters/ion_gsms_signal_source.cc @@ -0,0 +1,239 @@ +/*! + * \file ion_gsms_signal_source.h + * \brief GNSS-SDR Signal Source that reads sample streams following ION's GNSS-SDR metadata standard + * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#include "ion_gsms_signal_source.h" +#include "gnss_sdr_flags.h" +#include "gnss_sdr_string_literals.h" +#include "gnss_sdr_valve.h" +#include +#include +#include +#include + +#if USE_GLOG_AND_GFLAGS +#include +#else +#include +#endif + +using namespace std::string_literals; + +namespace +{ +std::vector parse_comma_list(const std::string& str) +{ + std::vector list{}; + std::size_t prev_comma_at{0}; + + while (prev_comma_at < str.size()) + { + std::size_t comma_at = str.find_first_of(',', prev_comma_at); + if (comma_at == std::string::npos) + { + comma_at = str.size(); + } + list.emplace_back(str.substr(prev_comma_at, (comma_at - prev_comma_at))); + prev_comma_at = comma_at + 1; + } + + return list; +} +} // anonymous namespace + + +IONGSMSSignalSource::IONGSMSSignalSource(const ConfigurationInterface* configuration, + const std::string& role, + unsigned int in_streams, + unsigned int out_streams, + Concurrent_Queue* queue) + : SignalSourceBase(configuration, role, "ION_GSMS_Signal_Source"s), + stream_ids_(parse_comma_list(configuration->property(role + ".streams"s, ""s))), + metadata_filepath_(configuration->property(role + ".metadata_filename"s, "../data/example_capture_metadata.sdrx"s)), + in_streams_(in_streams), + out_streams_(out_streams) +{ + if (in_streams_ > 0) + { + LOG(ERROR) << "A signal source does not have an input stream"; + } + if (out_streams_ <= 0) + { + LOG(ERROR) << "A signal source does not have an output stream"; + } + + // Parse XML metadata file + load_metadata(); + + // Make source vector + sources_ = make_stream_sources(stream_ids_); + + for (const auto& source : sources_) + { + for (std::size_t i = 0; i < source->output_stream_count(); ++i) + { + copy_blocks_.emplace_back(gr::blocks::copy::make(source->output_stream_item_size(i))); + valves_.emplace_back(gnss_sdr_make_valve(source->output_stream_item_size(i), source->output_stream_total_sample_count(i), queue)); + } + } +} + + +void IONGSMSSignalSource::load_metadata() +{ + metadata_ = std::make_shared(); + try + { + GnssMetadata::XmlProcessor xml_proc; + if (!xml_proc.Load(metadata_filepath_.c_str(), false, *metadata_)) + { + LOG(WARNING) << "Could not load XML metadata file " << metadata_filepath_; + std::cerr << "Could not load XML metadata file " << metadata_filepath_ << std::endl; + std::cout << "GNSS-SDR program ended.\n"; + exit(1); + } + } + catch (GnssMetadata::ApiException& e) + { + LOG(WARNING) << "API Exception while loading XML metadata file: " << std::to_string(e.Error()); + std::cerr << "Could not load XML metadata file " << metadata_filepath_ << " : " << std::to_string(e.Error()) << std::endl; + std::cout << "GNSS-SDR program ended.\n"; + exit(1); + } + catch (std::exception& e) + { + LOG(WARNING) << "Exception while loading XML metadata file: " << e.what(); + std::cerr << "Could not load XML metadata file " << metadata_filepath_ << " : " << e.what() << std::endl; + std::cout << "GNSS-SDR program ended.\n"; + exit(1); + } +} + + +std::vector IONGSMSSignalSource::make_stream_sources(const std::vector& stream_ids) const +{ + std::vector sources{}; + for (const auto& file : metadata_->Files()) + { + for (const auto& lane : metadata_->Lanes()) + { + if (lane.Id() == file.Lane().Id()) + { + for (const auto& block : lane.Blocks()) + { + bool block_done = false; + for (const auto& chunk : block.Chunks()) + { + for (const auto& lump : chunk.Lumps()) + { + for (const auto& stream : lump.Streams()) + { + bool found = false; + for (const auto& stream_id : stream_ids) + { + if (stream_id == stream.Id()) + { + found = true; + break; + } + } + if (found) + { + auto source = gnss_make_shared( + metadata_filepath_, + file, + block, + stream_ids); + + sources.push_back(source); + + // This file source will take care of any other matching streams in this block + // We can skip the rest of this block + block_done = true; + break; + } + } + + if (block_done) + { + break; + } + } + if (block_done) + { + break; + } + } + } + break; + } + } + } + + return sources; +} + + +void IONGSMSSignalSource::connect(gr::top_block_sptr top_block) +{ + std::size_t cumulative_index = 0; + for (const auto& source : sources_) + { + for (std::size_t i = 0; i < source->output_stream_count(); ++i, ++cumulative_index) + { + top_block->connect(source, i, copy_blocks_[cumulative_index], 0); + top_block->connect(copy_blocks_[cumulative_index], 0, valves_[cumulative_index], 0); + } + } +} + + +void IONGSMSSignalSource::disconnect(gr::top_block_sptr top_block) +{ + std::size_t cumulative_index = 0; + for (const auto& source : sources_) + { + for (std::size_t i = 0; i < source->output_stream_count(); ++i, ++cumulative_index) + { + top_block->disconnect(source, i, copy_blocks_[cumulative_index], 0); + top_block->disconnect(copy_blocks_[cumulative_index], 0, valves_[cumulative_index], 0); + } + } +} + + +gr::basic_block_sptr IONGSMSSignalSource::get_left_block() +{ + LOG(WARNING) << "Trying to get signal source left block."; + // return gr_basic_block_sptr(); + return IONGSMSFileSource::sptr(); +} + + +gr::basic_block_sptr IONGSMSSignalSource::get_right_block() +{ + return get_right_block(0); +} + + +gr::basic_block_sptr IONGSMSSignalSource::get_right_block(int RF_channel) +{ + if (RF_channel < 0 || RF_channel >= static_cast(copy_blocks_.size())) + { + LOG(WARNING) << "'RF_channel' out of bounds while trying to get signal source right block."; + return valves_[0]; + } + return valves_[RF_channel]; +} diff --git a/src/algorithms/signal_source/adapters/ion_gsms_signal_source.h b/src/algorithms/signal_source/adapters/ion_gsms_signal_source.h new file mode 100644 index 000000000..bcdedbc3d --- /dev/null +++ b/src/algorithms/signal_source/adapters/ion_gsms_signal_source.h @@ -0,0 +1,85 @@ +/*! + * \file ion_gsms_signal_source.h + * \brief GNSS-SDR Signal Source that reads sample streams following ION's GNSS-SDR metadata standard + * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + + +#ifndef GNSS_SDR_ION_GSMS_SIGNAL_SOURCE_H +#define GNSS_SDR_ION_GSMS_SIGNAL_SOURCE_H + +#include "configuration_interface.h" +#include "file_source_base.h" +#include "gnss_sdr_timestamp.h" +#include "ion_gsms.h" +#include +#include +#include +#include +#include + +/** \addtogroup Signal_Source + * \{ */ +/** \addtogroup Signal_Source_adapters + * \{ */ + +/*! + * \brief Class that reads signals samples from a file + * and adapts it to a SignalSourceInterface + */ +class IONGSMSSignalSource : public SignalSourceBase +{ +public: + IONGSMSSignalSource(const ConfigurationInterface* configuration, const std::string& role, + unsigned int in_streams, unsigned int out_streams, + Concurrent_Queue* queue); + + ~IONGSMSSignalSource() override = default; + +protected: + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + gr::basic_block_sptr get_right_block(int RF_channel) override; + + inline size_t item_size() override + { + return (*sources_.begin())->output_stream_item_size(0); + } + +private: + std::vector make_stream_sources(const std::vector& stream_ids) const; + + void load_metadata(); + + std::vector stream_ids_; + std::vector sources_; + std::vector> copy_blocks_; + std::vector> valves_; + + std::string metadata_filepath_; + std::shared_ptr metadata_; + + gnss_shared_ptr timestamp_block_; + std::string timestamp_file_; + + uint32_t in_streams_; + uint32_t out_streams_; +}; + + +/** \} */ +/** \} */ +#endif // GNSS_SDR_ION_GSMS_SIGNAL_SOURCE_H diff --git a/src/algorithms/signal_source/adapters/max2771_evkit_signal_source_fpga.cc b/src/algorithms/signal_source/adapters/max2771_evkit_signal_source_fpga.cc index 788b50e77..80b310034 100644 --- a/src/algorithms/signal_source/adapters/max2771_evkit_signal_source_fpga.cc +++ b/src/algorithms/signal_source/adapters/max2771_evkit_signal_source_fpga.cc @@ -140,13 +140,11 @@ MAX2771EVKITSignalSourceFPGA::MAX2771EVKITSignalSourceFPGA(const ConfigurationIn } } + std::vector MAX2771EVKITSignalSourceFPGA::setup_regs(void) { - std::vector register_values = std::vector(MAX2771_NUM_REGS); - - + auto register_values = std::vector(MAX2771_NUM_REGS); uint32_t LNA_mode = (LNA_active_) ? 0x0 : 0x2; - uint32_t Filter_Bandwidth; switch (bandwidth_) @@ -376,10 +374,10 @@ bool MAX2771EVKITSignalSourceFPGA::configure(std::vector register_valu return 0; } + MAX2771EVKITSignalSourceFPGA::~MAX2771EVKITSignalSourceFPGA() { - /* cleanup and exit */ - + // cleanup and exit if (rf_shutdown_) { chipen_ = false; @@ -392,7 +390,6 @@ MAX2771EVKITSignalSourceFPGA::~MAX2771EVKITSignalSourceFPGA() return; } - if (configure(register_values)) { std::cerr << "Error disabling the MAX2771 device " << '\n'; @@ -405,9 +402,10 @@ MAX2771EVKITSignalSourceFPGA::~MAX2771EVKITSignalSourceFPGA() } // disable buffer overflow checking and buffer monitoring - std::unique_lock lock_buffer_monitor(buffer_monitor_mutex); - enable_ovf_check_buffer_monitor_active_ = false; - lock_buffer_monitor.unlock(); + { + std::lock_guard lock_buffer_monitor(buffer_monitor_mutex); + enable_ovf_check_buffer_monitor_active_ = false; + } if (thread_buffer_monitor.joinable()) { @@ -426,12 +424,11 @@ void MAX2771EVKITSignalSourceFPGA::run_buffer_monitor_process() { buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status(); std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms)); - std::unique_lock lock(buffer_monitor_mutex); + std::lock_guard lock(buffer_monitor_mutex); if (enable_ovf_check_buffer_monitor_active_ == false) { enable_ovf_check_buffer_monitor_active = false; } - lock.unlock(); } } diff --git a/src/algorithms/signal_source/adapters/max2771_evkit_signal_source_fpga.h b/src/algorithms/signal_source/adapters/max2771_evkit_signal_source_fpga.h index 3008aa384..5ba036ca3 100644 --- a/src/algorithms/signal_source/adapters/max2771_evkit_signal_source_fpga.h +++ b/src/algorithms/signal_source/adapters/max2771_evkit_signal_source_fpga.h @@ -53,7 +53,6 @@ public: std::vector setup_regs(void); - inline size_t item_size() override { return item_size_; @@ -130,14 +129,13 @@ private: bool configure(std::vector register_values); void run_buffer_monitor_process(); + mutable std::mutex buffer_monitor_mutex; std::thread thread_buffer_monitor; std::shared_ptr buffer_monitor_fpga; std::shared_ptr spidev_fpga; - std::mutex buffer_monitor_mutex; - uint64_t freq_; // frequency of local oscillator uint64_t sample_rate_; diff --git a/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt b/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt index 24f067be6..2eca5157a 100644 --- a/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt @@ -10,17 +10,16 @@ if(ENABLE_RAW_UDP AND PCAP_FOUND) list(APPEND OPT_DRIVER_HEADERS gr_complex_ip_packet_source.h) endif() -if(ENABLE_AD936X_SDR) - set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} gr_complex_ip_packet_source.cc) - set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} gr_complex_ip_packet_source.h) -endif() - - -if(ENABLE_PLUTOSDR) +if(ENABLE_PLUTOSDR OR ENABLE_AD936X_SDR) set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ad936x_iio_source.cc) set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_iio_source.h) endif() +if(ENABLE_ION) + set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ion_gsms.cc) + set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ion_gsms.h) +endif() + set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES fifo_reader.cc unpack_byte_2bit_samples.cc diff --git a/src/algorithms/signal_source/gnuradio_blocks/ad936x_iio_source.cc b/src/algorithms/signal_source/gnuradio_blocks/ad936x_iio_source.cc index 0cf885fe2..c87006bd5 100644 --- a/src/algorithms/signal_source/gnuradio_blocks/ad936x_iio_source.cc +++ b/src/algorithms/signal_source/gnuradio_blocks/ad936x_iio_source.cc @@ -1,6 +1,7 @@ /*! * \file ad936x_iio_source.cc - * \brief A direct IIO custom front-end gnss-sdr signal gnuradio block for the AD936x AD front-end family with special FPGA custom functionalities. + * \brief A direct IIO custom front-end gnss-sdr signal gnuradio block for the + * AD936x AD front-end family with special FPGA custom functionalities. * \author Javier Arribas, jarribas(at)cttc.es * * ----------------------------------------------------------------------------- @@ -33,23 +34,23 @@ ad936x_iio_source_sptr ad936x_iio_make_source_sptr( - std::string pluto_uri_, - std::string board_type_, - long long bandwidth_, - long long sample_rate_, - long long freq_, - std::string rf_port_select_, - std::string rf_filter, - std::string gain_mode_rx0_, - std::string gain_mode_rx1_, + const std::string& pluto_uri_, + const std::string& board_type_, + int64_t bandwidth_, + int64_t sample_rate_, + int64_t freq_, + const std::string& rf_port_select_, + const std::string& rf_filter, + const std::string& gain_mode_rx0_, + const std::string& gain_mode_rx1_, double rf_gain_rx0_, double rf_gain_rx1_, bool enable_ch0, bool enable_ch1, - long long freq_2ch, + int64_t freq_2ch, bool ppsmode_, bool customsamplesize_, - std::string fe_ip_, + const std::string& fe_ip_, int fe_ctlport_, int ssize_, int bshift_, @@ -85,9 +86,10 @@ ad936x_iio_source_sptr ad936x_iio_make_source_sptr( tx_lo_channel_)); } -void ad936x_iio_source::ad9361_channel_demux_and_record(ad936x_iio_samples *samples_in, int nchannels, std::vector *files_out) + +void ad936x_iio_source::ad9361_channel_demux_and_record(ad936x_iio_samples* samples_in, int nchannels, std::vector* files_out) { - int32_t current_byte = 0; + uint32_t current_byte = 0; int16_t ch = 0; // std::cout << "nbytes: " << samples_in->n_bytes << " nsamples: " << samples_in->n_samples << " nch: " << nchannels << "\n"; while (current_byte < samples_in->n_bytes) @@ -101,24 +103,25 @@ void ad936x_iio_source::ad9361_channel_demux_and_record(ad936x_iio_samples *samp } } + ad936x_iio_source::ad936x_iio_source( - std::string pluto_uri_, - std::string board_type_, - long long bandwidth_, - long long sample_rate_, - long long freq_, - std::string rf_port_select_, - std::string rf_filter, - std::string gain_mode_rx0_, - std::string gain_mode_rx1_, + const std::string& pluto_uri_, + const std::string& board_type_, + int64_t bandwidth_, + int64_t sample_rate_, + int64_t freq_, + const std::string& rf_port_select_, + const std::string& rf_filter, + const std::string& gain_mode_rx0_, + const std::string& gain_mode_rx1_, double rf_gain_rx0_, double rf_gain_rx1_, bool enable_ch0, bool enable_ch1, - long long freq_2ch, + int64_t freq_2ch, bool ppsmode_, bool customsamplesize_, - std::string fe_ip_, + const std::string& fe_ip_, int fe_ctlport_, int ssize_, int bshift_, @@ -171,54 +174,81 @@ ad936x_iio_source::ad936x_iio_source( case 16: { std::cout << "FPGA sample size set to 16 bits per sample.\n"; - if (pps_rx->send_cmd("ssize=16\n") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("ssize=16\n") == false) + { + std::cout << "cmd send error!\n"; + } break; } case 8: { std::cout << "FPGA sample size set to 8 bits per sample.\n"; - if (pps_rx->send_cmd("ssize=8\n") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("ssize=8\n") == false) + { + std::cout << "cmd send error!\n"; + } break; } case 4: { std::cout << "FPGA sample size set to 4 bits per sample.\n"; - if (pps_rx->send_cmd("ssize=4\n") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("ssize=4\n") == false) + { + std::cout << "cmd send error!\n"; + } break; } case 2: { std::cout << "FPGA sample size set to 2 bits per sample.\n"; - if (pps_rx->send_cmd("ssize=2\n") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("ssize=2\n") == false) + { + std::cout << "cmd send error!\n"; + } break; } default: { std::cout << "WARNING: Unsupported ssize. FPGA sample size set to 16 bits per sample.\n"; - if (pps_rx->send_cmd("ssize=16") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("ssize=16") == false) + { + std::cout << "cmd send error!\n"; + } } } if (bshift_ >= 0 and bshift_ <= 14) { std::cout << "FPGA sample bits shift left set to " + std::to_string(bshift_) + " positions.\n"; - if (pps_rx->send_cmd("bshift=" + std::to_string(bshift_) + "\n") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("bshift=" + std::to_string(bshift_) + "\n") == false) + { + std::cout << "cmd send error!\n"; + } } else { std::cout << "WARNING: Unsupported bshift. FPGA sample bits shift left set to 0.\n"; - if (pps_rx->send_cmd("bshift=0\n") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("bshift=0\n") == false) + { + std::cout << "cmd send error!\n"; + } } if (spattern_ == true) { std::cout << "FPGA debug sample pattern is active!.\n"; - if (pps_rx->send_cmd("spattern=1\n") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("spattern=1\n") == false) + { + std::cout << "cmd send error!\n"; + } } else { std::cout << "FPGA debug sample pattern disabled.\n"; - if (pps_rx->send_cmd("spattern=0\n") == false) std::cout << "cmd send error!\n"; + if (pps_rx->send_cmd("spattern=0\n") == false) + { + std::cout << "cmd send error!\n"; + } } } else @@ -238,7 +268,7 @@ ad936x_iio_source::ad936x_iio_source( exit(1); } } - catch (std::exception const &ex) + catch (std::exception const& ex) { std::cerr << "STD exception: " << ex.what() << std::endl; exit(1); @@ -267,6 +297,7 @@ ad936x_iio_source::ad936x_iio_source( // } } + ad936x_iio_source::~ad936x_iio_source() { // Terminate PPS thread @@ -284,6 +315,7 @@ bool ad936x_iio_source::start() return ad936x_custom->start_sample_rx(false); } + bool ad936x_iio_source::stop() { std::cout << "stopping ad936x_iio_source...\n"; @@ -291,17 +323,17 @@ bool ad936x_iio_source::stop() return true; } + int ad936x_iio_source::general_work(int noutput_items, - __attribute__((unused)) gr_vector_int &ninput_items, - __attribute__((unused)) gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + __attribute__((unused)) gr_vector_int& ninput_items, + __attribute__((unused)) gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) { std::shared_ptr current_buffer; - ad936x_iio_samples *current_samples; + ad936x_iio_samples* current_samples; ad936x_custom->pop_sample_buffer(current_buffer); current_samples = current_buffer.get(); - // I and Q samples are interleaved in buffer: IQIQIQ... int32_t n_interleaved_iq_samples_per_channel = current_samples->n_bytes / (ad936x_custom->n_channels * 2); if (noutput_items < n_interleaved_iq_samples_per_channel) @@ -312,7 +344,7 @@ int ad936x_iio_source::general_work(int noutput_items, else { // ad9361_channel_demux_and_record(current_samples, ad936x_custom->n_channels, &samplesfile); - auto **out = reinterpret_cast(&output_items[0]); + auto** out = reinterpret_cast(&output_items[0]); uint32_t current_byte = 0; uint32_t current_byte_in_gr = 0; int16_t ch = 0; diff --git a/src/algorithms/signal_source/gnuradio_blocks/ad936x_iio_source.h b/src/algorithms/signal_source/gnuradio_blocks/ad936x_iio_source.h index 411906a3e..8f5a34c7c 100644 --- a/src/algorithms/signal_source/gnuradio_blocks/ad936x_iio_source.h +++ b/src/algorithms/signal_source/gnuradio_blocks/ad936x_iio_source.h @@ -1,6 +1,7 @@ /*! * \file ad936x_iio_source.h - * \brief A direct IIO custom front-end gnss-sdr signal gnuradio block for the AD936x AD front-end family with special FPGA custom functionalities. + * \brief A direct IIO custom front-end gnss-sdr signal gnuradio block for the + * AD936x AD front-end family with special FPGA custom functionalities. * \author Javier Arribas, jarribas(at)cttc.es * * ----------------------------------------------------------------------------- @@ -44,23 +45,23 @@ class ad936x_iio_source; using ad936x_iio_source_sptr = gnss_shared_ptr; ad936x_iio_source_sptr ad936x_iio_make_source_sptr( - std::string pluto_uri_, - std::string board_type_, - long long bandwidth_, - long long sample_rate_, - long long freq_, - std::string rf_port_select_, - std::string rf_filter, - std::string gain_mode_rx0_, - std::string gain_mode_rx1_, + const std::string &pluto_uri_, + const std::string &board_type_, + int64_t bandwidth_, + int64_t sample_rate_, + int64_t freq_, + const std::string &rf_port_select_, + const std::string &rf_filter, + const std::string &gain_mode_rx0_, + const std::string &gain_mode_rx1_, double rf_gain_rx0_, double rf_gain_rx1_, bool enable_ch0, bool enable_ch1, - long long freq_2ch, + int64_t freq_2ch, bool ppsmode_, bool customsamplesize_, - std::string fe_ip_, + const std::string &fe_ip_, int fe_ctlport_, int ssize_, int bshift_, @@ -90,23 +91,23 @@ public: private: friend ad936x_iio_source_sptr ad936x_iio_make_source_sptr( - std::string pluto_uri_, - std::string board_type_, - long long bandwidth_, - long long sample_rate_, - long long freq_, - std::string rf_port_select_, - std::string rf_filter, - std::string gain_mode_rx0_, - std::string gain_mode_rx1_, + const std::string &pluto_uri_, + const std::string &board_type_, + int64_t bandwidth_, + int64_t sample_rate_, + int64_t freq_, + const std::string &rf_port_select_, + const std::string &rf_filter, + const std::string &gain_mode_rx0_, + const std::string &gain_mode_rx1_, double rf_gain_rx0_, double rf_gain_rx1_, bool enable_ch0, bool enable_ch1, - long long freq_2ch, + int64_t freq_2ch, bool ppsmode_, bool customsamplesize_, - std::string fe_ip_, + const std::string &fe_ip_, int fe_ctlport_, int ssize_, int bshift_, @@ -116,23 +117,23 @@ private: int tx_lo_channel_); ad936x_iio_source( - std::string pluto_uri_, - std::string board_type_, - long long bandwidth_, - long long sample_rate_, - long long freq_, - std::string rf_port_select_, - std::string rf_filter, - std::string gain_mode_rx0_, - std::string gain_mode_rx1_, + const std::string &pluto_uri_, + const std::string &board_type_, + int64_t bandwidth_, + int64_t sample_rate_, + int64_t freq_, + const std::string &rf_port_select_, + const std::string &rf_filter, + const std::string &gain_mode_rx0_, + const std::string &gain_mode_rx1_, double rf_gain_rx0_, double rf_gain_rx1_, bool enable_ch0, bool enable_ch1, - long long freq_2ch, + int64_t freq_2ch, bool ppsmode_, bool customsamplesize_, - std::string fe_ip_, + const std::string &fe_ip_, int fe_ctlport_, int ssize_, int bshift_, @@ -141,7 +142,6 @@ private: bool high_side_lo_, int tx_lo_channel_); - void ad9361_channel_demux_to_buffer(ad936x_iio_samples *samples_in, int nchannels, gr_vector_void_star &output_items); void ad9361_channel_demux_and_record(ad936x_iio_samples *samples_in, int nchannels, std::vector *files_out); diff --git a/src/algorithms/signal_source/gnuradio_blocks/ion_gsms.cc b/src/algorithms/signal_source/gnuradio_blocks/ion_gsms.cc new file mode 100644 index 000000000..22a25868c --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/ion_gsms.cc @@ -0,0 +1,202 @@ +/*! + * \file ion_gsms.cc + * \brief GNU Radio block that reads a Block from a file following ION's GNSS-SDR metadata standard + * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#include "ion_gsms.h" +#include "gnuradio/block.h" +#include +#include +#include +#include + +#if USE_GLOG_AND_GFLAGS +#include +#else +#include +#endif + +IONGSMSFileSource::IONGSMSFileSource( + const fs::path& metadata_filepath, + const GnssMetadata::File& file, + const GnssMetadata::Block& block, + const std::vector& stream_ids) + : gr::sync_block( + "ion_gsms_file_source", + gr::io_signature::make(0, 0, 0), + make_output_signature(block, stream_ids)), + file_stream_(metadata_filepath.parent_path() / file.Url().Value(), std::ios::in | std::ios::binary), + io_buffer_offset_(0), + maximum_item_rate_(0), + chunk_cycle_length_(0) +{ + fs::path data_filepath = metadata_filepath.parent_path() / file.Url().Value(); + std::size_t block_offset = file.Offset(); + + if (!file_stream_.is_open()) + { + LOG(WARNING) << "ION_GSMS_Signal_Source - Unable to open the samples file: " << (data_filepath).c_str(); + std::cerr << "ION_GSMS_Signal_Source - Unable to open the samples file: " << (data_filepath).c_str() << std::endl; + std::cout << "GNSS-SDR program ended.\n"; + exit(1); + } + + // Skip offset and block header + file_stream_.seekg(file.Offset() + block_offset + block.SizeHeader()); + + std::size_t output_stream_offset = 0; + for (const auto& chunk : block.Chunks()) + { + chunk_data_.emplace_back(std::make_shared(chunk, stream_ids, output_stream_offset)); + chunk_cycle_length_ += chunk.CountWords() * chunk.SizeWord(); + const std::size_t out_count = chunk_data_.back()->output_stream_count(); + output_stream_offset += out_count; + for (std::size_t i = 0; i < out_count; ++i) + { + output_stream_item_sizes_.push_back(chunk_data_.back()->output_stream_item_size(i)); + output_stream_item_rates_.push_back(chunk_data_.back()->output_stream_item_rate(i)); + maximum_item_rate_ = std::max(chunk_data_.back()->output_stream_item_rate(i), maximum_item_rate_); + } + } + output_stream_count_ = output_stream_offset; + + output_stream_total_sample_counts_.resize(output_stream_count_); + + std::size_t cycle_count = block.Cycles(); + if (cycle_count == 0) + { + // Read the whole file + const std::size_t file_size = fs::file_size(data_filepath); + cycle_count = std::floor((file_size - block_offset - block.SizeHeader()) / chunk_cycle_length_); + } + + for (std::size_t i = 0; i < output_stream_count_; ++i) + { + output_stream_total_sample_counts_[i] = cycle_count * output_stream_item_rates_[i]; + } +} + + +std::size_t IONGSMSFileSource::output_stream_count() const +{ + return output_stream_count_; +} + + +std::size_t IONGSMSFileSource::output_stream_item_size(std::size_t stream_index) const +{ + return output_stream_item_sizes_[stream_index]; +} + + +std::size_t IONGSMSFileSource::output_stream_total_sample_count(std::size_t stream_index) const +{ + return output_stream_total_sample_counts_[stream_index]; +} + + +gr::io_signature::sptr IONGSMSFileSource::make_output_signature(const GnssMetadata::Block& block, const std::vector& stream_ids) +{ + int nstreams = 0; + std::vector item_sizes{}; + + for (const auto& chunk : block.Chunks()) + { + for (const auto& lump : chunk.Lumps()) + { + for (const auto& stream : lump.Streams()) + { + bool found = false; + for (const auto& stream_id : stream_ids) + { + if (stream_id == stream.Id()) + { + found = true; + break; + } + } + if (found) + { + ++nstreams; + std::size_t sample_bitsize = stream.Packedbits() / stream.RateFactor(); + if (stream.Packedbits() >= 2 * stream.RateFactor() * stream.Quantization()) + { + // Samples have 'Complex' format + sample_bitsize /= 2; + } + item_sizes.push_back(bits_to_item_size(sample_bitsize)); + } + } + } + } + + return gr::io_signature::makev( + nstreams, + nstreams, + item_sizes); +} + + +int IONGSMSFileSource::work( + int noutput_items, + gr_vector_const_void_star& input_items __attribute__((unused)), + gr_vector_void_star& output_items) +{ + // Compute the maximum number of samples that will be copied across all output buffer. + // If there are more than one output buffer (multichannel set up), the one with the most samples will be used as the maximum. + // + // Complex samples produce 2 items each (I and Q). In order to account for them, we subtract 1 from `noutput_items` and + // then floor the division. During testing, not doing this caused `max_sample_output` to oscillate between two values, thus + // resizing the `io_buffer_` on each call to `work()`. + const std::size_t max_sample_output = std::floor((noutput_items - 1.0) / maximum_item_rate_); + + // Resize the IO buffer to fit exactly the maximum amount of samples that will be outputted. + io_buffer_.resize(max_sample_output * chunk_cycle_length_); + + // We will be walking the IO buffer with this variable. + io_buffer_offset_ = 0; + + // Read samples from file into IO buffer + const std::size_t bytes_to_read = io_buffer_.size(); + file_stream_.read(io_buffer_.data(), bytes_to_read); + + // Reset `items_produced_` vector. This vector will accumulate the amount of items produced for each output stream. + items_produced_.clear(); + items_produced_.resize(output_items.size()); + + // Walk the IO buffer one chunk cycle at a time. See ION documentation for a definition of chunk and chunk cycle. + while (io_buffer_offset_ < bytes_to_read) + { + // Iterate chunks within a chunk cycle + for (auto& chunk : chunk_data_) + { + // Copy chunk into a separate buffer where the samples will be shifted from. + const std::size_t bytes_copied = chunk->read_from_buffer(reinterpret_cast(io_buffer_.data()), io_buffer_offset_); + + // Advance IO buffer offset + io_buffer_offset_ += bytes_copied; + + // Shift samples into output buffers following the appropriate unpacking strategy for this chunk. + chunk->write_to_output(output_items, items_produced_); + } + } + + // Call `produce(int, int)` with the appropriate item count for each output stream. + for (std::size_t i = 0; i < items_produced_.size(); ++i) + { + produce(i, items_produced_[i]); + } + + return WORK_CALLED_PRODUCE; +} diff --git a/src/algorithms/signal_source/gnuradio_blocks/ion_gsms.h b/src/algorithms/signal_source/gnuradio_blocks/ion_gsms.h new file mode 100644 index 000000000..4a6baa7e9 --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/ion_gsms.h @@ -0,0 +1,74 @@ +/*! + * \file ion_gsms.h + * \brief GNU Radio block that reads a Block from a file following ION's GNSS-SDR metadata standard + * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_ION_GSMS_H +#define GNSS_SDR_ION_GSMS_H + +#include "gnss_block_interface.h" +#include "gnss_sdr_filesystem.h" +#include "ion_gsms_chunk_data.h" +#include +#include +#include +#include +#include +#include +#include + +/** \addtogroup Signal_Source + * \{ */ +/** \addtogroup Signal_Source_gnuradio_blocks + * \{ */ + +class IONGSMSFileSource : public gr::sync_block +{ +public: + using sptr = gnss_shared_ptr; + + IONGSMSFileSource( + const fs::path& metadata_filepath, + const GnssMetadata::File& file, + const GnssMetadata::Block& block, + const std::vector& stream_ids); + + int work( + int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) override; + + std::size_t output_stream_count() const; + std::size_t output_stream_item_size(std::size_t stream_index) const; + std::size_t output_stream_total_sample_count(std::size_t stream_index) const; + +private: + static gr::io_signature::sptr make_output_signature(const GnssMetadata::Block& block, const std::vector& stream_ids); + + std::ifstream file_stream_; + std::vector io_buffer_; + std::size_t io_buffer_offset_; + std::vector items_produced_; + std::size_t output_stream_count_; + std::vector output_stream_item_sizes_; + std::vector output_stream_item_rates_; + std::vector output_stream_total_sample_counts_; + std::size_t maximum_item_rate_; + std::vector> chunk_data_; + std::size_t chunk_cycle_length_; +}; + +/** \} */ +/** \} */ +#endif // GNSS_SDR_ION_GSMS_H diff --git a/src/algorithms/signal_source/libs/CMakeLists.txt b/src/algorithms/signal_source/libs/CMakeLists.txt index 3506dc4f7..0df4f3303 100644 --- a/src/algorithms/signal_source/libs/CMakeLists.txt +++ b/src/algorithms/signal_source/libs/CMakeLists.txt @@ -7,14 +7,15 @@ set(OPT_SIGNAL_SOURCE_LIB_SOURCES "") set(OPT_SIGNAL_SOURCE_LIB_HEADERS "") + if(ENABLE_FMCOMMS2 OR ENABLE_AD9361) set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad9361_manager.cc) - set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad9361_manager.h) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ad9361_manager.h) endif() if(ENABLE_MAX2771) set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_spidev.cc) - set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_spidev.h) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_spidev.h) endif() if(ENABLE_FPGA) @@ -34,16 +35,21 @@ if((ENABLE_FPGA AND ENABLE_AD9361) OR ENABLE_MAX2771) set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_buffer_monitor.h) endif() -if(ENABLE_PLUTOSDR) - set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_samples.cc) - set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_samples.h) +if(ENABLE_PLUTOSDR OR ENABLE_AD936X_SDR) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ad936x_iio_samples.h) set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_custom.cc) - set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_custom.h) - set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} pps_samplestamp.h) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ad936x_iio_custom.h) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} pps_samplestamp.h) set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ppstcprx.cc) - set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ppstcprx.h) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ppstcprx.h) endif() +if(ENABLE_ION) + set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ion_gsms_chunk_data.cc) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ion_gsms_chunk_data.h) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ion_gsms_stream_encodings.h) + set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ion_gsms_chunk_unpacking_ctx.h) +endif() set(SIGNAL_SOURCE_LIB_SOURCES rtl_tcp_commands.cc @@ -107,7 +113,7 @@ if(GNURADIO_USES_STD_POINTERS) ) endif() -if(ENABLE_FMCOMMS2 OR ENABLE_AD9361 OR ENABLE_PLUTOSDR) +if(ENABLE_FMCOMMS2 OR ENABLE_AD9361 OR ENABLE_PLUTOSDR OR ENABLE_AD936X_SDR) target_link_libraries(signal_source_libs PUBLIC Iio::iio @@ -130,6 +136,10 @@ if(ENABLE_FPGA OR ENABLE_AD9361) ) endif() +if(ENABLE_ION) + target_link_libraries(signal_source_libs PUBLIC ION::ion algorithms_libs) +endif() + if(ENABLE_CLANG_TIDY) if(CLANG_TIDY_EXE) set_target_properties(signal_source_libs diff --git a/src/algorithms/signal_source/libs/ad9361_manager.cc b/src/algorithms/signal_source/libs/ad9361_manager.cc index 913488287..025f97627 100644 --- a/src/algorithms/signal_source/libs/ad9361_manager.cc +++ b/src/algorithms/signal_source/libs/ad9361_manager.cc @@ -349,7 +349,7 @@ bool config_ad9361_rx_local(uint64_t bandwidth_, #ifndef LIBAD9361_VERSION_GREATER_THAN_01 if (filter_source_ == "Design") { - std::cout << "Option filter_source=Design is not available in this version. Set to filter_source=Off\n"; + std::cout << "Option filter_source=Design is not available in this version of libad9361. Set to filter_source=Off\n"; filter_source_ = std::string("Off"); } if (Fpass_ != 0.0 or Fstop_ != 0.0) @@ -636,7 +636,7 @@ bool config_ad9361_rx_remote(const std::string &remote_host, { return false; } - if (setup_filter(std::move(filter_source_), bandwidth_, sample_rate_, freq_, rf_port_select_, ad9361_phy, rx_chan0, chn, 0, std::move(filter_filename_), Fpass_, Fstop_) == -1) + if (setup_filter(filter_source_, bandwidth_, sample_rate_, freq_, rf_port_select_, ad9361_phy, rx_chan0, chn, 0, std::move(filter_filename_), Fpass_, Fstop_) == -1) { return false; } diff --git a/src/algorithms/signal_source/libs/ad936x_iio_custom.cc b/src/algorithms/signal_source/libs/ad936x_iio_custom.cc index 72461bafd..c41d74b9a 100644 --- a/src/algorithms/signal_source/libs/ad936x_iio_custom.cc +++ b/src/algorithms/signal_source/libs/ad936x_iio_custom.cc @@ -1,6 +1,7 @@ /*! * \file ad936x_iio_custom.cc - * \brief A direct IIO custom front-end driver for the AD936x AD front-end family with special FPGA custom functionalities. + * \brief A direct IIO custom front-end driver for the AD936x AD front-end + * family with special FPGA custom functionalities. * \author Javier Arribas, jarribas(at)cttc.es * ----------------------------------------------------------------------------- * @@ -30,29 +31,36 @@ #include #endif -ad936x_iio_custom::ad936x_iio_custom(int debug_level_, int log_level_) +ad936x_iio_custom::ad936x_iio_custom( + int debug_level_, + int log_level_) : n_channels(0), + ctx(nullptr), + phy(nullptr), + stream_dev(nullptr), + dds_dev(nullptr), + receive_samples(false), + fpga_overflow(false), + sample_rate_sps(0), + debug_level(debug_level_), + log_level(log_level_), + PPS_mode(false) { - receive_samples = false; - fpga_overflow = false; - sample_rate_sps = 0; - ctx = NULL; - phy = NULL; - dds_dev = NULL; - stream_dev = NULL; - debug_level = debug_level_; - log_level = log_level_; - PPS_mode = false; - n_channels = 0; } ad936x_iio_custom::~ad936x_iio_custom() { // disable TX - if (phy != NULL) PlutoTxEnable(false); + if (phy != nullptr) + { + PlutoTxEnable(false); + } // Close device - if (ctx != NULL) iio_context_destroy(ctx); + if (ctx != nullptr) + { + iio_context_destroy(ctx); + } } @@ -68,7 +76,7 @@ void ad936x_iio_custom::set_pps_samplestamp_queue(std::shared_ptr ¶ms) { - for (std::vector::const_iterator it = params.begin(); - it != params.end(); ++it) + for (const auto ¶m : params) { - struct iio_channel *chn = NULL; - const char *attr = NULL; + struct iio_channel *chn = nullptr; + const char *attr = nullptr; size_t pos; int ret; - pos = it->find('='); + pos = param.find('='); if (pos == std::string::npos) { - std::cerr << "Malformed line: " << *it << std::endl; + std::cerr << "Malformed line: " << param << std::endl; continue; } - std::string key = it->substr(0, pos); - std::string val = it->substr(pos + 1, std::string::npos); + std::string key = param.substr(0, pos); + std::string val = param.substr(pos + 1, std::string::npos); ret = iio_device_identify_filename(phy, key.c_str(), &chn, &attr); @@ -196,13 +203,19 @@ void ad936x_iio_custom::configure_params(struct iio_device *phy, } if (chn) - ret = iio_channel_attr_write(chn, - attr, val.c_str()); + { + ret = iio_channel_attr_write(chn, + attr, val.c_str()); + } else if (iio_device_find_attr(phy, attr)) - ret = iio_device_attr_write(phy, attr, val.c_str()); + { + ret = iio_device_attr_write(phy, attr, val.c_str()); + } else - ret = iio_device_debug_attr_write(phy, - attr, val.c_str()); + { + ret = iio_device_debug_attr_write(phy, + attr, val.c_str()); + } if (ret < 0) { std::cerr << "Unable to write attribute " << key @@ -216,9 +229,9 @@ void ad936x_iio_custom::set_params_rx(struct iio_device *phy_device, unsigned long long frequency, unsigned long samplerate, unsigned long bandwidth, bool quadrature, bool rfdc, bool bbdc, - std::string gain1, double gain1_value, - std::string gain2, double gain2_value, - std::string port_select) + const std::string &gain1, double gain1_value, + const std::string &gain2, double gain2_value, + const std::string &port_select) { std::vector params; @@ -289,7 +302,7 @@ bool ad936x_iio_custom::config_ad9361_dds(uint64_t freq_rf_tx_hz_, std::to_string(phase_dds_deg_ * 1000.0)); params_dds.push_back("out_altvoltage0_TX1_I_F1_scale=" + std::to_string(scale_dds_)); - params_dds.push_back("out_altvoltage0_TX1_I_F1_raw=1"); + params_dds.emplace_back("out_altvoltage0_TX1_I_F1_raw=1"); // DDS TX CH1 Q (tone #1) params_dds.push_back("out_altvoltage2_TX1_Q_F1_frequency=" + std::to_string(freq_dds_tx_hz_)); @@ -297,7 +310,7 @@ bool ad936x_iio_custom::config_ad9361_dds(uint64_t freq_rf_tx_hz_, std::to_string(phase_dds_deg_ * 1000.0 + 270000.0)); params_dds.push_back("out_altvoltage2_TX1_Q_F1_scale=" + std::to_string(scale_dds_)); - params_dds.push_back("out_altvoltage2_TX1_Q_F1_raw=1"); + params_dds.emplace_back("out_altvoltage2_TX1_Q_F1_raw=1"); configure_params(dds_dev, params_dds); } @@ -318,7 +331,7 @@ bool ad936x_iio_custom::config_ad9361_dds(uint64_t freq_rf_tx_hz_, std::to_string(phase_dds_deg_ * 1000.0)); params_dds.push_back("out_altvoltage4_TX2_I_F1_scale=" + std::to_string(scale_dds_)); - params_dds.push_back("out_altvoltage4_TX2_I_F1_raw=1"); + params_dds.emplace_back("out_altvoltage4_TX2_I_F1_raw=1"); // DDS TX CH2 Q (tone #1) params_dds.push_back("out_altvoltage6_TX2_Q_F1_frequency=" + std::to_string(freq_dds_tx_hz_)); @@ -326,7 +339,7 @@ bool ad936x_iio_custom::config_ad9361_dds(uint64_t freq_rf_tx_hz_, std::to_string(phase_dds_deg_ * 1000.0 + 270000.0)); params_dds.push_back("out_altvoltage6_TX2_Q_F1_scale=" + std::to_string(scale_dds_)); - params_dds.push_back("out_altvoltage6_TX2_Q_F1_raw=1"); + params_dds.emplace_back("out_altvoltage6_TX2_Q_F1_raw=1"); configure_params(dds_dev, params_dds); } @@ -337,7 +350,7 @@ bool ad936x_iio_custom::config_ad9361_dds(uint64_t freq_rf_tx_hz_, bool ad936x_iio_custom::check_device() { - if (stream_dev != NULL) + if (stream_dev != nullptr) { return true; } @@ -350,8 +363,8 @@ bool ad936x_iio_custom::check_device() bool ad936x_iio_custom::get_iio_param(iio_device *dev, const std::string ¶m, std::string &value) { - struct iio_channel *chn = 0; - const char *attr = 0; + struct iio_channel *chn = nullptr; + const char *attr = nullptr; char valuestr[256]; int ret; ssize_t nchars; @@ -398,9 +411,12 @@ bool ad936x_iio_custom::read_die_temp(double &temp_c) { try { - uint32_t temp_mC = boost::lexical_cast(temp_mC_str); + auto temp_mC = boost::lexical_cast(temp_mC_str); temp_c = static_cast(temp_mC) / 1000.0; - if (temp_c > 120) temp_c = -1; + if (temp_c > 120) + { + temp_c = -1; + } return true; } catch (const boost::bad_lexical_cast &e) @@ -419,10 +435,10 @@ bool ad936x_iio_custom::read_die_temp(double &temp_c) bool ad936x_iio_custom::init_config_ad9361_rx(long long bandwidth_, long long sample_rate_, long long freq_, - std::string rf_port_select_, - std::string rf_filter, - std::string gain_mode_rx0_, - std::string gain_mode_rx1_, + const std::string &rf_port_select_, + const std::string &rf_filter, + const std::string &gain_mode_rx0_, + const std::string &gain_mode_rx1_, double rf_gain_rx0_, double rf_gain_rx1_, bool enable_ch0, @@ -432,16 +448,19 @@ bool ad936x_iio_custom::init_config_ad9361_rx(long long bandwidth_, bool high_side_lo_, int tx_lo_channel_) { - if (check_device() == false) return false; + if (check_device() == false) + { + return false; + } bool no_errors = true; std::cout << "Configuring phy device parameters...\n"; int ret; - if (rf_filter.compare("Disabled") == 0) + if (rf_filter == "Disabled") { std::cout << "LNA Filter switch is disabled.\n"; } - else if (rf_filter.compare("Auto") == 0) + else if (rf_filter == "Auto") { std::cout << "Selecting LNA RF filter based on the selected RF frequency... \n"; if (freq_ == 1575420000) @@ -498,9 +517,9 @@ bool ad936x_iio_custom::init_config_ad9361_rx(long long bandwidth_, params.push_back("out_voltage_rf_bandwidth=" + std::to_string(bandwidth_)); - params.push_back("in_voltage_quadrature_tracking_en=1"); - params.push_back("in_voltage_rf_dc_offset_tracking_en=1"); - params.push_back("in_voltage_bb_dc_offset_tracking_en=1"); + params.emplace_back("in_voltage_quadrature_tracking_en=1"); + params.emplace_back("in_voltage_rf_dc_offset_tracking_en=1"); + params.emplace_back("in_voltage_bb_dc_offset_tracking_en=1"); configure_params(phy, params); @@ -705,7 +724,10 @@ bool ad936x_iio_custom::init_config_ad9361_rx(long long bandwidth_, bool ad936x_iio_custom::set_rx_frequency(long long freq_hz) { - if (check_device() == false) return false; + if (check_device() == false) + { + return false; + } // Configure RX LO channel (NOTICE that altvoltage0 is the RX LO oscillator!, altvoltage1 is the TX oscillator) struct iio_channel *lo_ch; @@ -728,7 +750,10 @@ bool ad936x_iio_custom::set_rx_frequency(long long freq_hz) bool ad936x_iio_custom::get_rx_frequency(long long &freq_hz) { - if (check_device() == false) return false; + if (check_device() == false) + { + return false; + } // Configure RX LO channel (NOTICE that altvoltage0 is the RX LO oscillator!, altvoltage1 is the TX oscillator) struct iio_channel *lo_ch; @@ -749,9 +774,12 @@ bool ad936x_iio_custom::get_rx_frequency(long long &freq_hz) } -bool ad936x_iio_custom::setRXGain(int ch_num, std::string gain_mode, double gain_dB) +bool ad936x_iio_custom::setRXGain(int ch_num, const std::string &gain_mode, double gain_dB) { - if (check_device() == false) return false; + if (check_device() == false) + { + return false; + } std::vector params; if (ch_num == 0) { @@ -784,7 +812,10 @@ bool ad936x_iio_custom::setRXGain(int ch_num, std::string gain_mode, double gain double ad936x_iio_custom::get_rx_gain(int ch_num) { - if (check_device() == false) return -1; + if (check_device() == false) + { + return -1; + } double gain_dB; // gain in dB int ret = 0; if (ch_num == 0) @@ -815,7 +846,10 @@ double ad936x_iio_custom::get_rx_gain(int ch_num) bool ad936x_iio_custom::calibrate([[maybe_unused]] int ch, [[maybe_unused]] double bw_hz) { - if (check_device() == false) return false; + if (check_device() == false) + { + return false; + } // todo return true; } @@ -864,12 +898,13 @@ void ad936x_iio_custom::monitor_thread_fn() { ret = iio_device_reg_write(stream_dev, 0x80000088, val); if (ret) - fprintf(stderr, "Failed to clearn DMA status register: %s\n", - strerror(-ret)); + { + fprintf(stderr, "Failed to clearn DMA status register: %s\n", + strerror(-ret)); + } } sleep(1); } - return; } @@ -940,7 +975,7 @@ void ad936x_iio_custom::setPlutoGpo(int p) } -bool ad936x_iio_custom::select_rf_filter(std::string rf_filter) +bool ad936x_iio_custom::select_rf_filter(const std::string &rf_filter) { // adi,gpo-manual-mode-enable Enables GPO manual mode, this will conflict with automatic ENSM slave and eLNA mode // adi,gpo-manual-mode-enable-mask Enable bit mask, setting or clearing bits will change the level of the corresponding output. Bit0 → GPO, Bit1 → GPO1, Bit2 → GPO2, Bit3 → GP03 @@ -960,7 +995,10 @@ bool ad936x_iio_custom::select_rf_filter(std::string rf_filter) // 1 Enable // X Enable Mask if Identifier=0xF - if (check_device() == false) return false; + if (check_device() == false) + { + return false; + } // int plutoGpo = 0; int ret; ret = iio_device_debug_attr_write(phy, "adi,gpo-manual-mode-enable", "1"); @@ -971,7 +1009,7 @@ bool ad936x_iio_custom::select_rf_filter(std::string rf_filter) return false; } - if (rf_filter.compare("E1") == 0) + if (rf_filter == "E1") { // set gpio0 to switch L1 filter // setPlutoGpo(plutoGpo); @@ -982,7 +1020,7 @@ bool ad936x_iio_custom::select_rf_filter(std::string rf_filter) return false; } } - else if (rf_filter.compare("E5E6") == 0) + else if (rf_filter == "E5E6") { // set gpio0 to switch L5/L6 filter (GPO0) // plutoGpo = plutoGpo | 0x10; @@ -994,7 +1032,7 @@ bool ad936x_iio_custom::select_rf_filter(std::string rf_filter) return false; } } - if (rf_filter.compare("none") == 0) + if (rf_filter == "none") { std::cout << "RF external filter not selected\n"; } @@ -1107,18 +1145,18 @@ bool ad936x_iio_custom::start_sample_rx(bool ppsmode) switch (n_channels) { case 1: - channels.push_back("voltage0"); // Channel 0 I - channels.push_back("voltage1"); // Channel 0 Q + channels.emplace_back("voltage0"); // Channel 0 I + channels.emplace_back("voltage1"); // Channel 0 Q break; case 2: - channels.push_back("voltage0"); // Channel 0 I - channels.push_back("voltage1"); // Channel 0 Q - channels.push_back("voltage2"); // Channel 1 I - channels.push_back("voltage3"); // Channel 1 Q + channels.emplace_back("voltage0"); // Channel 0 I + channels.emplace_back("voltage1"); // Channel 0 Q + channels.emplace_back("voltage2"); // Channel 1 I + channels.emplace_back("voltage3"); // Channel 1 Q break; default: - channels.push_back("voltage0"); // Channel 0 I - channels.push_back("voltage1"); // Channel 0 Q + channels.emplace_back("voltage0"); // Channel 0 I + channels.emplace_back("voltage1"); // Channel 0 Q } receive_samples = true; @@ -1150,7 +1188,10 @@ void ad936x_iio_custom::push_sample_buffer(std::shared_ptr & void ad936x_iio_custom::capture(const std::vector &channels) { - if (check_device() == false) return; + if (check_device() == false) + { + return; + } struct iio_buffer *rxbuf; @@ -1178,16 +1219,14 @@ void ad936x_iio_custom::capture(const std::vector &channels) } else { - for (std::vector::const_iterator it = - channels.begin(); - it != channels.end(); ++it) + for (const auto &channel : channels) { struct iio_channel *chn = iio_device_find_channel(stream_dev, - it->c_str(), false); + channel.c_str(), false); if (!chn) { - std::cerr << "Channel " << it->c_str() << " not found\n"; + std::cerr << "Channel " << channel.c_str() << " not found\n"; return; } else @@ -1246,7 +1285,10 @@ void ad936x_iio_custom::capture(const std::vector &channels) items_in_buffer = static_cast(ret) / bytes_to_interleaved_iq_samples; - if (items_in_buffer == 0) return; + if (items_in_buffer == 0) + { + return; + } current_samples->n_channels = n_channels; current_samples->n_interleaved_iq_samples = items_in_buffer; diff --git a/src/algorithms/signal_source/libs/ad936x_iio_custom.h b/src/algorithms/signal_source/libs/ad936x_iio_custom.h index 83a61282a..0c6199968 100644 --- a/src/algorithms/signal_source/libs/ad936x_iio_custom.h +++ b/src/algorithms/signal_source/libs/ad936x_iio_custom.h @@ -1,6 +1,7 @@ /*! * \file ad936x_iio_custom.h - * \brief A direct IIO custom front-end driver for the AD936x AD front-end family with special FPGA custom functionalities. + * \brief A direct IIO custom front-end driver for the AD936x AD front-end + * family with special FPGA custom functionalities. * \author Javier Arribas, jarribas(at)cttc.es * ----------------------------------------------------------------------------- * @@ -14,41 +15,41 @@ */ -#ifndef SRC_LIBS_ad936x_iio_custom_H_ -#define SRC_LIBS_ad936x_iio_custom_H_ +#ifndef GNSS_SDR_AD936X_IIO_CUSTOM_H +#define GNSS_SDR_AD936X_IIO_CUSTOM_H +#include "ad936x_iio_samples.h" #include "concurrent_queue.h" #include "gnss_time.h" #include "pps_samplestamp.h" #include +#include +#include // multichip sync and high level functions #include #include - -#ifdef __APPLE__ -#include -#else -#include -#endif - -#include "ad936x_iio_samples.h" -#include // multichip sync and high level functions #include #include +/** \addtogroup Signal_Source + * \{ */ +/** \addtogroup Signal_Source_libs + * \{ */ + + class ad936x_iio_custom { public: ad936x_iio_custom(int debug_level_, int log_level_); virtual ~ad936x_iio_custom(); - bool initialize_device(std::string pluto_device_uri, std::string board_type); + bool initialize_device(const std::string &pluto_device_uri, const std::string &board_type); bool init_config_ad9361_rx(long long bandwidth_, long long sample_rate_, long long freq_, - std::string rf_port_select_, - std::string rf_filter, - std::string gain_mode_rx0_, - std::string gain_mode_rx1_, + const std::string &rf_port_select_, + const std::string &rf_filter, + const std::string &gain_mode_rx0_, + const std::string &gain_mode_rx1_, double rf_gain_rx0_, double rf_gain_rx1_, bool enable_ch0, @@ -61,7 +62,7 @@ public: bool calibrate(int ch, double bw_hz); double get_rx_gain(int ch_num); - bool setRXGain(int ch_num, std::string gain_mode, double gain_dB); + bool setRXGain(int ch_num, const std::string &gain_mode, double gain_dB); bool set_antenna_port(int ch, int antenna_idx); double get_frequency(int ch); @@ -93,9 +94,9 @@ private: unsigned long long frequency, unsigned long samplerate, unsigned long bandwidth, bool quadrature, bool rfdc, bool bbdc, - std::string gain1, double gain1_value, - std::string gain2, double gain2_value, - std::string port_select); + const std::string &gain1, double gain1_value, + const std::string &gain2, double gain2_value, + const std::string &port_select); bool config_ad9361_dds(uint64_t freq_rf_tx_hz_, double tx_attenuation_db_, @@ -107,7 +108,7 @@ private: void get_PPS_timestamp(); void capture(const std::vector &channels); - bool select_rf_filter(std::string rf_filter); + bool select_rf_filter(const std::string &rf_filter); void monitor_thread_fn(); @@ -120,15 +121,6 @@ private: struct iio_device *stream_dev; struct iio_device *dds_dev; - // stream - - uint64_t sample_rate_sps; - - - int debug_level; - int log_level; - bool PPS_mode; - std::mutex mtx; std::condition_variable cv; @@ -142,6 +134,14 @@ private: std::thread capture_samples_thread; std::thread overflow_monitor_thread; std::thread capture_time_thread; + + // stream + uint64_t sample_rate_sps; + int debug_level; + int log_level; + bool PPS_mode; }; -#endif /* SRC_LIBS_ad936x_iio_custom_H_ */ +/** \} */ +/** \} */ +#endif // GNSS_SDR_AD936X_IIO_CUSTOM_H diff --git a/src/algorithms/signal_source/libs/ad936x_iio_samples.cc b/src/algorithms/signal_source/libs/ad936x_iio_samples.cc deleted file mode 100644 index b9b7b505a..000000000 --- a/src/algorithms/signal_source/libs/ad936x_iio_samples.cc +++ /dev/null @@ -1,25 +0,0 @@ -/*! - * \file ad936x_iio_samples.cc - * \brief A class that holds a custom sample buffer for Analog Devices AD936x family front-ends. - * \author Javier Arribas, jarribas(at)cttc.es - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#include "ad936x_iio_samples.h" - -ad936x_iio_samples::ad936x_iio_samples() -{ - n_bytes = 0; - n_interleaved_iq_samples = 0; - step_bytes = 0; - n_channels = 0; -} diff --git a/src/algorithms/signal_source/libs/ad936x_iio_samples.h b/src/algorithms/signal_source/libs/ad936x_iio_samples.h index 63d30545b..5ff43d065 100644 --- a/src/algorithms/signal_source/libs/ad936x_iio_samples.h +++ b/src/algorithms/signal_source/libs/ad936x_iio_samples.h @@ -15,26 +15,32 @@ */ -#ifndef SRC_LIBS_ad936x_iio_samples_H_ -#define SRC_LIBS_ad936x_iio_samples_H_ +#ifndef GNSS_SDR_AD936X_IIO_SAMPLES_H +#define GNSS_SDR_AD936X_IIO_SAMPLES_H #define IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES 32768 * 4 - #define IIO_INPUTRAMFIFOSIZE 256 +#include #include -#include #include +/** \addtogroup Signal_Source + * \{ */ +/** \addtogroup Signal_Source_libs + * \{ */ + class ad936x_iio_samples { public: - ad936x_iio_samples(); - uint32_t n_bytes; - uint32_t n_interleaved_iq_samples; - uint16_t n_channels; - uint16_t step_bytes; + ad936x_iio_samples() = default; + uint32_t n_bytes{0}; + uint32_t n_interleaved_iq_samples{0}; + uint16_t n_channels{0}; + uint16_t step_bytes{0}; char buffer[IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES * 4 * 4]; // max 16 bits samples per buffer (4 channels, 2-bytes per I + 2-bytes per Q) }; +/** \} */ +/** \} */ #endif diff --git a/src/algorithms/signal_source/libs/ion_gsms_chunk_data.cc b/src/algorithms/signal_source/libs/ion_gsms_chunk_data.cc new file mode 100644 index 000000000..5a8cd823c --- /dev/null +++ b/src/algorithms/signal_source/libs/ion_gsms_chunk_data.cc @@ -0,0 +1,271 @@ +/*! + * \file ion_gsms_chunk_data.cc + * \brief Holds logic for reading and decoding samples from a chunk + * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#include "ion_gsms_chunk_data.h" +#include +#if USE_GLOG_AND_GFLAGS +#include +#else +#include +#endif + + +IONGSMSChunkData::IONGSMSChunkData(const GnssMetadata::Chunk& chunk, const std::vector& stream_ids, std::size_t output_stream_offset) + : chunk_(chunk), + sizeword_(chunk_.SizeWord()), + countwords_(chunk_.CountWords()) +{ + // Instantiate the Allocator functor + Allocator allocator(countwords_, buffer_); + // Call with_word_type with the Allocator functor + with_word_type(sizeword_, allocator); + + const std::size_t total_bitsize = sizeword_ * countwords_ * 8; + std::size_t used_bitsize = 0; + std::size_t output_streams = 0; + for (const auto& lump : chunk.Lumps()) + { + for (const auto& stream : lump.Streams()) + { + used_bitsize += stream.Packedbits(); + + bool found = false; + for (const auto& stream_id : stream_ids) + { + if (stream_id == stream.Id()) + { + found = true; + break; + } + } + if (found) + { + streams_.emplace_back(lump, stream, GnssMetadata::encoding_from_string(stream.Encoding()), output_streams + output_stream_offset); + ++output_streams; + std::size_t sample_bitsize = stream.Packedbits() / stream.RateFactor(); + std::size_t sample_rate = stream.RateFactor(); + if (stream.Packedbits() >= 2 * stream.RateFactor() * stream.Quantization()) + { + // Samples have 'Complex' format + sample_bitsize /= 2; + sample_rate *= 2; + } + output_stream_item_size_.push_back(bits_to_item_size(sample_bitsize)); + output_stream_item_rate_.push_back(sample_rate); + } + else + { + streams_.emplace_back(lump, stream, GnssMetadata::encoding_from_string(stream.Encoding()), -1); + } + } + } + + output_stream_count_ = output_streams; + padding_bitsize_ = total_bitsize - used_bitsize; +} + + +IONGSMSChunkData::~IONGSMSChunkData() +{ + Deleter deleter(static_cast(buffer_)); + with_word_type(sizeword_, deleter); +} + + +std::size_t IONGSMSChunkData::read_from_buffer(uint8_t* buffer, std::size_t offset) +{ + memset(buffer_, 0, sizeword_ * countwords_); + memcpy(buffer_, &buffer[offset], sizeword_ * countwords_); + return sizeword_ * countwords_; +} + + +void IONGSMSChunkData::write_to_output(gr_vector_void_star& outputs, std::vector& output_items) +{ + switch (sizeword_) + { + case 1: + unpack_words(outputs, output_items); + break; + case 2: + unpack_words(outputs, output_items); + break; + case 4: + unpack_words(outputs, output_items); + break; + case 8: + unpack_words(outputs, output_items); + break; + default: + LOG(ERROR) << "Unknown word size (" << std::to_string(sizeword_) << "), unpacking nothing."; + break; + } +} + + +std::size_t IONGSMSChunkData::output_stream_count() const +{ + return output_stream_count_; +} + + +std::size_t IONGSMSChunkData::output_stream_item_size(std::size_t stream_index) const +{ + return output_stream_item_size_[stream_index]; +} + + +std::size_t IONGSMSChunkData::output_stream_item_rate(std::size_t stream_index) const +{ + return output_stream_item_rate_[stream_index]; +} + + +template +void IONGSMSChunkData::unpack_words(gr_vector_void_star& outputs, std::vector& output_items) +{ + WT* data = static_cast(buffer_); + // TODO - Swap endiannes if needed + + IONGSMSChunkUnpackingCtx ctx{ + chunk_.Shift(), + data, + countwords_, + }; + + // Head padding + if (padding_bitsize_ > 0 && chunk_.Padding() == GnssMetadata::Chunk::Head) + { + ctx.shift_padding(padding_bitsize_); + } + + // Samples + for (const auto& [lump, stream, encoding, output_index] : streams_) + { + if (output_index == -1) + { + // skip stream + ctx.shift_padding(stream.Packedbits()); + } + else + { + output_items[output_index] += write_stream_samples(ctx, lump, stream, encoding, &outputs[output_index]); + } + } +} + + +template +std::size_t IONGSMSChunkData::write_stream_samples( + IONGSMSChunkUnpackingCtx& ctx, + const GnssMetadata::Lump& lump, + const GnssMetadata::IonStream& stream, + const GnssMetadata::StreamEncoding stream_encoding, + void** out) +{ + std::size_t sample_bitsize = stream.Packedbits() / stream.RateFactor(); + std::size_t sample_count = stream.RateFactor(); + + if (stream.Packedbits() >= 2 * stream.RateFactor() * stream.Quantization()) + { + // Samples have 'Complex' format + sample_bitsize /= 2; + sample_count *= 2; + } + + if (sample_bitsize <= 8) + { + write_n_samples(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, reinterpret_cast(out)); + } + else if (sample_bitsize <= 16) + { + write_n_samples(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, reinterpret_cast(out)); + } + else if (sample_bitsize <= 32) + { + write_n_samples(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, reinterpret_cast(out)); + } + else if (sample_bitsize <= 64) + { + write_n_samples(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, reinterpret_cast(out)); + } + + return sample_count; +} + + +template +void IONGSMSChunkData::write_n_samples( + IONGSMSChunkUnpackingCtx& ctx, + GnssMetadata::Lump::LumpShift lump_shift, + uint8_t sample_bitsize, + std::size_t sample_count, + GnssMetadata::StreamEncoding stream_encoding, + OT** out) +{ + if (lump_shift == GnssMetadata::Lump::shiftRight) + { + auto* sample = static_cast(*out); + sample += sample_count; + for (std::size_t i = 0; i < sample_count; ++i) + { + *sample = 0; + ctx.shift_sample(sample_bitsize, sample); + decode_sample(sample_bitsize, sample, stream_encoding); + --sample; + } + } + else // if (lump_shift == GnssMetadata::Lump::shiftLeft || lump_shift == GnssMetadata::Lump::shiftUndefined) + { + auto* sample = static_cast(*out); + for (std::size_t i = 0; i < sample_count; ++i) + { + *sample = 0; + ctx.shift_sample(sample_bitsize, sample); + decode_sample(sample_bitsize, sample, stream_encoding); + ++sample; + } + } + + (*out) += sample_count; +} + + +// Static utilities +template +void IONGSMSChunkData::decode_sample(const uint8_t sample_bitsize, Sample* sample, const GnssMetadata::StreamEncoding encoding) +{ + // using SampleType = std::remove_pointer_t; + switch (sample_bitsize) + { + case 2: + *sample = GnssMetadata::two_bit_look_up[encoding][*sample]; + break; + case 3: + *sample = GnssMetadata::three_bit_look_up[encoding][*sample]; + break; + case 4: + *sample = GnssMetadata::four_bit_look_up[encoding][*sample]; + break; + case 5: + *sample = GnssMetadata::five_bit_look_up[encoding][*sample]; + break; + default: + // TODO - Is this an error that can happen? + // for now we'll just do nothing, if the sample is this wide it may need no decoding + break; + } +} diff --git a/src/algorithms/signal_source/libs/ion_gsms_chunk_data.h b/src/algorithms/signal_source/libs/ion_gsms_chunk_data.h new file mode 100644 index 000000000..5170af848 --- /dev/null +++ b/src/algorithms/signal_source/libs/ion_gsms_chunk_data.h @@ -0,0 +1,188 @@ +/*! + * \file ion_gsms_chunk_data.h + * \brief Holds logic for reading and decoding samples from a chunk + * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_ION_GSMS_CHUNK_DATA_H +#define GNSS_SDR_ION_GSMS_CHUNK_DATA_H + +#include "ion_gsms_chunk_unpacking_ctx.h" +#include "ion_gsms_stream_encodings.h" +#include +#include +#include +#include +#include +#include +#include + + +inline std::size_t bits_to_item_size(std::size_t bit_count) +{ + if (bit_count <= 8) + { + return 1; + } + if (bit_count <= 16) + { + return 2; + } + if (bit_count <= 32) + { + return 4; + } + if (bit_count <= 64) + { + return 8; + } + + // You are asking too much of this humble processor + std::cerr << "Item size too large (" << std::to_string(bit_count) << "), returning nonsense.\n"; + return 1; +} + + +// Define a functor that has a templated operator() +struct Allocator +{ + size_t countwords_; + void*& buffer_; // Using void* to hold any type of pointer + + Allocator(size_t countwords, void*& buffer) + : countwords_(countwords), buffer_(buffer) {} + + template + void operator()() const + { + buffer_ = new WordType[countwords_]; + } +}; + + +// Define a functor to delete the allocated memory +struct Deleter +{ + void* buffer_; + + explicit Deleter(void* buffer) + : buffer_(buffer) {} + + template + void operator()() const + { + delete[] static_cast(buffer_); + } +}; + + +template +void with_word_type(uint8_t word_size, Callback callback) +{ + switch (word_size) + { + case 1: + callback.template operator()(); + break; + case 2: + callback.template operator()(); + break; + case 4: + callback.template operator()(); + break; + case 8: + callback.template operator()(); + break; + default: + std::cerr << "Unknown word size (" << std::to_string(word_size) << "), returning nonsense.\n"; + break; + } +} + +class IONGSMSChunkData +{ +public: + IONGSMSChunkData(const GnssMetadata::Chunk& chunk, const std::vector& stream_ids, std::size_t output_stream_offset); + + ~IONGSMSChunkData(); + + IONGSMSChunkData(const IONGSMSChunkData& rhl) = delete; + IONGSMSChunkData& operator=(const IONGSMSChunkData& rhl) = delete; + + IONGSMSChunkData(IONGSMSChunkData&& rhl) = delete; + IONGSMSChunkData& operator=(IONGSMSChunkData&& rhl) = delete; + + std::size_t read_from_buffer(uint8_t* buffer, std::size_t offset); + + void write_to_output(gr_vector_void_star& outputs, std::vector& output_items); + + std::size_t output_stream_count() const; + std::size_t output_stream_item_size(std::size_t stream_index) const; + std::size_t output_stream_item_rate(std::size_t stream_index) const; + +private: + template + void unpack_words(gr_vector_void_star& outputs, std::vector& output_items); + + template + std::size_t write_stream_samples( + IONGSMSChunkUnpackingCtx& ctx, + const GnssMetadata::Lump& lump, + const GnssMetadata::IonStream& stream, + GnssMetadata::StreamEncoding stream_encoding, + void** out); + + template + void write_n_samples( + IONGSMSChunkUnpackingCtx& ctx, + GnssMetadata::Lump::LumpShift lump_shift, + uint8_t sample_bitsize, + std::size_t sample_count, + GnssMetadata::StreamEncoding stream_encoding, + OT** out); + + template + static void decode_sample(uint8_t sample_bitsize, Sample* sample, GnssMetadata::StreamEncoding encoding); + + const GnssMetadata::Chunk& chunk_; + uint8_t sizeword_; + uint8_t countwords_; + uint8_t padding_bitsize_; + std::size_t output_stream_count_; + std::vector output_stream_item_size_; + std::vector output_stream_item_rate_; + + struct stream_metadata_t + { + const GnssMetadata::Lump& lump; + const GnssMetadata::IonStream& stream; + GnssMetadata::StreamEncoding stream_encoding; + int output_index = -1; + + stream_metadata_t( + const GnssMetadata::Lump& lump_, + const GnssMetadata::IonStream& stream_, + GnssMetadata::StreamEncoding stream_encoding_, + int output_index_ = -1) : lump(lump_), + stream(stream_), + stream_encoding(stream_encoding_), + output_index(output_index_) + { + } + }; + std::vector streams_; + + void* buffer_; +}; + +#endif // GNSS_SDR_ION_GSMS_CHUNK_DATA_H diff --git a/src/algorithms/signal_source/libs/ion_gsms_chunk_unpacking_ctx.h b/src/algorithms/signal_source/libs/ion_gsms_chunk_unpacking_ctx.h new file mode 100644 index 000000000..6799f1080 --- /dev/null +++ b/src/algorithms/signal_source/libs/ion_gsms_chunk_unpacking_ctx.h @@ -0,0 +1,184 @@ +/*! + * \file ion_gsms_chunk_unpacking_ctx.h + * \brief Holds state and provides utilities for unpacking samples from a chunk + * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com + * + * This is a template class, and thus, its member functions must be defined in the header file. + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H +#define GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H + +#include +#include +#include + +/** \addtogroup Signal_Source + * \{ */ +/** \addtogroup Signal_Source_libs + * \{ */ + +template +struct IONGSMSChunkUnpackingCtx +{ + static constexpr uint8_t word_bitsize_ = sizeof(WT) * 8; + + const GnssMetadata::Chunk::WordShift word_shift_direction_; + WT* iterator_ = nullptr; // Not owned by this class, MUST NOT destroy + WT current_word_{}; + uint8_t bitshift_ = 0; + + IONGSMSChunkUnpackingCtx( + const GnssMetadata::Chunk::WordShift word_shift, + WT* data_buffer, + uint8_t data_buffer_word_count) : word_shift_direction_(word_shift) + { + if (word_shift_direction_ == GnssMetadata::Chunk::Left) + { + iterator_ = data_buffer; + } + else if (word_shift_direction_ == GnssMetadata::Chunk::Right) + { + iterator_ = &data_buffer[data_buffer_word_count]; + } + if (iterator_) + { + advance_word(); // Initializes current_word_ + } + } + + void advance_word() + { + WT word = *iterator_; + if (word_shift_direction_ == GnssMetadata::Chunk::Left) + { + ++iterator_; + } + else if (word_shift_direction_ == GnssMetadata::Chunk::Right) + { + --iterator_; + } + + current_word_ = word; + } + + void shift_current_word(uint8_t n) + { + if ((n % word_bitsize_) == 0) + { + for (uint8_t i = 0; i < (n / word_bitsize_); ++i) + { + advance_word(); + } + return; + } + + if (word_shift_direction_ == GnssMetadata::Chunk::Left) + { + current_word_ <<= n; + } + else if (word_shift_direction_ == GnssMetadata::Chunk::Right) + { + current_word_ >>= n; + } + + bitshift_ += n; + if (bitshift_ >= word_bitsize_) + { + advance_word(); + bitshift_ -= word_bitsize_; + } + } + + void shift_padding(uint8_t n_bits) + { + if (n_bits == 0) + { + return; + } + + if ((n_bits + (bitshift_ % word_bitsize_)) >= word_bitsize_) + { + const uint8_t bits_shifted = word_bitsize_ - (bitshift_ % word_bitsize_); + + shift_current_word(bits_shifted); + shift_padding(n_bits - bits_shifted); + } + else + { + shift_current_word(n_bits); + } + } + + template + void shift_sample(uint8_t sample_bitsize, OT* output, uint8_t output_bit_offset = 0) + { + if (sample_bitsize % word_bitsize_ == 0) + { + const uint8_t words_per_sample = sample_bitsize / word_bitsize_; + for (uint8_t i = 0; i < words_per_sample; ++i) + { + if (word_shift_direction_ == GnssMetadata::Chunk::Left) + { + *output |= (current_word_ << ((words_per_sample - 1 - i) * word_bitsize_)); + } + else if (word_shift_direction_ == GnssMetadata::Chunk::Right) + { + *output |= (current_word_ << (i * word_bitsize_)); + // TODO - reverse bit order of sample? maybe? + } + advance_word(); + } + } + else if ((sample_bitsize + (bitshift_ % word_bitsize_)) > word_bitsize_) + { + const uint8_t bits_shifted = word_bitsize_ - (bitshift_ % word_bitsize_); + + if (word_shift_direction_ == GnssMetadata::Chunk::Left) + { + WT mask = ~((1 << (word_bitsize_ - bits_shifted)) - 1); + *output |= ((current_word_ & mask) >> output_bit_offset); + } + else if (word_shift_direction_ == GnssMetadata::Chunk::Right) + { + WT mask = ((1 << (bits_shifted)) - 1); + *output |= (current_word_ & mask) << output_bit_offset; + // TODO - reverse bit order of sample? maybe? + } + + shift_current_word(bits_shifted); + shift_sample(sample_bitsize - bits_shifted, output, bits_shifted); + } + else + { + if (word_shift_direction_ == GnssMetadata::Chunk::Left) + { + WT mask = ~((1 << (word_bitsize_ - sample_bitsize)) - 1); + OT sample = (current_word_ & mask) >> (word_bitsize_ - sample_bitsize); + *output |= (sample) >> output_bit_offset; + } + else if (word_shift_direction_ == GnssMetadata::Chunk::Right) + { + WT mask = ((1 << (sample_bitsize)) - 1); + *output |= (current_word_ & mask) << output_bit_offset; + // TODO - reverse bit order of sample? maybe? + } + + shift_current_word(sample_bitsize); + } + } +}; + +/** \} */ +/** \} */ +#endif // GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H diff --git a/src/algorithms/signal_source/libs/ion_gsms_stream_encodings.h b/src/algorithms/signal_source/libs/ion_gsms_stream_encodings.h new file mode 100644 index 000000000..5b39e6497 --- /dev/null +++ b/src/algorithms/signal_source/libs/ion_gsms_stream_encodings.h @@ -0,0 +1,170 @@ +/*! + * \file ion_gsms_stream_encodings.h + * \brief Implements look up tables for all encodings in the standard + * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com + * + * These tables are taken from the stardard's official document. + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_ION_GSMS_STREAM_ENCODINGS_H +#define GNSS_SDR_ION_GSMS_STREAM_ENCODINGS_H + +#include + +/** \addtogroup Signal_Source + * \{ */ +/** \addtogroup Signal_Source_libs + * \{ */ + +namespace GnssMetadata +{ + +using StreamEncoding = unsigned char; + +namespace StreamEncodings +{ + +constexpr unsigned char SIGN = 0; +constexpr unsigned char OB = 1; +constexpr unsigned char SM = 2; +constexpr unsigned char MS = 3; +constexpr unsigned char TC = 4; +constexpr unsigned char OG = 5; +constexpr unsigned char OBA = 6; +constexpr unsigned char SMA = 7; +constexpr unsigned char MSA = 8; +constexpr unsigned char TCA = 9; +constexpr unsigned char OGA = 10; +constexpr unsigned char FP = 11; + +} // namespace StreamEncodings + +inline StreamEncoding encoding_from_string(const std::string& str) +{ + if (str == "SIGN") + { + return StreamEncodings::SIGN; + } + if (str == "OB") + { + return StreamEncodings::OB; + } + if (str == "SM") + { + return StreamEncodings::SM; + } + if (str == "MS") + { + return StreamEncodings::MS; + } + if (str == "TC") + { + return StreamEncodings::TC; + } + if (str == "OG") + { + return StreamEncodings::OG; + } + if (str == "OBA") + { + return StreamEncodings::OBA; + } + if (str == "SMA") + { + return StreamEncodings::SMA; + } + if (str == "MSA") + { + return StreamEncodings::MSA; + } + if (str == "TCA") + { + return StreamEncodings::TCA; + } + if (str == "OGA") + { + return StreamEncodings::OGA; + } + if (str == "FP") + { + return StreamEncodings::FP; + } + return 0; +} + +template +inline T two_bit_look_up[11][4]{ + {}, // [0] + {-2, -1, 0, 1}, // [1 /*OB*/] + {0, 1, 0, -1}, // [2 /*SM*/] + {0, 0, 1, -1}, // [3 /*MS*/] + {0, 1, -2, -1}, // [4 /*TC*/] + {-2, -1, 1, 0}, // [5 /*OG*/] + {-3, -1, 1, 3}, // [6 /*OBA*/] + {1, 3, -1, -3}, // [7 /*SMA*/] + {1, -1, 3, -3}, // [8 /*MSA*/] + {1, 3, -3, -1}, // [9 /*TCA*/] + {-3, -1, 3, 1}, // [10 /*OGA*/] +}; + +template +inline T three_bit_look_up[11][8]{ + {}, // [0] + {-4, -3, -2, -1, 0, 1, 2, 3}, // [1 /*OB*/] + {0, 1, 2, 3, 0, -1, -2, -3}, // [2 /*SM*/] + {0, 0, 1, -1, 0, 0, 1, -1}, // [3 /*MS*/] + {0, 1, 2, 3, -4, -3, -2, -1}, // [4 /*TC*/] + {-4, -3, -1, -2, 3, 2, 0, 1}, // [5 /*OG*/] + {-7, -5, -3, -1, 1, 3, 5, 7}, // [6 /*OBA*/] + {1, 3, 5, 7, -1, -3, -5, -7}, // [7 /*SMA*/] + {1, -1, 3, -3, 5, -5, 7, -7}, // [8 /*MSA*/] + {1, 3, 5, 7, -7, -5, -3, -1}, // [9 /*TCA*/] + {-7, -5, -1, -3, 7, 5, 1, 3}, // [10 /*OGA*/] +}; + +template +inline T four_bit_look_up[11][16]{ + {}, // [0] + {-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}, // [1 /*OB*/] + {0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7}, // [2 /*SM*/] + {0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1}, // [3 /*MS*/] + {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}, // [4 /*TC*/] + {-8, -7, -5, -6, -1, -2, -4, -3, 7, 6, 4, 5, 0, 1, 3, 2}, // [5 /*OG*/] + {-15, -13, -11, -9, -7, -5, -3, -1, 1, 3, 5, 7, 9, 11, 13, 15}, // [6 /*OBA*/] + {1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15}, // [7 /*SMA*/] + {1, -1, 3, -3, 5, -5, 7, -7, 9, -9, 11, -11, 13, -13, 15, -15}, // [8 /*MSA*/] + {1, 3, 5, 7, 9, 11, 13, 15, -15, -13, -11, -9, -7, -5, -3, -1}, // [9 /*TCA*/] + {-15, -13, -9, -11, -1, -3, -7, -5, 15, 13, 9, 11, 1, 3, 7, 5}, // [10 /*OGA*/] +}; + +template +inline T five_bit_look_up[11][32]{ + {}, // [0] + {-16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, // [1 /*OB*/] + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15}, // [2 /*SM*/] + {0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1}, // [3 /*MS*/] + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1}, // [4 /*TC*/] + {-16, -15, -13, -14, -9, -10, -12, -11, -1, -2, -4, -3, -8, -7, -5, -6, 15, 14, 12, 13, 8, 9, 11, 10, 0, 1, 3, 2, 7, 6, 4, 5}, // [5 /*OG*/] + {-31, -29, -27, -25, -23, -21, -19, -17, -15, -13, -11, -9, -7, -5, -3, -1, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // [6 /*OBA*/] + {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, -1, -3, -5, -7, -9, -11, -13, -15, -17, -19, -21, -23, -25, -27, -29, -31}, // [7 /*SMA*/] + {1, -1, 3, -3, 5, -5, 7, -7, 9, -9, 11, -11, 13, -13, 15, -15, 17, -17, 19, -19, 21, -21, 23, -23, 25, -25, 27, -27, 29, -29, 31, -31}, // [8 /*MSA*/] + {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, -31, -29, -27, -25, -23, -21, -19, -17, -15, -13, -11, -9, -7, -5, -3, -1}, // [9 /*TCA*/] + {-31, -29, -25, -27, -17, -19, -23, -21, -1, -3, -7, -5, -15, -13, -9, -11, 31, 29, 25, 27, 17, 19, 23, 21, 1, 3, 7, 5, 15, 13, 9, 11}, // [10 /*OGA*/] +}; + +} // namespace GnssMetadata + + +/** \} */ +/** \} */ +#endif // GNSS_SDR_ION_GSMS_STREAM_ENCODINGS_H diff --git a/src/algorithms/signal_source/libs/ppstcprx.cc b/src/algorithms/signal_source/libs/ppstcprx.cc index c23261aff..94dda2052 100644 --- a/src/algorithms/signal_source/libs/ppstcprx.cc +++ b/src/algorithms/signal_source/libs/ppstcprx.cc @@ -20,19 +20,6 @@ #include #include -pps_tcp_rx::pps_tcp_rx() -{ - // TODO Auto-generated constructor stub - is_connected = false; - clientSd = -1; -} - - -pps_tcp_rx::~pps_tcp_rx() -{ - // TODO Auto-generated destructor stub -} - void pps_tcp_rx::set_pps_samplestamp_queue(std::shared_ptr> queue) { @@ -40,7 +27,7 @@ void pps_tcp_rx::set_pps_samplestamp_queue(std::shared_ptr> Pps_queue; - int clientSd; + int clientSd{-1}; public: - volatile bool is_connected; - pps_tcp_rx(); - virtual ~pps_tcp_rx(); + volatile bool is_connected{false}; + pps_tcp_rx() = default; + virtual ~pps_tcp_rx() = default; - void receive_pps(std::string ip_address, int port); - bool send_cmd(std::string cmd); + void receive_pps(const std::string& ip_address, int port); + bool send_cmd(std::string cmd) const; void set_pps_samplestamp_queue(std::shared_ptr> queue); }; diff --git a/src/core/receiver/CMakeLists.txt b/src/core/receiver/CMakeLists.txt index cacef7f6f..ba945f69b 100644 --- a/src/core/receiver/CMakeLists.txt +++ b/src/core/receiver/CMakeLists.txt @@ -70,6 +70,10 @@ if(ENABLE_FPGA) target_compile_definitions(core_receiver PUBLIC -DENABLE_FPGA=1) endif() +if(ENABLE_ION) + target_compile_definitions(core_receiver PRIVATE -DENABLE_ION_SOURCE=1) +endif() + if(GNURADIO_USES_STD_POINTERS) target_compile_definitions(core_receiver PUBLIC -DGNURADIO_USES_STD_POINTERS=1) endif() @@ -90,6 +94,10 @@ if(ENABLE_PLUTOSDR) target_compile_definitions(core_receiver PRIVATE -DPLUTOSDR_DRIVER=1) endif() +if(ENABLE_AD936X_SDR) + target_compile_definitions(core_receiver PRIVATE -DAD936X_SDR_DRIVER=1) +endif() + if(ENABLE_FMCOMMS2) target_compile_definitions(core_receiver PRIVATE -DFMCOMMS2_DRIVER=1) endif() diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index ce77442ee..fceadefb9 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -163,6 +163,10 @@ #include "plutosdr_signal_source.h" #endif +#if AD936X_SDR_DRIVER +#include "ad936x_custom_signal_source.h" +#endif + #if FMCOMMS2_DRIVER #include "fmcomms2_signal_source.h" #endif @@ -196,6 +200,11 @@ #include "gps_l1_ca_dll_pll_tracking_gpu.h" #endif +#if ENABLE_ION_SOURCE +#undef Owner +#include "ion_gsms_signal_source.h" +#endif + using namespace std::string_literals; namespace @@ -759,7 +768,14 @@ std::unique_ptr GNSSBlockFactory::GetBlock( block = std::move(block_); } #endif - +#if ENABLE_ION_SOURCE + else if (implementation == "ION_GSMS_Signal_Source") + { + std::unique_ptr block_ = std::make_unique(configuration, role, in_streams, + out_streams, queue); + block = std::move(block_); + } +#endif #if RAW_ARRAY_DRIVER else if (implementation == "Raw_Array_Signal_Source") { @@ -795,6 +811,8 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams, queue); block = std::move(block_); } +#endif +#if PLUTOSDR_DRIVER || AD936X_SDR_DRIVER else if (implementation == "Ad936x_Custom_Signal_Source") { std::unique_ptr block_ = std::make_unique(configuration, role, in_streams,