Skip to content

Commit

Permalink
Add support for BladeRF devices
Browse files Browse the repository at this point in the history
Many thanks to Steven Rossel for the work he did during his student
project.
  • Loading branch information
mpbraendli committed Nov 26, 2021
1 parent 22fd7d7 commit 558a210
Show file tree
Hide file tree
Showing 9 changed files with 528 additions and 8 deletions.
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ odr_dabmod_SOURCES += \
src/output/USRPTime.h \
src/output/Lime.cpp \
src/output/Lime.h \
src/output/BladeRF.cpp \
src/output/BladeRF.h \
src/PhaseReference.cpp \
src/PhaseReference.h \
src/QpskSymbolMapper.cpp \
Expand Down
18 changes: 14 additions & 4 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# You should have received a copy of the GNU General Public License
# along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>.

AC_PREREQ([2.71])
AC_PREREQ([2.69])
AC_INIT([ODR-DabMod],[2.4.2],[[email protected]])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
Expand Down Expand Up @@ -58,6 +58,9 @@ AC_ARG_ENABLE([easydabv3],
AC_ARG_ENABLE([limesdr],
[AS_HELP_STRING([--enable-limesdr], [Build for LimeSDR board])],
[], [enable_limesdr=no])
AC_ARG_ENABLE([bladerf],
[AS_HELP_STRING([--enable-bladerf], [Build for BladeRF boards])],
[], [enable_bladerf=no])

# UHD support control
AC_ARG_ENABLE([output_uhd],
Expand Down Expand Up @@ -110,9 +113,13 @@ AS_IF([test "x$enable_limesdr" = "xyes"],
[AC_CHECK_LIB([LimeSuite], [LMS_Init], [LIMESDR_LIBS="-lLimeSuite"],
[AC_MSG_ERROR([LimeSDR LimeSuite is required])])])

AS_IF([test "x$enable_bladerf" = "xyes"],
[AC_CHECK_LIB([bladeRF], [bladerf_open], [BLADERF_LIBS="-lbladeRF"],
[AC_MSG_ERROR([BladeRF library is required])])])

AC_SUBST([CFLAGS], ["$CFLAGS $EXTRA $FFTW_CFLAGS $SOAPYSDR_CFLAGS $PTHREAD_CFLAGS"])
AC_SUBST([CXXFLAGS], ["$CXXFLAGS $EXTRA $FFTW_CFLAGS $SOAPYSDR_CFLAGS $PTHREAD_CFLAGS"])
AC_SUBST([LIBS], ["$FFTW_LIBS $SOAPYSDR_LIBS $PTHREAD_LIBS $ZMQ_LIBS $LIMESDR_LIBS"])
AC_SUBST([LIBS], ["$FFTW_LIBS $SOAPYSDR_LIBS $PTHREAD_LIBS $ZMQ_LIBS $LIMESDR_LIBS $BLADERF_LIBS"])

AS_IF([test "x$enable_easydabv3" = "xyes" && test "x$enable_output_uhd" == "xyes"],
AC_MSG_ERROR([Cannot enable both EasyDABv3 and UHD output]))
Expand All @@ -135,7 +142,10 @@ AS_IF([test "x$enable_soapysdr" = "xyes"],
[AC_DEFINE(HAVE_SOAPYSDR, [1], [Define if SoapySDR output is enabled])])

AS_IF([test "x$enable_limesdr" = "xyes"],
[AC_DEFINE(HAVE_LIMESDR, [1], [Define if LimeSDR input is enabled]) ])
[AC_DEFINE(HAVE_LIMESDR, [1], [Define if LimeSDR output is enabled]) ])

AS_IF([test "x$enable_bladerf" = "xyes"],
[AC_DEFINE(HAVE_BLADERF, [1], [Define if BladeRF output is enabled]) ])

AS_IF([test "x$enable_easydabv3" = "xyes"],
AC_DEFINE(BUILD_FOR_EASYDABV3, [1], [Define if we are building for EasyDABv3]))
Expand Down Expand Up @@ -207,7 +217,7 @@ echo "***********************************************"
echo
enabled=""
disabled=""
for feat in prof trace output_uhd zeromq soapysdr easydabv3 limesdr
for feat in prof trace output_uhd zeromq soapysdr easydabv3 limesdr bladerf
do
eval var=\$enable_$feat
AS_IF([test "x$var" = "xyes"],
Expand Down
19 changes: 18 additions & 1 deletion doc/example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ enabled=0
polycoeffile=polyCoefs

[output]
; choose output: possible values: uhd, file, zmq, soapysdr, limesdr
; choose output: possible values: uhd, file, zmq, soapysdr, limesdr, bladerf
output=uhd

[fileoutput]
Expand Down Expand Up @@ -339,6 +339,23 @@ channel=13C
; of using the FFT-based resampler.
upsample=1

; section defining the BladeRF output settings.
[bladerfoutput]
; bladerfoutput is currently under development
device=
; The reference clock to use.
; possible values : pps, 10mhz
; Others values than above lead to disable refclk_src
refclk_source=
;master_clock_rate, not configurable with bladeRF, fundamental clock runs at 38.4 MHz
; txgain range: -23.75 .. 66 [dB]
txgain = 20
;tx_antenna -> not available
channel = 13C
bandwidth = 1800000



; Used for running single-frequency networks
[delaymanagement]
; Enable handling of timestamps for SFN
Expand Down
32 changes: 32 additions & 0 deletions src/ConfigParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,36 @@ static void parse_configfile(
mod_settings.useLimeOutput = true;
}
#endif

#if defined(HAVE_BLADERF)
else if (output_selected == "bladerf") {
auto& outputbladerf_conf = mod_settings.sdr_device_config;
outputbladerf_conf.device = pt.Get("bladerfoutput.device", "");
outputbladerf_conf.refclk_src = pt.Get("bladerfoutput.refclk_source", "");
outputbladerf_conf.txgain = pt.GetReal("bladerfoutput.txgain", 0.0);
outputbladerf_conf.frequency = pt.GetReal("bladerfoutput.frequency", 0);
outputbladerf_conf.bandwidth = pt.GetReal("bladerfoutput.bandwidth", 0);
std::string chan = pt.Get("bladerfoutput.channel", "");
outputbladerf_conf.dabMode = mod_settings.dabMode;

if (outputbladerf_conf.frequency == 0 && chan == "") {
std::cerr << " BladeRF output enabled, but neither frequency nor channel defined.\n";
throw std::runtime_error("Configuration error");
}
else if (outputbladerf_conf.frequency == 0) {
outputbladerf_conf.frequency = parseChannel(chan);
}
else if (outputbladerf_conf.frequency != 0 && chan != "") {
std::cerr << " BladeRF output: cannot define both frequency and channel.\n";
throw std::runtime_error("Configuration error");
}

outputbladerf_conf.dpdFeedbackServerPort = pt.GetInteger("bladerfoutput.dpd_port", 0);

mod_settings.useBladeRFOutput = true;
}
#endif

#if defined(HAVE_ZEROMQ)
else if (output_selected == "zmq") {
mod_settings.outputName = pt.Get("zmqoutput.listen", "");
Expand All @@ -354,6 +384,7 @@ static void parse_configfile(
throw std::runtime_error("Configuration error");
}


#if defined(HAVE_OUTPUT_UHD)
mod_settings.sdr_device_config.enableSync = (pt.GetInteger("delaymanagement.synchronous", 0) == 1);
mod_settings.sdr_device_config.muteNoTimestamps = (pt.GetInteger("delaymanagement.mutenotimestamps", 0) == 1);
Expand All @@ -378,6 +409,7 @@ static void parse_configfile(

#endif


/* Read TII parameters from config file */
mod_settings.tiiConfig.enable = pt.GetInteger("tii.enable", 0);
mod_settings.tiiConfig.comb = pt.GetInteger("tii.comb", 0);
Expand Down
5 changes: 4 additions & 1 deletion src/ConfigParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "output/UHD.h"
#include "output/Soapy.h"
#include "output/Lime.h"
#include "output/BladeRF.h"

#define ZMQ_INPUT_MAX_FRAME_QUEUE 500

Expand All @@ -51,6 +52,8 @@ struct mod_settings_t {
bool useUHDOutput = false;
bool useSoapyOutput = false;
bool useLimeOutput = false;
bool useBladeRFOutput = false;
const std::string BladeRFOutputFormat = "s16"; // to transmit SC16 IQ

size_t outputRate = 2048000;
size_t clockRate = 0;
Expand Down Expand Up @@ -84,7 +87,7 @@ struct mod_settings_t {
// Settings for the OFDM windowing
size_t ofdmWindowOverlap = 0;

#if defined(HAVE_OUTPUT_UHD) || defined(HAVE_SOAPYSDR) || defined(HAVE_LIMESDR)
#if defined(HAVE_OUTPUT_UHD) || defined(HAVE_SOAPYSDR) || defined(HAVE_LIMESDR) || defined(HAVE_BLADERF)
Output::SDRDeviceConfig sdr_device_config;
#endif

Expand Down
24 changes: 23 additions & 1 deletion src/DabMod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "output/UHD.h"
#include "output/Soapy.h"
#include "output/Lime.h"
#include "output/BladeRF.h"
#include "OutputZeroMQ.h"
#include "InputReader.h"
#include "PcDebug.h"
Expand Down Expand Up @@ -157,6 +158,13 @@ static void printModSettings(const mod_settings_t& mod_settings)
" master_clock_rate: " <<
mod_settings.sdr_device_config.masterClockRate << "\n";
}
#endif
#if defined(HAVE_BLADERF)
else if (mod_settings.useBladeRFOutput) {
ss << " BladeRF\n"
" Device: " << mod_settings.sdr_device_config.device << "\n" <<
" refclk: " << mod_settings.sdr_device_config.refclk_src << "\n";
}
#endif
else if (mod_settings.useZeroMQOutput) {
ss << " ZeroMQ\n" <<
Expand Down Expand Up @@ -251,6 +259,16 @@ static shared_ptr<ModOutput> prepare_output(
rcs.enrol((Output::SDR*)output.get());
}
#endif
#if defined(HAVE_BLADERF)
else if (s.useBladeRFOutput) {
/* We normalise specifically for the BladeRF output : range [-2048; 2047] */
s.normalise = 2047.0f / normalise_factor;
s.sdr_device_config.sampleRate = s.outputRate;
auto bladerfdevice = make_shared<Output::BladeRF>(s.sdr_device_config);
output = make_shared<Output::SDR>(s.sdr_device_config, bladerfdevice);
rcs.enrol((Output::SDR*)output.get());
}
#endif
#if defined(HAVE_ZEROMQ)
else if (s.useZeroMQOutput) {
/* We normalise the same way as for the UHD output */
Expand Down Expand Up @@ -301,7 +319,8 @@ int launch_modulator(int argc, char* argv[])
mod_settings.useUHDOutput or
mod_settings.useZeroMQOutput or
mod_settings.useSoapyOutput or
mod_settings.useLimeOutput)) {
mod_settings.useLimeOutput or
mod_settings.useBladeRFOutput)) {
throw std::runtime_error("Configuration error: Output not specified");
}

Expand All @@ -314,6 +333,9 @@ int launch_modulator(int argc, char* argv[])
mod_settings.fileOutputFormat == "s16")) {
format_converter = make_shared<FormatConverter>(mod_settings.fileOutputFormat);
}
else if (mod_settings.useBladeRFOutput) {
format_converter = make_shared<FormatConverter>(mod_settings.BladeRFOutputFormat);
}

auto output = prepare_output(mod_settings);

Expand Down
Loading

0 comments on commit 558a210

Please sign in to comment.