Merge branch 'MrCry0-feat/support-bladerf' into next

This commit is contained in:
Carles Fernandez
2026-08-27 11:43:47 +02:00
16 changed files with 1246 additions and 2 deletions
+1
View File
@@ -71,6 +71,7 @@ Marcus Alagar mvala079@gmail.com Contributor
Mathieu Favreau favreau.mathieu@hotmail.com Contributor
Miguel Gómez López mgomezl@ing.uc3m.es Contributor
Minhaj Uddin Ahmad mahmad12@crimson.ua.edu Contributor
Oleksandr Suvorov github@say.od.ua Contributor
Pedro Pereira pereirapedrocp@gmail.com Contributor
Piyush Gupta piyush04111999@gmail.com Contributor
Rodrigo Muñoz rodrigo.munoz@proteinlab.cl Contributor
+4
View File
@@ -137,6 +137,10 @@ authors:
email: wsilberm@google.com
family-names: Silberman
given-names: Will
- alias: MrCry0
email: github@say.od.ua
family-names: Suvorov
given-names: Oleksandr
- email: tonetto.dev@gmail.com
family-names: Tonetto
given-names: Leonardo
+32
View File
@@ -71,6 +71,8 @@ option(ENABLE_OSMOSDR "Enable the use of OsmoSDR and other front-ends (RTL-based
option(ENABLE_LIMESDR "Enable the use of LimeSDR and Custom LimeSDR as signal source" OFF)
option(ENABLE_BLADERF "Enable the use of bladeRF front-ends as signal source, requires libbladeRF" OFF)
option(ENABLE_POCKETSDR "Enable the use of Pocket SDR FE front-ends as signal source, requires gr-pocketsdr" OFF)
option(ENABLE_FMCOMMS2 "Enable the use of FMCOMMS4-EBZ + ZedBoard hardware, requires gr-iio" OFF)
@@ -387,6 +389,7 @@ set(GNSSSDR_CLANG_MIN_VERSION "3.4.0")
set(GNSSSDR_GCC_MIN_VERSION "4.7.2")
set(GNSSSDR_GFLAGS_MIN_VERSION "2.1.2")
set(GNSSSDR_GNURADIO_MIN_VERSION "3.7.3")
set(GNSSSDR_LIBBLADERF_MIN_VERSION "2.6.0")
set(GNSSSDR_MAKO_MIN_VERSION "0.4.2")
set(GNSSSDR_MATIO_MIN_VERSION "1.5.3")
set(GNSSSDR_PROTOBUF_MIN_VERSION "3.0.0")
@@ -2893,6 +2896,34 @@ endif()
##########################################
# libbladeRF - OPTIONAL
# https://github.com/Nuand/bladeRF
##########################################
find_package(LIBBLADERF)
set_package_properties(LIBBLADERF PROPERTIES
PURPOSE "Used for communication with bladeRF front-ends."
TYPE OPTIONAL
)
if(ENABLE_BLADERF)
if(LIBBLADERF_FOUND)
message(STATUS "The driver for bladeRF will be compiled.")
message(STATUS " You can disable it with 'cmake -DENABLE_BLADERF=OFF ..'")
else()
if(ENABLE_PACKAGING)
message(WARNING "libbladeRF has not been found. Source blocks depending on it will NOT be built.")
else()
message(FATAL_ERROR "libbladeRF required to build gnss-sdr with the optional BLADERF driver")
endif()
set(ENABLE_BLADERF OFF)
endif()
else()
message(STATUS "The (optional) driver for bladeRF is not enabled.")
message(STATUS " Enable it with 'cmake -DENABLE_BLADERF=ON ..' to add support for bladeRF.")
endif()
################################################
# gr-pocketsdr - OPTIONAL
# https://github.com/minhaj6/gr-pocketsdr
@@ -3371,6 +3402,7 @@ add_subdirectory(utils)
add_feature_info(ENABLE_UHD ENABLE_UHD "Enables UHD_Signal_Source for using RF front-ends from the USRP family. Requires gr-uhd.")
add_feature_info(ENABLE_OSMOSDR ENABLE_OSMOSDR "Enables Osmosdr_Signal_Source and RtlTcp_Signal_Source for using RF front-ends compatible with the OsmoSDR driver. Requires gr-osmosdr.")
add_feature_info(ENABLE_LIMESDR ENABLE_LIMESDR "Enables Limesdr_Signal_Source. Requires gr-limesdr.")
add_feature_info(ENABLE_BLADERF ENABLE_BLADERF "Enables Bladerf_Signal_Source. Requires libbladeRF.")
add_feature_info(ENABLE_POCKETSDR ENABLE_POCKETSDR "Enables Pocket_SDR_Signal_Source. Requires gr-pocketsdr.")
add_feature_info(ENABLE_FMCOMMS2 ENABLE_FMCOMMS2 "Enables Fmcomms2_Signal_Source for FMCOMMS2/3/4 devices. Requires libiio, libad9361-dev, and gr-iio.")
add_feature_info(ENABLE_PLUTOSDR ENABLE_PLUTOSDR "Enables Plutosdr_Signal_Source and Ad936x_Custom_Signal_Source for using ADALM-PLUTO boards. Requires libiio, libad9361-dev, and gr-iio.")
+32 -2
View File
@@ -171,7 +171,7 @@ dependencies with:
```
$ sudo apt install build-essential cmake git gnuradio-dev gr-limesdr gr-osmosdr \
libabsl-dev libad9361-dev libarmadillo-dev libblas-dev \
libabsl-dev libad9361-dev libarmadillo-dev libbladerf-dev libblas-dev \
libboost-chrono-dev libboost-date-time-dev libboost-dev \
libboost-filesystem-dev libboost-serialization-dev libboost-thread-dev \
libcpu-features-dev libgtest-dev libiio-dev liblapack-dev libmatio-dev \
@@ -183,7 +183,7 @@ On older versions:
```
$ sudo apt install build-essential cmake git gnuradio-dev gr-limesdr gr-osmosdr \
libad9361-dev libarmadillo-dev libblas-dev \
libad9361-dev libarmadillo-dev libbladerf-dev libblas-dev \
libboost-chrono-dev libboost-date-time-dev libboost-dev \
libboost-filesystem-dev libboost-serialization-dev libboost-system-dev \
libboost-thread-dev \
@@ -609,6 +609,36 @@ $ sudo cmake --install build
(in order to disable the `Osmosdr_Signal_Source` compilation, you can pass
`-DENABLE_OSMOSDR=OFF` to cmake and build GNSS-SDR again).
#### Build BladeRF support (OPTIONAL)
GNSS-SDR can talk to Nuand's [bladeRF](https://www.nuand.com/) front-ends
(bladeRF x40, x115, and bladeRF 2.0 Micro xA4/xA9) directly through
`libbladeRF`, without going through OsmoSDR. This requires `libbladeRF` v2.6.0
or newer (needed for reliable bladeRF 2.0 Micro support); older packaged
versions (e.g., the one currently in Ubuntu's `universe` repository) are
rejected at `cmake` configuration time with a message asking you to upgrade.
Install the library and headers (e.g., on Debian / Ubuntu,
`sudo apt install libbladerf-dev`, then check its version with
`pkg-config --modversion libbladeRF`; if it is older than 2.6.0, build
`libbladeRF` from source instead -- see
[Nuand's bladeRF repository](https://github.com/Nuand/bladeRF)), then configure
GNSS-SDR to build the `Bladerf_Signal_Source` by:
```
$ cmake -S . -B build -DENABLE_BLADERF=ON
$ cmake --build build
$ sudo cmake --install build
```
(in order to disable the `Bladerf_Signal_Source` compilation, you can pass
`-DENABLE_BLADERF=OFF` to cmake and build GNSS-SDR again). A sample
configuration file is provided at
[conf/RealTime_input/gnss-sdr_GPS_L1_bladeRF_native.conf](./conf/RealTime_input/gnss-sdr_GPS_L1_bladeRF_native.conf).
Note that, unlike the `Osmosdr_Signal_Source` path, `libbladeRF` exposes a
single overall RX gain instead of separate LNA / VGA1 / VGA2 stages, and only
single-channel (SISO) reception is currently supported (bladeRF 2.0 Micro xA9's
second RX channel is not yet exposed).
#### Build FMCOMMS2 based SDR Hardware support (OPTIONAL)
Install the [libiio](https://github.com/analogdevicesinc/libiio.git) (>=v0.11),
+115
View File
@@ -0,0 +1,115 @@
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR.
#
# SPDX-FileCopyrightText: 2011-2026 C. Fernandez-Prades cfernandez(at)cttc.es
# SPDX-License-Identifier: BSD-3-Clause
# Tries to find libbladeRF.
#
# Usage of this module as follows:
#
# find_package(LIBBLADERF)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# LIBBLADERF_ROOT Set this variable to the root installation of
# libbladeRF if the module has problems finding
# the proper installation path.
#
# Variables defined by this module:
#
# LIBBLADERF_FOUND System has libbladeRF libs/headers
# LIBBLADERF_LIBRARIES The libbladeRF libraries (bladeRF)
# LIBBLADERF_INCLUDE_DIRS The location of libbladeRF headers
#
# Provides the following imported target:
# Bladerf::bladerf
#
if(NOT COMMAND feature_summary)
include(FeatureSummary)
endif()
if(NOT PKG_CONFIG_FOUND)
include(FindPkgConfig)
endif()
if(NOT DEFINED GNSSSDR_LIB_PATHS)
include(GnsssdrFindPaths)
endif()
pkg_check_modules(PC_LIBBLADERF libbladeRF)
if(NOT LIBBLADERF_ROOT)
set(LIBBLADERF_ROOT_USER_DEFINED /usr)
else()
set(LIBBLADERF_ROOT_USER_DEFINED ${LIBBLADERF_ROOT})
endif()
if(DEFINED ENV{LIBBLADERF_ROOT})
set(LIBBLADERF_ROOT_USER_DEFINED
${LIBBLADERF_ROOT_USER_DEFINED}
$ENV{LIBBLADERF_ROOT}
)
endif()
set(LIBBLADERF_ROOT_USER_DEFINED
${LIBBLADERF_ROOT_USER_DEFINED}
${CMAKE_INSTALL_PREFIX}
)
find_path(LIBBLADERF_INCLUDE_DIRS
NAMES libbladeRF.h
HINTS ${PC_LIBBLADERF_INCLUDEDIR}
PATHS ${LIBBLADERF_ROOT_USER_DEFINED}/include
${GNSSSDR_INCLUDE_PATHS}
)
find_library(LIBBLADERF_LIBRARIES
NAMES bladeRF
HINTS ${PC_LIBBLADERF_LIBDIR}
PATHS ${LIBBLADERF_ROOT_USER_DEFINED}/lib
${LIBBLADERF_ROOT_USER_DEFINED}/lib64
${GNSSSDR_LIB_PATHS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LIBBLADERF DEFAULT_MSG LIBBLADERF_LIBRARIES LIBBLADERF_INCLUDE_DIRS)
if(PC_LIBBLADERF_VERSION)
set(LIBBLADERF_VERSION ${PC_LIBBLADERF_VERSION})
endif()
if(LIBBLADERF_FOUND AND LIBBLADERF_VERSION AND DEFINED GNSSSDR_LIBBLADERF_MIN_VERSION)
if(LIBBLADERF_VERSION VERSION_LESS GNSSSDR_LIBBLADERF_MIN_VERSION)
message(STATUS "libbladeRF v${LIBBLADERF_VERSION} was found, but GNSS-SDR requires at least v${GNSSSDR_LIBBLADERF_MIN_VERSION}. Please upgrade libbladeRF: https://github.com/Nuand/bladeRF")
set(LIBBLADERF_FOUND FALSE)
unset(LIBBLADERF_LIBRARIES CACHE)
unset(LIBBLADERF_INCLUDE_DIRS CACHE)
endif()
endif()
if(LIBBLADERF_FOUND AND LIBBLADERF_VERSION)
set_package_properties(LIBBLADERF PROPERTIES
DESCRIPTION "Nuand bladeRF library (found: v${LIBBLADERF_VERSION})"
)
else()
set_package_properties(LIBBLADERF PROPERTIES
DESCRIPTION "Nuand bladeRF library"
)
endif()
set_package_properties(LIBBLADERF PROPERTIES
URL "https://github.com/Nuand/bladeRF"
)
if(LIBBLADERF_FOUND AND NOT TARGET Bladerf::bladerf)
add_library(Bladerf::bladerf SHARED IMPORTED)
set_target_properties(Bladerf::bladerf PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
IMPORTED_LOCATION "${LIBBLADERF_LIBRARIES}"
INTERFACE_INCLUDE_DIRECTORIES "${LIBBLADERF_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${LIBBLADERF_LIBRARIES}"
)
endif()
mark_as_advanced(LIBBLADERF_LIBRARIES LIBBLADERF_INCLUDE_DIRS)
@@ -0,0 +1,113 @@
; This is a GNSS-SDR configuration file
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
; SPDX-License-Identifier: GPL-3.0-or-later
; SPDX-FileCopyrightText: (C) 2010-2026 (see AUTHORS file for a list of contributors)
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=2000000
;######### SIGNAL_SOURCE CONFIG ############
; Native libbladeRF signal source (requires the -DENABLE_BLADERF=ON building
; flag). Works with bladeRF x40, x115, and bladeRF 2.0 Micro xA4/xA9 (single
; RX channel). Unlike the Osmosdr_Signal_Source path (see
; gnss-sdr_GPS_L1_bladeRF.conf), libbladeRF exposes a single overall RX gain
; instead of separate LNA/VGA1/VGA2 stages.
SignalSource.implementation=Bladerf_Signal_Source
SignalSource.item_type=gr_complex
SignalSource.sampling_frequency=2000000
SignalSource.freq=1575420000
SignalSource.bandwidth=2000000
SignalSource.gain=40
SignalSource.AGC_enabled=false
; Enable to power an active GNSS antenna from the RX bias tee (bladeRF 2.0
; Micro only; ignored with a warning on bladeRF1 boards).
SignalSource.rx_bias_tee=false
; Leave empty to open the first bladeRF found, or set a specific unit's
; serial number here.
SignalSource.device_serial=
SignalSource.samples=0
SignalSource.dump=false
SignalSource.dump_filename=./signal_source.dat
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Signal_Conditioner
;######### DATA_TYPE_ADAPTER CONFIG ############
DataTypeAdapter.implementation=Pass_Through
;######### INPUT_FILTER CONFIG ############
InputFilter.implementation=Freq_Xlating_Fir_Filter
InputFilter.decimation_factor=1
InputFilter.input_item_type=gr_complex
InputFilter.output_item_type=gr_complex
InputFilter.taps_item_type=float
InputFilter.number_of_taps=5
InputFilter.number_of_bands=2
InputFilter.band1_begin=0.0
InputFilter.band1_end=0.85
InputFilter.band2_begin=0.9
InputFilter.band2_end=1.0
InputFilter.ampl1_begin=1.0
InputFilter.ampl1_end=1.0
InputFilter.ampl2_begin=0.0
InputFilter.ampl2_end=0.0
InputFilter.band1_error=1.0
InputFilter.band2_error=1.0
InputFilter.filter_type=bandpass
InputFilter.grid_density=16
InputFilter.dump=false
InputFilter.dump_filename=./input_filter.dat
;######### RESAMPLER CONFIG ############
Resampler.implementation=Pass_Through
;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=8
Channels.in_acquisition=1
Channel.signal=1C
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.coherent_integration_time_ms=1
Acquisition_1C.threshold=2.5
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=500
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat
;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.pll_bw_hz=40.0;
Tracking_1C.dll_bw_hz=2.0;
Tracking_1C.order=3;
Tracking_1C.early_late_space_chips=0.5;
Tracking_1C.dump=false
Tracking_1C.dump_filename=./tracking_ch_
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.iono_model=Broadcast
PVT.trop_model=Saastamoinen
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.rtcm_tcp_port=2101
PVT.rtcm_MT1019_rate_ms=5000
PVT.rtcm_MT1077_rate_ms=1000
PVT.rinex_version=2
@@ -0,0 +1,254 @@
; This is a GNSS-SDR configuration file
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
; SPDX-License-Identifier: GPL-3.0-or-later
; SPDX-FileCopyrightText: (C) 2010-2026 (see AUTHORS file for a list of contributors)
; You can define your own receiver and invoke it by doing
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf
;
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=8000000
GNSS-SDR.Beidou_banned_prns=56,57,58
;######### SIGNAL_SOURCE CONFIG ############
; Native libbladeRF signal source (requires the -DENABLE_BLADERF=ON building
; flag and libbladeRF v2.6.0+; see gnss-sdr_GPS_L1_bladeRF_native.conf).
; One wideband capture centered between the BeiDou B1I band (1561.098 MHz)
; and the GLONASS L1 band (~1602 MHz) is split, below, into three sub-bands
; by three parallel Freq_Xlating_Fir_Filter chains tapping the same physical
; bladeRF stream (SignalSource.RF_channels=3): BeiDou B1I, GPS L1 C/A +
; Galileo E1 (co-located at 1575.42 MHz), and GLONASS L1 C/A.
; Requires a bladeRF 2.0 Micro (AD9361-based); 56 Msps / 56 MHz bandwidth is
; at its maximum supported bandwidth.
SignalSource.implementation=Bladerf_Signal_Source
SignalSource.item_type=gr_complex
SignalSource.sampling_frequency=56000000
SignalSource.freq=1584000000
SignalSource.bandwidth=56000000
SignalSource.gain=40
SignalSource.AGC_enabled=false
SignalSource.rx_bias_tee=false
SignalSource.device_serial=
SignalSource.samples=0
SignalSource.RF_channels=3
SignalSource.dump=false
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner0.implementation=Signal_Conditioner
SignalConditioner1.implementation=Signal_Conditioner
SignalConditioner2.implementation=Signal_Conditioner
;######### DATA_TYPE_ADAPTER CONFIG ############
DataTypeAdapter0.implementation=Pass_Through
DataTypeAdapter1.implementation=Pass_Through
DataTypeAdapter2.implementation=Pass_Through
;######### INPUT_FILTER CONFIG ############
; Sub-band 0: BeiDou B1I (1561.098 MHz), RF_channel_ID=0
InputFilter0.implementation=Freq_Xlating_Fir_Filter
InputFilter0.decimation_factor=7
InputFilter0.input_item_type=gr_complex
InputFilter0.output_item_type=gr_complex
InputFilter0.taps_item_type=float
InputFilter0.filter_type=lowpass
InputFilter0.bw=7000000
InputFilter0.tw=500000
InputFilter0.IF=-22902000
InputFilter0.sampling_frequency=56000000
InputFilter0.dump=false
InputFilter0.dump_filename=./input_filter.dat
;######### INPUT_FILTER CONFIG ############
; Sub-band 1: GPS L1 C/A + Galileo E1 (1575.42 MHz), RF_channel_ID=1
InputFilter1.implementation=Freq_Xlating_Fir_Filter
InputFilter1.decimation_factor=7
InputFilter1.input_item_type=gr_complex
InputFilter1.output_item_type=gr_complex
InputFilter1.taps_item_type=float
InputFilter1.filter_type=lowpass
InputFilter1.bw=7000000
InputFilter1.tw=500000
InputFilter1.IF=-8580000
InputFilter1.sampling_frequency=56000000
InputFilter1.dump=false
InputFilter1.dump_filename=./input_filter.dat
;######### INPUT_FILTER CONFIG ############
; Sub-band 2: GLONASS L1 C/A (~1602 MHz, FDMA), RF_channel_ID=2
InputFilter2.implementation=Freq_Xlating_Fir_Filter
InputFilter2.decimation_factor=7
InputFilter2.input_item_type=gr_complex
InputFilter2.output_item_type=gr_complex
InputFilter2.taps_item_type=float
InputFilter2.filter_type=lowpass
InputFilter2.bw=7000000
InputFilter2.tw=500000
InputFilter2.IF=18000000
InputFilter2.sampling_frequency=56000000
InputFilter2.dump=false
InputFilter2.dump_filename=./input_filter.dat
;######### RESAMPLER CONFIG ############
Resampler0.implementation=Pass_Through
Resampler1.implementation=Pass_Through
Resampler2.implementation=Pass_Through
;######### CHANNELS GLOBAL CONFIG ############
Channels_1B.count=10
Channels_1C.count=10
Channels_B1.count=14
Channels_1G.count=8
Channels_1B.RF_channel_ID=1
Channels_1C.RF_channel_ID=1
Channels_B1.RF_channel_ID=0
Channels_1G.RF_channel_ID=2
Channels.in_acquisition=2
;######### ACQUISITION BEIDOU CONFIG ############
Acquisition_B1.implementation=BEIDOU_B1I_PCPS_Acquisition
Acquisition_B1.item_type=gr_complex
Acquisition_B1.coherent_integration_time_ms=2
Acquisition_B1.pfa=0.000002
Acquisition_B1.doppler_max=6000
Acquisition_B1.doppler_step=100
Acquisition_B1.dump=false
Acquisition_B1.dump_filename=./bds_acq
Acquisition_B1.bit_transition_flag=false
;######### ACQUISITION GPS CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.coherent_integration_time_ms=1
Acquisition_1C.pfa=0.015
Acquisition_1C.doppler_max=6000
Acquisition_1C.doppler_step=200
Acquisition_1C.max_dwells=4
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat
;######### ACQUISITION GALILEO CONFIG ############
Acquisition_1B.implementation=Galileo_E1_PCPS_Ambiguous_Acquisition
Acquisition_1B.coherent_integration_time_ms=2
Acquisition_1B.pfa=0.025
Acquisition_1B.doppler_max=6000
Acquisition_1B.doppler_step=200
Acquisition_1B.max_dwells=4
Acquisition_1B.cboc=true
Acquisition_1B.dump=false
Acquisition_1B.dump_filename=./acq_dump.dat
;######### ACQUISITION GLONASS CONFIG ############
Acquisition_1G.implementation=GLONASS_L1_CA_PCPS_Acquisition
Acquisition_1G.item_type=gr_complex
Acquisition_1G.coherent_integration_time_ms=1
Acquisition_1G.max_dwells=4
Acquisition_1G.pfa=0.02
Acquisition_1G.doppler_max=6000
Acquisition_1G.doppler_step=100
Acquisition_1G.dump=false
Acquisition_1G.dump_filename=./G1_acq
;######### TRACKING BEIDOU CONFIG ############
Tracking_B1.implementation=BEIDOU_B1I_DLL_PLL_Tracking
Tracking_B1.item_type=gr_complex
Tracking_B1.extend_correlation_symbols=10
Tracking_B1.pll_bw_hz=50.0
Tracking_B1.dll_bw_hz=2.00
Tracking_B1.pll_bw_narrow_hz=15.0
Tracking_B1.dll_bw_narrow_hz=1.50
Tracking_B1.dump=false
Tracking_B1.dump_filename=./epl_tracking_ch_
;######### TRACKING GPS CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.extend_correlation_symbols=10
Tracking_1C.early_late_space_chips=0.5
Tracking_1C.early_late_space_narrow_chips=0.15
Tracking_1C.pll_bw_hz=30.0
Tracking_1C.dll_bw_hz=2.0
Tracking_1C.pll_bw_narrow_hz=10.0
Tracking_1C.dll_bw_narrow_hz=1.50
Tracking_1C.fll_bw_hz=10
Tracking_1C.enable_fll_pull_in=true
Tracking_1C.enable_fll_steady_state=false
Tracking_1C.dump=false
Tracking_1C.dump_filename=tracking_ch_
;######### TRACKING GALILEO CONFIG ############
Tracking_1B.implementation=Galileo_E1_DLL_PLL_VEML_Tracking
Tracking_1B.extend_correlation_symbols=4
Tracking_1B.item_type=gr_complex
Tracking_1B.pll_bw_hz=30.0
Tracking_1B.dll_bw_hz=2.0
Tracking_1B.pll_bw_narrow_hz=20.0
Tracking_1B.dll_bw_narrow_hz=1.50
Tracking_1B.track_pilot=true
Tracking_1B.enable_fll_pull_in=true
Tracking_1B.enable_fll_steady_state=false
Tracking_1B.fll_bw_hz=20
;######### TRACKING GLONASS CONFIG ############
Tracking_1G.implementation=GLONASS_L1_CA_DLL_PLL_Tracking
Tracking_1G.item_type=gr_complex
Tracking_1G.pll_bw_hz=40
Tracking_1G.dll_bw_hz=2.5
Tracking_1G.extend_correlation_ms=1
Tracking_1G.pll_bw_narrow_hz=20
Tracking_1G.dll_bw_narrow_hz=1.5
Tracking_1G.dump=false
Tracking_1G.dump_filename=./epl_tracking_ch_
;######### TELEMETRY DECODER BEIDOU CONFIG ############
TelemetryDecoder_B1.implementation=BEIDOU_B1I_Telemetry_Decoder
TelemetryDecoder_B1.dump=false
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
;######### TELEMETRY DECODER GALILEO E1B CONFIG ############
TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder
TelemetryDecoder_1B.dump=false
;######### TELEMETRY DECODER GLONASS CONFIG ############
TelemetryDecoder_1G.implementation=GLONASS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1G.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.threshold_reject_GDOP=100
PVT.elevation_mask=3
PVT.raim_fde=1
PVT.positioning_mode=Single ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.enable_rx_clock_correction=true
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.rtcm_tcp_port=2101
PVT.rtcm_MT1019_rate_ms=5000
PVT.rtcm_MT1077_rate_ms=1000
PVT.rinex_version=2
+9
View File
@@ -220,6 +220,15 @@ All notable changes to GNSS-SDR will be documented in this file.
the RTKLIB navigation structure, and adds `qzss_utc_model.xml`,
`qzss_iono.xml`, `qzss_cnav_utc_model.xml`, and `qzss_cnav_iono.xml` to the
XML storage output.
- Added a `Bladerf_Signal_Source` for interoperability with Nuand's bladeRF
front-ends (bladeRF x40, x115, and bladeRF 2.0 Micro xA4/xA9), streaming RX
samples directly through `libbladeRF` (requires the `-DENABLE_BLADERF=ON`
building flag) instead of going through `gr-osmosdr`. Supports single-channel
(SISO) reception, an optional RX bias tee for powering an active antenna on
the 2.0 Micro, and exposes a single overall RX gain (unlike the `if_gain` /
`rf_gain` split used by `Osmosdr_Signal_Source`). A sample configuration file
is provided at `conf/RealTime_input/gnss-sdr_GPS_L1_bladeRF_native.conf`.
Contributed by @MrCry0.
- Added a new Signal Source implementation `Pocket_SDR_Signal_Source`, which
supports
[Pocket SDR FE](https://www.datagnss.com/products/pocketsdr-gnss-receiver)
@@ -101,6 +101,13 @@ if(ENABLE_LIMESDR)
endif()
endif()
if(ENABLE_BLADERF)
if(LIBBLADERF_FOUND)
list(APPEND OPT_DRIVER_SOURCES bladerf_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS bladerf_signal_source.h)
endif()
endif()
if(ENABLE_POCKETSDR)
if(GRPOCKETSDR_FOUND)
list(APPEND OPT_DRIVER_SOURCES pocket_sdr_signal_source.cc)
@@ -0,0 +1,161 @@
/*!
* \file bladerf_signal_source.cc
* \brief Signal source for the Nuand bladeRF family of front-ends (bladeRF
* x40, x115, and bladeRF 2.0 Micro xA4/xA9), using libbladeRF directly.
* \author Oleksandr Suvorov, 2026.
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "bladerf_signal_source.h"
#include "configuration_interface.h"
#include "gnss_frequencies.h"
#include "gnss_sdr_string_literals.h"
#include "gnss_sdr_valve.h"
#include <gnuradio/blocks/file_sink.h>
#include <stdexcept>
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h>
#else
#include <absl/log/log.h>
#endif
using namespace std::string_literals;
BladerfSignalSource::BladerfSignalSource(const ConfigurationInterface* configuration,
const std::string& role,
unsigned int in_stream,
unsigned int out_stream,
Concurrent_Queue<pmt::pmt_t>* queue)
: SignalSourceBase(configuration, role, "Bladerf_Signal_Source"s),
item_type_(configuration->property(role + ".item_type", std::string("gr_complex"))),
dump_filename_(configuration->property(role + ".dump_filename", std::string("./data/signal_source.dat"))),
bladerf_args_(configuration->property(role + ".bladerf_args", std::string())),
device_serial_(configuration->property(role + ".device_serial", std::string())),
sample_rate_(configuration->property(role + ".sampling_frequency", 2.0e6)),
freq_(configuration->property(role + ".freq", FREQ1)),
bandwidth_(configuration->property(role + ".bandwidth", sample_rate_)),
gain_(configuration->property(role + ".gain", 40.0)),
samples_(configuration->property(role + ".samples", int64_t(0))),
in_stream_(in_stream),
out_stream_(out_stream),
num_buffers_(configuration->property(role + ".num_buffers", 32u)),
buffer_size_(configuration->property(role + ".buffer_size", 32768u)),
num_transfers_(configuration->property(role + ".num_transfers", 16u)),
stream_timeout_ms_(configuration->property(role + ".stream_timeout_ms", 3000u)),
agc_enabled_(configuration->property(role + ".AGC_enabled", false)),
rx_bias_tee_(configuration->property(role + ".rx_bias_tee", false)),
dump_(configuration->property(role + ".dump", false))
{
if (item_type_ != "gr_complex")
{
std::string error_message = "bladeRF: item_type '" + item_type_ + "' not supported, only 'gr_complex' is supported.";
LOG(ERROR) << error_message;
throw std::invalid_argument(error_message);
}
item_size_ = sizeof(gr_complex);
try
{
bladerf_source_ = bladerf_make_source_sptr(bladerf_args_, device_serial_,
sample_rate_, freq_, bandwidth_, gain_, agc_enabled_, rx_bias_tee_,
num_buffers_, buffer_size_, num_transfers_, stream_timeout_ms_);
}
catch (const std::exception& e)
{
LOG(WARNING) << "bladeRF exception: " << e.what();
throw std::invalid_argument("Wrong bladeRF arguments");
}
if (samples_ != 0)
{
DLOG(INFO) << "Send STOP signal after " << samples_ << " samples";
valve_ = gnss_sdr_make_valve(item_size_, samples_, queue);
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
}
if (dump_)
{
DLOG(INFO) << "Dumping output into file " << dump_filename_;
file_sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str());
DLOG(INFO) << "file_sink(" << file_sink_->unique_id() << ")";
}
if (in_stream_ > 0)
{
LOG(ERROR) << "A signal source does not have an input stream";
}
if (out_stream_ > 1)
{
LOG(ERROR) << "This implementation only supports one output stream";
}
}
void BladerfSignalSource::connect(gr::top_block_sptr top_block)
{
if (samples_ != 0)
{
top_block->connect(bladerf_source_, 0, valve_, 0);
DLOG(INFO) << "connected bladeRF source to valve";
if (dump_)
{
top_block->connect(valve_, 0, file_sink_, 0);
DLOG(INFO) << "connected valve to file sink";
}
}
else
{
if (dump_)
{
top_block->connect(bladerf_source_, 0, file_sink_, 0);
DLOG(INFO) << "connected bladeRF source to file sink";
}
}
}
void BladerfSignalSource::disconnect(gr::top_block_sptr top_block)
{
if (samples_ != 0)
{
top_block->disconnect(bladerf_source_, 0, valve_, 0);
if (dump_)
{
top_block->disconnect(valve_, 0, file_sink_, 0);
}
}
else
{
if (dump_)
{
top_block->disconnect(bladerf_source_, 0, file_sink_, 0);
}
}
}
gr::basic_block_sptr BladerfSignalSource::get_left_block()
{
LOG(WARNING) << "Trying to get signal source left block.";
return {};
}
gr::basic_block_sptr BladerfSignalSource::get_right_block()
{
if (samples_ != 0)
{
return valve_;
}
return bladerf_source_;
}
@@ -0,0 +1,93 @@
/*!
* \file bladerf_signal_source.h
* \brief Signal source for the Nuand bladeRF family of front-ends (bladeRF
* x40, x115, and bladeRF 2.0 Micro xA4/xA9), using libbladeRF directly.
* \author Oleksandr Suvorov, 2026.
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BLADERF_SIGNAL_SOURCE_H
#define GNSS_SDR_BLADERF_SIGNAL_SOURCE_H
#include "bladerf_source.h"
#include "concurrent_queue.h"
#include "signal_source_base.h"
#include <gnuradio/blocks/file_sink.h>
#include <pmt/pmt.h>
#include <cstdint>
#include <string>
/** \addtogroup Signal_Source
* \{ */
/** \addtogroup Signal_Source_adapters
* \{ */
class ConfigurationInterface;
/*!
* \brief This class instantiates the bladeRF signal source, streaming RX
* samples directly through libbladeRF (no gr-osmosdr or other intermediate
* driver required).
*/
class BladerfSignalSource : public SignalSourceBase
{
public:
BladerfSignalSource(const ConfigurationInterface* configuration,
const std::string& role, unsigned int in_stream,
unsigned int out_stream, Concurrent_Queue<pmt::pmt_t>* queue);
~BladerfSignalSource() = default;
inline size_t item_size() override
{
return item_size_;
}
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;
private:
bladerf_source_sptr bladerf_source_;
gnss_shared_ptr<gr::block> valve_;
gr::blocks::file_sink::sptr file_sink_;
std::string item_type_;
std::string dump_filename_;
std::string bladerf_args_;
std::string device_serial_;
double sample_rate_;
double freq_;
double bandwidth_;
double gain_;
size_t item_size_;
int64_t samples_;
unsigned int in_stream_;
unsigned int out_stream_;
unsigned int num_buffers_;
unsigned int buffer_size_;
unsigned int num_transfers_;
unsigned int stream_timeout_ms_;
bool agc_enabled_;
bool rx_bias_tee_;
bool dump_;
};
/** \} */
/** \} */
#endif // GNSS_SDR_BLADERF_SIGNAL_SOURCE_H
@@ -20,6 +20,11 @@ if(ENABLE_ION)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ion_gsms.h)
endif()
if(ENABLE_BLADERF AND LIBBLADERF_FOUND)
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} bladerf_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} bladerf_source.h)
endif()
set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
fifo_reader.cc
unpack_byte_2bit_samples.cc
@@ -103,6 +108,13 @@ if(ENABLE_RAW_UDP AND PCAP_FOUND)
)
endif()
if(ENABLE_BLADERF AND LIBBLADERF_FOUND)
target_link_libraries(signal_source_gr_blocks
PRIVATE
Bladerf::bladerf
)
endif()
# Fix for Boost Asio < 1.70
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
if((CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND (Boost_VERSION_STRING VERSION_LESS 1.70.0))
@@ -0,0 +1,284 @@
/*!
* \file bladerf_source.cc
* \brief GNU Radio source block for Nuand's bladeRF front-ends (bladeRF x40,
* x115, and bladeRF 2.0 Micro xA4/xA9), implemented directly against
* libbladeRF.
* \author Oleksandr Suvorov, 2026.
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "bladerf_source.h"
#include <gnuradio/io_signature.h>
// bladeRF2.h relies on macros defined by libbladeRF.h but does not include
// it itself, so this order must be preserved (protected against
// clang-format's alphabetical include sorting).
// clang-format off
#include <libbladeRF.h>
#include <bladeRF2.h>
// clang-format on
#include <algorithm>
#include <cstring>
#include <sstream>
#include <stdexcept>
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h>
#else
#include <absl/log/log.h>
#endif
namespace
{
constexpr bladerf_channel kRxChannel = BLADERF_CHANNEL_RX(0);
std::string make_device_identifier(const std::string &bladerf_args, const std::string &device_serial)
{
if (!bladerf_args.empty())
{
return bladerf_args;
}
if (!device_serial.empty())
{
return "*:serial=" + device_serial;
}
return {};
}
} // namespace
void bladerf_source::bladerf_deleter::operator()(struct bladerf *dev) const
{
if (dev != nullptr)
{
bladerf_close(dev);
}
}
bladerf_source_sptr bladerf_make_source_sptr(
const std::string &bladerf_args,
const std::string &device_serial,
double sample_rate,
double freq,
double bandwidth,
double gain,
bool agc_enabled,
bool rx_bias_tee,
unsigned int num_buffers,
unsigned int buffer_size,
unsigned int num_transfers,
unsigned int stream_timeout_ms)
{
return bladerf_source_sptr(new bladerf_source(bladerf_args, device_serial,
sample_rate, freq, bandwidth, gain, agc_enabled, rx_bias_tee,
num_buffers, buffer_size, num_transfers, stream_timeout_ms));
}
bladerf_source::bladerf_source(
const std::string &bladerf_args,
const std::string &device_serial,
double sample_rate,
double freq,
double bandwidth,
double gain,
bool agc_enabled,
bool rx_bias_tee,
unsigned int num_buffers,
unsigned int buffer_size,
unsigned int num_transfers,
unsigned int stream_timeout_ms)
: gr::sync_block("bladerf_source",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(1, 1, sizeof(gr_complex))),
buffer_size_(buffer_size),
stream_timeout_ms_(stream_timeout_ms),
streaming_(false)
{
const std::string identifier = make_device_identifier(bladerf_args, device_serial);
struct bladerf *raw_dev = nullptr;
int status = bladerf_open(&raw_dev, identifier.empty() ? nullptr : identifier.c_str());
if (status != 0)
{
std::ostringstream oss;
oss << "bladeRF: unable to open device '" << identifier << "': " << bladerf_strerror(status);
LOG(ERROR) << oss.str();
throw std::runtime_error(oss.str());
}
dev_.reset(raw_dev);
std::cout << "bladeRF: opened board '" << bladerf_get_board_name(dev_.get()) << "'\n";
LOG(INFO) << "bladeRF: opened board '" << bladerf_get_board_name(dev_.get()) << "'";
bladerf_sample_rate actual_sample_rate = 0;
status = bladerf_set_sample_rate(dev_.get(), kRxChannel, static_cast<bladerf_sample_rate>(sample_rate), &actual_sample_rate);
if (status != 0)
{
std::ostringstream oss;
oss << "bladeRF: unable to set sample rate: " << bladerf_strerror(status);
LOG(ERROR) << oss.str();
throw std::runtime_error(oss.str());
}
std::cout << "bladeRF: actual RX sample rate: " << actual_sample_rate << " [SPS]\n";
bladerf_bandwidth actual_bandwidth = 0;
status = bladerf_set_bandwidth(dev_.get(), kRxChannel, static_cast<bladerf_bandwidth>(bandwidth), &actual_bandwidth);
if (status != 0)
{
std::ostringstream oss;
oss << "bladeRF: unable to set bandwidth: " << bladerf_strerror(status);
LOG(ERROR) << oss.str();
throw std::runtime_error(oss.str());
}
std::cout << "bladeRF: actual RX bandwidth: " << actual_bandwidth << " [Hz]\n";
status = bladerf_set_frequency(dev_.get(), kRxChannel, static_cast<bladerf_frequency>(freq));
if (status != 0)
{
std::ostringstream oss;
oss << "bladeRF: unable to set frequency: " << bladerf_strerror(status);
LOG(ERROR) << oss.str();
throw std::runtime_error(oss.str());
}
std::cout << "bladeRF: RX frequency set to " << freq << " [Hz]\n";
status = bladerf_set_gain_mode(dev_.get(), kRxChannel, agc_enabled ? BLADERF_GAIN_DEFAULT : BLADERF_GAIN_MGC);
if (status != 0)
{
LOG(WARNING) << "bladeRF: unable to set gain mode: " << bladerf_strerror(status);
}
if (!agc_enabled)
{
status = bladerf_set_gain(dev_.get(), kRxChannel, static_cast<bladerf_gain>(gain));
if (status != 0)
{
LOG(WARNING) << "bladeRF: unable to set gain: " << bladerf_strerror(status);
}
}
if (rx_bias_tee)
{
status = bladerf_set_bias_tee(dev_.get(), kRxChannel, true);
if (status != 0)
{
LOG(WARNING) << "bladeRF: unable to enable RX bias tee (not supported on this board?): " << bladerf_strerror(status);
}
}
status = bladerf_sync_config(dev_.get(), BLADERF_RX_X1, BLADERF_FORMAT_SC16_Q11_META,
num_buffers, buffer_size_, num_transfers, stream_timeout_ms_);
if (status != 0)
{
std::ostringstream oss;
oss << "bladeRF: unable to configure synchronous RX stream: " << bladerf_strerror(status);
LOG(ERROR) << oss.str();
throw std::runtime_error(oss.str());
}
raw_buffer_.resize(static_cast<size_t>(buffer_size_) * 2);
// Hint the GNU Radio scheduler to negotiate a large output buffer for
// this block. Without this, the scheduler was observed requesting
// noutput_items as small as ~4096 per work() call regardless of how
// large a batch this block was willing to hand over, forcing
// bladerf_sync_rx() to be invoked far more often than the underlying
// stream's buffering (num_buffers * buffer_size_) could absorb any
// scheduling delay against, causing frequent RX overruns (confirmed via
// BLADERF_META_STATUS_OVERRUN once that reporting was wired up).
this->set_min_output_buffer(2097152);
}
bool bladerf_source::start()
{
int status = bladerf_enable_module(dev_.get(), kRxChannel, true);
if (status != 0)
{
LOG(ERROR) << "bladeRF: unable to enable RX module: " << bladerf_strerror(status);
return false;
}
streaming_ = true;
return true;
}
bool bladerf_source::stop()
{
if (streaming_)
{
int status = bladerf_enable_module(dev_.get(), kRxChannel, false);
if (status != 0)
{
LOG(WARNING) << "bladeRF: unable to disable RX module: " << bladerf_strerror(status);
}
streaming_ = false;
}
return true;
}
int bladerf_source::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
(void)input_items;
// Honor whatever batch size GNU Radio's scheduler is ready to accept,
// instead of artificially capping every call to buffer_size_ (the
// underlying stream's per-transfer size, not a limit on bladerf_sync_rx's
// own request size). Capping here forced far more, smaller round trips
// through bladerf_sync_rx than necessary, which made the source
// sensitive to ordinary OS scheduling jitter on any request that missed
// its real-time window.
const auto num_samples = static_cast<unsigned int>(noutput_items);
if (raw_buffer_.size() < static_cast<size_t>(num_samples) * 2)
{
raw_buffer_.resize(static_cast<size_t>(num_samples) * 2);
}
struct bladerf_metadata meta;
std::memset(&meta, 0, sizeof(meta));
meta.flags = BLADERF_META_FLAG_RX_NOW;
const int status = bladerf_sync_rx(dev_.get(), raw_buffer_.data(), num_samples, &meta, stream_timeout_ms_);
if (status == BLADERF_ERR_TIMEOUT)
{
return 0;
}
if (status != 0)
{
LOG(ERROR) << "bladeRF: sync_rx failed: " << bladerf_strerror(status);
return -1;
}
if ((meta.status & BLADERF_META_STATUS_OVERRUN) != 0)
{
LOG(WARNING) << "bladeRF: RX overrun detected, samples were dropped (requested "
<< num_samples << ", got " << meta.actual_count << ")";
}
// meta.actual_count reflects how many samples in raw_buffer_ are
// actually valid for this call; on a discontinuity it can be less than
// num_samples, and reading past it is undefined per libbladeRF's docs.
const unsigned int valid_samples = std::min(num_samples, meta.actual_count);
auto *out = reinterpret_cast<gr_complex *>(output_items[0]);
for (unsigned int i = 0; i < valid_samples; i++)
{
const float i_val = static_cast<float>(raw_buffer_[2 * i]) / 2048.0F;
const float q_val = static_cast<float>(raw_buffer_[(2 * i) + 1]) / 2048.0F;
out[i] = gr_complex(i_val, q_val);
}
return static_cast<int>(valid_samples);
}
@@ -0,0 +1,115 @@
/*!
* \file bladerf_source.h
* \brief GNU Radio source block for Nuand's bladeRF front-ends (bladeRF x40,
* x115, and bladeRF 2.0 Micro xA4/xA9), implemented directly against
* libbladeRF.
* \author Oleksandr Suvorov, 2026.
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BLADERF_SOURCE_H
#define GNSS_SDR_BLADERF_SOURCE_H
#include "gnss_block_interface.h"
#include <gnuradio/sync_block.h>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
/** \addtogroup Signal_Source
* \{ */
/** \addtogroup Signal_Source_gnuradio_blocks
* \{ */
class bladerf_source;
using bladerf_source_sptr = gnss_shared_ptr<bladerf_source>;
bladerf_source_sptr bladerf_make_source_sptr(
const std::string &bladerf_args,
const std::string &device_serial,
double sample_rate,
double freq,
double bandwidth,
double gain,
bool agc_enabled,
bool rx_bias_tee,
unsigned int num_buffers,
unsigned int buffer_size,
unsigned int num_transfers,
unsigned int stream_timeout_ms);
/*!
* \brief This class implements a GNU Radio source block that streams RX
* samples from a bladeRF device (single RX channel) using libbladeRF's
* synchronous streaming API, converting the device's native
* BLADERF_FORMAT_SC16_Q11 samples to gr_complex.
*/
class bladerf_source : public gr::sync_block
{
public:
~bladerf_source() override = default;
bool start() override;
bool stop() override;
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items) override;
private:
friend bladerf_source_sptr bladerf_make_source_sptr(
const std::string &bladerf_args,
const std::string &device_serial,
double sample_rate,
double freq,
double bandwidth,
double gain,
bool agc_enabled,
bool rx_bias_tee,
unsigned int num_buffers,
unsigned int buffer_size,
unsigned int num_transfers,
unsigned int stream_timeout_ms);
bladerf_source(
const std::string &bladerf_args,
const std::string &device_serial,
double sample_rate,
double freq,
double bandwidth,
double gain,
bool agc_enabled,
bool rx_bias_tee,
unsigned int num_buffers,
unsigned int buffer_size,
unsigned int num_transfers,
unsigned int stream_timeout_ms);
struct bladerf_deleter
{
void operator()(struct bladerf *dev) const;
};
std::unique_ptr<struct bladerf, bladerf_deleter> dev_;
std::vector<int16_t> raw_buffer_;
unsigned int buffer_size_;
unsigned int stream_timeout_ms_;
bool streaming_;
};
/** \} */
/** \} */
#endif // GNSS_SDR_BLADERF_SOURCE_H
+4
View File
@@ -124,6 +124,10 @@ if(ENABLE_LIMESDR)
target_compile_definitions(core_receiver PRIVATE -DLIMESDR_DRIVER=1)
endif()
if(ENABLE_BLADERF)
target_compile_definitions(core_receiver PRIVATE -DBLADERF_DRIVER=1)
endif()
if(ENABLE_POCKETSDR)
target_compile_definitions(core_receiver PRIVATE -DPOCKETSDR_DRIVER=1)
endif()
+10
View File
@@ -146,6 +146,10 @@
#include "limesdr_signal_source.h"
#endif
#if BLADERF_DRIVER
#include "bladerf_signal_source.h"
#endif
#if POCKETSDR_DRIVER
#include "pocket_sdr_signal_source.h"
#endif
@@ -348,6 +352,12 @@ std::unique_ptr<SignalSourceInterface> get_signal_source_block(
return std::make_unique<LimesdrSignalSource>(configuration, role, in_streams, out_streams, queue);
}
#endif
#if BLADERF_DRIVER
else if (implementation == "Bladerf_Signal_Source")
{
return std::make_unique<BladerfSignalSource>(configuration, role, in_streams, out_streams, queue);
}
#endif
#if POCKETSDR_DRIVER
else if (implementation == "Pocket_SDR_Signal_Source")
{