Skip to content
Snippets Groups Projects
Commit a2ce78f9 authored by Sergey Musikhin's avatar Sergey Musikhin
Browse files

ocmsdr sources for bladerf

parent 85d332b2
No related branches found
No related tags found
No related merge requests found
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
include(GrPlatform) #define LIB_SUFFIX include(GrPlatform) #define LIB_SUFFIX
list(APPEND bladeRF_sources list(APPEND bladeRF_sources
source_impl.cc source_impl.cc
source_impl.cc
) )
set(bladeRF_sources "${bladeRF_sources}" PARENT_SCOPE) set(bladeRF_sources "${bladeRF_sources}" PARENT_SCOPE)
...@@ -21,8 +20,17 @@ if(NOT bladeRF_sources) ...@@ -21,8 +20,17 @@ if(NOT bladeRF_sources)
return() return()
endif(NOT bladeRF_sources) endif(NOT bladeRF_sources)
MACRO (APPEND_LIB_LIST)
SET (gr_bladerf_libs "${gr_bladerf_libs};${ARGN}" CACHE INTERNAL "lib list")
ENDMACRO(APPEND_LIB_LIST)
set(gr_bladerf_libs "" CACHE INTERNAL "lib that accumulates link targets")
APPEND_LIB_LIST(gnuradio::gnuradio-runtime)
add_library(gnuradio-bladeRF SHARED ${bladeRF_sources}) add_library(gnuradio-bladeRF SHARED ${bladeRF_sources})
target_link_libraries(gnuradio-bladeRF gnuradio::gnuradio-runtime) target_link_libraries(gnuradio-bladeRF ${gr_bladerf_libs})
target_include_directories(gnuradio-bladeRF target_include_directories(gnuradio-bladeRF
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
PUBLIC $<INSTALL_INTERFACE:include> PUBLIC $<INSTALL_INTERFACE:include>
...@@ -35,6 +43,9 @@ if(APPLE) ...@@ -35,6 +43,9 @@ if(APPLE)
) )
endif(APPLE) endif(APPLE)
add_subdirectory(bladerf)
######################################################################## ########################################################################
# Install built library files # Install built library files
######################################################################## ########################################################################
......
/* -*- c++ -*- */
/*
* Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef OSMOSDR_ARG_HELPERS_H
#define OSMOSDR_ARG_HELPERS_H
#include <iostream>
#include <vector>
#include <map>
#include <gnuradio/io_signature.h>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <ciso646>
typedef std::map< std::string, std::string > dict_t;
typedef std::pair< std::string, std::string > pair_t;
inline std::string dict_to_args_string( const dict_t &d )
{
std::string out;
for (const pair_t pair : d)
{
if (not out.empty()) out += ",";
out += pair.first + "='" + pair.second + "'";
}
return out;
}
inline std::vector< std::string > args_to_vector( const std::string &args )
{
std::vector< std::string > result;
boost::escaped_list_separator<char> separator("\\", " ", "'");
typedef boost::tokenizer< boost::escaped_list_separator<char> > tokenizer_t;
tokenizer_t tokens(args, separator);
for (std::string token : tokens)
result.push_back(token);
return result;
}
inline std::vector< std::string > params_to_vector( const std::string &params )
{
std::vector< std::string > result;
boost::escaped_list_separator<char> separator("\\", ",", "'");
typedef boost::tokenizer< boost::escaped_list_separator<char> > tokenizer_t;
tokenizer_t tokens(params, separator);
for (std::string token : tokens)
result.push_back(token);
return result;
}
inline pair_t param_to_pair( const std::string &param )
{
pair_t result;
std::size_t pos = param.find('=');
if(pos != std::string::npos)
{
result.first = param.substr(0, pos);
result.second = param.substr(pos + 1);
}
else
{
result.first = param;
result.second = "";
}
return result;
}
inline dict_t params_to_dict( const std::string &params )
{
dict_t result;
std::vector< std::string > param_list = params_to_vector( params );
for (std::string param : param_list)
{
pair_t pair = param_to_pair( param );
std::string value = pair.second;
if (value.length() && value[0] == '\'' && value[ value.length() - 1 ] == '\'')
value = value.substr(1, value.length() - 1);
result[ pair.first ] = value;
}
return result;
}
struct is_nchan_argument
{
bool operator ()(const std::string &str)
{
return str.find("numchan=") == 0;
}
};
inline gr::io_signature::sptr args_to_io_signature( const std::string &args )
{
size_t max_nchan = 0;
size_t dev_nchan = 0;
std::vector< std::string > arg_list = args_to_vector( args );
for (std::string arg : arg_list)
{
if ( arg.find( "numchan=" ) == 0 ) // try to parse global nchan value
{
pair_t pair = param_to_pair( arg );
max_nchan = boost::lexical_cast<size_t>( pair.second );
}
}
arg_list.erase( std::remove_if( // remove any global nchan tokens
arg_list.begin(),
arg_list.end(),
is_nchan_argument() ),
arg_list.end() );
// try to parse device specific nchan values, assume 1 channel if none given
for (std::string arg : arg_list)
{
dict_t dict = params_to_dict(arg);
if (dict.count("nchan"))
{
dev_nchan += boost::lexical_cast<size_t>( dict["nchan"] );
}
else // no channels given via args
{
dev_nchan++; // assume one channel
}
}
// if at least one nchan was given, perform a sanity check
if ( max_nchan && dev_nchan && max_nchan != dev_nchan )
throw std::runtime_error("Wrong device arguments specified. Missing nchan?");
const size_t nchan = std::max<size_t>(dev_nchan, 1); // assume at least one
return gr::io_signature::make(nchan, nchan, sizeof(gr_complex));
}
#endif // OSMOSDR_ARG_HELPERS_H
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of gr-bladeRF
#
# gr-bladeRF is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3, or
# (at your option) any later version.
#
# gr-bladeRF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-bladeRF; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
########################################################################
# This file included, use CMake directory variables
########################################################################
target_include_directories(gnuradio-bladeRF PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${LIBBLADERF_INCLUDE_DIRS}
${Volk_INCLUDE_DIRS}
)
APPEND_LIB_LIST(
${LIBBLADERF_LIBRARIES}
${Volk_LIBRARIES}
)
list(APPEND bladeRF_sources
${CMAKE_CURRENT_SOURCE_DIR}/bladerf_source_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/bladerf_sink_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/bladerf_common.cc
)
set(bladeRF_sources ${bladeRF_sources} PARENT_SCOPE)
This diff is collapsed.
/* -*- c++ -*- */
/*
* Copyright 2013-2017 Nuand LLC
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BLADERF_COMMON_H
#define INCLUDED_BLADERF_COMMON_H
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include <libbladeRF.h>
#include "osmosdr/ranges.h"
#include "arg_helpers.h"
#include "bladerf_compat.h"
#ifdef _MSC_VER
#include <cstddef>
typedef ptrdiff_t ssize_t;
#endif //_MSC_VER
#define BLADERF_DEBUG_ENABLE
typedef std::shared_ptr<struct bladerf> bladerf_sptr;
/* Identification of the bladeRF hardware in use */
typedef enum {
BOARD_TYPE_UNKNOWN, /**< Board type is unknown */
BOARD_TYPE_NONE, /**< Uninitialized or no board present */
BOARD_TYPE_BLADERF_1, /**< bladeRF 1 (LMS6002D-based, 1RX/1TX) */
BOARD_TYPE_BLADERF_2, /**< bladeRF 2 (AD9361-based, 2RX/2TX) */
} bladerf_board_type;
/* Mapping of bladerf_channel to bool */
typedef std::map<bladerf_channel, bool> bladerf_channel_enable_map;
/* Mapping of bladerf_channel to gnuradio port/chan */
typedef std::map<bladerf_channel, int> bladerf_channel_map;
/* Convenience macros for throwing a runtime error */
#define BLADERF_THROW(message) \
{ \
throw std::runtime_error(std::string(__FUNCTION__) + ": " + message); \
}
#define BLADERF_THROW_STATUS(status, message) \
{ \
BLADERF_THROW(boost::str(boost::format("%s: %s (%d)") % message \
% bladerf_strerror(status) % status)); \
}
/* Convenience macros for printing a warning message to stderr */
#define BLADERF_WARNING(message) \
{ \
std::cerr << _pfx << __FUNCTION__ << ": " << message << std::endl; \
}
#define BLADERF_WARN_STATUS(status, message) \
{ \
BLADERF_WARNING(message << ": " << bladerf_strerror(status)); \
} \
/* Convenience macro for printing an informational message to stdout */
#define BLADERF_INFO(message) \
{ \
std::cout << _pfx << __FUNCTION__ << ": " << message << std::endl; \
}
/* Convenience macro for printing a debug message to stdout */
#ifdef BLADERF_DEBUG_ENABLE
#define BLADERF_DEBUG(message) BLADERF_INFO("DEBUG: " << message)
#else
#define BLADERF_DEBUG(message)
#endif // BLADERF_DEBUG_ENABLE
/* Given a bladerf_channel_layout, calculate the number of streams */
size_t num_streams(bladerf_channel_layout layout);
/**
* Common class for bladeRF interaction
*/
class bladerf_common
{
public:
/*****************************************************************************
* Public methods
****************************************************************************/
bladerf_common();
protected:
/*****************************************************************************
* Protected methods
****************************************************************************/
/**
* Handle initialization and parameters common to both source & sink
*
* Specify arguments in key=value,key=value format, e.g.
* bladerf=0,buffers=512
*
* Recognized arguments:
* Key Allowed values
* ---------------------------------------------------------------------------
* REQUIRED:
* bladerf a valid instance or serial number
* USB INTERFACE CONTROL:
* buffers (default: NUM_BUFFERS)
* buflen (default: NUM_SAMPLES_PER_BUFFER)
* stream_timeout valid time in milliseconds (default: 3000)
* transfers (default: NUM_TRANSFERS)
* FPGA CONTROL:
* enable_metadata 1 to enable metadata
* fpga a path to a valid .rbf file
* fpga-reload 1 to force reloading the FPGA unconditionally
* RF CONTROL:
* agc 1 to enable, 0 to disable (default: hardware-dependent)
* agc_mode default, manual, fast, slow, hybrid (default: default)
* loopback bb_txlpf_rxvga2, bb_txlpf_rxlpf, bb_txvga1_rxvga2,
* bb_txvga1_rxlpf, rf_lna1, rf_lna2, rf_lna3, firmware,
* ad9361_bist, none (default: none)
* ** Note: valid on receive channels only
* rxmux baseband, 12bit, 32bit, digital (default: baseband)
* ** Note: valid on receive channels only
* smb a valid frequency
* tamer internal, external_1pps, external (default: internal)
* xb200 auto, auto3db, 50M, 144M, 222M, custom (default: auto)
* MISC:
* verbosity verbose, debug, info, warning, error, critical, silent
* (default: info)
* ** Note: applies only to libbladeRF logging
*/
void init(dict_t const &dict, bladerf_direction direction);
/* Get a vector of available devices */
static std::vector<std::string> devices();
/* Get the type of the open bladeRF board */
bladerf_board_type get_board_type();
/* Get the maximum number of channels supported in a given direction */
size_t get_max_channels(bladerf_direction direction);
void set_channel_enable(bladerf_channel ch, bool enable);
bool get_channel_enable(bladerf_channel ch);
/* Set libbladeRF verbosity */
void set_verbosity(std::string const &verbosity);
/* Convert an antenna/channel name (e.g. "RX2") to a bladerf_channel */
bladerf_channel str2channel(std::string const &ch);
/* Convert a bladerf_channel to an antenna/channel name (e.g. "RX2") */
std::string channel2str(bladerf_channel ch);
/* Convert a bladerf_channel to a hardware port identifier */
int channel2rfport(bladerf_channel ch);
/* Using the channel map, get the bladerf_channel for a gnuradio chan */
bladerf_channel chan2channel(bladerf_direction direction, size_t chan = 0);
/* Get range of supported sampling rates for channel ch */
osmosdr::meta_range_t sample_rates(bladerf_channel ch);
/* Set sampling rate on channel ch to rate */
double set_sample_rate(double rate, bladerf_channel ch);
/* Get the current sampling rate on channel ch */
double get_sample_rate(bladerf_channel ch);
/* Get range of supported RF frequencies for channel ch */
osmosdr::freq_range_t freq_range(bladerf_channel ch);
/* Set center RF frequency of channel ch to freq */
double set_center_freq(double freq, bladerf_channel ch);
/* Get the center RF frequency of channel ch */
double get_center_freq(bladerf_channel ch);
/* Get range of supported bandwidths for channel ch */
osmosdr::freq_range_t filter_bandwidths(bladerf_channel ch);
/* Set the bandwidth on channel ch to bandwidth */
double set_bandwidth(double bandwidth, bladerf_channel ch);
/* Get the current bandwidth of channel ch */
double get_bandwidth(bladerf_channel ch);
/* Get the names of gain stages on channel ch */
std::vector<std::string> get_gain_names(bladerf_channel ch);
/* Get range of supported overall gain values on channel ch */
osmosdr::gain_range_t get_gain_range(bladerf_channel ch);
/* Get range of supported gain values for gain stage 'name' on channel ch */
osmosdr::gain_range_t get_gain_range(std::string const &name,
bladerf_channel ch);
/* Enable or disable the automatic gain control on channel ch */
bool set_gain_mode(bool automatic, bladerf_channel ch,
bladerf_gain_mode agc_mode = BLADERF_GAIN_DEFAULT);
/* Get the current automatic gain control status on channel ch */
bool get_gain_mode(bladerf_channel ch);
/* Set the overall gain value on channel ch */
double set_gain(double gain, bladerf_channel ch);
/* Set the gain of stage 'name' on channel ch */
double set_gain(double gain, std::string const &name, bladerf_channel ch);
/* Get the overall gain value on channel ch */
double get_gain(bladerf_channel ch);
/* Get the gain of stage 'name' on channel ch */
double get_gain(std::string const &name, bladerf_channel ch);
/* Get the list of antennas supported by a channel */
std::vector<std::string> get_antennas(bladerf_direction dir);
bool set_antenna(bladerf_direction dir, size_t chan, const std::string &antenna);
/* Set the DC offset on channel ch */
int set_dc_offset(std::complex<double> const &offset, bladerf_channel ch);
/* Set the IQ balance on channel ch */
int set_iq_balance(std::complex<double> const &balance, bladerf_channel ch);
/* Get the list of supported clock sources */
std::vector<std::string> get_clock_sources(size_t mboard = 0);
/* Set the clock source to */
void set_clock_source(std::string const &source, size_t mboard = 0);
/* Get the name of the current clock source */
std::string get_clock_source(size_t mboard = 0);
/* Set the SMB frequency */
void set_smb_frequency(double frequency);
/* Get the current SMB frequency */
double get_smb_frequency();
/*****************************************************************************
* Protected members
****************************************************************************/
bladerf_sptr _dev; /**< shared pointer for the active device */
std::string _pfx; /**< prefix for console messages */
unsigned int _failures; /**< counter for consecutive rx/tx failures */
size_t _num_buffers; /**< number of buffers to allocate */
size_t _samples_per_buffer; /**< how many samples per buffer */
size_t _num_transfers; /**< number of active backend transfers */
unsigned int _stream_timeout; /**< timeout for backend transfers */
bladerf_format _format; /**< sample format to use */
bladerf_channel_map _chanmap; /**< map of antennas to channels */
bladerf_channel_enable_map _enables; /**< enabled channels */
/*****************************************************************************
* Protected constants
****************************************************************************/
/* Maximum bladerf_sync_{rx,tx} failures to allow before giving up */
static const unsigned int MAX_CONSECUTIVE_FAILURES = 3;
/* BladeRF IQ correction parameters */
static const int16_t DCOFF_SCALE = 2048;
static const int16_t GAIN_SCALE = 4096;
static const int16_t PHASE_SCALE = 4096;
private:
/*****************************************************************************
* Private methods
****************************************************************************/
/* Open the bladeRF described by device_name. Returns a sptr if successful */
bladerf_sptr open(const std::string &device_name);
/* Called by shared_ptr when a bladerf_sptr hits a refcount of 0 */
static void close(void *dev);
/* If a device described by devinfo is open, this returns a sptr to it */
static bladerf_sptr get_cached_device(struct bladerf_devinfo devinfo);
/* Prints a summary of device information */
void print_device_info();
bool is_antenna_valid(bladerf_direction dir, const std::string &antenna);
/*****************************************************************************
* Private members
****************************************************************************/
static std::mutex _devs_mutex; /**< mutex for access to _devs */
static std::list<std::weak_ptr<struct bladerf>> _devs; /**< dev cache */
};
#endif
/* -*- c++ -*- */
/*
* Copyright 2017 Nuand LLC
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BLADERF_COMPAT_H
#define INCLUDED_BLADERF_COMPAT_H
#if defined(LIBBLADERF_API_VERSION) && (LIBBLADERF_API_VERSION < 0x01080100)
#warning Old libbladeRF detected: using compatibility workarounds.
#define BLADERF_COMPATIBILITY
/* New libbladeRF supports multiple channels, via various enums. */
typedef bladerf_module bladerf_channel;
#define BLADERF_CHANNEL_RX(ch) BLADERF_MODULE_RX
#define BLADERF_CHANNEL_TX(ch) BLADERF_MODULE_TX
#define BLADERF_CHANNEL_INVALID BLADERF_MODULE_INVALID
typedef bladerf_module bladerf_channel_layout;
#define BLADERF_RX_X1 BLADERF_MODULE_RX
#define BLADERF_TX_X1 BLADERF_MODULE_TX
#define BLADERF_RX_X2 BLADERF_MODULE_INVALID
#define BLADERF_TX_X2 BLADERF_MODULE_INVALID
typedef bladerf_module bladerf_direction;
#define BLADERF_RX BLADERF_MODULE_RX
#define BLADERF_TX BLADERF_MODULE_TX
#define BLADERF_DIRECTION_MASK (0x1)
/* Changed API calls */
static
int bladerf_get_frequency(struct bladerf *dev,
bladerf_channel ch,
uint64_t *freq) // was unsigned int *frequency
{
unsigned int f32 = 0;
int status = bladerf_get_frequency(dev, ch, &f32);
*freq = static_cast<uint64_t>(f32);
return status;
}
static
int bladerf_sync_tx(struct bladerf *dev,
void const *samples, // was void *samples
unsigned int num_samples,
struct bladerf_metadata *metadata,
unsigned int timeout_ms)
{
void *s = const_cast<void *>(samples);
return bladerf_sync_tx(dev, s, num_samples, metadata, timeout_ms);
}
/* Changed enums/defines */
#define BLADERF_GAIN_DEFAULT BLADERF_GAIN_AUTOMATIC
#define BLADERF_GAIN_MGC BLADERF_GAIN_MANUAL
#define BLADERF_RX_MUX_BASEBAND BLADERF_RX_MUX_BASEBAND_LMS
/* New functionality with no equivalent */
#define BLADERF_LB_AD9361_BIST BLADERF_LB_NONE
#define bladerf_get_board_name(name) "bladerf1"
#endif // libbladeRF < 1.8.1
#endif // INCLUDED_BLADERF_COMPAT_H
/* -*- c++ -*- */
/*
* Copyright 2013-2017 Nuand LLC
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
/*
* config.h is generated by configure. It contains the results
* of probing for features, options etc. It should be the first
* file included in your .cc file.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <iostream>
#include <boost/assign.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h>
#include <volk/volk.h>
#include "arg_helpers.h"
#include "bladerf_sink_c.h"
#include "osmosdr/sink.h"
using namespace boost::assign;
/******************************************************************************
* Functions
******************************************************************************/
/*
* Create a new instance of bladerf_sink_c and return
* a boost shared_ptr. This is effectively the public constructor.
*/
bladerf_sink_c_sptr make_bladerf_sink_c(const std::string &args)
{
return gnuradio::get_initial_sptr(new bladerf_sink_c(args));
}
/******************************************************************************
* Private methods
******************************************************************************/
/*
* The private constructor
*/
bladerf_sink_c::bladerf_sink_c(const std::string &args) :
gr::sync_block( "bladerf_sink_c",
args_to_io_signature(args),
gr::io_signature::make(0, 0, 0)),
_16icbuf(NULL),
_32fcbuf(NULL),
_in_burst(false),
_running(false)
{
dict_t dict = params_to_dict(args);
/* Perform src/sink agnostic initializations */
init(dict, BLADERF_TX);
/* Check for RX-only params */
if (dict.count("loopback")) {
BLADERF_WARNING("Warning: 'loopback' has been specified on a bladeRF "
"sink, and will have no effect. This parameter should be "
"specified on the associated bladeRF source.");
}
if (dict.count("rxmux")) {
BLADERF_WARNING("Warning: 'rxmux' has been specified on a bladeRF sink, "
"and will have no effect.");
}
/* Bias tee */
if (dict.count("biastee")) {
set_biastee_mode(dict["biastee"]);
}
/* Initialize channel <-> antenna map */
for (std::string ant : get_antennas()) {
_chanmap[str2channel(ant)] = -1;
}
/* Bounds-checking output signature depending on our underlying hardware */
if (get_num_channels() > get_max_channels()) {
BLADERF_WARNING("Warning: number of channels specified on command line ("
<< get_num_channels() << ") is greater than the maximum "
"number supported by this device (" << get_max_channels()
<< "). Resetting to " << get_max_channels() << ".");
set_input_signature(gr::io_signature::make(get_max_channels(),
get_max_channels(),
sizeof(gr_complex)));
}
/* Set up constraints */
int const alignment_multiple = volk_get_alignment() / sizeof(gr_complex);
set_alignment(std::max(1,alignment_multiple));
set_max_noutput_items(_samples_per_buffer);
set_output_multiple(get_num_channels());
/* Set channel layout */
_layout = (get_num_channels() > 1) ? BLADERF_TX_X2 : BLADERF_TX_X1;
/* Initial wiring of antennas to channels */
for (size_t ch = 0; ch < get_num_channels(); ++ch) {
set_channel_enable(BLADERF_CHANNEL_TX(ch), true);
_chanmap[BLADERF_CHANNEL_TX(ch)] = ch;
}
BLADERF_DEBUG("initialization complete");
}
/******************************************************************************
* Public methods
******************************************************************************/
std::string bladerf_sink_c::name()
{
return "bladeRF transmitter";
}
std::vector<std::string> bladerf_sink_c::get_devices()
{
return bladerf_common::devices();
}
size_t bladerf_sink_c::get_max_channels()
{
return bladerf_common::get_max_channels(BLADERF_TX);
}
size_t bladerf_sink_c::get_num_channels()
{
return input_signature()->max_streams();
}
bool bladerf_sink_c::start()
{
int status;
BLADERF_DEBUG("starting sink");
gr::thread::scoped_lock guard(d_mutex);
_in_burst = false;
status = bladerf_sync_config(_dev.get(), _layout, _format, _num_buffers,
_samples_per_buffer, _num_transfers,
_stream_timeout);
if (status != 0) {
BLADERF_THROW_STATUS(status, "bladerf_sync_config failed");
}
for (size_t ch = 0; ch < get_max_channels(); ++ch) {
bladerf_channel brfch = BLADERF_CHANNEL_TX(ch);
if (get_channel_enable(brfch)) {
status = bladerf_enable_module(_dev.get(), brfch, true);
if (status != 0) {
BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
}
}
}
/* Allocate memory for conversions in work() */
size_t alignment = volk_get_alignment();
_16icbuf = reinterpret_cast<int16_t *>(volk_malloc(2*_samples_per_buffer*sizeof(int16_t), alignment));
_32fcbuf = reinterpret_cast<gr_complex *>(volk_malloc(_samples_per_buffer*sizeof(gr_complex), alignment));
_running = true;
return true;
}
bool bladerf_sink_c::stop()
{
int status;
BLADERF_DEBUG("stopping sink");
gr::thread::scoped_lock guard(d_mutex);
if (!_running) {
BLADERF_WARNING("sink already stopped, nothing to do here");
return true;
}
_running = false;
for (size_t ch = 0; ch < get_max_channels(); ++ch) {
bladerf_channel brfch = BLADERF_CHANNEL_TX(ch);
if (get_channel_enable(brfch)) {
status = bladerf_enable_module(_dev.get(), brfch, false);
if (status != 0) {
BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
}
}
}
/* Deallocate conversion memory */
volk_free(_16icbuf);
volk_free(_32fcbuf);
_16icbuf = NULL;
_32fcbuf = NULL;
return true;
}
int bladerf_sink_c::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
int status;
size_t nstreams = num_streams(_layout);
gr::thread::scoped_lock guard(d_mutex);
// if we aren't running, nothing to do here
if (!_running) {
return 0;
}
// copy the samples from input_items
gr_complex const **in = reinterpret_cast<gr_complex const **>(&input_items[0]);
if (nstreams > 1) {
// we need to interleave the streams as we copy
gr_complex *intl_out = _32fcbuf;
for (size_t i = 0; i < (noutput_items/nstreams); ++i) {
for (size_t n = 0; n < nstreams; ++n) {
memcpy(intl_out++, in[n]++, sizeof(gr_complex));
}
}
} else {
// no interleaving to do: simply copy everything
memcpy(_32fcbuf, in[0], noutput_items * sizeof(gr_complex));
}
// convert floating point to fixed point and scale
// input_items is gr_complex (2x float), so num_points is 2*noutput_items
volk_32f_s32f_convert_16i(_16icbuf, reinterpret_cast<float const *>(_32fcbuf),
SCALING_FACTOR, 2*noutput_items);
// transmit the samples from the temp buffer
if (BLADERF_FORMAT_SC16_Q11_META == _format) {
status = transmit_with_tags(_16icbuf, noutput_items);
} else {
status = bladerf_sync_tx(_dev.get(), static_cast<void const *>(_16icbuf),
noutput_items, NULL, _stream_timeout);
}
// handle failure
if (status != 0) {
BLADERF_WARNING("bladerf_sync_tx error: " << bladerf_strerror(status));
++_failures;
if (_failures >= MAX_CONSECUTIVE_FAILURES) {
BLADERF_WARNING("Consecutive error limit hit. Shutting down.");
return WORK_DONE;
}
} else {
_failures = 0;
}
return noutput_items;
}
int bladerf_sink_c::transmit_with_tags(int16_t const *samples,
int noutput_items)
{
int status;
int count = 0;
// For a long burst, we may be transmitting the burst contents over
// multiple work calls, so we'll just be sending the entire buffer
// Therefore, we initialize our indicies for this case.
int start_idx = 0;
int end_idx = (noutput_items - 1);
struct bladerf_metadata meta;
std::vector<gr::tag_t> tags;
int const INVALID_IDX = -1;
int16_t const zeros[8] = { 0 };
memset(&meta, 0, sizeof(meta));
BLADERF_DEBUG("transmit_with_tags(" << noutput_items << ")");
// Important Note: We assume that these tags are ordered by their offsets.
// This is true for GNU Radio 3.7.7.x, since the GR runtime libs store
// these in a multimap.
//
// If you're using an earlier GNU Radio version, you may have to sort
// the tags vector.
get_tags_in_window(tags, 0, 0, noutput_items);
if (tags.size() == 0) {
if (_in_burst) {
BLADERF_DEBUG("TX'ing " << noutput_items << " samples within a burst...");
return bladerf_sync_tx(_dev.get(), samples, noutput_items,
&meta, _stream_timeout);
} else {
BLADERF_WARNING("Dropping " << noutput_items
<< " samples not in a burst.");
}
}
for (gr::tag_t tag : tags) {
// Upon seeing an SOB tag, update our offset. We'll TX the start of the
// burst when we see an EOB or at the end of this function - whichever
// occurs first.
if (pmt::symbol_to_string(tag.key) == "tx_sob") {
if (_in_burst) {
BLADERF_WARNING("Got SOB while already within a burst");
return BLADERF_ERR_INVAL;
} else {
start_idx = static_cast<int>(tag.offset - nitems_read(0));
BLADERF_DEBUG("Got SOB " << start_idx << " samples into work payload");
meta.flags |= (BLADERF_META_FLAG_TX_NOW | BLADERF_META_FLAG_TX_BURST_START);
_in_burst = true;
}
} else if (pmt::symbol_to_string(tag.key) == "tx_eob") {
if (!_in_burst) {
BLADERF_WARNING("Got EOB while not in burst");
return BLADERF_ERR_INVAL;
}
// Upon seeing an EOB, transmit what we have and reset our state
end_idx = static_cast<int>(tag.offset - nitems_read(0));
BLADERF_DEBUG("Got EOB " << end_idx << " samples into work payload");
if ((start_idx == INVALID_IDX) || (start_idx > end_idx)) {
BLADERF_DEBUG("Buffer indicies are in an invalid state!");
return BLADERF_ERR_INVAL;
}
count = end_idx - start_idx + 1;
BLADERF_DEBUG("TXing @ EOB [" << start_idx << ":" << end_idx << "]");
status = bladerf_sync_tx(_dev.get(),
static_cast<void const *>(&samples[2 * start_idx]),
count, &meta, _stream_timeout);
if (status != 0) {
return status;
}
/* TODO: libbladeRF should now take care of this for us,
* as of the libbladeRF version that includes the
* TX_UPDATE_TIMESTAMP flag. Verify this potentially remove this.
* (The meta.flags changes would then be applied to the previous
* bladerf_sync_tx() call.)
*/
BLADERF_DEBUG("TXing Zeros with burst end flag");
meta.flags &= ~(BLADERF_META_FLAG_TX_NOW | BLADERF_META_FLAG_TX_BURST_START);
meta.flags |= BLADERF_META_FLAG_TX_BURST_END;
status = bladerf_sync_tx(_dev.get(), static_cast<void const *>(zeros),
4, &meta, _stream_timeout);
/* Reset our state */
start_idx = INVALID_IDX;
end_idx = (noutput_items - 1);
meta.flags = 0;
_in_burst = false;
if (status != 0) {
BLADERF_DEBUG("Failed to send zero samples to flush EOB");
return status;
}
}
}
// We had a start of burst with no end yet - transmit those samples
if (_in_burst) {
count = end_idx - start_idx + 1;
BLADERF_DEBUG("TXing SOB [" << start_idx << ":" << end_idx << "]");
status = bladerf_sync_tx(_dev.get(),
static_cast<void const *>(&samples[2 * start_idx]),
count, &meta, _stream_timeout);
}
return status;
}
osmosdr::meta_range_t bladerf_sink_c::get_sample_rates()
{
return sample_rates(chan2channel(BLADERF_TX, 0));
}
double bladerf_sink_c::set_sample_rate(double rate)
{
return bladerf_common::set_sample_rate(rate, chan2channel(BLADERF_TX, 0));
}
double bladerf_sink_c::get_sample_rate()
{
return bladerf_common::get_sample_rate(chan2channel(BLADERF_TX, 0));
}
osmosdr::freq_range_t bladerf_sink_c::get_freq_range(size_t chan)
{
return bladerf_common::freq_range(chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::set_center_freq(double freq, size_t chan)
{
return bladerf_common::set_center_freq(freq, chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::get_center_freq(size_t chan)
{
return bladerf_common::get_center_freq(chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::set_freq_corr(double ppm, size_t chan)
{
/* TODO: Write the VCTCXO with a correction value (also changes RX ppm value!) */
BLADERF_WARNING("Frequency correction is not implemented.");
return get_freq_corr(chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::get_freq_corr(size_t chan)
{
/* TODO: Return back the frequency correction in ppm */
return 0;
}
std::vector<std::string> bladerf_sink_c::get_gain_names(size_t chan)
{
return bladerf_common::get_gain_names(chan2channel(BLADERF_TX, chan));
}
osmosdr::gain_range_t bladerf_sink_c::get_gain_range(size_t chan)
{
return bladerf_common::get_gain_range(chan2channel(BLADERF_TX, chan));
}
osmosdr::gain_range_t bladerf_sink_c::get_gain_range(const std::string &name,
size_t chan)
{
return bladerf_common::get_gain_range(name, chan2channel(BLADERF_TX, chan));
}
bool bladerf_sink_c::set_gain_mode(bool automatic, size_t chan)
{
return bladerf_common::set_gain_mode(automatic,
chan2channel(BLADERF_TX, chan));
}
bool bladerf_sink_c::get_gain_mode(size_t chan)
{
return bladerf_common::get_gain_mode(chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::set_gain(double gain, size_t chan)
{
return bladerf_common::set_gain(gain, chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::set_gain(double gain, const std::string &name,
size_t chan)
{
return bladerf_common::set_gain(gain, name, chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::get_gain(size_t chan)
{
return bladerf_common::get_gain(chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::get_gain(const std::string &name, size_t chan)
{
return bladerf_common::get_gain(name, chan2channel(BLADERF_TX, chan));
}
std::vector<std::string> bladerf_sink_c::get_antennas(size_t chan)
{
return bladerf_common::get_antennas(BLADERF_TX);
}
std::string bladerf_sink_c::set_antenna(const std::string &antenna,
size_t chan)
{
bool _was_running = _running;
if (_was_running) {
stop();
}
bladerf_common::set_antenna(BLADERF_TX, chan, antenna);
if (_was_running) {
start();
}
return get_antenna(chan);
}
std::string bladerf_sink_c::get_antenna(size_t chan)
{
return channel2str(chan2channel(BLADERF_TX, chan));
}
void bladerf_sink_c::set_dc_offset(const std::complex < double > &offset,
size_t chan)
{
int status;
status = bladerf_common::set_dc_offset(offset, chan2channel(BLADERF_TX, chan));
if (status != 0) {
BLADERF_THROW_STATUS(status, "could not set dc offset");
}
}
void bladerf_sink_c::set_iq_balance(const std::complex < double > &balance,
size_t chan)
{
int status;
status = bladerf_common::set_iq_balance(balance, chan2channel(BLADERF_TX, chan));
if (status != 0) {
BLADERF_THROW_STATUS(status, "could not set iq balance");
}
}
osmosdr::freq_range_t bladerf_sink_c::get_bandwidth_range(size_t chan)
{
return filter_bandwidths(chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::set_bandwidth(double bandwidth, size_t chan)
{
return bladerf_common::set_bandwidth(bandwidth, chan2channel(BLADERF_TX, chan));
}
double bladerf_sink_c::get_bandwidth(size_t chan)
{
return bladerf_common::get_bandwidth(chan2channel(BLADERF_TX, chan));
}
std::vector < std::string > bladerf_sink_c::get_clock_sources(size_t mboard)
{
return bladerf_common::get_clock_sources(mboard);
}
void bladerf_sink_c::set_clock_source(const std::string &source,
size_t mboard)
{
bladerf_common::set_clock_source(source, mboard);
}
std::string bladerf_sink_c::get_clock_source(size_t mboard)
{
return bladerf_common::get_clock_source(mboard);
}
void bladerf_sink_c::set_biastee_mode(const std::string &mode)
{
int status;
bool enable;
if (mode == "on" || mode == "1" || mode == "rx") {
enable = true;
} else {
enable = false;
}
status = bladerf_set_bias_tee(_dev.get(), BLADERF_CHANNEL_TX(0), enable);
if (BLADERF_ERR_UNSUPPORTED == status) {
// unsupported, but not worth crashing out
BLADERF_WARNING("Bias-tee not supported by device");
} else if (status != 0) {
BLADERF_THROW_STATUS(status, "Failed to set bias-tee");
}
}
/* -*- c++ -*- */
/*
* Copyright 2013-2017 Nuand LLC
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BLADERF_SINK_C_H
#define INCLUDED_BLADERF_SINK_C_H
#include <gnuradio/sync_block.h>
#include "sink_iface.h"
#include "bladerf_common.h"
#include "osmosdr/ranges.h"
class bladerf_sink_c;
/*
* We use std::shared_ptr's instead of raw pointers for all access
* to gr_blocks (and many other data structures). The shared_ptr gets
* us transparent reference counting, which greatly simplifies storage
* management issues. This is especially helpful in our hybrid
* C++ / Python system.
*
* See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
*
* As a convention, the _sptr suffix indicates a std::shared_ptr
*/
typedef std::shared_ptr<bladerf_sink_c> bladerf_sink_c_sptr;
/*!
* \brief Return a shared_ptr to a new instance of bladerf_sink_c.
*
* To avoid accidental use of raw pointers, bladerf_sink_c's
* constructor is private. make_bladerf_sink_c is the public
* interface for creating new instances.
*/
bladerf_sink_c_sptr make_bladerf_sink_c(const std::string &args = "");
class bladerf_sink_c :
public gr::sync_block,
public sink_iface,
protected bladerf_common
{
private:
// The friend declaration allows bladerf_make_sink_c to
// access the private constructor.
friend bladerf_sink_c_sptr make_bladerf_sink_c(const std::string &args);
bladerf_sink_c(const std::string &args);
bool is_antenna_valid(const std::string &antenna);
public:
std::string name();
static std::vector<std::string> get_devices();
size_t get_max_channels(void);
size_t get_num_channels(void);
bool start();
bool stop();
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
osmosdr::meta_range_t get_sample_rates(void);
double set_sample_rate(double rate);
double get_sample_rate(void);
osmosdr::freq_range_t get_freq_range(size_t chan = 0);
double set_center_freq(double freq, size_t chan = 0);
double get_center_freq(size_t chan = 0);
double set_freq_corr(double ppm, size_t chan = 0);
double get_freq_corr(size_t chan = 0);
std::vector<std::string> get_gain_names(size_t chan = 0);
osmosdr::gain_range_t get_gain_range(size_t chan = 0);
osmosdr::gain_range_t get_gain_range(const std::string &name,
size_t chan = 0);
bool set_gain_mode(bool automatic, size_t chan = 0);
bool get_gain_mode(size_t chan = 0);
double set_gain(double gain, size_t chan = 0);
double set_gain(double gain, const std::string &name, size_t chan = 0);
double get_gain(size_t chan = 0);
double get_gain(const std::string &name, size_t chan = 0);
std::vector<std::string> get_antennas(size_t chan = 0);
std::string set_antenna(const std::string &antenna, size_t chan = 0);
std::string get_antenna(size_t chan = 0);
void set_dc_offset(const std::complex<double> &offset, size_t chan);
void set_iq_balance(const std::complex<double> &balance, size_t chan);
osmosdr::freq_range_t get_bandwidth_range(size_t chan = 0);
double set_bandwidth(double bandwidth, size_t chan = 0);
double get_bandwidth(size_t chan = 0);
std::vector<std::string> get_clock_sources(size_t mboard);
void set_clock_source(const std::string &source, size_t mboard = 0);
std::string get_clock_source(size_t mboard);
void set_biastee_mode(const std::string &mode);
private:
int transmit_with_tags(int16_t const *samples, int noutput_items);
// Sample-handling buffers
int16_t *_16icbuf; /**< raw samples to bladeRF */
gr_complex *_32fcbuf; /**< intermediate buffer for conversions */
bool _in_burst; /**< are we currently in a burst? */
bool _running; /**< is the sink running? */
bladerf_channel_layout _layout; /**< channel layout */
gr::thread::mutex d_mutex; /**< mutex to protect set/work access */
/* Scaling factor used when converting from float to int16_t */
const float SCALING_FACTOR = 2048.0f;
};
#endif // INCLUDED_BLADERF_SINK_C_H
This diff is collapsed.
/* -*- c++ -*- */
/*
* Copyright 2013-2017 Nuand LLC
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BLADERF_SOURCE_C_H
#define INCLUDED_BLADERF_SOURCE_C_H
#include <gnuradio/sync_block.h>
#include "source_iface.h"
#include "bladerf_common.h"
#include "osmosdr/ranges.h"
class bladerf_source_c;
/*
* We use std::shared_ptr's instead of raw pointers for all access
* to gr_blocks (and many other data structures). The shared_ptr gets
* us transparent reference counting, which greatly simplifies storage
* management issues. This is especially helpful in our hybrid
* C++ / Python system.
*
* See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
*
* As a convention, the _sptr suffix indicates a std::shared_ptr
*/
typedef std::shared_ptr<bladerf_source_c> bladerf_source_c_sptr;
/*!
* \brief Return a shared_ptr to a new instance of bladerf_source_c.
*
* To avoid accidental use of raw pointers, bladerf_source_c's
* constructor is private. bladerf_make_source_c is the public
* interface for creating new instances.
*/
bladerf_source_c_sptr make_bladerf_source_c(const std::string &args = "");
class bladerf_source_c :
public gr::sync_block,
public source_iface,
protected bladerf_common
{
private:
// The friend declaration allows bladerf_make_source_c to
// access the private constructor.
friend bladerf_source_c_sptr make_bladerf_source_c(const std::string &args);
bladerf_source_c(const std::string &args);
bool is_antenna_valid(const std::string &antenna);
public:
std::string name();
static std::vector<std::string> get_devices();
size_t get_max_channels(void);
size_t get_num_channels(void);
bool start();
bool stop();
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
osmosdr::meta_range_t get_sample_rates(void);
double set_sample_rate(double rate);
double get_sample_rate(void);
osmosdr::freq_range_t get_freq_range(size_t chan = 0);
double set_center_freq(double freq, size_t chan = 0);
double get_center_freq(size_t chan = 0);
double set_freq_corr(double ppm, size_t chan = 0);
double get_freq_corr(size_t chan = 0);
std::vector<std::string> get_gain_names(size_t chan = 0);
osmosdr::gain_range_t get_gain_range(size_t chan = 0);
osmosdr::gain_range_t get_gain_range(const std::string &name,
size_t chan = 0);
bool set_gain_mode(bool automatic, size_t chan = 0);
bool get_gain_mode(size_t chan = 0);
double set_gain(double gain, size_t chan = 0);
double set_gain(double gain, const std::string &name, size_t chan = 0);
double get_gain(size_t chan = 0);
double get_gain(const std::string &name, size_t chan = 0);
std::vector<std::string> get_antennas(size_t chan = 0);
std::string set_antenna(const std::string &antenna, size_t chan = 0);
std::string get_antenna(size_t chan = 0);
void set_dc_offset_mode(int mode, size_t chan = 0);
void set_dc_offset(const std::complex<double> &offset, size_t chan = 0);
void set_iq_balance_mode(int mode, size_t chan = 0);
void set_iq_balance(const std::complex<double> &balance, size_t chan = 0);
osmosdr::freq_range_t get_bandwidth_range(size_t chan = 0);
double set_bandwidth(double bandwidth, size_t chan = 0);
double get_bandwidth(size_t chan = 0);
std::vector<std::string> get_clock_sources(size_t mboard);
void set_clock_source(const std::string &source, size_t mboard = 0);
std::string get_clock_source(size_t mboard);
void set_biastee_mode(const std::string &mode);
void set_loopback_mode(const std::string &loopback);
void set_rx_mux_mode(const std::string &rxmux);
void set_agc_mode(const std::string &agcmode);
private:
// Sample-handling buffers
int16_t *_16icbuf; /**< raw samples from bladeRF */
gr_complex *_32fcbuf; /**< intermediate buffer to gnuradio */
bool _running; /**< is the source running? */
bladerf_channel_layout _layout; /**< channel layout */
bladerf_gain_mode _agcmode; /**< gain mode when AGC is enabled */
gr::thread::mutex d_mutex; /**< mutex to protect set/work access */
/* Scaling factor used when converting from int16_t to float */
const float SCALING_FACTOR = 2048.0f;
};
#endif // INCLUDED_BLADERF_SOURCE_C_H
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include "source_impl.h" #include "source_impl.h"
#include "arg_helpers.h"
namespace gr { namespace gr {
namespace bladeRF { namespace bladeRF {
...@@ -16,22 +17,15 @@ namespace gr { ...@@ -16,22 +17,15 @@ namespace gr {
return gnuradio::make_block_sptr<source_impl>(args); return gnuradio::make_block_sptr<source_impl>(args);
} }
inline gr::io_signature::sptr make_io_signature( const std::string &args )
{
size_t max_nchan = 0;
size_t dev_nchan = 0;
const size_t nchan = std::max<size_t>(dev_nchan, 1); // assume at least one
return gr::io_signature::make(nchan, nchan, sizeof(gr_complex));
}
/* /*
* The private constructor * The private constructor
*/ */
source_impl::source_impl(const std::string & args) source_impl::source_impl(const std::string & args)
: gr::hier_block2("source", : gr::hier_block2("source",
gr::io_signature::make(0,0,0), gr::io_signature::make(0,0,0),
make_io_signature(args)) args_to_io_signature(args))
{ {
//connect(self(), 0, d_firstblock, 0); //connect(self(), 0, d_firstblock, 0);
// connect other blocks // connect other blocks
//connect(d_lastblock, 0, self(), 0); //connect(d_lastblock, 0, self(), 0);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment