1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-04 15:30:01 +00:00

Merge from upstream next (#27)

* Decouple the FPGA DMA signal source from the AD9361 FPGA signal source.

* Add the MAX2771_EVKIT FPGA signal source and the ENABLE_FPGA_MAX2771_EVKIT flag to enable it.

* Adjust cross-compilation flags to properly support FPGA signal sources

* fix signal source names for consistency

* Detect if the spidev driver is installed when the ENABLE_MAX2771 flag is set. Detect if the DMA proxy driver is installed when the ENABLE_DMA_PROXY flag is set. Check if ENABLE_FPGA is set when either ENABLE_MAX2771 or ENABLE_DMA_PROXY is set.

* fix FPGA signal source names for consistency

* Fix FPGA-related CMakefile flags

* make cpplint happy

* make cpplint happy

* make cmakelint happy

* make clang-format happy

* Replaced the AD9361 FPGA signal source with the ADRV9361_Z7035 FPGA and the FMCOMMS5 FPGA signal sources.

* Bump local version of GoogleTest to 1.15.2 and Protocol Buffers to 27.3

* Avoid code duplication in CMake modules

* Update clang-tidy job

* Clang Tidy fixes

* Improve efficiency of Concurrent_Map and Concurrent_Queue classes

* Fix segmentation fault if the SignalSource implementation is not available

* Moved decimation factor count variable to the class

* Avoid possible runtime error when PVT.enable_rx_clock_correction=true

* Fix formatting

* Fix clang-tidy job

* Capitalize FPGA in class implementation names

* Capitalize acronyms in FPGA-related class names

* Instantiate sources only once

* Update changelog

* Bump version of google benchmark to 1.9.0

* Fix CMakeLists header file list in signal source libs

Header file paths were being appended to the source files list.

This is not that important since, in general, you don't need to add the header files to the cmake target.

* Added ION GNSS SDR Metadata Standard signal source

* Only specify outputs for the requested streams

* Fixed block iteration withing a file

The `File` object only holds a shallow reference to its `Lane` (without the list of blocks). So we must retrieve the full reference manually.

* Treat data file paths as relative to the metadata file

The data file paths are actually not native paths but URLs, this covers most cases but not all of them.

* Fixed decoding errors and refactored each class into its own file

* Fixed sample count error & refactored

* Bufferef IO & propagate configuration inside ION source

* Reset sample value before writing new one

Sample values are ORed into the output buffer because they may need a few read/write operations depending on alignment.
So, if we don't set the value to 0 before doing this, all samples quickly become 0xFF after a few cycles of the output buffer.

* Simpler handling of simpler bit formats

If a sample is the same size as a word, it is much easier to read.

* Less callback shenanigans

* Fix wrong buffer size

* Fixed conditional compilation issues

And added a comment

* Linting fixes

* Fixed arithmetic operations on pointers

* Fix formatting

* Use lock_guard instead of unique_lock

* Create a CMake target for the ION dependency for consistency

* Improve formatting, add missing include

* Fixes for C++ standards older than 20. Avoid C++20-specific lambda templates

* Update changelog

* Add Victor to the list of authors

* Fix CMake error

* Fix building error

* Fix building

* Add -DENABLE_ION=ON to CI jobs

* Fix CMake lists

* Catch all exceptions

* Fix building for -DENABLE_PLUTOSDR=ON

* Removed unused member fields and function parameters

* Use std::ifstream instead of FILE for reading sample data

* Fixed includes and code style

* Simplified disconnect() function

We can disconnect the sources directly instead of disconnecting each of their outputs.

* Implemented range check in `IONGSMSSignalSource::get_right_block(int)`

* Moved ION GSMS file source to `gnuradio_blocks/` directory

Also fixed some header guards.

* Fixed ION GNSS Metadata Standard dependency version

* Simplified by removing a very shallow class

`ion_gnss_metadata_handler` was only reading the metadata file, which can easily be done in `ion_gsms_signal_source`.

* Added valves to properly handle end of samples

* Cleaner exit if the data file is not found

* Fix uninitialized warning

* Remove unused configuration parameter. Uniformize guard names

* Fix for CMake < 3.14

* fix configuration options for the FPGA-based AD9361-based boards

* Put the global function into an anonymous namespace

Use emplace_back instead of push_back

* Make private member metadata_ a std::shared_pointer

* Simplify code

* Remove ION source from CI

* Apply clang-tidy fixes

* Initialize the receiver local oscillator frequency to GPS_L5_FREQ_HZ by default in the ADRV9361Z7035 FPGA signal source and remove unnecessary include files.

* Sort out building flags and improve their reporting

* Allow building Ad936x_Custom_Signal_Source when gnuradio-iio is not available

* Bump local version of Protocol Buffers to v28.0

* Update AArch64 features to Linux 6.10.6

* Update AArch64 features to Linux 6.10.6

* Fix merging

---------

Co-authored-by: Marc Majoral <majoralmarc@gmail.com>
Co-authored-by: cesaaargm <cesare.martinez@proton.me>
Co-authored-by: Xavier Guerrero-Pau <xguerrero@cttc.es>
Co-authored-by: Victor Castillo <victorcastilloaguero@gmail.com>
This commit is contained in:
Carles Fernandez 2024-08-31 10:07:44 +02:00 committed by GitHub
parent 94d7635612
commit 3ec25f2347
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 2153 additions and 388 deletions

1
.gitignore vendored
View File

@ -28,4 +28,3 @@ HAS_*
gnss_sdr_pvt.nmea
build-debug/
build-release/

View File

@ -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

View File

@ -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"

View File

@ -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
"$<$<CONFIG:Debug>:${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}>"
"$<$<CONFIG:Release>:${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}>"
"$<$<CONFIG:RelWithDebInfo>:${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}>"
"$<$<CONFIG:MinSizeRel>:${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}>"
"$<$<CONFIG:NoOptWithASM>:${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}>"
"$<$<CONFIG:Coverage>:${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}>"
"$<$<CONFIG:O2WithASM>:${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}>"
"$<$<CONFIG:O3WithASM>:${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}>"
"$<$<CONFIG:ASAN>:${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.")

View File

@ -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.

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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

View File

@ -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++)

View File

@ -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<uint64_t>(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<uint64_t>(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<Fpga_Switch>();
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<Fpga_buffer_monitor>(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<std::mutex> lock_buffer_monitor(buffer_monitor_mutex);
enable_ovf_check_buffer_monitor_active_ = false;
lock_buffer_monitor.unlock();
{
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> lock_dyn_bit_sel(dynamic_bit_selection_mutex);
bit_selection_enabled = enable_dynamic_bit_selection_;
}
if (bit_selection_enabled == true)
{
std::unique_lock<std::mutex> lock(dynamic_bit_selection_mutex);
enable_dynamic_bit_selection_ = false;
lock.unlock();
{
std::lock_guard<std::mutex> 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<std::mutex> lock(dynamic_bit_selection_mutex);
std::lock_guard<std::mutex> 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<std::mutex> lock(buffer_monitor_mutex);
std::lock_guard<std::mutex> lock(buffer_monitor_mutex);
if (enable_ovf_check_buffer_monitor_active_ == false)
{
enable_ovf_check_buffer_monitor_active = false;
}
lock.unlock();
}
}

View File

@ -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<Fpga_dynamic_bit_selection> dynamic_bit_selection_fpga;
std::shared_ptr<Fpga_buffer_monitor> 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_;

View File

@ -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<Fpga_Switch>();
switch_fpga->set_switch_position(switch_to_real_time_mode);
@ -217,7 +208,6 @@ Fmcomms5SignalSourceFPGA::Fmcomms5SignalSourceFPGA(const ConfigurationInterface
buffer_monitor_fpga = std::make_shared<Fpga_buffer_monitor>(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<std::mutex> lock_buffer_monitor(buffer_monitor_mutex);
enable_ovf_check_buffer_monitor_active_ = false;
lock_buffer_monitor.unlock();
{
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> lock_dyn_bit_sel(dynamic_bit_selection_mutex);
bit_selection_enabled = enable_dynamic_bit_selection_;
}
if (bit_selection_enabled == true)
{
std::unique_lock<std::mutex> lock(dynamic_bit_selection_mutex);
enable_dynamic_bit_selection_ = false;
lock.unlock();
{
std::lock_guard<std::mutex> 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<std::mutex> lock(dynamic_bit_selection_mutex);
std::lock_guard<std::mutex> 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<std::mutex> lock(buffer_monitor_mutex);
std::lock_guard<std::mutex> lock(buffer_monitor_mutex);
if (enable_ovf_check_buffer_monitor_active_ == false)
{
enable_ovf_check_buffer_monitor_active = false;
}
lock.unlock();
}
}

View File

@ -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<Fpga_dynamic_bit_selection> dynamic_bit_selection_fpga;
std::shared_ptr<Fpga_buffer_monitor> 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_;

View File

@ -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 <gnuradio/blocks/copy.h>
#include <cstdlib>
#include <iostream>
#include <unordered_set>
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h>
#else
#include <absl/log/log.h>
#endif
using namespace std::string_literals;
namespace
{
std::vector<std::string> parse_comma_list(const std::string& str)
{
std::vector<std::string> 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<pmt::pmt_t>* 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<GnssMetadata::Metadata>();
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<IONGSMSFileSource::sptr> IONGSMSSignalSource::make_stream_sources(const std::vector<std::string>& stream_ids) const
{
std::vector<IONGSMSFileSource::sptr> 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<IONGSMSFileSource>(
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<int>(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];
}

View File

@ -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 <GnssMetadata.h>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
/** \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<pmt::pmt_t>* 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<IONGSMSFileSource::sptr> make_stream_sources(const std::vector<std::string>& stream_ids) const;
void load_metadata();
std::vector<std::string> stream_ids_;
std::vector<IONGSMSFileSource::sptr> sources_;
std::vector<gnss_shared_ptr<gr::block>> copy_blocks_;
std::vector<gnss_shared_ptr<gr::block>> valves_;
std::string metadata_filepath_;
std::shared_ptr<GnssMetadata::Metadata> metadata_;
gnss_shared_ptr<Gnss_Sdr_Timestamp> timestamp_block_;
std::string timestamp_file_;
uint32_t in_streams_;
uint32_t out_streams_;
};
/** \} */
/** \} */
#endif // GNSS_SDR_ION_GSMS_SIGNAL_SOURCE_H

View File

@ -140,13 +140,11 @@ MAX2771EVKITSignalSourceFPGA::MAX2771EVKITSignalSourceFPGA(const ConfigurationIn
}
}
std::vector<uint32_t> MAX2771EVKITSignalSourceFPGA::setup_regs(void)
{
std::vector<uint32_t> register_values = std::vector<uint32_t>(MAX2771_NUM_REGS);
auto register_values = std::vector<uint32_t>(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<uint32_t> 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<std::mutex> lock_buffer_monitor(buffer_monitor_mutex);
enable_ovf_check_buffer_monitor_active_ = false;
lock_buffer_monitor.unlock();
{
std::lock_guard<std::mutex> 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<std::mutex> lock(buffer_monitor_mutex);
std::lock_guard<std::mutex> lock(buffer_monitor_mutex);
if (enable_ovf_check_buffer_monitor_active_ == false)
{
enable_ovf_check_buffer_monitor_active = false;
}
lock.unlock();
}
}

View File

@ -53,7 +53,6 @@ public:
std::vector<uint32_t> setup_regs(void);
inline size_t item_size() override
{
return item_size_;
@ -130,14 +129,13 @@ private:
bool configure(std::vector<uint32_t> register_values);
void run_buffer_monitor_process();
mutable std::mutex buffer_monitor_mutex;
std::thread thread_buffer_monitor;
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_fpga;
std::shared_ptr<Fpga_spidev> spidev_fpga;
std::mutex buffer_monitor_mutex;
uint64_t freq_; // frequency of local oscillator
uint64_t sample_rate_;

View File

@ -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

View File

@ -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<std::fstream> *files_out)
void ad936x_iio_source::ad9361_channel_demux_and_record(ad936x_iio_samples* samples_in, int nchannels, std::vector<std::fstream>* 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<ad936x_iio_samples> 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<int8_t **>(&output_items[0]);
auto** out = reinterpret_cast<int8_t**>(&output_items[0]);
uint32_t current_byte = 0;
uint32_t current_byte_in_gr = 0;
int16_t ch = 0;

View File

@ -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>;
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<std::fstream> *files_out);

View File

@ -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 <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h>
#else
#include <absl/log/log.h>
#endif
IONGSMSFileSource::IONGSMSFileSource(
const fs::path& metadata_filepath,
const GnssMetadata::File& file,
const GnssMetadata::Block& block,
const std::vector<std::string>& 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<IONGSMSChunkData>(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<std::string>& stream_ids)
{
int nstreams = 0;
std::vector<int> 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<uint8_t*>(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;
}

View File

@ -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 <gnuradio/block.h>
#include <gnuradio/sync_block.h>
#include <cstddef>
#include <fstream>
#include <memory>
#include <string>
#include <vector>
/** \addtogroup Signal_Source
* \{ */
/** \addtogroup Signal_Source_gnuradio_blocks
* \{ */
class IONGSMSFileSource : public gr::sync_block
{
public:
using sptr = gnss_shared_ptr<IONGSMSFileSource>;
IONGSMSFileSource(
const fs::path& metadata_filepath,
const GnssMetadata::File& file,
const GnssMetadata::Block& block,
const std::vector<std::string>& 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<std::string>& stream_ids);
std::ifstream file_stream_;
std::vector<char> io_buffer_;
std::size_t io_buffer_offset_;
std::vector<int> items_produced_;
std::size_t output_stream_count_;
std::vector<std::size_t> output_stream_item_sizes_;
std::vector<std::size_t> output_stream_item_rates_;
std::vector<std::size_t> output_stream_total_sample_counts_;
std::size_t maximum_item_rate_;
std::vector<std::shared_ptr<IONGSMSChunkData>> chunk_data_;
std::size_t chunk_cycle_length_;
};
/** \} */
/** \} */
#endif // GNSS_SDR_ION_GSMS_H

View File

@ -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

View File

@ -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;
}

View File

@ -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 <absl/log/log.h>
#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<Concurrent_Que
}
bool ad936x_iio_custom::initialize_device(std::string pluto_device_uri, std::string board_type)
bool ad936x_iio_custom::initialize_device(const std::string &pluto_device_uri, const std::string &board_type)
{
// Find devices
if (pluto_device_uri == "local")
@ -123,7 +131,7 @@ bool ad936x_iio_custom::initialize_device(std::string pluto_device_uri, std::str
ctx = iio_create_context_from_uri(pluto_device_uri.c_str());
}
if (ctx == NULL)
if (ctx == nullptr)
{
std::cout << "Unable to create context from uri: " << pluto_device_uri << std::endl;
return false;
@ -131,16 +139,16 @@ bool ad936x_iio_custom::initialize_device(std::string pluto_device_uri, std::str
phy = iio_context_find_device(ctx, "ad9361-phy");
if (phy == NULL)
if (phy == nullptr)
{
std::cout << "Unable to find ad9361-phy device from uri: " << pluto_device_uri << std::endl;
return false;
}
if (board_type.compare("fmcomms5") == 0)
if (board_type == "fmcomms5")
{
stream_dev = iio_context_find_device(ctx, "cf-ad9361-A"); // first ad9361 in FMCOMMS5
if (stream_dev == NULL)
if (stream_dev == nullptr)
{
std::cout << "Unable to find cf-ad9361-A device from uri: " << pluto_device_uri << std::endl;
return false;
@ -149,13 +157,13 @@ bool ad936x_iio_custom::initialize_device(std::string pluto_device_uri, std::str
else
{
stream_dev = iio_context_find_device(ctx, "cf-ad9361-lpc"); // regular AD9361 stream device in single AD9361 boards
if (stream_dev == NULL)
if (stream_dev == nullptr)
{
std::cout << "Unable to find cf-ad9361-lpc device from uri: " << pluto_device_uri << std::endl;
return false;
};
dds_dev = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); // DDS core for LO oscillator (external transverter operation)
if (stream_dev == NULL)
if (stream_dev == nullptr)
{
std::cout << "Warning: Unable to find cf-ad9361-dds-core-lpc device from uri: " << pluto_device_uri << std::endl;
};
@ -168,23 +176,22 @@ bool ad936x_iio_custom::initialize_device(std::string pluto_device_uri, std::str
void ad936x_iio_custom::configure_params(struct iio_device *phy,
const std::vector<std::string> &params)
{
for (std::vector<std::string>::const_iterator it = params.begin();
it != params.end(); ++it)
for (const auto &param : 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<std::string> 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 &param, 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<uint32_t>(temp_mC_str);
auto temp_mC = boost::lexical_cast<uint32_t>(temp_mC_str);
temp_c = static_cast<double>(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<std::string> 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<ad936x_iio_samples> &
void ad936x_iio_custom::capture(const std::vector<std::string> &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<std::string> &channels)
}
else
{
for (std::vector<std::string>::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<std::string> &channels)
items_in_buffer = static_cast<unsigned long>(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;

View File

@ -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 <boost/atomic.hpp>
#include <iio.h>
#include <ad9361.h> // multichip sync and high level functions
#include <memory>
#include <string>
#ifdef __APPLE__
#include <iio/iio.h>
#else
#include <iio.h>
#endif
#include "ad936x_iio_samples.h"
#include <ad9361.h> // multichip sync and high level functions
#include <thread>
#include <vector>
/** \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<std::string> &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

View File

@ -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;
}

View File

@ -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 <cstdint>
#include <memory>
#include <stdint.h>
#include <vector>
/** \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

View File

@ -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 <cstring>
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h>
#else
#include <absl/log/log.h>
#endif
IONGSMSChunkData::IONGSMSChunkData(const GnssMetadata::Chunk& chunk, const std::vector<std::string>& 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<void*>(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<int>& output_items)
{
switch (sizeword_)
{
case 1:
unpack_words<int8_t>(outputs, output_items);
break;
case 2:
unpack_words<int16_t>(outputs, output_items);
break;
case 4:
unpack_words<int32_t>(outputs, output_items);
break;
case 8:
unpack_words<int64_t>(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 <typename WT>
void IONGSMSChunkData::unpack_words(gr_vector_void_star& outputs, std::vector<int>& output_items)
{
WT* data = static_cast<WT*>(buffer_);
// TODO - Swap endiannes if needed
IONGSMSChunkUnpackingCtx<WT> 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 <typename WT>
std::size_t IONGSMSChunkData::write_stream_samples(
IONGSMSChunkUnpackingCtx<WT>& 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<WT, int8_t>(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, reinterpret_cast<int8_t**>(out));
}
else if (sample_bitsize <= 16)
{
write_n_samples<WT, int16_t>(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, reinterpret_cast<int16_t**>(out));
}
else if (sample_bitsize <= 32)
{
write_n_samples<WT, int32_t>(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, reinterpret_cast<int32_t**>(out));
}
else if (sample_bitsize <= 64)
{
write_n_samples<WT, int64_t>(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, reinterpret_cast<int64_t**>(out));
}
return sample_count;
}
template <typename WT, typename OT>
void IONGSMSChunkData::write_n_samples(
IONGSMSChunkUnpackingCtx<WT>& 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<OT*>(*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<OT*>(*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 <typename Sample>
void IONGSMSChunkData::decode_sample(const uint8_t sample_bitsize, Sample* sample, const GnssMetadata::StreamEncoding encoding)
{
// using SampleType = std::remove_pointer_t<decltype(sample)>;
switch (sample_bitsize)
{
case 2:
*sample = GnssMetadata::two_bit_look_up<Sample>[encoding][*sample];
break;
case 3:
*sample = GnssMetadata::three_bit_look_up<Sample>[encoding][*sample];
break;
case 4:
*sample = GnssMetadata::four_bit_look_up<Sample>[encoding][*sample];
break;
case 5:
*sample = GnssMetadata::five_bit_look_up<Sample>[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;
}
}

View File

@ -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 <gnuradio/block.h>
#include <GnssMetadata.h>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <string>
#include <vector>
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 <typename WordType>
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 <typename WordType>
void operator()() const
{
delete[] static_cast<WordType*>(buffer_);
}
};
template <typename Callback>
void with_word_type(uint8_t word_size, Callback callback)
{
switch (word_size)
{
case 1:
callback.template operator()<int8_t>();
break;
case 2:
callback.template operator()<int16_t>();
break;
case 4:
callback.template operator()<int32_t>();
break;
case 8:
callback.template operator()<int64_t>();
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<std::string>& 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<int>& 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 <typename WT>
void unpack_words(gr_vector_void_star& outputs, std::vector<int>& output_items);
template <typename WT>
std::size_t write_stream_samples(
IONGSMSChunkUnpackingCtx<WT>& ctx,
const GnssMetadata::Lump& lump,
const GnssMetadata::IonStream& stream,
GnssMetadata::StreamEncoding stream_encoding,
void** out);
template <typename WT, typename OT>
void write_n_samples(
IONGSMSChunkUnpackingCtx<WT>& ctx,
GnssMetadata::Lump::LumpShift lump_shift,
uint8_t sample_bitsize,
std::size_t sample_count,
GnssMetadata::StreamEncoding stream_encoding,
OT** out);
template <typename Sample>
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<std::size_t> output_stream_item_size_;
std::vector<std::size_t> 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<stream_metadata_t> streams_;
void* buffer_;
};
#endif // GNSS_SDR_ION_GSMS_CHUNK_DATA_H

View File

@ -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 <gnuradio/block.h>
#include <GnssMetadata.h>
#include <cstdint>
/** \addtogroup Signal_Source
* \{ */
/** \addtogroup Signal_Source_libs
* \{ */
template <typename WT>
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 <typename OT>
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

View File

@ -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 <string>
/** \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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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

View File

@ -20,19 +20,6 @@
#include <utility>
#include <vector>
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<Concurrent_Queue<PpsSamplestamp>> queue)
{
@ -40,7 +27,7 @@ void pps_tcp_rx::set_pps_samplestamp_queue(std::shared_ptr<Concurrent_Queue<PpsS
}
bool pps_tcp_rx::send_cmd(std::string cmd)
bool pps_tcp_rx::send_cmd(std::string cmd) const
{
if (is_connected == true)
{
@ -64,7 +51,7 @@ bool pps_tcp_rx::send_cmd(std::string cmd)
}
void pps_tcp_rx::receive_pps(std::string ip_address, int port)
void pps_tcp_rx::receive_pps(const std::string &ip_address, int port)
{
// create a message buffer
char buf[1500];
@ -117,7 +104,7 @@ void pps_tcp_rx::receive_pps(std::string ip_address, int port)
{
try
{
new_pps.samplestamp = std::strtoul(data.at(0).substr(found + 3).c_str(), NULL, 0);
new_pps.samplestamp = std::strtoul(data.at(0).substr(found + 3).c_str(), nullptr, 0);
}
catch (const std::exception &ex)
{
@ -133,7 +120,7 @@ void pps_tcp_rx::receive_pps(std::string ip_address, int port)
{
try
{
new_pps.overflow_reg = std::stoi(data.at(1).substr(found + 2).c_str(), NULL, 0);
new_pps.overflow_reg = std::stoi(data.at(1).substr(found + 2).c_str(), nullptr, 0);
}
catch (const std::exception &ex)
{
@ -155,7 +142,9 @@ void pps_tcp_rx::receive_pps(std::string ip_address, int port)
}
}
else
new_pps_line += c;
{
new_pps_line += c;
}
}
}
else

View File

@ -28,15 +28,15 @@ class pps_tcp_rx
{
private:
std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> 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<Concurrent_Queue<PpsSamplestamp>> queue);
};

View File

@ -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()

View File

@ -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<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
block = std::move(block_);
}
#endif
#if ENABLE_ION_SOURCE
else if (implementation == "ION_GSMS_Signal_Source")
{
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<IONGSMSSignalSource>(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<GNSSBlockInterface> 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<GNSSBlockInterface> block_ = std::make_unique<Ad936xCustomSignalSource>(configuration, role, in_streams,