mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-04 23:40:04 +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:
parent
94d7635612
commit
3ec25f2347
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,4 +28,3 @@ HAS_*
|
|||||||
gnss_sdr_pvt.nmea
|
gnss_sdr_pvt.nmea
|
||||||
build-debug/
|
build-debug/
|
||||||
build-release/
|
build-release/
|
||||||
|
|
||||||
|
1
AUTHORS
1
AUTHORS
@ -64,6 +64,7 @@ Marc Sales marcsales92@gmail.com Contributor
|
|||||||
Piyush Gupta piyush04111999@gmail.com Contributor
|
Piyush Gupta piyush04111999@gmail.com Contributor
|
||||||
Rodrigo Muñoz rodrigo.munoz@proteinlab.cl Contributor
|
Rodrigo Muñoz rodrigo.munoz@proteinlab.cl Contributor
|
||||||
Stefan van der Linden spvdlinden@gmail.com Contributor
|
Stefan van der Linden spvdlinden@gmail.com Contributor
|
||||||
|
Víctor Castillo-Agüero victorcastilloaguero@gmail.com Contributor
|
||||||
Will Silberman wsilberm@google.com Contributor
|
Will Silberman wsilberm@google.com Contributor
|
||||||
Carlos Paniego carpanie@hotmail.com Artwork
|
Carlos Paniego carpanie@hotmail.com Artwork
|
||||||
|
|
||||||
|
@ -34,6 +34,11 @@ authors:
|
|||||||
email: mara.branzanti@gmail.com
|
email: mara.branzanti@gmail.com
|
||||||
family-names: Branzanti
|
family-names: Branzanti
|
||||||
given-names: Mara
|
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
|
- alias: acebrianjuan
|
||||||
email: acebrianjuan@gmail.com
|
email: acebrianjuan@gmail.com
|
||||||
family-names: "Cebrián-Juan"
|
family-names: "Cebrián-Juan"
|
||||||
|
178
CMakeLists.txt
178
CMakeLists.txt
@ -57,6 +57,8 @@ option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal
|
|||||||
|
|
||||||
option(ENABLE_ZMQ "Enable GNU Radio ZeroMQ Messaging, requires gr-zeromq" ON)
|
option(ENABLE_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
|
# Performance analysis tools
|
||||||
option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF)
|
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_GFLAGS_LOCAL_VERSION "2.2.2")
|
||||||
set(GNSSSDR_GLOG_LOCAL_VERSION "0.7.1")
|
set(GNSSSDR_GLOG_LOCAL_VERSION "0.7.1")
|
||||||
set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.27")
|
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_PUGIXML_LOCAL_VERSION "1.14")
|
||||||
set(GNSSSDR_GTEST_LOCAL_VERSION "1.15.2")
|
set(GNSSSDR_GTEST_LOCAL_VERSION "1.15.2")
|
||||||
set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "origin/master")
|
set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "origin/master")
|
||||||
set(GNSSSDR_GNSSTK_LOCAL_VERSION "14.3.0")
|
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_MATHJAX_EXTERNAL_VERSION "2.7.7")
|
||||||
set(GNSSSDR_ABSL_LOCAL_VERSION "origin/master") # live at head (see https://abseil.io/about/releases)
|
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."
|
PURPOSE "Used for communication with the AD9361 chipset."
|
||||||
TYPE OPTIONAL
|
TYPE OPTIONAL
|
||||||
)
|
)
|
||||||
if(ENABLE_AD9361 OR ENABLE_FMCOMMS2)
|
if(ENABLE_AD9361 OR ENABLE_FMCOMMS2 OR ENABLE_PLUTOSDR)
|
||||||
if(NOT LIBIIO_FOUND)
|
if(NOT LIBIIO_FOUND)
|
||||||
message(STATUS "libiio not found, its installation is required.")
|
message(STATUS "libiio not found, its installation is required.")
|
||||||
message(STATUS "Please build and install the following projects:")
|
message(STATUS "Please build and install the following projects:")
|
||||||
@ -3270,6 +3272,161 @@ if(ENABLE_AD9361 OR ENABLE_FMCOMMS2)
|
|||||||
endif()
|
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.
|
# 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_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_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_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_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 for using ADALM-PLUTO boards. Requires 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_AD9361 ENABLE_AD9361 "Enables Ad9361_Fpga_Signal_Source for devices with the AD9361 chipset. Requires libiio and libad9361-dev.")
|
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_MAX2771 ENABLE_MAX2771 "Enables FPGA_MAX2771_EVKIT_Signal_Source for devices with the MAX2771 chipset. Requires the spidev driver")
|
add_feature_info(ENABLE_FPGA ENABLE_FPGA "Enables building of processing blocks for FPGA offloading.")
|
||||||
add_feature_info(ENABLE_DMA_PROXY ENABLE_DMA_PROXY "Enables DMA Signal_Source. Requires the DMA Proxy driver")
|
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_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_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_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_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_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_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_GPERFTOOLS ENABLE_GPERFTOOLS "Enables performance analysis. Requires Gperftools.")
|
||||||
add_feature_info(ENABLE_GPROF ENABLE_GPROF "Enables performance analysis with 'gprof'.")
|
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_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_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_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_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_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_PACKAGING ENABLE_PACKAGING "Enables software packaging.")
|
||||||
add_feature_info(ENABLE_OWN_GLOG ENABLE_OWN_GLOG "Forces the downloading and building of Google glog.")
|
add_feature_info(ENABLE_OWN_GLOG ENABLE_OWN_GLOG "Forces the downloading and building of Google glog.")
|
||||||
|
@ -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
|
- `-DENABLE_DMA_PROXY`: Checks if the DMA proxy driver is installed for
|
||||||
controlling the DMA in the FPGA and enables its usage.
|
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:
|
### Improvements in Portability:
|
||||||
|
|
||||||
- Fix building against google-glog 0.7.x.
|
- Fix building against google-glog 0.7.x.
|
||||||
|
@ -227,11 +227,11 @@
|
|||||||
#endif // defined(CPU_FEATURES_ARCH_X86)
|
#endif // defined(CPU_FEATURES_ARCH_X86)
|
||||||
|
|
||||||
#if defined(CPU_FEATURES_ARCH_ANY_ARM)
|
#if defined(CPU_FEATURES_ARCH_ANY_ARM)
|
||||||
#if defined(__ARM_NEON__)
|
#if defined(__ARM_NEON)
|
||||||
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1
|
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1
|
||||||
#else
|
#else
|
||||||
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0
|
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0
|
||||||
#endif // defined(__ARM_NEON__)
|
#endif // defined(__ARM_NEON)
|
||||||
#endif // defined(CPU_FEATURES_ARCH_ANY_ARM)
|
#endif // defined(CPU_FEATURES_ARCH_ANY_ARM)
|
||||||
|
|
||||||
#if defined(CPU_FEATURES_ARCH_MIPS)
|
#if defined(CPU_FEATURES_ARCH_MIPS)
|
||||||
|
@ -182,6 +182,31 @@ typedef struct
|
|||||||
int smef16f16 : 1; // FP16 to FP16 outer product.
|
int smef16f16 : 1; // FP16 to FP16 outer product.
|
||||||
int mops : 1; // Standardized memory operations.
|
int mops : 1; // Standardized memory operations.
|
||||||
int hbc : 1; // Hinted conditional branches.
|
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.
|
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
|
||||||
} Aarch64Features;
|
} Aarch64Features;
|
||||||
@ -280,6 +305,24 @@ typedef enum
|
|||||||
AARCH64_SME_F16F16,
|
AARCH64_SME_F16F16,
|
||||||
AARCH64_MOPS,
|
AARCH64_MOPS,
|
||||||
AARCH64_HBC,
|
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_,
|
AARCH64_LAST_,
|
||||||
} Aarch64FeaturesEnum;
|
} Aarch64FeaturesEnum;
|
||||||
|
|
||||||
|
@ -94,6 +94,24 @@ CPU_FEATURES_START_CPP_NAMESPACE
|
|||||||
#define AARCH64_HWCAP2_SME_F16F16 (1UL << 42)
|
#define AARCH64_HWCAP2_SME_F16F16 (1UL << 42)
|
||||||
#define AARCH64_HWCAP2_MOPS (1UL << 43)
|
#define AARCH64_HWCAP2_MOPS (1UL << 43)
|
||||||
#define AARCH64_HWCAP2_HBC (1UL << 44)
|
#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
|
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
|
||||||
#define ARM_HWCAP_SWP (1UL << 0)
|
#define ARM_HWCAP_SWP (1UL << 0)
|
||||||
|
@ -103,7 +103,28 @@
|
|||||||
LINE(AARCH64_SME_F16F16, smef16f16, "smef16f16", 0, \
|
LINE(AARCH64_SME_F16F16, smef16f16, "smef16f16", 0, \
|
||||||
AARCH64_HWCAP2_SME_F16F16) \
|
AARCH64_HWCAP2_SME_F16F16) \
|
||||||
LINE(AARCH64_MOPS, mops, "mops", 0, AARCH64_HWCAP2_MOPS) \
|
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_PREFIX Aarch64
|
||||||
#define INTROSPECTION_ENUM_PREFIX AARCH64
|
#define INTROSPECTION_ENUM_PREFIX AARCH64
|
||||||
#include "define_introspection_and_hwcaps.inl"
|
#include "define_introspection_and_hwcaps.inl"
|
@ -326,6 +326,24 @@ CPU revision : 3)");
|
|||||||
EXPECT_FALSE(info.features.smef16f16);
|
EXPECT_FALSE(info.features.smef16f16);
|
||||||
EXPECT_FALSE(info.features.mops);
|
EXPECT_FALSE(info.features.mops);
|
||||||
EXPECT_FALSE(info.features.hbc);
|
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)
|
#elif defined(CPU_FEATURES_OS_MACOS)
|
||||||
TEST_F(CpuidAarch64Test, FromDarwinSysctlFromName)
|
TEST_F(CpuidAarch64Test, FromDarwinSysctlFromName)
|
||||||
|
@ -25,6 +25,14 @@ if(ENABLE_PLUTOSDR)
|
|||||||
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_custom_signal_source.h)
|
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_custom_signal_source.h)
|
||||||
endif()
|
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)
|
if(ENABLE_FMCOMMS2)
|
||||||
###############################################
|
###############################################
|
||||||
# FMCOMMS2 based SDR Hardware
|
# FMCOMMS2 based SDR Hardware
|
||||||
@ -103,6 +111,11 @@ if(ENABLE_ZMQ)
|
|||||||
list(APPEND OPT_DRIVER_HEADERS zmq_signal_source.h)
|
list(APPEND OPT_DRIVER_HEADERS zmq_signal_source.h)
|
||||||
endif()
|
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
|
set(SIGNAL_SOURCE_ADAPTER_SOURCES
|
||||||
signal_source_base.cc
|
signal_source_base.cc
|
||||||
file_source_base.cc
|
file_source_base.cc
|
||||||
@ -169,7 +182,7 @@ target_include_directories(signal_source_adapters
|
|||||||
${GNSSSDR_SOURCE_DIR}/src/core/interfaces
|
${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
|
target_link_libraries(signal_source_adapters
|
||||||
PUBLIC
|
PUBLIC
|
||||||
signal_source_libs
|
signal_source_libs
|
||||||
@ -239,14 +252,14 @@ if(ENABLE_LIMESDR AND GRLIMESDR_FOUND)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_AD9361 AND LIBIIO_FOUND)
|
if(LIBIIO_FOUND)
|
||||||
target_link_libraries(signal_source_adapters
|
target_link_libraries(signal_source_adapters
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Iio::iio
|
Iio::iio
|
||||||
)
|
)
|
||||||
endif()
|
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)
|
||||||
if(LIBAD9361_VERSION VERSION_GREATER 0.1)
|
if(LIBAD9361_VERSION VERSION_GREATER 0.1)
|
||||||
target_compile_definitions(signal_source_adapters
|
target_compile_definitions(signal_source_adapters
|
||||||
|
@ -76,8 +76,11 @@ Ad936xCustomSignalSource::Ad936xCustomSignalSource(const ConfigurationInterface*
|
|||||||
item_size_ = sizeof(gr_complex);
|
item_size_ = sizeof(gr_complex);
|
||||||
// 1. Make the driver instance
|
// 1. Make the driver instance
|
||||||
bool customsamplesize = false;
|
bool customsamplesize = false;
|
||||||
if (ssize_ != 12 or spattern_ == true) customsamplesize = true; // custom FPGA DMA firmware
|
if (ssize_ != 12 || spattern_ == true)
|
||||||
if (ssize_ == 12) // default original FPGA DMA firmware
|
{
|
||||||
|
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
|
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++)
|
for (int n = 0; n < n_channels; n++)
|
||||||
{
|
{
|
||||||
if (n == 0) inverted_spectrum_vec.push_back(inverted_spectrum_ch0_);
|
if (n == 0)
|
||||||
if (n == 1) inverted_spectrum_vec.push_back(inverted_spectrum_ch1_);
|
{
|
||||||
|
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++)
|
for (int n = 0; n < n_channels; n++)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file adrv9361_z7035_signal_source_fpga.cc
|
* \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.
|
* directly connected to the FPGA accelerators.
|
||||||
* This source implements only the AD9361 control. It is NOT compatible with
|
* This source implements only the AD9361 control. It is NOT compatible with
|
||||||
* conventional SDR acquisition and tracking blocks.
|
* 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_rx1_(configuration->property(role + ".gain_mode_rx1", default_gain_mode)),
|
||||||
gain_mode_rx2_(configuration->property(role + ".gain_mode_rx2", 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)),
|
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_)),
|
filter_filename_(configuration->property(role + ".filter_filename", filter_file_)),
|
||||||
rf_gain_rx1_(configuration->property(role + ".gain_rx1", default_manual_gain_rx1)),
|
rf_gain_rx1_(configuration->property(role + ".gain_rx1", default_manual_gain_rx1)),
|
||||||
rf_gain_rx2_(configuration->property(role + ".gain_rx2", default_manual_gain_rx2)),
|
rf_gain_rx2_(configuration->property(role + ".gain_rx2", default_manual_gain_rx2)),
|
||||||
scale_dds_dbfs_(configuration->property(role + ".scale_dds_dbfs", -3.0)),
|
scale_dds_dbfs_(configuration->property(role + ".scale_dds_dbfs", -3.0)),
|
||||||
phase_dds_deg_(configuration->property(role + ".phase_dds_deg", 0.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)),
|
tx_attenuation_db_(configuration->property(role + ".tx_attenuation_db", default_tx_attenuation_db)),
|
||||||
freq0_(configuration->property(role + ".freq", 0)),
|
freq0_(configuration->property(role + ".freq", GPS_L5_FREQ_HZ)),
|
||||||
freq1_(configuration->property(role + ".freq1", static_cast<uint64_t>(GPS_L5_FREQ_HZ))),
|
|
||||||
sample_rate_(configuration->property(role + ".sampling_frequency", default_bandwidth)),
|
sample_rate_(configuration->property(role + ".sampling_frequency", default_bandwidth)),
|
||||||
bandwidth_(configuration->property(role + ".bandwidth", default_bandwidth)),
|
bandwidth_(configuration->property(role + ".bandwidth", default_bandwidth)),
|
||||||
freq_dds_tx_hz_(configuration->property(role + ".freq_dds_tx_hz", uint64_t(10000))),
|
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),
|
out_stream_(out_stream),
|
||||||
item_size_(sizeof(int8_t)),
|
item_size_(sizeof(int8_t)),
|
||||||
enable_dds_lo_(configuration->property(role + ".enable_dds_lo", false)),
|
enable_dds_lo_(configuration->property(role + ".enable_dds_lo", false)),
|
||||||
filter_auto_(configuration->property(role + ".filter_auto", false)),
|
|
||||||
quadrature_(configuration->property(role + ".quadrature", true)),
|
quadrature_(configuration->property(role + ".quadrature", true)),
|
||||||
rf_dc_(configuration->property(role + ".rf_dc", true)),
|
rf_dc_(configuration->property(role + ".rf_dc", true)),
|
||||||
bb_dc_(configuration->property(role + ".bb_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));
|
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 = std::make_shared<Fpga_Switch>();
|
||||||
switch_fpga->set_switch_position(switch_to_real_time_mode);
|
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";
|
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
|
try
|
||||||
{
|
{
|
||||||
config_ad9361_rx_local(bandwidth_,
|
config_ad9361_rx_local(bandwidth_,
|
||||||
sample_rate_,
|
sample_rate_,
|
||||||
freq0_,
|
freq0_,
|
||||||
freq1_,
|
freq1,
|
||||||
rf_port_select_,
|
rf_port_select_,
|
||||||
rx1_enable_,
|
rx1_enable_,
|
||||||
rx2_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);
|
buffer_monitor_fpga = std::make_shared<Fpga_buffer_monitor>(num_freq_bands, dump_, dump_filename);
|
||||||
thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); });
|
thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); });
|
||||||
|
|
||||||
|
|
||||||
// dynamic bits selection
|
// dynamic bits selection
|
||||||
if (enable_dynamic_bit_selection_)
|
if (enable_dynamic_bit_selection_)
|
||||||
{
|
{
|
||||||
@ -278,15 +270,23 @@ Adrv9361z7035SignalSourceFPGA::Adrv9361z7035SignalSourceFPGA(const Configuration
|
|||||||
|
|
||||||
Adrv9361z7035SignalSourceFPGA::~Adrv9361z7035SignalSourceFPGA()
|
Adrv9361z7035SignalSourceFPGA::~Adrv9361z7035SignalSourceFPGA()
|
||||||
{
|
{
|
||||||
/* cleanup and exit */
|
// cleanup and exit
|
||||||
|
|
||||||
if (rf_shutdown_)
|
if (rf_shutdown_)
|
||||||
{
|
{
|
||||||
std::cout << "* AD9361 Disabling RX streaming channels\n";
|
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_)
|
if (enable_dds_lo_)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -301,24 +301,27 @@ Adrv9361z7035SignalSourceFPGA::~Adrv9361z7035SignalSourceFPGA()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// disable buffer overflow checking and buffer monitoring
|
// 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;
|
std::lock_guard<std::mutex> lock_buffer_monitor(buffer_monitor_mutex);
|
||||||
lock_buffer_monitor.unlock();
|
enable_ovf_check_buffer_monitor_active_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (thread_buffer_monitor.joinable())
|
if (thread_buffer_monitor.joinable())
|
||||||
{
|
{
|
||||||
thread_buffer_monitor.join();
|
thread_buffer_monitor.join();
|
||||||
}
|
}
|
||||||
|
bool bit_selection_enabled = false;
|
||||||
std::unique_lock<std::mutex> lock_dyn_bit_sel(dynamic_bit_selection_mutex);
|
{
|
||||||
bool bit_selection_enabled = enable_dynamic_bit_selection_;
|
std::lock_guard<std::mutex> lock_dyn_bit_sel(dynamic_bit_selection_mutex);
|
||||||
lock_dyn_bit_sel.unlock();
|
bit_selection_enabled = enable_dynamic_bit_selection_;
|
||||||
|
}
|
||||||
|
|
||||||
if (bit_selection_enabled == true)
|
if (bit_selection_enabled == true)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(dynamic_bit_selection_mutex);
|
{
|
||||||
enable_dynamic_bit_selection_ = false;
|
std::lock_guard<std::mutex> lock(dynamic_bit_selection_mutex);
|
||||||
lock.unlock();
|
enable_dynamic_bit_selection_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (thread_dynamic_bit_selection.joinable())
|
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
|
// setting the bit selection to the top bits
|
||||||
dynamic_bit_selection_fpga->bit_selection();
|
dynamic_bit_selection_fpga->bit_selection();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(Gain_control_period_ms));
|
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)
|
if (enable_dynamic_bit_selection_ == false)
|
||||||
{
|
{
|
||||||
dynamic_bit_selection_active = 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();
|
buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms));
|
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)
|
if (enable_ovf_check_buffer_monitor_active_ == false)
|
||||||
{
|
{
|
||||||
enable_ovf_check_buffer_monitor_active = false;
|
enable_ovf_check_buffer_monitor_active = false;
|
||||||
}
|
}
|
||||||
lock.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file adrv9361_z7035_signal_source_fpga.h
|
* \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.
|
* directly connected to the FPGA accelerators.
|
||||||
* This source implements only the AD9361 control. It is NOT compatible with
|
* This source implements only the AD9361 control. It is NOT compatible with
|
||||||
* conventional SDR acquisition and tracking blocks.
|
* conventional SDR acquisition and tracking blocks.
|
||||||
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "fpga_buffer_monitor.h"
|
#include "fpga_buffer_monitor.h"
|
||||||
#include "fpga_dma-proxy.h"
|
|
||||||
#include "fpga_dynamic_bit_selection.h"
|
#include "fpga_dynamic_bit_selection.h"
|
||||||
#include "fpga_switch.h"
|
#include "fpga_switch.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "gnss_block_interface.h"
|
||||||
@ -78,13 +77,14 @@ private:
|
|||||||
const uint32_t buffer_monitor_period_ms = 1000;
|
const uint32_t buffer_monitor_period_ms = 1000;
|
||||||
// buffer overflow and buffer monitoring initial delay
|
// buffer overflow and buffer monitoring initial delay
|
||||||
const uint32_t buffer_monitoring_initial_delay_ms = 2000;
|
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;
|
const int32_t switch_to_real_time_mode = 2;
|
||||||
|
|
||||||
void run_dynamic_bit_selection_process();
|
void run_dynamic_bit_selection_process();
|
||||||
void run_buffer_monitor_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_dynamic_bit_selection;
|
||||||
std::thread thread_buffer_monitor;
|
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_dynamic_bit_selection> dynamic_bit_selection_fpga;
|
||||||
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_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_rx1_;
|
||||||
std::string gain_mode_rx2_;
|
std::string gain_mode_rx2_;
|
||||||
std::string rf_port_select_;
|
std::string rf_port_select_;
|
||||||
@ -109,7 +106,6 @@ private:
|
|||||||
double tx_attenuation_db_;
|
double tx_attenuation_db_;
|
||||||
|
|
||||||
uint64_t freq0_; // frequency of local oscillator for ADRV9361-A 0
|
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 sample_rate_;
|
||||||
uint64_t bandwidth_;
|
uint64_t bandwidth_;
|
||||||
uint64_t freq_dds_tx_hz_;
|
uint64_t freq_dds_tx_hz_;
|
||||||
@ -124,7 +120,6 @@ private:
|
|||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
|
|
||||||
bool enable_dds_lo_;
|
bool enable_dds_lo_;
|
||||||
bool filter_auto_;
|
|
||||||
bool quadrature_;
|
bool quadrature_;
|
||||||
bool rf_dc_;
|
bool rf_dc_;
|
||||||
bool bb_dc_;
|
bool bb_dc_;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file fmcomms5_signal_source_fpga.cc
|
* \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.
|
* to the FPGA accelerators.
|
||||||
* This source implements only the AD9361 control. It is NOT compatible with
|
* This source implements only the AD9361 control. It is NOT compatible with
|
||||||
* conventional SDR acquisition and tracking blocks.
|
* 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_rx1_(configuration->property(role + ".gain_mode_rx1", default_gain_mode)),
|
||||||
gain_mode_rx2_(configuration->property(role + ".gain_mode_rx2", 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)),
|
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_)),
|
filter_filename_(configuration->property(role + ".filter_filename", filter_file_)),
|
||||||
rf_gain_rx1_(configuration->property(role + ".gain_rx1", default_manual_gain_rx1)),
|
rf_gain_rx1_(configuration->property(role + ".gain_rx1", default_manual_gain_rx1)),
|
||||||
rf_gain_rx2_(configuration->property(role + ".gain_rx2", default_manual_gain_rx2)),
|
rf_gain_rx2_(configuration->property(role + ".gain_rx2", default_manual_gain_rx2)),
|
||||||
@ -63,7 +64,6 @@ Fmcomms5SignalSourceFPGA::Fmcomms5SignalSourceFPGA(const ConfigurationInterface
|
|||||||
in_stream_(in_stream),
|
in_stream_(in_stream),
|
||||||
out_stream_(out_stream),
|
out_stream_(out_stream),
|
||||||
item_size_(sizeof(int8_t)),
|
item_size_(sizeof(int8_t)),
|
||||||
filter_auto_(configuration->property(role + ".filter_auto", false)),
|
|
||||||
quadrature_(configuration->property(role + ".quadrature", true)),
|
quadrature_(configuration->property(role + ".quadrature", true)),
|
||||||
rf_dc_(configuration->property(role + ".rf_dc", true)),
|
rf_dc_(configuration->property(role + ".rf_dc", true)),
|
||||||
bb_dc_(configuration->property(role + ".bb_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;
|
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 = std::make_shared<Fpga_Switch>();
|
||||||
switch_fpga->set_switch_position(switch_to_real_time_mode);
|
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);
|
buffer_monitor_fpga = std::make_shared<Fpga_buffer_monitor>(num_freq_bands, dump_, dump_filename);
|
||||||
thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); });
|
thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); });
|
||||||
|
|
||||||
|
|
||||||
// dynamic bits selection
|
// dynamic bits selection
|
||||||
if (enable_dynamic_bit_selection_)
|
if (enable_dynamic_bit_selection_)
|
||||||
{
|
{
|
||||||
@ -238,36 +228,45 @@ Fmcomms5SignalSourceFPGA::Fmcomms5SignalSourceFPGA(const ConfigurationInterface
|
|||||||
|
|
||||||
Fmcomms5SignalSourceFPGA::~Fmcomms5SignalSourceFPGA()
|
Fmcomms5SignalSourceFPGA::~Fmcomms5SignalSourceFPGA()
|
||||||
{
|
{
|
||||||
/* cleanup and exit */
|
// cleanup and exit
|
||||||
|
|
||||||
if (rf_shutdown_)
|
if (rf_shutdown_)
|
||||||
{
|
{
|
||||||
std::cout << "* Disabling RX streaming channels\n";
|
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
|
// 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;
|
std::lock_guard<std::mutex> lock_buffer_monitor(buffer_monitor_mutex);
|
||||||
lock_buffer_monitor.unlock();
|
enable_ovf_check_buffer_monitor_active_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (thread_buffer_monitor.joinable())
|
if (thread_buffer_monitor.joinable())
|
||||||
{
|
{
|
||||||
thread_buffer_monitor.join();
|
thread_buffer_monitor.join();
|
||||||
}
|
}
|
||||||
|
bool bit_selection_enabled = false;
|
||||||
std::unique_lock<std::mutex> lock_dyn_bit_sel(dynamic_bit_selection_mutex);
|
{
|
||||||
bool bit_selection_enabled = enable_dynamic_bit_selection_;
|
std::lock_guard<std::mutex> lock_dyn_bit_sel(dynamic_bit_selection_mutex);
|
||||||
lock_dyn_bit_sel.unlock();
|
bit_selection_enabled = enable_dynamic_bit_selection_;
|
||||||
|
}
|
||||||
|
|
||||||
if (bit_selection_enabled == true)
|
if (bit_selection_enabled == true)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(dynamic_bit_selection_mutex);
|
{
|
||||||
enable_dynamic_bit_selection_ = false;
|
std::lock_guard<std::mutex> lock(dynamic_bit_selection_mutex);
|
||||||
lock.unlock();
|
enable_dynamic_bit_selection_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (thread_dynamic_bit_selection.joinable())
|
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
|
// setting the bit selection to the top bits
|
||||||
dynamic_bit_selection_fpga->bit_selection();
|
dynamic_bit_selection_fpga->bit_selection();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(Gain_control_period_ms));
|
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)
|
if (enable_dynamic_bit_selection_ == false)
|
||||||
{
|
{
|
||||||
dynamic_bit_selection_active = 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();
|
buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms));
|
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)
|
if (enable_ovf_check_buffer_monitor_active_ == false)
|
||||||
{
|
{
|
||||||
enable_ovf_check_buffer_monitor_active = false;
|
enable_ovf_check_buffer_monitor_active = false;
|
||||||
}
|
}
|
||||||
lock.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file fmcomms5_signal_source_fpga.h
|
* \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.
|
* to the FPGA accelerators.
|
||||||
* This source implements only the AD9361 control. It is NOT compatible with
|
* This source implements only the AD9361 control. It is NOT compatible with
|
||||||
* conventional SDR acquisition and tracking blocks.
|
* conventional SDR acquisition and tracking blocks.
|
||||||
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "fpga_buffer_monitor.h"
|
#include "fpga_buffer_monitor.h"
|
||||||
#include "fpga_dma-proxy.h"
|
|
||||||
#include "fpga_dynamic_bit_selection.h"
|
#include "fpga_dynamic_bit_selection.h"
|
||||||
#include "fpga_switch.h"
|
#include "fpga_switch.h"
|
||||||
#include "gnss_block_interface.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_dump_filename = std::string("FPGA_buffer_monitor_dump.dat");
|
||||||
const std::string default_rf_port_select = std::string("A_BALANCED");
|
const std::string default_rf_port_select = std::string("A_BALANCED");
|
||||||
const std::string default_gain_mode = std::string("slow_attack");
|
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_rx1 = 64.0;
|
||||||
const double default_manual_gain_rx2 = 64.0;
|
const double default_manual_gain_rx2 = 64.0;
|
||||||
const uint64_t default_bandwidth = 12500000;
|
const uint64_t default_bandwidth = 12500000;
|
||||||
@ -78,13 +76,14 @@ private:
|
|||||||
const uint32_t buffer_monitor_period_ms = 1000;
|
const uint32_t buffer_monitor_period_ms = 1000;
|
||||||
// buffer overflow and buffer monitoring initial delay
|
// buffer overflow and buffer monitoring initial delay
|
||||||
const uint32_t buffer_monitoring_initial_delay_ms = 2000;
|
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;
|
const int32_t switch_to_real_time_mode = 2;
|
||||||
|
|
||||||
void run_dynamic_bit_selection_process();
|
void run_dynamic_bit_selection_process();
|
||||||
void run_buffer_monitor_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_dynamic_bit_selection;
|
||||||
std::thread thread_buffer_monitor;
|
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_dynamic_bit_selection> dynamic_bit_selection_fpga;
|
||||||
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_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_rx1_;
|
||||||
std::string gain_mode_rx2_;
|
std::string gain_mode_rx2_;
|
||||||
std::string rf_port_select_;
|
std::string rf_port_select_;
|
||||||
@ -117,7 +113,6 @@ private:
|
|||||||
|
|
||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
|
|
||||||
bool filter_auto_;
|
|
||||||
bool quadrature_;
|
bool quadrature_;
|
||||||
bool rf_dc_;
|
bool rf_dc_;
|
||||||
bool bb_dc_;
|
bool bb_dc_;
|
||||||
|
239
src/algorithms/signal_source/adapters/ion_gsms_signal_source.cc
Normal file
239
src/algorithms/signal_source/adapters/ion_gsms_signal_source.cc
Normal 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];
|
||||||
|
}
|
@ -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
|
@ -140,13 +140,11 @@ MAX2771EVKITSignalSourceFPGA::MAX2771EVKITSignalSourceFPGA(const ConfigurationIn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<uint32_t> MAX2771EVKITSignalSourceFPGA::setup_regs(void)
|
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 LNA_mode = (LNA_active_) ? 0x0 : 0x2;
|
||||||
|
|
||||||
uint32_t Filter_Bandwidth;
|
uint32_t Filter_Bandwidth;
|
||||||
|
|
||||||
switch (bandwidth_)
|
switch (bandwidth_)
|
||||||
@ -376,10 +374,10 @@ bool MAX2771EVKITSignalSourceFPGA::configure(std::vector<uint32_t> register_valu
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MAX2771EVKITSignalSourceFPGA::~MAX2771EVKITSignalSourceFPGA()
|
MAX2771EVKITSignalSourceFPGA::~MAX2771EVKITSignalSourceFPGA()
|
||||||
{
|
{
|
||||||
/* cleanup and exit */
|
// cleanup and exit
|
||||||
|
|
||||||
if (rf_shutdown_)
|
if (rf_shutdown_)
|
||||||
{
|
{
|
||||||
chipen_ = false;
|
chipen_ = false;
|
||||||
@ -392,7 +390,6 @@ MAX2771EVKITSignalSourceFPGA::~MAX2771EVKITSignalSourceFPGA()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (configure(register_values))
|
if (configure(register_values))
|
||||||
{
|
{
|
||||||
std::cerr << "Error disabling the MAX2771 device " << '\n';
|
std::cerr << "Error disabling the MAX2771 device " << '\n';
|
||||||
@ -405,9 +402,10 @@ MAX2771EVKITSignalSourceFPGA::~MAX2771EVKITSignalSourceFPGA()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// disable buffer overflow checking and buffer monitoring
|
// 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;
|
std::lock_guard<std::mutex> lock_buffer_monitor(buffer_monitor_mutex);
|
||||||
lock_buffer_monitor.unlock();
|
enable_ovf_check_buffer_monitor_active_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (thread_buffer_monitor.joinable())
|
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();
|
buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms));
|
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)
|
if (enable_ovf_check_buffer_monitor_active_ == false)
|
||||||
{
|
{
|
||||||
enable_ovf_check_buffer_monitor_active = false;
|
enable_ovf_check_buffer_monitor_active = false;
|
||||||
}
|
}
|
||||||
lock.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@ public:
|
|||||||
|
|
||||||
std::vector<uint32_t> setup_regs(void);
|
std::vector<uint32_t> setup_regs(void);
|
||||||
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -130,14 +129,13 @@ private:
|
|||||||
bool configure(std::vector<uint32_t> register_values);
|
bool configure(std::vector<uint32_t> register_values);
|
||||||
void run_buffer_monitor_process();
|
void run_buffer_monitor_process();
|
||||||
|
|
||||||
|
mutable std::mutex buffer_monitor_mutex;
|
||||||
|
|
||||||
std::thread thread_buffer_monitor;
|
std::thread thread_buffer_monitor;
|
||||||
|
|
||||||
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_fpga;
|
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_fpga;
|
||||||
std::shared_ptr<Fpga_spidev> spidev_fpga;
|
std::shared_ptr<Fpga_spidev> spidev_fpga;
|
||||||
|
|
||||||
std::mutex buffer_monitor_mutex;
|
|
||||||
|
|
||||||
uint64_t freq_; // frequency of local oscillator
|
uint64_t freq_; // frequency of local oscillator
|
||||||
uint64_t sample_rate_;
|
uint64_t sample_rate_;
|
||||||
|
|
||||||
|
@ -10,17 +10,16 @@ if(ENABLE_RAW_UDP AND PCAP_FOUND)
|
|||||||
list(APPEND OPT_DRIVER_HEADERS gr_complex_ip_packet_source.h)
|
list(APPEND OPT_DRIVER_HEADERS gr_complex_ip_packet_source.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_AD936X_SDR)
|
if(ENABLE_PLUTOSDR OR 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)
|
|
||||||
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ad936x_iio_source.cc)
|
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ad936x_iio_source.cc)
|
||||||
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_iio_source.h)
|
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_iio_source.h)
|
||||||
endif()
|
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
|
set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
||||||
fifo_reader.cc
|
fifo_reader.cc
|
||||||
unpack_byte_2bit_samples.cc
|
unpack_byte_2bit_samples.cc
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file ad936x_iio_source.cc
|
* \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
|
* \author Javier Arribas, jarribas(at)cttc.es
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
@ -33,23 +34,23 @@
|
|||||||
|
|
||||||
|
|
||||||
ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
||||||
std::string pluto_uri_,
|
const std::string& pluto_uri_,
|
||||||
std::string board_type_,
|
const std::string& board_type_,
|
||||||
long long bandwidth_,
|
int64_t bandwidth_,
|
||||||
long long sample_rate_,
|
int64_t sample_rate_,
|
||||||
long long freq_,
|
int64_t freq_,
|
||||||
std::string rf_port_select_,
|
const std::string& rf_port_select_,
|
||||||
std::string rf_filter,
|
const std::string& rf_filter,
|
||||||
std::string gain_mode_rx0_,
|
const std::string& gain_mode_rx0_,
|
||||||
std::string gain_mode_rx1_,
|
const std::string& gain_mode_rx1_,
|
||||||
double rf_gain_rx0_,
|
double rf_gain_rx0_,
|
||||||
double rf_gain_rx1_,
|
double rf_gain_rx1_,
|
||||||
bool enable_ch0,
|
bool enable_ch0,
|
||||||
bool enable_ch1,
|
bool enable_ch1,
|
||||||
long long freq_2ch,
|
int64_t freq_2ch,
|
||||||
bool ppsmode_,
|
bool ppsmode_,
|
||||||
bool customsamplesize_,
|
bool customsamplesize_,
|
||||||
std::string fe_ip_,
|
const std::string& fe_ip_,
|
||||||
int fe_ctlport_,
|
int fe_ctlport_,
|
||||||
int ssize_,
|
int ssize_,
|
||||||
int bshift_,
|
int bshift_,
|
||||||
@ -85,9 +86,10 @@ ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
|||||||
tx_lo_channel_));
|
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;
|
int16_t ch = 0;
|
||||||
// std::cout << "nbytes: " << samples_in->n_bytes << " nsamples: " << samples_in->n_samples << " nch: " << nchannels << "\n";
|
// std::cout << "nbytes: " << samples_in->n_bytes << " nsamples: " << samples_in->n_samples << " nch: " << nchannels << "\n";
|
||||||
while (current_byte < samples_in->n_bytes)
|
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(
|
ad936x_iio_source::ad936x_iio_source(
|
||||||
std::string pluto_uri_,
|
const std::string& pluto_uri_,
|
||||||
std::string board_type_,
|
const std::string& board_type_,
|
||||||
long long bandwidth_,
|
int64_t bandwidth_,
|
||||||
long long sample_rate_,
|
int64_t sample_rate_,
|
||||||
long long freq_,
|
int64_t freq_,
|
||||||
std::string rf_port_select_,
|
const std::string& rf_port_select_,
|
||||||
std::string rf_filter,
|
const std::string& rf_filter,
|
||||||
std::string gain_mode_rx0_,
|
const std::string& gain_mode_rx0_,
|
||||||
std::string gain_mode_rx1_,
|
const std::string& gain_mode_rx1_,
|
||||||
double rf_gain_rx0_,
|
double rf_gain_rx0_,
|
||||||
double rf_gain_rx1_,
|
double rf_gain_rx1_,
|
||||||
bool enable_ch0,
|
bool enable_ch0,
|
||||||
bool enable_ch1,
|
bool enable_ch1,
|
||||||
long long freq_2ch,
|
int64_t freq_2ch,
|
||||||
bool ppsmode_,
|
bool ppsmode_,
|
||||||
bool customsamplesize_,
|
bool customsamplesize_,
|
||||||
std::string fe_ip_,
|
const std::string& fe_ip_,
|
||||||
int fe_ctlport_,
|
int fe_ctlport_,
|
||||||
int ssize_,
|
int ssize_,
|
||||||
int bshift_,
|
int bshift_,
|
||||||
@ -171,54 +174,81 @@ ad936x_iio_source::ad936x_iio_source(
|
|||||||
case 16:
|
case 16:
|
||||||
{
|
{
|
||||||
std::cout << "FPGA sample size set to 16 bits per sample.\n";
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case 8:
|
case 8:
|
||||||
{
|
{
|
||||||
std::cout << "FPGA sample size set to 8 bits per sample.\n";
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
std::cout << "FPGA sample size set to 4 bits per sample.\n";
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
std::cout << "FPGA sample size set to 2 bits per sample.\n";
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
std::cout << "WARNING: Unsupported ssize. FPGA sample size set to 16 bits per sample.\n";
|
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)
|
if (bshift_ >= 0 and bshift_ <= 14)
|
||||||
{
|
{
|
||||||
std::cout << "FPGA sample bits shift left set to " + std::to_string(bshift_) + " positions.\n";
|
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
|
else
|
||||||
{
|
{
|
||||||
std::cout << "WARNING: Unsupported bshift. FPGA sample bits shift left set to 0.\n";
|
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)
|
if (spattern_ == true)
|
||||||
{
|
{
|
||||||
std::cout << "FPGA debug sample pattern is active!.\n";
|
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
|
else
|
||||||
{
|
{
|
||||||
std::cout << "FPGA debug sample pattern disabled.\n";
|
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
|
else
|
||||||
@ -238,7 +268,7 @@ ad936x_iio_source::ad936x_iio_source(
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception const &ex)
|
catch (std::exception const& ex)
|
||||||
{
|
{
|
||||||
std::cerr << "STD exception: " << ex.what() << std::endl;
|
std::cerr << "STD exception: " << ex.what() << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -267,6 +297,7 @@ ad936x_iio_source::ad936x_iio_source(
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ad936x_iio_source::~ad936x_iio_source()
|
ad936x_iio_source::~ad936x_iio_source()
|
||||||
{
|
{
|
||||||
// Terminate PPS thread
|
// Terminate PPS thread
|
||||||
@ -284,6 +315,7 @@ bool ad936x_iio_source::start()
|
|||||||
return ad936x_custom->start_sample_rx(false);
|
return ad936x_custom->start_sample_rx(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ad936x_iio_source::stop()
|
bool ad936x_iio_source::stop()
|
||||||
{
|
{
|
||||||
std::cout << "stopping ad936x_iio_source...\n";
|
std::cout << "stopping ad936x_iio_source...\n";
|
||||||
@ -291,17 +323,17 @@ bool ad936x_iio_source::stop()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ad936x_iio_source::general_work(int noutput_items,
|
int ad936x_iio_source::general_work(int noutput_items,
|
||||||
__attribute__((unused)) gr_vector_int &ninput_items,
|
__attribute__((unused)) gr_vector_int& ninput_items,
|
||||||
__attribute__((unused)) gr_vector_const_void_star &input_items,
|
__attribute__((unused)) gr_vector_const_void_star& input_items,
|
||||||
gr_vector_void_star &output_items)
|
gr_vector_void_star& output_items)
|
||||||
{
|
{
|
||||||
std::shared_ptr<ad936x_iio_samples> current_buffer;
|
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);
|
ad936x_custom->pop_sample_buffer(current_buffer);
|
||||||
current_samples = current_buffer.get();
|
current_samples = current_buffer.get();
|
||||||
|
|
||||||
|
|
||||||
// I and Q samples are interleaved in buffer: IQIQIQ...
|
// 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);
|
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)
|
if (noutput_items < n_interleaved_iq_samples_per_channel)
|
||||||
@ -312,7 +344,7 @@ int ad936x_iio_source::general_work(int noutput_items,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// ad9361_channel_demux_and_record(current_samples, ad936x_custom->n_channels, &samplesfile);
|
// 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 = 0;
|
||||||
uint32_t current_byte_in_gr = 0;
|
uint32_t current_byte_in_gr = 0;
|
||||||
int16_t ch = 0;
|
int16_t ch = 0;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file ad936x_iio_source.h
|
* \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
|
* \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>;
|
using ad936x_iio_source_sptr = gnss_shared_ptr<ad936x_iio_source>;
|
||||||
|
|
||||||
ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
||||||
std::string pluto_uri_,
|
const std::string &pluto_uri_,
|
||||||
std::string board_type_,
|
const std::string &board_type_,
|
||||||
long long bandwidth_,
|
int64_t bandwidth_,
|
||||||
long long sample_rate_,
|
int64_t sample_rate_,
|
||||||
long long freq_,
|
int64_t freq_,
|
||||||
std::string rf_port_select_,
|
const std::string &rf_port_select_,
|
||||||
std::string rf_filter,
|
const std::string &rf_filter,
|
||||||
std::string gain_mode_rx0_,
|
const std::string &gain_mode_rx0_,
|
||||||
std::string gain_mode_rx1_,
|
const std::string &gain_mode_rx1_,
|
||||||
double rf_gain_rx0_,
|
double rf_gain_rx0_,
|
||||||
double rf_gain_rx1_,
|
double rf_gain_rx1_,
|
||||||
bool enable_ch0,
|
bool enable_ch0,
|
||||||
bool enable_ch1,
|
bool enable_ch1,
|
||||||
long long freq_2ch,
|
int64_t freq_2ch,
|
||||||
bool ppsmode_,
|
bool ppsmode_,
|
||||||
bool customsamplesize_,
|
bool customsamplesize_,
|
||||||
std::string fe_ip_,
|
const std::string &fe_ip_,
|
||||||
int fe_ctlport_,
|
int fe_ctlport_,
|
||||||
int ssize_,
|
int ssize_,
|
||||||
int bshift_,
|
int bshift_,
|
||||||
@ -90,23 +91,23 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
friend ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
||||||
std::string pluto_uri_,
|
const std::string &pluto_uri_,
|
||||||
std::string board_type_,
|
const std::string &board_type_,
|
||||||
long long bandwidth_,
|
int64_t bandwidth_,
|
||||||
long long sample_rate_,
|
int64_t sample_rate_,
|
||||||
long long freq_,
|
int64_t freq_,
|
||||||
std::string rf_port_select_,
|
const std::string &rf_port_select_,
|
||||||
std::string rf_filter,
|
const std::string &rf_filter,
|
||||||
std::string gain_mode_rx0_,
|
const std::string &gain_mode_rx0_,
|
||||||
std::string gain_mode_rx1_,
|
const std::string &gain_mode_rx1_,
|
||||||
double rf_gain_rx0_,
|
double rf_gain_rx0_,
|
||||||
double rf_gain_rx1_,
|
double rf_gain_rx1_,
|
||||||
bool enable_ch0,
|
bool enable_ch0,
|
||||||
bool enable_ch1,
|
bool enable_ch1,
|
||||||
long long freq_2ch,
|
int64_t freq_2ch,
|
||||||
bool ppsmode_,
|
bool ppsmode_,
|
||||||
bool customsamplesize_,
|
bool customsamplesize_,
|
||||||
std::string fe_ip_,
|
const std::string &fe_ip_,
|
||||||
int fe_ctlport_,
|
int fe_ctlport_,
|
||||||
int ssize_,
|
int ssize_,
|
||||||
int bshift_,
|
int bshift_,
|
||||||
@ -116,23 +117,23 @@ private:
|
|||||||
int tx_lo_channel_);
|
int tx_lo_channel_);
|
||||||
|
|
||||||
ad936x_iio_source(
|
ad936x_iio_source(
|
||||||
std::string pluto_uri_,
|
const std::string &pluto_uri_,
|
||||||
std::string board_type_,
|
const std::string &board_type_,
|
||||||
long long bandwidth_,
|
int64_t bandwidth_,
|
||||||
long long sample_rate_,
|
int64_t sample_rate_,
|
||||||
long long freq_,
|
int64_t freq_,
|
||||||
std::string rf_port_select_,
|
const std::string &rf_port_select_,
|
||||||
std::string rf_filter,
|
const std::string &rf_filter,
|
||||||
std::string gain_mode_rx0_,
|
const std::string &gain_mode_rx0_,
|
||||||
std::string gain_mode_rx1_,
|
const std::string &gain_mode_rx1_,
|
||||||
double rf_gain_rx0_,
|
double rf_gain_rx0_,
|
||||||
double rf_gain_rx1_,
|
double rf_gain_rx1_,
|
||||||
bool enable_ch0,
|
bool enable_ch0,
|
||||||
bool enable_ch1,
|
bool enable_ch1,
|
||||||
long long freq_2ch,
|
int64_t freq_2ch,
|
||||||
bool ppsmode_,
|
bool ppsmode_,
|
||||||
bool customsamplesize_,
|
bool customsamplesize_,
|
||||||
std::string fe_ip_,
|
const std::string &fe_ip_,
|
||||||
int fe_ctlport_,
|
int fe_ctlport_,
|
||||||
int ssize_,
|
int ssize_,
|
||||||
int bshift_,
|
int bshift_,
|
||||||
@ -141,7 +142,6 @@ private:
|
|||||||
bool high_side_lo_,
|
bool high_side_lo_,
|
||||||
int tx_lo_channel_);
|
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_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);
|
void ad9361_channel_demux_and_record(ad936x_iio_samples *samples_in, int nchannels, std::vector<std::fstream> *files_out);
|
||||||
|
|
||||||
|
202
src/algorithms/signal_source/gnuradio_blocks/ion_gsms.cc
Normal file
202
src/algorithms/signal_source/gnuradio_blocks/ion_gsms.cc
Normal 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;
|
||||||
|
}
|
74
src/algorithms/signal_source/gnuradio_blocks/ion_gsms.h
Normal file
74
src/algorithms/signal_source/gnuradio_blocks/ion_gsms.h
Normal 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
|
@ -7,14 +7,15 @@
|
|||||||
|
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES "")
|
set(OPT_SIGNAL_SOURCE_LIB_SOURCES "")
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS "")
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS "")
|
||||||
|
|
||||||
if(ENABLE_FMCOMMS2 OR ENABLE_AD9361)
|
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_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()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_MAX2771)
|
if(ENABLE_MAX2771)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_spidev.cc)
|
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()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_FPGA)
|
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)
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_buffer_monitor.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_PLUTOSDR)
|
if(ENABLE_PLUTOSDR OR ENABLE_AD936X_SDR)
|
||||||
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_HEADERS} ad936x_iio_samples.h)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_samples.h)
|
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_custom.cc)
|
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_HEADERS} 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} pps_samplestamp.h)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ppstcprx.cc)
|
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()
|
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
|
set(SIGNAL_SOURCE_LIB_SOURCES
|
||||||
rtl_tcp_commands.cc
|
rtl_tcp_commands.cc
|
||||||
@ -107,7 +113,7 @@ if(GNURADIO_USES_STD_POINTERS)
|
|||||||
)
|
)
|
||||||
endif()
|
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
|
target_link_libraries(signal_source_libs
|
||||||
PUBLIC
|
PUBLIC
|
||||||
Iio::iio
|
Iio::iio
|
||||||
@ -130,6 +136,10 @@ if(ENABLE_FPGA OR ENABLE_AD9361)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_ION)
|
||||||
|
target_link_libraries(signal_source_libs PUBLIC ION::ion algorithms_libs)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_CLANG_TIDY)
|
if(ENABLE_CLANG_TIDY)
|
||||||
if(CLANG_TIDY_EXE)
|
if(CLANG_TIDY_EXE)
|
||||||
set_target_properties(signal_source_libs
|
set_target_properties(signal_source_libs
|
||||||
|
@ -349,7 +349,7 @@ bool config_ad9361_rx_local(uint64_t bandwidth_,
|
|||||||
#ifndef LIBAD9361_VERSION_GREATER_THAN_01
|
#ifndef LIBAD9361_VERSION_GREATER_THAN_01
|
||||||
if (filter_source_ == "Design")
|
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");
|
filter_source_ = std::string("Off");
|
||||||
}
|
}
|
||||||
if (Fpass_ != 0.0 or Fstop_ != 0.0)
|
if (Fpass_ != 0.0 or Fstop_ != 0.0)
|
||||||
@ -636,7 +636,7 @@ bool config_ad9361_rx_remote(const std::string &remote_host,
|
|||||||
{
|
{
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file ad936x_iio_custom.cc
|
* \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
|
* \author Javier Arribas, jarribas(at)cttc.es
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
@ -30,29 +31,36 @@
|
|||||||
#include <absl/log/log.h>
|
#include <absl/log/log.h>
|
||||||
#endif
|
#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()
|
ad936x_iio_custom::~ad936x_iio_custom()
|
||||||
{
|
{
|
||||||
// disable TX
|
// disable TX
|
||||||
if (phy != NULL) PlutoTxEnable(false);
|
if (phy != nullptr)
|
||||||
|
{
|
||||||
|
PlutoTxEnable(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Close device
|
// 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
|
// Find devices
|
||||||
if (pluto_device_uri == "local")
|
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());
|
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;
|
std::cout << "Unable to create context from uri: " << pluto_device_uri << std::endl;
|
||||||
return false;
|
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");
|
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;
|
std::cout << "Unable to find ad9361-phy device from uri: " << pluto_device_uri << std::endl;
|
||||||
return false;
|
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
|
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;
|
std::cout << "Unable to find cf-ad9361-A device from uri: " << pluto_device_uri << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -149,13 +157,13 @@ bool ad936x_iio_custom::initialize_device(std::string pluto_device_uri, std::str
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream_dev = iio_context_find_device(ctx, "cf-ad9361-lpc"); // regular AD9361 stream device in single AD9361 boards
|
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;
|
std::cout << "Unable to find cf-ad9361-lpc device from uri: " << pluto_device_uri << std::endl;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
dds_dev = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); // DDS core for LO oscillator (external transverter operation)
|
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;
|
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,
|
void ad936x_iio_custom::configure_params(struct iio_device *phy,
|
||||||
const std::vector<std::string> ¶ms)
|
const std::vector<std::string> ¶ms)
|
||||||
{
|
{
|
||||||
for (std::vector<std::string>::const_iterator it = params.begin();
|
for (const auto ¶m : params)
|
||||||
it != params.end(); ++it)
|
|
||||||
{
|
{
|
||||||
struct iio_channel *chn = NULL;
|
struct iio_channel *chn = nullptr;
|
||||||
const char *attr = NULL;
|
const char *attr = nullptr;
|
||||||
size_t pos;
|
size_t pos;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pos = it->find('=');
|
pos = param.find('=');
|
||||||
if (pos == std::string::npos)
|
if (pos == std::string::npos)
|
||||||
{
|
{
|
||||||
std::cerr << "Malformed line: " << *it << std::endl;
|
std::cerr << "Malformed line: " << param << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string key = it->substr(0, pos);
|
std::string key = param.substr(0, pos);
|
||||||
std::string val = it->substr(pos + 1, std::string::npos);
|
std::string val = param.substr(pos + 1, std::string::npos);
|
||||||
|
|
||||||
ret = iio_device_identify_filename(phy,
|
ret = iio_device_identify_filename(phy,
|
||||||
key.c_str(), &chn, &attr);
|
key.c_str(), &chn, &attr);
|
||||||
@ -196,13 +203,19 @@ void ad936x_iio_custom::configure_params(struct iio_device *phy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (chn)
|
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))
|
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
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
std::cerr << "Unable to write attribute " << key
|
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 long frequency,
|
||||||
unsigned long samplerate, unsigned long bandwidth,
|
unsigned long samplerate, unsigned long bandwidth,
|
||||||
bool quadrature, bool rfdc, bool bbdc,
|
bool quadrature, bool rfdc, bool bbdc,
|
||||||
std::string gain1, double gain1_value,
|
const std::string &gain1, double gain1_value,
|
||||||
std::string gain2, double gain2_value,
|
const std::string &gain2, double gain2_value,
|
||||||
std::string port_select)
|
const std::string &port_select)
|
||||||
{
|
{
|
||||||
std::vector<std::string> params;
|
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));
|
std::to_string(phase_dds_deg_ * 1000.0));
|
||||||
params_dds.push_back("out_altvoltage0_TX1_I_F1_scale=" +
|
params_dds.push_back("out_altvoltage0_TX1_I_F1_scale=" +
|
||||||
std::to_string(scale_dds_));
|
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)
|
// DDS TX CH1 Q (tone #1)
|
||||||
params_dds.push_back("out_altvoltage2_TX1_Q_F1_frequency=" +
|
params_dds.push_back("out_altvoltage2_TX1_Q_F1_frequency=" +
|
||||||
std::to_string(freq_dds_tx_hz_));
|
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));
|
std::to_string(phase_dds_deg_ * 1000.0 + 270000.0));
|
||||||
params_dds.push_back("out_altvoltage2_TX1_Q_F1_scale=" +
|
params_dds.push_back("out_altvoltage2_TX1_Q_F1_scale=" +
|
||||||
std::to_string(scale_dds_));
|
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);
|
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));
|
std::to_string(phase_dds_deg_ * 1000.0));
|
||||||
params_dds.push_back("out_altvoltage4_TX2_I_F1_scale=" +
|
params_dds.push_back("out_altvoltage4_TX2_I_F1_scale=" +
|
||||||
std::to_string(scale_dds_));
|
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)
|
// DDS TX CH2 Q (tone #1)
|
||||||
params_dds.push_back("out_altvoltage6_TX2_Q_F1_frequency=" +
|
params_dds.push_back("out_altvoltage6_TX2_Q_F1_frequency=" +
|
||||||
std::to_string(freq_dds_tx_hz_));
|
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));
|
std::to_string(phase_dds_deg_ * 1000.0 + 270000.0));
|
||||||
params_dds.push_back("out_altvoltage6_TX2_Q_F1_scale=" +
|
params_dds.push_back("out_altvoltage6_TX2_Q_F1_scale=" +
|
||||||
std::to_string(scale_dds_));
|
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);
|
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()
|
bool ad936x_iio_custom::check_device()
|
||||||
{
|
{
|
||||||
if (stream_dev != NULL)
|
if (stream_dev != nullptr)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -350,8 +363,8 @@ bool ad936x_iio_custom::check_device()
|
|||||||
|
|
||||||
bool ad936x_iio_custom::get_iio_param(iio_device *dev, const std::string ¶m, std::string &value)
|
bool ad936x_iio_custom::get_iio_param(iio_device *dev, const std::string ¶m, std::string &value)
|
||||||
{
|
{
|
||||||
struct iio_channel *chn = 0;
|
struct iio_channel *chn = nullptr;
|
||||||
const char *attr = 0;
|
const char *attr = nullptr;
|
||||||
char valuestr[256];
|
char valuestr[256];
|
||||||
int ret;
|
int ret;
|
||||||
ssize_t nchars;
|
ssize_t nchars;
|
||||||
@ -398,9 +411,12 @@ bool ad936x_iio_custom::read_die_temp(double &temp_c)
|
|||||||
{
|
{
|
||||||
try
|
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;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const boost::bad_lexical_cast &e)
|
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_,
|
bool ad936x_iio_custom::init_config_ad9361_rx(long long bandwidth_,
|
||||||
long long sample_rate_,
|
long long sample_rate_,
|
||||||
long long freq_,
|
long long freq_,
|
||||||
std::string rf_port_select_,
|
const std::string &rf_port_select_,
|
||||||
std::string rf_filter,
|
const std::string &rf_filter,
|
||||||
std::string gain_mode_rx0_,
|
const std::string &gain_mode_rx0_,
|
||||||
std::string gain_mode_rx1_,
|
const std::string &gain_mode_rx1_,
|
||||||
double rf_gain_rx0_,
|
double rf_gain_rx0_,
|
||||||
double rf_gain_rx1_,
|
double rf_gain_rx1_,
|
||||||
bool enable_ch0,
|
bool enable_ch0,
|
||||||
@ -432,16 +448,19 @@ bool ad936x_iio_custom::init_config_ad9361_rx(long long bandwidth_,
|
|||||||
bool high_side_lo_,
|
bool high_side_lo_,
|
||||||
int tx_lo_channel_)
|
int tx_lo_channel_)
|
||||||
{
|
{
|
||||||
if (check_device() == false) return false;
|
if (check_device() == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool no_errors = true;
|
bool no_errors = true;
|
||||||
std::cout << "Configuring phy device parameters...\n";
|
std::cout << "Configuring phy device parameters...\n";
|
||||||
int ret;
|
int ret;
|
||||||
if (rf_filter.compare("Disabled") == 0)
|
if (rf_filter == "Disabled")
|
||||||
{
|
{
|
||||||
std::cout << "LNA Filter switch is disabled.\n";
|
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";
|
std::cout << "Selecting LNA RF filter based on the selected RF frequency... \n";
|
||||||
if (freq_ == 1575420000)
|
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=" +
|
params.push_back("out_voltage_rf_bandwidth=" +
|
||||||
std::to_string(bandwidth_));
|
std::to_string(bandwidth_));
|
||||||
|
|
||||||
params.push_back("in_voltage_quadrature_tracking_en=1");
|
params.emplace_back("in_voltage_quadrature_tracking_en=1");
|
||||||
params.push_back("in_voltage_rf_dc_offset_tracking_en=1");
|
params.emplace_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_bb_dc_offset_tracking_en=1");
|
||||||
|
|
||||||
configure_params(phy, params);
|
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)
|
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)
|
// Configure RX LO channel (NOTICE that altvoltage0 is the RX LO oscillator!, altvoltage1 is the TX oscillator)
|
||||||
struct iio_channel *lo_ch;
|
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)
|
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)
|
// Configure RX LO channel (NOTICE that altvoltage0 is the RX LO oscillator!, altvoltage1 is the TX oscillator)
|
||||||
struct iio_channel *lo_ch;
|
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;
|
std::vector<std::string> params;
|
||||||
if (ch_num == 0)
|
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)
|
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
|
double gain_dB; // gain in dB
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (ch_num == 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)
|
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
|
// todo
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -864,12 +898,13 @@ void ad936x_iio_custom::monitor_thread_fn()
|
|||||||
{
|
{
|
||||||
ret = iio_device_reg_write(stream_dev, 0x80000088, val);
|
ret = iio_device_reg_write(stream_dev, 0x80000088, val);
|
||||||
if (ret)
|
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);
|
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 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
|
// 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
|
// 1 Enable
|
||||||
// X Enable Mask if Identifier=0xF
|
// X Enable Mask if Identifier=0xF
|
||||||
|
|
||||||
if (check_device() == false) return false;
|
if (check_device() == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// int plutoGpo = 0;
|
// int plutoGpo = 0;
|
||||||
int ret;
|
int ret;
|
||||||
ret = iio_device_debug_attr_write(phy, "adi,gpo-manual-mode-enable", "1");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rf_filter.compare("E1") == 0)
|
if (rf_filter == "E1")
|
||||||
{
|
{
|
||||||
// set gpio0 to switch L1 filter
|
// set gpio0 to switch L1 filter
|
||||||
// setPlutoGpo(plutoGpo);
|
// setPlutoGpo(plutoGpo);
|
||||||
@ -982,7 +1020,7 @@ bool ad936x_iio_custom::select_rf_filter(std::string rf_filter)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rf_filter.compare("E5E6") == 0)
|
else if (rf_filter == "E5E6")
|
||||||
{
|
{
|
||||||
// set gpio0 to switch L5/L6 filter (GPO0)
|
// set gpio0 to switch L5/L6 filter (GPO0)
|
||||||
// plutoGpo = plutoGpo | 0x10;
|
// plutoGpo = plutoGpo | 0x10;
|
||||||
@ -994,7 +1032,7 @@ bool ad936x_iio_custom::select_rf_filter(std::string rf_filter)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rf_filter.compare("none") == 0)
|
if (rf_filter == "none")
|
||||||
{
|
{
|
||||||
std::cout << "RF external filter not selected\n";
|
std::cout << "RF external filter not selected\n";
|
||||||
}
|
}
|
||||||
@ -1107,18 +1145,18 @@ bool ad936x_iio_custom::start_sample_rx(bool ppsmode)
|
|||||||
switch (n_channels)
|
switch (n_channels)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
channels.push_back("voltage0"); // Channel 0 I
|
channels.emplace_back("voltage0"); // Channel 0 I
|
||||||
channels.push_back("voltage1"); // Channel 0 Q
|
channels.emplace_back("voltage1"); // Channel 0 Q
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
channels.push_back("voltage0"); // Channel 0 I
|
channels.emplace_back("voltage0"); // Channel 0 I
|
||||||
channels.push_back("voltage1"); // Channel 0 Q
|
channels.emplace_back("voltage1"); // Channel 0 Q
|
||||||
channels.push_back("voltage2"); // Channel 1 I
|
channels.emplace_back("voltage2"); // Channel 1 I
|
||||||
channels.push_back("voltage3"); // Channel 1 Q
|
channels.emplace_back("voltage3"); // Channel 1 Q
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
channels.push_back("voltage0"); // Channel 0 I
|
channels.emplace_back("voltage0"); // Channel 0 I
|
||||||
channels.push_back("voltage1"); // Channel 0 Q
|
channels.emplace_back("voltage1"); // Channel 0 Q
|
||||||
}
|
}
|
||||||
|
|
||||||
receive_samples = true;
|
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)
|
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;
|
struct iio_buffer *rxbuf;
|
||||||
|
|
||||||
@ -1178,16 +1219,14 @@ void ad936x_iio_custom::capture(const std::vector<std::string> &channels)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (std::vector<std::string>::const_iterator it =
|
for (const auto &channel : channels)
|
||||||
channels.begin();
|
|
||||||
it != channels.end(); ++it)
|
|
||||||
{
|
{
|
||||||
struct iio_channel *chn =
|
struct iio_channel *chn =
|
||||||
iio_device_find_channel(stream_dev,
|
iio_device_find_channel(stream_dev,
|
||||||
it->c_str(), false);
|
channel.c_str(), false);
|
||||||
if (!chn)
|
if (!chn)
|
||||||
{
|
{
|
||||||
std::cerr << "Channel " << it->c_str() << " not found\n";
|
std::cerr << "Channel " << channel.c_str() << " not found\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
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;
|
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_channels = n_channels;
|
||||||
current_samples->n_interleaved_iq_samples = items_in_buffer;
|
current_samples->n_interleaved_iq_samples = items_in_buffer;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file ad936x_iio_custom.h
|
* \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
|
* \author Javier Arribas, jarribas(at)cttc.es
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
@ -14,41 +15,41 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef SRC_LIBS_ad936x_iio_custom_H_
|
#ifndef GNSS_SDR_AD936X_IIO_CUSTOM_H
|
||||||
#define SRC_LIBS_ad936x_iio_custom_H_
|
#define GNSS_SDR_AD936X_IIO_CUSTOM_H
|
||||||
|
|
||||||
|
#include "ad936x_iio_samples.h"
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_time.h"
|
#include "gnss_time.h"
|
||||||
#include "pps_samplestamp.h"
|
#include "pps_samplestamp.h"
|
||||||
#include <boost/atomic.hpp>
|
#include <boost/atomic.hpp>
|
||||||
|
#include <iio.h>
|
||||||
|
#include <ad9361.h> // multichip sync and high level functions
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#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 <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
/** \addtogroup Signal_Source
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Signal_Source_libs
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
|
||||||
class ad936x_iio_custom
|
class ad936x_iio_custom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ad936x_iio_custom(int debug_level_, int log_level_);
|
ad936x_iio_custom(int debug_level_, int log_level_);
|
||||||
virtual ~ad936x_iio_custom();
|
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_,
|
bool init_config_ad9361_rx(long long bandwidth_,
|
||||||
long long sample_rate_,
|
long long sample_rate_,
|
||||||
long long freq_,
|
long long freq_,
|
||||||
std::string rf_port_select_,
|
const std::string &rf_port_select_,
|
||||||
std::string rf_filter,
|
const std::string &rf_filter,
|
||||||
std::string gain_mode_rx0_,
|
const std::string &gain_mode_rx0_,
|
||||||
std::string gain_mode_rx1_,
|
const std::string &gain_mode_rx1_,
|
||||||
double rf_gain_rx0_,
|
double rf_gain_rx0_,
|
||||||
double rf_gain_rx1_,
|
double rf_gain_rx1_,
|
||||||
bool enable_ch0,
|
bool enable_ch0,
|
||||||
@ -61,7 +62,7 @@ public:
|
|||||||
bool calibrate(int ch, double bw_hz);
|
bool calibrate(int ch, double bw_hz);
|
||||||
|
|
||||||
double get_rx_gain(int ch_num);
|
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);
|
bool set_antenna_port(int ch, int antenna_idx);
|
||||||
double get_frequency(int ch);
|
double get_frequency(int ch);
|
||||||
@ -93,9 +94,9 @@ private:
|
|||||||
unsigned long long frequency,
|
unsigned long long frequency,
|
||||||
unsigned long samplerate, unsigned long bandwidth,
|
unsigned long samplerate, unsigned long bandwidth,
|
||||||
bool quadrature, bool rfdc, bool bbdc,
|
bool quadrature, bool rfdc, bool bbdc,
|
||||||
std::string gain1, double gain1_value,
|
const std::string &gain1, double gain1_value,
|
||||||
std::string gain2, double gain2_value,
|
const std::string &gain2, double gain2_value,
|
||||||
std::string port_select);
|
const std::string &port_select);
|
||||||
|
|
||||||
bool config_ad9361_dds(uint64_t freq_rf_tx_hz_,
|
bool config_ad9361_dds(uint64_t freq_rf_tx_hz_,
|
||||||
double tx_attenuation_db_,
|
double tx_attenuation_db_,
|
||||||
@ -107,7 +108,7 @@ private:
|
|||||||
void get_PPS_timestamp();
|
void get_PPS_timestamp();
|
||||||
void capture(const std::vector<std::string> &channels);
|
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();
|
void monitor_thread_fn();
|
||||||
|
|
||||||
@ -120,15 +121,6 @@ private:
|
|||||||
struct iio_device *stream_dev;
|
struct iio_device *stream_dev;
|
||||||
struct iio_device *dds_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::mutex mtx;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
|
|
||||||
@ -142,6 +134,14 @@ private:
|
|||||||
std::thread capture_samples_thread;
|
std::thread capture_samples_thread;
|
||||||
std::thread overflow_monitor_thread;
|
std::thread overflow_monitor_thread;
|
||||||
std::thread capture_time_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
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -15,26 +15,32 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef SRC_LIBS_ad936x_iio_samples_H_
|
#ifndef GNSS_SDR_AD936X_IIO_SAMPLES_H
|
||||||
#define SRC_LIBS_ad936x_iio_samples_H_
|
#define GNSS_SDR_AD936X_IIO_SAMPLES_H
|
||||||
|
|
||||||
#define IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES 32768 * 4
|
#define IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES 32768 * 4
|
||||||
|
|
||||||
#define IIO_INPUTRAMFIFOSIZE 256
|
#define IIO_INPUTRAMFIFOSIZE 256
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdint.h>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
/** \addtogroup Signal_Source
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Signal_Source_libs
|
||||||
|
* \{ */
|
||||||
|
|
||||||
class ad936x_iio_samples
|
class ad936x_iio_samples
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ad936x_iio_samples();
|
ad936x_iio_samples() = default;
|
||||||
uint32_t n_bytes;
|
uint32_t n_bytes{0};
|
||||||
uint32_t n_interleaved_iq_samples;
|
uint32_t n_interleaved_iq_samples{0};
|
||||||
uint16_t n_channels;
|
uint16_t n_channels{0};
|
||||||
uint16_t step_bytes;
|
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)
|
char buffer[IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES * 4 * 4]; // max 16 bits samples per buffer (4 channels, 2-bytes per I + 2-bytes per Q)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
/** \} */
|
||||||
#endif
|
#endif
|
||||||
|
271
src/algorithms/signal_source/libs/ion_gsms_chunk_data.cc
Normal file
271
src/algorithms/signal_source/libs/ion_gsms_chunk_data.cc
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
188
src/algorithms/signal_source/libs/ion_gsms_chunk_data.h
Normal file
188
src/algorithms/signal_source/libs/ion_gsms_chunk_data.h
Normal 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
|
184
src/algorithms/signal_source/libs/ion_gsms_chunk_unpacking_ctx.h
Normal file
184
src/algorithms/signal_source/libs/ion_gsms_chunk_unpacking_ctx.h
Normal 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
|
170
src/algorithms/signal_source/libs/ion_gsms_stream_encodings.h
Normal file
170
src/algorithms/signal_source/libs/ion_gsms_stream_encodings.h
Normal 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
|
@ -20,19 +20,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#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)
|
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)
|
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
|
// create a message buffer
|
||||||
char buf[1500];
|
char buf[1500];
|
||||||
@ -117,7 +104,7 @@ void pps_tcp_rx::receive_pps(std::string ip_address, int port)
|
|||||||
{
|
{
|
||||||
try
|
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)
|
catch (const std::exception &ex)
|
||||||
{
|
{
|
||||||
@ -133,7 +120,7 @@ void pps_tcp_rx::receive_pps(std::string ip_address, int port)
|
|||||||
{
|
{
|
||||||
try
|
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)
|
catch (const std::exception &ex)
|
||||||
{
|
{
|
||||||
@ -155,7 +142,9 @@ void pps_tcp_rx::receive_pps(std::string ip_address, int port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
new_pps_line += c;
|
{
|
||||||
|
new_pps_line += c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -28,15 +28,15 @@ class pps_tcp_rx
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> Pps_queue;
|
std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> Pps_queue;
|
||||||
int clientSd;
|
int clientSd{-1};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
volatile bool is_connected;
|
volatile bool is_connected{false};
|
||||||
pps_tcp_rx();
|
pps_tcp_rx() = default;
|
||||||
virtual ~pps_tcp_rx();
|
virtual ~pps_tcp_rx() = default;
|
||||||
|
|
||||||
void receive_pps(std::string ip_address, int port);
|
void receive_pps(const std::string& ip_address, int port);
|
||||||
bool send_cmd(std::string cmd);
|
bool send_cmd(std::string cmd) const;
|
||||||
|
|
||||||
void set_pps_samplestamp_queue(std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> queue);
|
void set_pps_samplestamp_queue(std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> queue);
|
||||||
};
|
};
|
||||||
|
@ -70,6 +70,10 @@ if(ENABLE_FPGA)
|
|||||||
target_compile_definitions(core_receiver PUBLIC -DENABLE_FPGA=1)
|
target_compile_definitions(core_receiver PUBLIC -DENABLE_FPGA=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_ION)
|
||||||
|
target_compile_definitions(core_receiver PRIVATE -DENABLE_ION_SOURCE=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(GNURADIO_USES_STD_POINTERS)
|
if(GNURADIO_USES_STD_POINTERS)
|
||||||
target_compile_definitions(core_receiver PUBLIC -DGNURADIO_USES_STD_POINTERS=1)
|
target_compile_definitions(core_receiver PUBLIC -DGNURADIO_USES_STD_POINTERS=1)
|
||||||
endif()
|
endif()
|
||||||
@ -90,6 +94,10 @@ if(ENABLE_PLUTOSDR)
|
|||||||
target_compile_definitions(core_receiver PRIVATE -DPLUTOSDR_DRIVER=1)
|
target_compile_definitions(core_receiver PRIVATE -DPLUTOSDR_DRIVER=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_AD936X_SDR)
|
||||||
|
target_compile_definitions(core_receiver PRIVATE -DAD936X_SDR_DRIVER=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_FMCOMMS2)
|
if(ENABLE_FMCOMMS2)
|
||||||
target_compile_definitions(core_receiver PRIVATE -DFMCOMMS2_DRIVER=1)
|
target_compile_definitions(core_receiver PRIVATE -DFMCOMMS2_DRIVER=1)
|
||||||
endif()
|
endif()
|
||||||
|
@ -163,6 +163,10 @@
|
|||||||
#include "plutosdr_signal_source.h"
|
#include "plutosdr_signal_source.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if AD936X_SDR_DRIVER
|
||||||
|
#include "ad936x_custom_signal_source.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FMCOMMS2_DRIVER
|
#if FMCOMMS2_DRIVER
|
||||||
#include "fmcomms2_signal_source.h"
|
#include "fmcomms2_signal_source.h"
|
||||||
#endif
|
#endif
|
||||||
@ -196,6 +200,11 @@
|
|||||||
#include "gps_l1_ca_dll_pll_tracking_gpu.h"
|
#include "gps_l1_ca_dll_pll_tracking_gpu.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_ION_SOURCE
|
||||||
|
#undef Owner
|
||||||
|
#include "ion_gsms_signal_source.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std::string_literals;
|
using namespace std::string_literals;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -759,7 +768,14 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
|||||||
block = std::move(block_);
|
block = std::move(block_);
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#if RAW_ARRAY_DRIVER
|
||||||
else if (implementation == "Raw_Array_Signal_Source")
|
else if (implementation == "Raw_Array_Signal_Source")
|
||||||
{
|
{
|
||||||
@ -795,6 +811,8 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
|||||||
out_streams, queue);
|
out_streams, queue);
|
||||||
block = std::move(block_);
|
block = std::move(block_);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if PLUTOSDR_DRIVER || AD936X_SDR_DRIVER
|
||||||
else if (implementation == "Ad936x_Custom_Signal_Source")
|
else if (implementation == "Ad936x_Custom_Signal_Source")
|
||||||
{
|
{
|
||||||
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<Ad936xCustomSignalSource>(configuration, role, in_streams,
|
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<Ad936xCustomSignalSource>(configuration, role, in_streams,
|
||||||
|
Loading…
Reference in New Issue
Block a user