libbladeRF 2.0 Release Notes
Attention
libbladeRF 2.0 introduces breaking changes to the parameter lists for bladerf_get_frequency(), bladerf_stream(), and bladerf_sync_config().
Existing code using these functions must be updated to be compatible with this version. See the RF frequencies are now uint64_t and Streaming API changes for MIMO sections for guidance.
Additionally, if you use bladerf_get_gain() and/or bladerf_set_gain(), be aware that the gain range for these functions has shifted. See bladerf_{get,set}_gain range standardization for guidance.

This document describes many of the changes in libbladeRF 2.0, our latest major version increment that features significant changes. This release adds support for the bladeRF 2.0 Micro, and improves the API for all bladeRF products. This is also the first release with bindings for the Python programming language.

We are very excited to release this library alongside the new bladeRF Micro. libbladeRF 2.0 began as a fork of the bladeRF codebase. Across the FPGA, firmware, and host software trees, we added 95,000+ lines (and deleted 18,000+) to the bladeRF codebase, in more than 600 commits.

In case you experience any bugs or missing features, please use our issue tracker at https://github.com/Nuand/bladeRF/issues to report any problems you encounter with this release. Also, visit our forums at https://nuand.com/forums/ to discuss this release with other bladeRF users.

# Significant changes to the libbladeRF API

We attempted to minimize the changes required to make existing applications work with libbladeRF 2.0. However, the nature of this project required some changes to the API. Many of the changes can be transparently handled by compilers. However, applications will generally need to be recompiled and relinked to work with this version.

Each topic has a table describing the affected functions, the importance of this change, and the recommended action. Please see Definitions for "Importance" for definitions of the words used in the "Importance" column.

## RF frequencies are now uint64_t

In libbladeRF 1.x, RF frequencies were specified as 32-bit unsigned int. To support the wider frequency range of the bladeRF Micro, frequencies are now specified as uint64_t, which is typedef'd as bladerf_frequency.

Required actions
API ComponentImportanceAction

The frequency parameter is now a pointer to a bladerf_frequency.

Warning
Applications using this function must be modified to pass in the correct type.

Required for full compatibility

Note
This action is required to use RF frequencies above ~4 GHz.

The frequency parameter is now of type bladerf_frequency.

Note
Compilers will generally implicitly cast unsigned int to bladerf_frequency, but frequencies above UINT32_MAX will not be available.
Remarks

## Streaming API changes for MIMO

The data transfer APIs were expanded to support MIMO (multiple-input, multiple-output). This capability is used to transmit or receive samples via multiple RF ports simultaneously.

Required actions
API ComponentImportanceAction

The bladerf_module argument has been replaced with bladerf_channel_layout.

Replace BLADERF_MODULE_RX with BLADERF_RX_X1, and BLADERF_MODULE_TX with BLADERF_TX_X1.

Warning
Applications using these functions must be modified to pass in the correct type.
Note
Existing bladerf_module values are valid for SISO applications, but an explicit cast is usually required:
void configure_module_sync(bladerf_module module) {
// ...
status = bladerf_sync_config(dev, (bladerf_channel_layout)module, format, num_buffers, buffer_size, num_transfers, stream_timeout);
// ...
}
API_EXPORT int CALL_CONV bladerf_sync_config(struct bladerf *dev, bladerf_channel_layout layout, bladerf_format format, unsigned int num_buffers, unsigned int buffer_size, unsigned int num_transfers, unsigned int stream_timeout)

The bladerf_module argument has been replaced with bladerf_direction.

Replace BLADERF_MODULE_RX with BLADERF_RX, and BLADERF_MODULE_TX with BLADERF_TX.

Note
Existing bladerf_module values are still valid, and a cast should not be necessary.
bladerf_sync_tx() Informational The samples parameter is now a pointer to a const, to enforce safety. This should not impact user code.
Remarks
What is a channel?
BLADERF_FORMAT_SC16_Q11 describes the sample interleaving format.
bladerf_interleave_stream_buffer() - Interleaves contiguous blocks of samples in preparation for MIMO TX.
bladerf_deinterleave_stream_buffer() - Deinterleaves samples into contiguous blocks after MIMO RX.
bladerf_get_channel_count() - Get the number of RX or TX channels supported by the given device.

In libbladeRF 1.x, bladerf_module was an enum with two valid choices: BLADERF_MODULE_RX and BLADERF_MODULE_TX. To support MIMO, this enum has been replaced with bladerf_channel, and a pair of convenience macros have been defined to specify channels: BLADERF_CHANNEL_RX(ch) and BLADERF_CHANNEL_TX(ch).

For backwards compatibility, bladerf_module is a typedef of bladerf_channel, and the BLADERF_MODULE_RX and BLADERF_MODULE_TX identifiers are now macros for BLADERF_CHANNEL_RX(0) and BLADERF_CHANNEL_TX(0) respectively.

Note that some bladerf_module instances have been replaced with bladerf_direction and bladerf_channel_layout depending on context. See the Streaming API changes for MIMO section elsewhere in this document.

Required actions
API ComponentImportanceAction

Required for full compatibility

Note
This action is required to fully support devices with multiple channels. Without these changes, only the first channel will be available for use.

Replace bladerf_module with bladerf_channel.

Replace BLADERF_MODULE_RX with BLADERF_CHANNEL_RX(0), or generally, BLADERF_CHANNEL_RX(channel_number)

Replace BLADERF_MODULE_TX with BLADERF_CHANNEL_TX(0), or generally, BLADERF_CHANNEL_TX(channel_number)

Remarks
What is a channel?
bladerf_get_channel_count() - Get the number of RX or TX channels supported by the given device.

## Defined BLADERF_*_{MAX,MIN,etc} constants replaced by bladerf_get_*_range functions

The precompiler constants for supported minimum/maximum values have been deprecated and replaced with a set of context-aware functions. The old constants will be removed in a later release.

Required actions
API ComponentImportanceAction

Required for full compatibility

Note
This action is required for proper functioning of new bladeRF models. The old constants are only valid for the original bladeRF, and are not valid for other models.

Use bladerf_get_gain_stage_range() to retrieve the range of allowable gains for a specific gain stage.

BLADERF_SAMPLERATE_MIN Use bladerf_get_sample_rate_range() to retrieve the range of allowable sample rates for a given channel.
BLADERF_BANDWIDTH_MIN Use bladerf_get_bandwidth_range() to retrieve the supported range of bandwidths for a given channel.

Use bladerf_get_frequency_range() to retrieve the supported range of frequencies for a given channel.

Note
The range will vary depending on the particular hardware configuration, such as if a XB-200 is attached.

An example use of bladerf_get_frequency_range():

{
int status;
status = bladerf_get_frequency_range(dev, channel, &range);
if (status < 0) {
// error case
}
return ((frequency / range.scale) >= range.min && (frequency / range.scale) <= range.max);
}
Remarks
• Don't use the legacy BLADERF_*_{MIN,MAX} defines or any hardcoded values derived from them.
• Don't assume that the ranges will remain constant throughout operation, or that they are the same for all channels.
• Don't hardcode ranges, or guess them based on the board model.
• Do remember that the ranges can change depending on configuration, e.g. bladerf_get_gain_range() may return different values for an RX channel depending on the configured center frequency.
• Do call bladerf_get_*_range() every time you need to know – don't cache it!
• Do test to ensure user-supplied values are valid before using them, when possible.
• Do handle BLADERF_ERR_RANGE errors when setting values, especially if you don't check for validity first. The library will only return this if it is not sensible to clamp the value to be within range, e.g. with bladerf_set_sample_rate().
bladerf_get_gain_stages() - Get a list of available gain stages.
bladerf_set_gain() - Set overall system gain.
bladerf_get_gain() - Get overall system gain.

## bladerf_{get,set}_gain range standardization

Previously, the ranges used by bladerf_get_gain() and bladerf_set_gain() were somewhat arbitrary, with a value of 0 being the minimum possible gain, and the maximum possible gain being the sum of the max gain for all gain stages.

To allow the same gain settings to produce similar results on all bladeRF models, we've adjusted the gain ranges for these two functions to define 60 dB as the maximum available gain on RX, and roughly +0 dBm output power on TX.

Required actions
API ComponentImportanceAction

Required for full compatibility

Note
This change affects the meaning of the values passed to/from these functions, and the impact should be reviewed to avoid unexpected results.
60 dB is now defined as:
• RX channels: Maximum RX Gain
• TX channels: +0 dBm TX power (CW, approximate)
Note
Individual gain stages (bladerf_set_gain_stage() and bladerf_get_gain_stage()) still expect raw hardware-specific values.
The TX Gain is not calibrated, and the actual output power will vary from board to board, frequency to frequency, and even between different output ports on the same board. Applications requiring precise control of TX power should consider calibration.
System gain proportioning

## Common parameter types now have typedefs

For semantic clarity, common parameter types now have typedefs.

Required actions
API ComponentImportanceAction

The declarations for these functions were changed to use defined types. No changes are immediately necessary, with the exception of bladerf_frequency.

The new types are:

RF frequencies are now uint64_t
Todo:
Issue #577: Using printf() with a bladerf_frequency or bladerf_timestamp currently require knowing that they are actually uint64_t, e.g. printf("the frequency is %" PRIu64 " Hz\n", freq);.

# New features

## Multiple platform support

We reorganized libbladeRF to easily support multiple hardware platforms. You will find a new directory tree, host/libraries/libbladeRF/src/board/, containing subdirectories for each supported platform (currently bladerf1/ for the LMS6002D-based bladeRF family, and bladerf2/ for the AD9361-based bladeRF Micro family).

Likewise, product-specific API calls have been moved into two new header files: bladeRF1.h and bladeRF2.h. Functions which apply to all boards remain in libbladeRF.h.

Refer to bladeRF1.h and bladeRF2.h for a list of affected functions.
Note
Using API calls specified in bladeRF1.h or bladeRF2.h is not recommended for most use cases. They are provided for backwards compatibility and low-level hardware control, and are subject to change.

We also rearranged a number of source files into subdirectories of host/libraries/libbladeRF/src/. In addition to the pre-existing backend/, you'll also find board/ (product-specific code), driver/ (device drivers), expansion/ (expansion board drivers), helpers/ (helpful utility functions), and streaming/ (sample streaming code).

## Gain control improvements

The original manual gain control functionality in libbladeRF was very low-level and hardware-specific, and requires significant knowledge of the underlying RF module to adjust. As such, new gain control methods have been introduced to the API, and the following functions are now deprecated:

Instead, applications should use one of approaches described below.

### Automatic Gain Control (AGC)

Automatic gain control is available for RX channels, starting with libbladeRF v1.9.0 and FPGA v0.7.0. AGC continually adjusts the system's gain to ensure the received signal has a high dynamic range, while avoiding clipping.

As of this writing, the available gain modes are:

Note
{
int i, status;
const struct bladerf_gain_modes *modes = NULL;
// What gain modes are available?
status = bladerf_get_gain_modes(dev, channel, &modes);
if (status < 0) {
// error case
}
for (i = 0; i < status; ++i) {
printf("enum %d is gain mode %s\n", modes[i]->mode, modes[i]->name);
}
// Get current gain mode
status = bladerf_get_gain_mode(dev, channel, &mode);
if (status < 0) {
// error case
}
printf("current gain mode: %d\n", mode);
// Enable AGC
status = bladerf_set_gain_mode(dev, channel, mode);
if (status < 0) {
// error case
}
}
const char * name

### System gain proportioning

In previous versions, setting the gain required careful proportioning of gain between LNAs and VGAs. To reduce the implementation burden, an overall gain may now be specified, and the RFIC's gain stages will be set appropriately.

The gain scales are defined such that a 60 dB gain on a TX channel is approximately 0 dBm CW output, and a 60 dB gain on a RX channel is the maximum available amplification.

Note
bladerf_set_gain() may be unavailable or may not operate as expected if Automatic Gain Control (AGC) is enabled, or if the channel is not currently enabled.
The range returned by bladerf_get_gain_range() may vary depending on the selected center frequency.
void gain_example(struct bladerf *dev, bladerf_channel channel, int gain)
{
int old_gain, status;
const struct bladerf_range *range = NULL;
// What is the valid range?
status = bladerf_get_gain_range(dev, channel, &range);
if (status < 0) {
// error case
}
// What is the current gain?
status = bladerf_get_gain(dev, channel, &old_gain);
if (status < 0) {
// error case
};
printf("Channel %d current gain: %4d dB (Range: [%g, %g])\n",
channel, old_gain, range->min * range->scale, range->max * range->scale);
// Set the new gain value
status = bladerf_set_gain(dev, channel, gain);
if (status < 0) {
// error case
};
}
...
gain_example(dev, BLADERF_CHANNEL_TX(0), 60); // set 60 dB TX gain (~ 0 dBm)
gain_example(dev, BLADERF_CHANNEL_RX(0), 60); // set 60 dB RX gain (max)
int64_t max
int64_t min

### Individual gain stage control

Advanced implementations that need to directly configure the gain stages may use the following family of functions:

Note
The values set here will be reflected in bladerf_get_gain(), but using bladerf_set_gain() will override any individual gain stage settings on a particular channel.
bladerf_set_gain_stage() may be unavailable or may not operate as expected if Automatic Gain Control (AGC) is enabled, or if the channel is not currently enabled.
The range returned by bladerf_get_gain_stage_range() may vary depending on the selected center frequency.

## New hardware features

libbladeRF 2.0 includes support for new hardware features on the bladeRF Micro.

### Bias tees

The bias tees apply a +5 VDC bias to the SMA connectors, which may be used for powering active antennas or inline amplifiers.

Warning
Enabling the bias tee on one channel enables it for all channels in that direction; e.g. enabling RX1 will enable both RX1 and RX2 simultaneously. Use caution if there are multiple devices attached to the bladeRF Micro.

### Clock references and controls

An external frequency reference may be connected to the J95 U.FL connector ("REFIN") to discipline the onboard VCTCXO. By default, this port expects 10 MHz, but it can be configured for reference frequencies between 5 MHz and 300 MHz.

bladerf_get_pll_lock_state() - verifying PLL lock

Alternatively, a 38.4 MHz clock may be provided into the CLKIN port.

bladerf_get_clock_select(), bladerf_set_clock_select() - select between internal and external (J93) clock

There is also a CLKOUT port, which can provide a buffered 38.4 MHz system clock output.

bladerf_get_clock_output(), bladerf_set_clock_output() - enable or disable clock output (J92)

### Power status

Functions are provided to determine how the board is currently being powered, what the bus voltage is, and what the system current and power draws are.

bladerf_get_power_source() - query how the board is currently powered

### RFIC temperature

The RFIC has an onboard temperature sensor, which may be useful for environmental monitoring, or for determining if the RFIC's synthesizers should be re-tuned after a significant temperature shift.

# Further information

## What is a channel?

In the bladeRF architecture, a channel is a single, unidirectional RF path. There is a 1:1 mapping between a bladerf_channel and a physical RF port.

On the original bladeRF, there are two channels available:

On the bladeRF Micro, there are four channels available:

Generally speaking, you will want to apply settings to a specific channel.

Note that some groups of channels may share some settings on some hardware: for example, if you bladerf_set_frequency() on a bladeRF Micro's BLADERF_CHANNEL_RX(0), it will also change the frequency of BLADERF_CHANNEL_RX(1), because both RX ports share the same local oscillator.

There are some functions which always apply to all the RX channels or all the TX channels. These accept a bladerf_direction argument:

Finally, there are two functions which accept a bladerf_channel_layout. This specifies two things: the direction (RX vs TX), and the number of channels interleaved in the sample buffers (currently 1 or 2).

## Definitions for "Importance"

WordMeaning
Required This change must be performed to build code against libbladeRF 2.0. Compile errors will result if you fail to do so.
Required for full compatibility

This change is not required for building, but some functionality may be missing or unavailable with some devices.

A Note will be included to describe the impact of not making this change.

Optional This change is optional, but recommended for clarity and/or future compatibility.
Informational This is an informational item, and no action is necessary or expected.