gr-osmosdr/lib/bladerf/bladerf_common.h

295 lines
12 KiB
C++

/* -*- 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 <string>
#include <vector>
#include <boost/thread/mutex.hpp>
#include <boost/weak_ptr.hpp>
#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 boost::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 boost::mutex _devs_mutex; /**< mutex for access to _devs */
static std::list<boost::weak_ptr<struct bladerf>> _devs; /**< dev cache */
};
#endif