summaryrefslogtreecommitdiff
path: root/Radio/HW/BladeRF/include/libbladeRF.h
diff options
context:
space:
mode:
authorArturs Artamonovs <arturs.artamonovs@protonmail.com>2024-11-03 15:56:55 +0000
committerArturs Artamonovs <arturs.artamonovs@protonmail.com>2024-11-03 15:56:55 +0000
commitcf4444e7390365df43ecbd3d130015c1e06ef88f (patch)
tree8a6eb114135a04d5efd5af213577b4fac47532ae /Radio/HW/BladeRF/include/libbladeRF.h
parentca50c0f64f1b2fce46b4cb83ed111854bac13852 (diff)
downloadPrySDR-cf4444e7390365df43ecbd3d130015c1e06ef88f.tar.gz
PrySDR-cf4444e7390365df43ecbd3d130015c1e06ef88f.zip
BladeRF library compiles
Diffstat (limited to 'Radio/HW/BladeRF/include/libbladeRF.h')
-rw-r--r--Radio/HW/BladeRF/include/libbladeRF.h4501
1 files changed, 4501 insertions, 0 deletions
diff --git a/Radio/HW/BladeRF/include/libbladeRF.h b/Radio/HW/BladeRF/include/libbladeRF.h
new file mode 100644
index 0000000..6124465
--- /dev/null
+++ b/Radio/HW/BladeRF/include/libbladeRF.h
@@ -0,0 +1,4501 @@
+/**
+ * @file libbladeRF.h
+ *
+ * @brief bladeRF library
+ *
+ * Copyright (C) 2013-2017 Nuand LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef LIBBLADERF_H_
+#define LIBBLADERF_H_
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/**
+ * @ingroup FN_LIBRARY_VERSION
+ *
+ * libbladeRF API version
+ *
+ * As of libbladeRF v1.5.0, this macro is defined to assist with feature
+ * detection. Generally, this will be used as follows:
+ *
+ * @code
+ * #if defined(LIBBLADERF_API_VERSION) && (LIBBLADERF_API_VERSION >= 0x01050000)
+ * // ... Use features added in libbladeRF v1.5.0 ...
+ * #endif
+ * @endcode
+ *
+ * This value is defined as follows:
+ * `(major << 24) | (minor << 16) | (patch << 8) | (reserved << 0)`
+ *
+ * The reserved field may be used at a later date to denote additions between
+ * releases. It will be set to zero when not used.
+ *
+ * This value is intended to track the values returned by bladerf_version().
+ * Fields are updated per the scheme defined here:
+ *
+ * https://github.com/Nuand/bladeRF/blob/master/doc/development/versioning.md
+ */
+#define LIBBLADERF_API_VERSION (0x02050100)
+
+#ifdef __cplusplus
+extern "C" {
+#else
+/**
+ * stdbool.h is not applicable for C++ programs, as the language inherently
+ * provides the bool type.
+ *
+ * Users of Visual Studio 2012 and earlier will need to supply a stdbool.h
+ * implementation, as it is not included with the toolchain. One is provided
+ * with the bladeRF source code. Visual Studio 2013 onward supplies this header.
+ */
+#include <stdbool.h>
+#endif
+
+// clang-format off
+#if defined _WIN32 || defined __CYGWIN__
+# include <windows.h>
+# define CALL_CONV __cdecl
+# ifdef __GNUC__
+# define API_EXPORT __attribute__ ((dllexport))
+# else
+# define API_EXPORT __declspec(dllexport)
+# endif
+#elif defined _DOXYGEN_ONLY_ || defined MATLAB_LINUX_THUNK_BUILD_
+ /** Marks an API routine to be made visible to the dynamic loader.
+ * This is OS and/or compiler-specific. */
+# define API_EXPORT
+ /** Specifies calling convention, if necessary.
+ * This is OS and/or compiler-specific. */
+# define CALL_CONV
+#else
+# define API_EXPORT __attribute__ ((visibility ("default")))
+# define CALL_CONV
+#endif
+// clang-format on
+
+/**
+ * @defgroup FN_INIT Initialization
+ *
+ * The functions in this section provide the ability query and inspect available
+ * devices, initialize them, and deinitialize them.
+ *
+ * See the \link boilerplate.html Device configuration boilerplate\endlink
+ * page for an overview on how to open and configure a device.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/** This structure is an opaque device handle */
+struct bladerf;
+
+/**
+ * Backend by which the host communicates with the device
+ */
+typedef enum {
+ BLADERF_BACKEND_ANY, /**< "Don't Care" -- use any available
+ * backend */
+ BLADERF_BACKEND_LINUX, /**< Linux kernel driver */
+ BLADERF_BACKEND_LIBUSB, /**< libusb */
+ BLADERF_BACKEND_CYPRESS, /**< CyAPI */
+ BLADERF_BACKEND_DUMMY = 100, /**< Dummy used for development purposes */
+} bladerf_backend;
+
+/** Length of device description string, including NUL-terminator */
+#define BLADERF_DESCRIPTION_LENGTH 33
+
+/** Length of device serial number string, including NUL-terminator */
+#define BLADERF_SERIAL_LENGTH 33
+
+/**
+ * Information about a bladeRF attached to the system
+ */
+struct bladerf_devinfo {
+ bladerf_backend backend; /**< Backend to use when connecting to
+ * device */
+ char serial[BLADERF_SERIAL_LENGTH]; /**< Device serial number string */
+ uint8_t usb_bus; /**< Bus # device is attached to */
+ uint8_t usb_addr; /**< Device address on bus */
+ unsigned int instance; /**< Device instance or ID */
+
+ /** Manufacturer description string */
+ char manufacturer[BLADERF_DESCRIPTION_LENGTH];
+ char product[BLADERF_DESCRIPTION_LENGTH]; /**< Product description string */
+};
+
+/**
+ * Information about a bladeRF attached to the system
+ */
+struct bladerf_backendinfo {
+ int handle_count; /**< Backend handle count */
+ void *handle; /**< Backend handle for device */
+ int lock_count; /**< Backend lock count */
+ void *lock; /**< Backend lock for device */
+};
+
+/**
+ * Open specified device using a device identifier string. See
+ * bladerf_open_with_devinfo() if a device identifier string is not readily
+ * available.
+ *
+ * The general form of the device identifier string is;
+ * @code{.txt}
+ * <backend>:[device=<bus>:<addr>] [instance=<n>] [serial=<serial>]
+ * @endcode
+ *
+ * An empty ("") or NULL device identifier will result in the first
+ * encountered device being opened (using the first discovered backend)
+ *
+ * The 'backend' describes the mechanism used to communicate with the device,
+ * and may be one of the following:
+ * - *: Any available backend
+ * - libusb: libusb (See libusb changelog notes for required version, given
+ * your OS and controller)
+ * - cypress: Cypress CyUSB/CyAPI backend (Windows only)
+ *
+ * If no arguments are provided after the backend, the first encountered
+ * device on the specified backend will be opened. Note that a backend is
+ * required, if any arguments are to be provided.
+ *
+ * Next, any provided arguments are provide as used to find the desired device.
+ * Be sure not to over constrain the search. Generally, only one of the above
+ * is required -- providing all of these may over constrain the search for the
+ * desired device (e.g., if a serial number matches, but not on the specified
+ * bus and address.)
+ *
+ * - device=\<bus\>:\<addr\>
+ * - Specifies USB bus and address. Decimal or hex prefixed by '0x' is
+ * permitted.
+ * - instance=\<n\>
+ * - Nth instance encountered, 0-indexed
+ * - serial=\<serial\>
+ * - Device's serial number.
+ *
+ * Below is an example of how to open a device with a specific serial
+ * number, using any avaiable backend supported by libbladeRF:
+ *
+ * @code {.c}
+ * struct bladerf *dev;
+ * int status = bladerf_open(&dev, "*:serial=f12ce1037830a1b27f3ceeba1f521413");
+ * if (status != 0) {
+ * fprintf(stderr, "Unable to open device: %s\n",
+ * bladerf_strerror(status));
+ * return status;
+ * }
+ * @endcode
+ *
+ * @param[out] device Update with device handle on success
+ * @param[in] device_identifier Device identifier, formatted as described
+ * above
+ *
+ * @return 0 on success, or value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_open(struct bladerf **device,
+ const char *device_identifier);
+
+/**
+ * Close device
+ *
+ * @note Failing to close a device will result in memory leaks.
+ *
+ * @post `device` is deallocated and may no longer be used.
+ *
+ * @param device Device handle previously obtained by bladerf_open(). This
+ * function does nothing if device is NULL.
+ */
+API_EXPORT
+void CALL_CONV bladerf_close(struct bladerf *device);
+
+/**
+ * Opens device specified by provided bladerf_devinfo structure
+ *
+ * This function is generally preferred over bladerf_open() when a device
+ * identifier string is not already provided.
+ *
+ * The most common uses of this function are to:
+ * - Open a device based upon the results of bladerf_get_device_list()
+ * - Open a specific device based upon its serial number
+ *
+ * Below is an example of how to use this function to open a device with a
+ * specific serial number:
+ *
+ * @snippet open_via_serial.c example_snippet
+ *
+ * @param[out] device Update with device handle on success
+ * @param[in] devinfo Device specification. If NULL, any available
+ * device will be opened.
+ *
+ * @return 0 on success, or value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_open_with_devinfo(struct bladerf **device,
+ struct bladerf_devinfo *devinfo);
+
+/**
+ * Obtain a list of bladeRF devices attached to the system
+ *
+ * @param[out] devices
+ *
+ * @return number of items in returned device list, or value from
+ * \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_device_list(struct bladerf_devinfo **devices);
+
+/**
+ * Free device list returned by bladerf_get_device_list()
+ *
+ * @param[inout] devices List of available devices
+ */
+API_EXPORT
+void CALL_CONV bladerf_free_device_list(struct bladerf_devinfo *devices);
+
+/**
+ * Initialize a device identifier information structure to a "wildcard" state.
+ *
+ * The values in each field will match any value for that field.
+ *
+ * @note Passing a bladerf_devinfo initialized with this function to
+ * bladerf_open_with_devinfo() will match the first device found.
+ */
+API_EXPORT
+void CALL_CONV bladerf_init_devinfo(struct bladerf_devinfo *info);
+
+/**
+ * Fill out a provided bladerf_devinfo structure, given an open device handle.
+ *
+ * @pre `dev` must be a valid device handle.
+ *
+ * @param dev Device handle previously obtained with bladerf_open()
+ * @param[out] info Device information populated by this function
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_devinfo(struct bladerf *dev,
+ struct bladerf_devinfo *info);
+
+
+/**
+ * Fill out a provided bladerf_backendinfo structure, given an open device handle.
+ *
+ * @pre `dev` must be a valid device handle.
+ *
+ * @param dev Device handle previously obtained with bladerf_open()
+ * @param[out] info Backend information populated by this function
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_backendinfo(struct bladerf *dev,
+ struct bladerf_backendinfo *info);
+/**
+ * Populate a device identifier information structure using the provided
+ * device identifier string.
+ *
+ * @param[in] devstr Device identifier string, formated as described
+ * in the bladerf_open() documentation
+ * @param[out] info Upon success, this will be filled out according to the
+ * provided device identifier string, with wildcards for
+ * any fields that were not provided.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_devinfo_from_str(const char *devstr,
+ struct bladerf_devinfo *info);
+
+/**
+ * Test whether two device identifier information structures match, taking
+ * wildcard values into account.
+ *
+ * @param[in] a the first bladerf_devinfo struct
+ * @param[in] b the second bladerf_devinfo struct
+ */
+API_EXPORT
+bool CALL_CONV bladerf_devinfo_matches(const struct bladerf_devinfo *a,
+ const struct bladerf_devinfo *b);
+
+/**
+ * Test whether a provided device string matches a device described by
+ * the provided bladerf_devinfo structure
+ *
+ * @param[in] dev_str Devices string, formated as described in the
+ * the documentation of bladerf_open
+ * @param[in] info Device info to compare with
+ *
+ * @return true upon a match, false otherwise
+ */
+API_EXPORT
+bool CALL_CONV bladerf_devstr_matches(const char *dev_str,
+ struct bladerf_devinfo *info);
+
+/**
+ * Retrieve the backend string associated with the specified
+ * backend enumeration value.
+ *
+ * @return A string that can used to specify the `backend` portion of a device
+ * identifier string. (See bladerf_open().)
+ */
+API_EXPORT
+const char *CALL_CONV bladerf_backend_str(bladerf_backend backend);
+
+/**
+ * Enable or disable USB device reset operation upon opening a device for
+ * future bladerf_open() and bladerf_open_with_devinfo() calls.
+ *
+ * This operation has been found to be necessary on Linux-based systems for
+ * some USB 3.0 controllers on Linux.
+ *
+ * This <b>does not</b> reset the state of the device in terms of its frequency,
+ * gain, sample rate, etc. settings.
+ *
+ * @param[in] enabled Set true to enable the use of the USB device reset,
+ * and false otherwise.
+ */
+API_EXPORT
+void CALL_CONV bladerf_set_usb_reset_on_open(bool enabled);
+
+/** @} (End FN_INIT) */
+
+/**
+ * @defgroup FN_INFO Device properties
+ *
+ * These functions provide the ability to query various pieces of information
+ * from an attached device.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Range structure
+ */
+struct bladerf_range {
+ int64_t min; /**< Minimum value */
+ int64_t max; /**< Maximum value */
+ int64_t step; /**< Step of value */
+ float scale; /**< Unit scale */
+};
+
+/**
+ * Serial number structure
+ */
+struct bladerf_serial {
+ char serial[BLADERF_SERIAL_LENGTH]; /**< Device serial number string */
+};
+
+/**
+ * Version structure for FPGA, firmware, libbladeRF, and associated utilities
+ */
+struct bladerf_version {
+ uint16_t major; /**< Major version */
+ uint16_t minor; /**< Minor version */
+ uint16_t patch; /**< Patch version */
+ const char *describe; /**< Version string with any additional suffix
+ * information.
+ *
+ * @warning Do not attempt to modify or free()
+ * this string. */
+};
+
+/**
+ * FPGA device variant (size)
+ */
+typedef enum {
+ BLADERF_FPGA_UNKNOWN = 0, /**< Unable to determine FPGA variant */
+ BLADERF_FPGA_40KLE = 40, /**< 40 kLE FPGA */
+ BLADERF_FPGA_115KLE = 115, /**< 115 kLE FPGA */
+ BLADERF_FPGA_A4 = 49, /**< 49 kLE FPGA (A4) */
+ BLADERF_FPGA_A5 = 77, /**< 77 kLE FPGA (A5) */
+ BLADERF_FPGA_A9 = 301 /**< 301 kLE FPGA (A9) */
+} bladerf_fpga_size;
+
+/**
+ * This enum describes the USB Speed at which the bladeRF is connected.
+ * Speeds not listed here are not supported.
+ */
+typedef enum {
+ BLADERF_DEVICE_SPEED_UNKNOWN,
+ BLADERF_DEVICE_SPEED_HIGH,
+ BLADERF_DEVICE_SPEED_SUPER
+} bladerf_dev_speed;
+
+/**
+ * FPGA configuration source
+ *
+ * Note: the numbering of this enum must match NuandFpgaConfigSource in
+ * firmware_common/bladeRF.h
+ */
+typedef enum {
+ BLADERF_FPGA_SOURCE_UNKNOWN = 0, /**< Uninitialized/invalid */
+ BLADERF_FPGA_SOURCE_FLASH = 1, /**< Last FPGA load was from flash */
+ BLADERF_FPGA_SOURCE_HOST = 2 /**< Last FPGA load was from host */
+} bladerf_fpga_source;
+
+/**
+ * Query a device's serial number (deprecated)
+ *
+ * @param dev Device handle
+ * @param[out] serial This user-supplied buffer, which <b>must be at least
+ * ::BLADERF_SERIAL_LENGTH bytes</b>, will be updated to
+ * contain a NUL-terminated serial number string. If an
+ * error occurs (as indicated by a non-zero return value),
+ * no data will be written to this buffer.
+ *
+ * @deprecated New code should use ::bladerf_get_serial_struct instead.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_serial(struct bladerf *dev, char *serial);
+
+/**
+ * Query a device's serial number
+ *
+ * @param dev Device handle
+ * @param[out] serial Pointer to a bladerf_serial structure, which will be
+ * populated with a `serial` string on success.
+ *
+ * Example code:
+ *
+ * @code
+ * struct bladerf_serial sn;
+ *
+ * status = bladerf_get_serial_struct(dev, &sn);
+ * if (status < 0) {
+ * // error handling here
+ * }
+ *
+ * printf("Serial number: %s\n", sn.serial);
+ * @endcode
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_serial_struct(struct bladerf *dev,
+ struct bladerf_serial *serial);
+
+/**
+ * Query a device's FPGA size
+ *
+ * @param dev Device handle
+ * @param[out] size Will be updated with the on-board FPGA's size. If an
+ * error occurs, no data will be written to this pointer.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_fpga_size(struct bladerf *dev,
+ bladerf_fpga_size *size);
+
+/**
+ * Query a device's expected FPGA bitstream length, in bytes
+ *
+ * @param dev Device handle
+ * @param[out] size Will be updated with expected bitstream length. If an
+ * error occurs, no data will be written to this pointer.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_fpga_bytes(struct bladerf *dev, size_t *size);
+
+/**
+ * Query a device's Flash size
+ *
+ * @param dev Device handle
+ * @param[out] size Will be updated with the size of the onboard flash,
+ * in bytes. If an error occurs, no data will be written
+ * to this pointer.
+ * @param[out] is_guess True if the flash size is a guess (using FPGA size).
+ * False if the flash ID was queried and its size
+ * was successfully decoded.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_flash_size(struct bladerf *dev,
+ uint32_t *size,
+ bool *is_guess);
+
+/**
+ * Query firmware version
+ *
+ * @param dev Device handle
+ * @param[out] version Updated to contain firmware version
+ *
+ * @return 0 on success, value from \ref RETCODES list upon failing to retrieve
+ * this information from the device.
+ */
+API_EXPORT
+int CALL_CONV bladerf_fw_version(struct bladerf *dev,
+ struct bladerf_version *version);
+
+/**
+ * Check FPGA configuration status
+ *
+ * @param dev Device handle
+ *
+ * @return 1 if FPGA is configured, 0 if it is not,
+ * and value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_is_fpga_configured(struct bladerf *dev);
+
+/**
+ * Query FPGA version
+ *
+ * @param dev Device handle
+ * @param[out] version Updated to contain firmware version
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_fpga_version(struct bladerf *dev,
+ struct bladerf_version *version);
+
+/**
+ * Query FPGA configuration source
+ *
+ * Determine whether the FPGA image was loaded from flash, or if it was
+ * loaded from the host, by asking the firmware for the last-known FPGA
+ * configuration source.
+ *
+ * @param dev Device handle
+ * @param[out] source Source of the configuration
+ *
+ * @return 0 on success, ::BLADERF_ERR_UNSUPPORTED if the
+ * BLADERF_CAP_FW_FPGA_SOURCE capability is not present, value from \ref
+ * RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_fpga_source(struct bladerf *dev,
+ bladerf_fpga_source *source);
+
+/**
+ * Obtain the bus speed at which the device is operating
+ *
+ * @param dev Device handle
+ *
+ * @return Device speed enumeration
+ */
+API_EXPORT
+bladerf_dev_speed CALL_CONV bladerf_device_speed(struct bladerf *dev);
+
+/**
+ * Get the board name
+ *
+ * @param dev Device handle
+ *
+ * @return Pointer to C string with the board's model name, either `bladerf1`
+ * for a bladeRF x40/x115, or `bladerf2` for a bladeRF Micro.
+ */
+API_EXPORT
+const char *CALL_CONV bladerf_get_board_name(struct bladerf *dev);
+
+/** @} (End FN_INFO) */
+
+/**
+ * @defgroup FN_CHANNEL Channel control
+ *
+ * The RX and TX channels are independently configurable. As such, many
+ * libbladeRF functions require a ::bladerf_channel parameter to specify the
+ * desired channel.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Channel type
+ *
+ * Example usage:
+ *
+ * @code{.c}
+ * // RX Channel 0
+ * bladerf_channel ch = BLADERF_CHANNEL_RX(0);
+ *
+ * // RX Channel 1
+ * bladerf_channel ch = BLADERF_CHANNEL_RX(1);
+ *
+ * // TX Channel 0
+ * bladerf_channel ch = BLADERF_CHANNEL_TX(0);
+ *
+ * // TX Channel 1
+ * bladerf_channel ch = BLADERF_CHANNEL_TX(1);
+ * @endcode
+ */
+typedef int bladerf_channel;
+
+/**
+ * RX Channel Macro
+ *
+ * Example usage:
+ *
+ * @code{.c}
+ * // RX Channel 0
+ * bladerf_channel ch = BLADERF_CHANNEL_RX(0);
+ *
+ * // RX Channel 1
+ * bladerf_channel ch = BLADERF_CHANNEL_RX(1);
+ * @endcode
+ */
+#define BLADERF_CHANNEL_RX(ch) (bladerf_channel)(((ch) << 1) | 0x0)
+
+/**
+ * TX Channel Macro
+ *
+ * Example usage:
+ *
+ * @code{.c}
+ * // TX Channel 0
+ * bladerf_channel ch = BLADERF_CHANNEL_TX(0);
+ *
+ * // TX Channel 1
+ * bladerf_channel ch = BLADERF_CHANNEL_TX(1);
+ * @endcode
+ */
+#define BLADERF_CHANNEL_TX(ch) (bladerf_channel)(((ch) << 1) | 0x1)
+
+/**
+ * Invalid channel
+ */
+#define BLADERF_CHANNEL_INVALID (bladerf_channel)(-1)
+
+/** @cond IGNORE */
+#define BLADERF_DIRECTION_MASK (0x1)
+/** @endcond */
+
+/** @cond IGNORE */
+/* Backwards compatible mapping to `bladerf_module`. */
+typedef bladerf_channel bladerf_module;
+#define BLADERF_MODULE_INVALID BLADERF_CHANNEL_INVALID
+#define BLADERF_MODULE_RX BLADERF_CHANNEL_RX(0)
+#define BLADERF_MODULE_TX BLADERF_CHANNEL_TX(0)
+/** @endcond */
+
+/**
+ * Convenience macro: true if argument is a TX channel
+ */
+#define BLADERF_CHANNEL_IS_TX(ch) (ch & BLADERF_TX)
+
+/**
+ * Stream direction
+ */
+typedef enum {
+ BLADERF_RX = 0, /**< Receive direction */
+ BLADERF_TX = 1, /**< Transmit direction */
+} bladerf_direction;
+
+/**
+ * Stream channel layout
+ */
+typedef enum {
+ BLADERF_RX_X1 = 0, /**< x1 RX (SISO) */
+ BLADERF_TX_X1 = 1, /**< x1 TX (SISO) */
+ BLADERF_RX_X2 = 2, /**< x2 RX (MIMO) */
+ BLADERF_TX_X2 = 3, /**< x2 TX (MIMO) */
+} bladerf_channel_layout;
+
+/**
+ * Get the number of RX or TX channels supported by the given device
+ *
+ * @param dev Device handle
+ * @param[in] dir Stream direction
+ *
+ * @return Number of channels
+ */
+API_EXPORT
+size_t CALL_CONV bladerf_get_channel_count(struct bladerf *dev,
+ bladerf_direction dir);
+
+/**
+ * @defgroup FN_GAIN Gain
+ *
+ * These functions provide control over the device's RX and TX gain stages.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Gain value, in decibels (dB)
+ *
+ * May be positive or negative.
+ */
+typedef int bladerf_gain;
+
+/**
+ * Gain control modes
+ *
+ * In general, the default mode is automatic gain control. This will
+ * continuously adjust the gain to maximize dynamic range and minimize clipping.
+ *
+ * @note Implementers are encouraged to simply present a boolean choice between
+ * "AGC On" (::BLADERF_GAIN_DEFAULT) and "AGC Off" (::BLADERF_GAIN_MGC).
+ * The remaining choices are for advanced use cases.
+ */
+typedef enum {
+ /** Device-specific default (automatic, when available)
+ *
+ * On the bladeRF x40 and x115 with FPGA versions >= v0.7.0, this is
+ * automatic gain control.
+ *
+ * On the bladeRF 2.0 Micro, this is BLADERF_GAIN_SLOWATTACK_AGC with
+ * reasonable default settings.
+ */
+ BLADERF_GAIN_DEFAULT,
+
+ /** Manual gain control
+ *
+ * Available on all bladeRF models.
+ */
+ BLADERF_GAIN_MGC,
+
+ /** Automatic gain control, fast attack (advanced)
+ *
+ * Only available on the bladeRF 2.0 Micro. This is an advanced option, and
+ * typically requires additional configuration for ideal performance.
+ */
+ BLADERF_GAIN_FASTATTACK_AGC,
+
+ /** Automatic gain control, slow attack (advanced)
+ *
+ * Only available on the bladeRF 2.0 Micro. This is an advanced option, and
+ * typically requires additional configuration for ideal performance.
+ */
+ BLADERF_GAIN_SLOWATTACK_AGC,
+
+ /** Automatic gain control, hybrid attack (advanced)
+ *
+ * Only available on the bladeRF 2.0 Micro. This is an advanced option, and
+ * typically requires additional configuration for ideal performance.
+ */
+ BLADERF_GAIN_HYBRID_AGC,
+} bladerf_gain_mode;
+
+/** Default AGC mode (for backwards compatibility with libbladeRF 1.x) */
+#define BLADERF_GAIN_AUTOMATIC BLADERF_GAIN_DEFAULT
+/** Manual gain control (for backwards compatibility with libbladeRF 1.x) */
+#define BLADERF_GAIN_MANUAL BLADERF_GAIN_MGC
+
+/**
+ * Mapping between C string description of gain modes and bladerf_gain_mode
+ */
+struct bladerf_gain_modes {
+ const char *name; /**< Name of gain mode */
+ bladerf_gain_mode mode; /**< Gain mode enumeration */
+};
+
+/**
+ * Set overall system gain
+ *
+ * This sets an overall system gain, optimally proportioning the gain between
+ * multiple gain stages if applicable.
+ *
+ * @see Use bladerf_get_gain_range() to determine the range of system gain.
+ *
+ * On receive channels, 60 dB is the maximum gain level.
+ *
+ * On transmit channels, 60 dB is defined as approximately 0 dBm. Note that
+ * this is not a calibrated value, and the actual output power will vary based
+ * on a multitude of factors.
+ *
+ * @todo The gain ranges are not shifted to account for external accessories,
+ * such as amplifiers and LNAs.
+ *
+ * @note Values outside the valid gain range will be clamped.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] gain Desired gain, in dB
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_gain(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_gain gain);
+
+/**
+ * Get overall system gain
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] gain Gain, in dB
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_gain *gain);
+
+/**
+ * Set gain control mode
+ *
+ * Sets the mode for hardware AGC. Not all channels or boards will support
+ * all possible values (e.g. transmit channels); invalid combinations will
+ * return ::BLADERF_ERR_UNSUPPORTED.
+ *
+ * The special value of ::BLADERF_GAIN_DEFAULT will return hardware AGC to
+ * its default value at initialization.
+ *
+ * @see bladerf_gain_mode for implementation guidance
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] mode Desired gain mode
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_gain_mode(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_gain_mode mode);
+
+/**
+ * Get gain control mode
+ *
+ * Gets the current mode for hardware AGC. If the channel or board does not
+ * meaningfully have a gain mode (e.g. transmit channels), mode will be
+ * set to ::BLADERF_GAIN_DEFAULT and `0` will be returned.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] mode Gain mode
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain_mode(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_gain_mode *mode);
+
+/**
+ * Get available gain control modes
+ *
+ * Populates `modes` with a pointer to an array of structs containing the
+ * supported gain modes.
+ *
+ * This function may be called with `NULL` for `modes` to determine the number
+ * of gain modes supported.
+ *
+ * @see bladerf_gain_mode for implementation guidance
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] modes Supported gain modes
+ *
+ * @return Number of gain modes on success, value from \ref RETCODES list on
+ * failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain_modes(struct bladerf *dev,
+ bladerf_channel ch,
+ const struct bladerf_gain_modes **modes);
+
+/**
+ * Get range of overall system gain
+ *
+ * @note This may vary depending on the configured frequency, so it should be
+ * checked after setting the desired frequency.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] range Gain range
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain_range(struct bladerf *dev,
+ bladerf_channel ch,
+ const struct bladerf_range **range);
+
+/**
+ * Set the gain for a specific gain stage
+ *
+ * @note Values outside the valid gain range will be clipped.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] stage Gain stage name
+ * @param[in] gain Desired gain
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_gain_stage(struct bladerf *dev,
+ bladerf_channel ch,
+ const char *stage,
+ bladerf_gain gain);
+
+/**
+ * Set the gain for a specific gain stage
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] stage Gain stage name
+ * @param[out] gain Gain
+ *
+ * Note that, in some cases, gain may be negative (e.g. transmit channels).
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain_stage(struct bladerf *dev,
+ bladerf_channel ch,
+ const char *stage,
+ bladerf_gain *gain);
+
+/**
+ * Get gain range of a specific gain stage
+ *
+ * @note This may vary depending on the configured frequency, so it should be
+ * checked after setting the desired frequency.
+ *
+ * This function may be called with `NULL` for `range` to test if a given gain
+ * range exists.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] stage Gain stage name
+ * @param[out] range Gain range
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain_stage_range(struct bladerf *dev,
+ bladerf_channel ch,
+ const char *stage,
+ const struct bladerf_range **range);
+
+/**
+ * Get a list of available gain stages
+ *
+ * This function may be called with `NULL` for `stages`, or 0 for `count`, to
+ * determine the number of gain stages.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] stages Gain stage names
+ * @param[out] count Number to populate
+ *
+ * @return Number of gain stages on success, value from \ref RETCODES list on
+ * failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain_stages(struct bladerf *dev,
+ bladerf_channel ch,
+ const char **stages,
+ size_t count);
+
+/** @} (End of FN_GAIN) */
+
+/**
+ * @defgroup FN_SAMPLING Sample rate
+ *
+ * This section presents functionality pertaining to configuring the
+ * sample rate and mode of the device's RX and TX channels.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Sample rate, in samples per second (sps)
+ */
+typedef unsigned int bladerf_sample_rate;
+
+/**
+ * Rational sample rate representation
+ *
+ * Sample rates are in the form of
+ * @f[
+ * rate = integer + \frac{num}{den}
+ * @f]
+ */
+struct bladerf_rational_rate {
+ uint64_t integer; /**< Integer portion */
+ uint64_t num; /**< Numerator in fractional portion */
+ uint64_t den; /**< Denominator in fractional portion. This must be
+ * greater than 0. */
+};
+
+/**
+ * Configure the channel's sample rate to the specified rate in Hz.
+ *
+ * @note This requires the sample rate is an integer value of Hz. Use
+ * bladerf_set_rational_sample_rate() for more arbitrary values.
+ *
+ * @see Use bladerf_get_sample_rate_range() to determine the range of supported
+ * sample rates.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] rate Sample rate
+ * @param[out] actual If non-NULL, this is written with the actual
+ * sample rate achieved.
+ *
+ * @return 0 on success, value from \ref RETCODES list upon failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_sample_rate(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_sample_rate rate,
+ bladerf_sample_rate *actual);
+
+/**
+ * Configure the channel's sample rate as a rational fraction of Hz.
+ *
+ * @see Use bladerf_get_sample_rate_range() to determine the range of supported
+ * sample rates.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel to change
+ * @param[in] rate Rational sample rate
+ * @param[out] actual If non-NULL, this is written with the actual
+ * rational sample rate achieved.
+ *
+ * @return 0 on success, value from \ref RETCODES list upon failure
+ */
+API_EXPORT
+int CALL_CONV
+ bladerf_set_rational_sample_rate(struct bladerf *dev,
+ bladerf_channel ch,
+ struct bladerf_rational_rate *rate,
+ struct bladerf_rational_rate *actual);
+/**
+ * Get the channel's current sample rate in Hz
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] rate Current sample rate
+ *
+ * @return 0 on success, value from \ref RETCODES list upon failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_sample_rate(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_sample_rate *rate);
+
+/**
+ * Get the channel's supported range of sample rates
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] range Sample rate range
+ *
+ * @return 0 on success, value from \ref RETCODES list upon failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_sample_rate_range(struct bladerf *dev,
+ bladerf_channel ch,
+ const struct bladerf_range **range);
+
+/**
+ * Get the channel's sample rate in rational Hz
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] rate Current rational sample rate
+ *
+ * @return 0 on success, value from \ref RETCODES list upon failure
+ */
+API_EXPORT
+int CALL_CONV
+ bladerf_get_rational_sample_rate(struct bladerf *dev,
+ bladerf_channel ch,
+ struct bladerf_rational_rate *rate);
+
+/** @} (End of FN_SAMPLING) */
+
+/**
+ * @defgroup FN_BANDWIDTH Bandwidth
+ *
+ * This section defines functionality for configuring a channel's bandwidth. In
+ * most cases, one should define the bandwidth to be less than the sample rate
+ * to minimize the impact of aliasing.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Bandwidth, in hertz (Hz)
+ */
+typedef unsigned int bladerf_bandwidth;
+
+/**
+ * Set the bandwidth of the channel to the specified value in Hz
+ *
+ * The underlying device is capable of a discrete set of bandwidth values. The
+ * caller should check the `actual` parameter to determine which of these
+ * discrete bandwidth values is actually used for the requested bandwidth.
+ *
+ * @see Use bladerf_get_bandwidth_range() to determine the range of supported
+ * bandwidths.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] bandwidth Desired bandwidth
+ * @param[out] actual If non-NULL, written with the actual bandwidth that
+ * the device was able to achieve.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_bandwidth(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_bandwidth bandwidth,
+ bladerf_bandwidth *actual);
+
+/**
+ * Get the bandwidth of the channel
+ *
+ * @param dev Device Handle
+ * @param[in] ch Channel
+ * @param[out] bandwidth Actual bandwidth in Hz
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_bandwidth(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_bandwidth *bandwidth);
+
+/**
+ * Get the supported range of bandwidths for a channel
+ *
+ * @param dev Device Handle
+ * @param[in] ch Channel
+ * @param[out] range Bandwidth range
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_bandwidth_range(struct bladerf *dev,
+ bladerf_channel ch,
+ const struct bladerf_range **range);
+
+/** @} (End of FN_BANDWIDTH) */
+
+/**
+ * @defgroup FN_TUNING Frequency
+ *
+ * These functions provide the ability to tune the RX and TX channels.
+ *
+ * See \link tuning.html this page\endlink for more detailed information about
+ * how the API performs this tuning, and for example code snippets.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * RF center frequency, in hertz (Hz)
+ *
+ * @see Format macros for fprintf() and fscanf(): `BLADERF_PRIuFREQ`,
+ * `BLADERF_PRIxFREQ`, `BLADERF_SCNuFREQ`, `BLADERF_SCNxFREQ`
+ *
+ * @remark Prior to libbladeRF 2.0.0, frequencies were specified as
+ * `unsigned int`.
+ */
+typedef uint64_t bladerf_frequency;
+
+/** printf format for frequencies in unsigned decimal */
+#define BLADERF_PRIuFREQ PRIu64
+/** printf format for frequencies in hexadecimal */
+#define BLADERF_PRIxFREQ PRIx64
+/** scanf format for frequencies in unsigned decimal */
+#define BLADERF_SCNuFREQ SCNu64
+/** scanf format for frequencies in hexadecimal */
+#define BLADERF_SCNxFREQ SCNx64
+
+/**
+ * Select the appropriate band path given a frequency in Hz.
+ *
+ * @note Most API users will not need to use this function, as
+ * bladerf_set_frequency() calls this internally after tuning the device.
+ *
+ * The high band is used for `frequency` above 1.5 GHz on bladeRF1 and above
+ * 3.0 GHz on bladeRF2. Otherwise, the low band is used.
+ *
+ * @see bladerf_get_frequency_range() to determine the range of supported
+ * frequencies.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] frequency Tuned frequency
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_select_band(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_frequency frequency);
+
+/**
+ * Set channel's frequency in Hz.
+ *
+ * @note On the bladeRF1 platform, it is recommended to keep the RX and TX
+ * frequencies at least 1 MHz apart, and to digitally mix on the RX side
+ * if reception closer to the TX frequency is required.
+ *
+ * @note On the bladeRF2, there is one oscillator for all RX channels and one
+ * oscillator for all TX channels. Therefore, changing one channel will
+ * change the frequency of all channels in that direction.
+ *
+ * This function calls bladerf_select_band() internally, and performs all
+ * other tasks required to prepare the channel for the given frequency.
+ *
+ * @see bladerf_get_frequency_range() to determine the range of supported
+ * frequencies.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] frequency Desired frequency
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_frequency(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_frequency frequency);
+/**
+ * Get channel's current frequency in Hz
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] frequency Current frequency
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_frequency(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_frequency *frequency);
+
+/**
+ * Get the supported range of frequencies for a channel
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] range Frequency range
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_frequency_range(struct bladerf *dev,
+ bladerf_channel ch,
+ const struct bladerf_range **range);
+
+/** @} (End of FN_TUNING) */
+
+/**
+ * @defgroup FN_LOOPBACK Internal loopback
+ *
+ * The bladeRF provides a variety of loopback modes to aid in development and
+ * testing.
+ *
+ * In general, the digital or baseband loopback modes provide the most "ideal"
+ * operating conditions, while the internal RF loopback modes introduce more of
+ * the typical nonidealities of analog systems.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Loopback options
+ */
+typedef enum {
+ /** Disables loopback and returns to normal operation. */
+ BLADERF_LB_NONE = 0,
+
+ /** Firmware loopback inside of the FX3 */
+ BLADERF_LB_FIRMWARE,
+
+ /** Baseband loopback. TXLPF output is connected to the RXVGA2 input. */
+ BLADERF_LB_BB_TXLPF_RXVGA2,
+
+ /** Baseband loopback. TXVGA1 output is connected to the RXVGA2 input. */
+ BLADERF_LB_BB_TXVGA1_RXVGA2,
+
+ /** Baseband loopback. TXLPF output is connected to the RXLPF input. */
+ BLADERF_LB_BB_TXLPF_RXLPF,
+
+ /** Baseband loopback. TXVGA1 output is connected to RXLPF input. */
+ BLADERF_LB_BB_TXVGA1_RXLPF,
+
+ /**
+ * RF loopback. The TXMIX output, through the AUX PA, is connected to the
+ * output of LNA1.
+ */
+ BLADERF_LB_RF_LNA1,
+
+ /**
+ * RF loopback. The TXMIX output, through the AUX PA, is connected to the
+ * output of LNA2.
+ */
+ BLADERF_LB_RF_LNA2,
+
+ /**
+ * RF loopback. The TXMIX output, through the AUX PA, is connected to the
+ * output of LNA3.
+ */
+ BLADERF_LB_RF_LNA3,
+
+ /** RFIC digital loopback (built-in self-test) */
+ BLADERF_LB_RFIC_BIST,
+} bladerf_loopback;
+
+/**
+ * Mapping of human-readable names to loopback modes
+ */
+struct bladerf_loopback_modes {
+ const char *name; /**< Name of loopback mode */
+ bladerf_loopback mode; /**< Loopback mode enumeration */
+};
+
+/**
+ * Get loopback modes
+ *
+ * Populates `modes` with a pointer to an array of structs containing the
+ * supported loopback modes.
+ *
+ * This function may be called with `NULL` for `modes` to determine the number
+ * of loopback modes supported.
+ *
+ * @param dev Device handle
+ * @param[out] modes Supported loopback modes
+ *
+ * @return Number of loopback modes on success, value from \ref RETCODES list
+ * on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_loopback_modes(
+ struct bladerf *dev, const struct bladerf_loopback_modes **modes);
+
+/**
+ * Test if a given loopback mode is supported on this device.
+ *
+ * @param dev Device handle
+ * @param[in] mode bladerf_loopback enum to check
+ *
+ * @return true if supported, false if not (or on error)
+ */
+API_EXPORT bool CALL_CONV bladerf_is_loopback_mode_supported(
+ struct bladerf *dev, bladerf_loopback mode);
+
+/**
+ * Apply specified loopback mode
+ *
+ * @note Loopback modes should only be enabled or disabled while the RX and TX
+ * channels are both disabled (and therefore, when no samples are being
+ * actively streamed). Otherwise, unexpected behavior may occur.
+ *
+ * @param dev Device handle
+ * @param[in] lb Loopback mode. Note that BLADERF_LB_NONE disables the
+ * use of loopback functionality.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_loopback(struct bladerf *dev, bladerf_loopback lb);
+
+/**
+ * Get current loopback mode
+ *
+ * @param dev Device handle
+ * @param[out] lb Current loopback mode
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_loopback(struct bladerf *dev, bladerf_loopback *lb);
+
+/** @} (End of FN_LOOPBACK) */
+
+/**
+ * @defgroup FN_TRIG Triggers
+ *
+ * Trigger functionality introduced in bladeRF FPGA v0.6.0 allows TX and/or RX
+ * samples to be gated via a trigger signal. This allows multiple devices to
+ * synchronize their TX/RX operations upon the reception of a trigger event.
+ *
+ * The set of functions presented in this section of the API provides control
+ * over this triggering functionality. It is intended that these functions be
+ * used \b prior to starting sample streams. Attempting to use these functions
+ * while streaming may yield undefined and undesirable behavior.
+ *
+ * These functions are thread-safe.
+ *
+ * For devices running at the same sample rate, the trigger event should
+ * achieve synchronization within +/- 1 sample on each device in the chain.
+ *
+ * @note As of FPGA v0.6.0, `mini_exp[1]` has been allocated as the trigger
+ * signal. However, this API section is designed to allow future signals
+ * to be added, including users' software and hardware customizations.
+ *
+ * @note <b>Important</b>: Ensure that you disarm triggers <b>before</b>
+ * stopping sample streams (i.e., calling bladerf_enable_module() with
+ * `enable = false`). Otherwise, the operation of shutting down streams
+ * will block for the entire duration of the stream timeout (or infinitely
+ * if the timeouts were set to 0).
+ *
+ * These functions are thread-safe.
+ *
+ * The standard usage of these functions is shown below. This example assumes:
+ *
+ * - The two devices are connected such they share a common ground and their
+ * `mini_exp[1]` pins are connected. `mini_exp[1]` is J71-4 on bladeRF
+ * x40/x115, and J51-1 on bladeRF xA4/xA5/xA9.
+ *
+ * - Both devices are already configured to utilize a common clock signal via
+ * the external SMB connection. Generally, this will consist of one device
+ * to outputting its reference clock via the SMB clock port, and
+ * configuring the other device(s) to use the SMB clock port as a reference
+ * clock input. This may be achieved using the bladerf_set_smb_mode()
+ * function, found in the \ref FN_SMB_CLOCK section.
+ *
+ *
+ * @code{.c}
+ *
+ * int status;
+ * bladerf_channel channel = BLADERF_CHANNEL_RX(0);
+ * bladerf_trigger_signal signal = BLADERF_TRIGGER_J71_4;
+ *
+ * // Allocate and initialize a bladerf_trigger structure for each
+ * // trigger in the system.
+ * struct bladerf_trigger trig_master, trig_slave;
+ *
+ * status = bladerf_trigger_init(dev_master, channel, signal, &trig_master);
+ * if (status == 0) {
+ * trig_master.role = BLADERF_TRIGGER_ROLE_MASTER;
+ * } else {
+ * goto handle_error;
+ * }
+ *
+ * status = bladerf_trigger_init(dev_slave1, channel, signal, &trig_slave);
+ * if (status == 0) {
+ * master_rx.role = BLADERF_TRIGGER_ROLE_SLAVE;
+ * } else {
+ * goto handle_error;
+ * }
+ *
+ * // Arm the triggering functionality on each device
+ * status = bladerf_trigger_arm(dev_master, &trig_master, true, 0, 0);
+ * if (status != 0) {
+ * goto handle_error;
+ * }
+ *
+ * status = bladerf_trigger_arm(dev_slave, &trig_slave, true, 0, 0);
+ * if (status != 0) {
+ * goto handle_error;
+ * }
+ *
+ * // Call bladerf_sync_config() and bladerf_sync_rx() on each device.
+ * // Ensure the timeout parameters used are long enough to accommodate
+ * // the expected time until the trigger will be fired.
+ * status = start_rx_streams(dev_master, dev_slave);
+ * if (status != 0) {
+ * goto handle_error;
+ * }
+ *
+ * // Fire the trigger signal
+ * status = bladerf_trigger_fire(dev_master, &trig_master);
+ * if (status != 0) {
+ * goto handle_error;
+ * }
+ *
+ * // Handle RX signals and then shut down streams.
+ * // Synchronized samples should now be reaching the host following the
+ * // reception of the external trigger signal.
+ * status = handle_rx_operations(dev_master, dev_slave);
+ * if (status != 0) {
+ * goto handle_error;
+ * }
+ *
+ * // Disable triggering on all devices to restore normal RX operation
+ * trig_master.role = BLADERF_TRIGGER_ROLE_DISABLED;
+ * status = bladerf_trigger_arm(dev_master, &trig_master, false, 0, 0);
+ * if (status != 0) {
+ * goto handle_error;
+ * }
+ *
+ * trig_slave.role = BLADERF_TRIGGER_ROLE_DISABLED;
+ * status = bladerf_trigger_arm(dev_master, &trig_slave, false, 0, 0);
+ * if (status != 0) {
+ * goto handle_error;
+ * }
+ *
+ * @endcode
+ *
+ * @{
+ */
+
+/**
+ * This value denotes the role of a device in a trigger chain.
+ */
+typedef enum {
+ /** Invalid role selection */
+ BLADERF_TRIGGER_ROLE_INVALID = -1,
+
+ /**
+ * Triggering functionality is disabled on this device. Samples are not
+ * gated and the trigger signal is an input.
+ */
+ BLADERF_TRIGGER_ROLE_DISABLED,
+
+ /**
+ * This device is the trigger master. Its trigger signal will be an output
+ * and this device will determine when all devices shall trigger.
+ */
+ BLADERF_TRIGGER_ROLE_MASTER,
+
+ /**
+ * This device is the trigger slave. This device's trigger signal will be an
+ * input and this devices will wait for the master's trigger signal
+ * assertion.
+ */
+ BLADERF_TRIGGER_ROLE_SLAVE,
+} bladerf_trigger_role;
+
+/**
+ * Trigger signal selection
+ *
+ * This selects pin or signal used for the trigger.
+ *
+ * @note ::BLADERF_TRIGGER_J71_4, ::BLADERF_TRIGGER_J51_1, and
+ * ::BLADERF_TRIGGER_MINI_EXP_1 are the only valid options as of FPGA
+ * v0.6.0. All three values have the same behavior and may be used
+ * interchangably.
+ *
+ * The `BLADERF_TRIGGER_USER_*` values have been added to allow users to modify
+ * both hardware and software implementations to add custom triggers, while
+ * maintaining libbladeRF API compatibility. Official bladeRF releases will
+ * not utilize these user signal IDs.
+ */
+typedef enum {
+ BLADERF_TRIGGER_INVALID = -1, /**< Invalid selection */
+ BLADERF_TRIGGER_J71_4, /**< J71 pin 4, mini_exp[1] on x40/x115 */
+ BLADERF_TRIGGER_J51_1, /**< J51 pin 1, mini_exp[1] on xA4/xA5/xA9 */
+ BLADERF_TRIGGER_MINI_EXP_1, /**< mini_exp[1], hardware-independent */
+
+ BLADERF_TRIGGER_USER_0 = 128, /**< Reserved for user SW/HW customizations */
+ BLADERF_TRIGGER_USER_1, /**< Reserved for user SW/HW customizations */
+ BLADERF_TRIGGER_USER_2, /**< Reserved for user SW/HW customizations */
+ BLADERF_TRIGGER_USER_3, /**< Reserved for user SW/HW customizations */
+ BLADERF_TRIGGER_USER_4, /**< Reserved for user SW/HW customizations */
+ BLADERF_TRIGGER_USER_5, /**< Reserved for user SW/HW customizations */
+ BLADERF_TRIGGER_USER_6, /**< Reserved for user SW/HW customizations */
+ BLADERF_TRIGGER_USER_7, /**< Reserved for user SW/HW customizations */
+} bladerf_trigger_signal;
+
+/**
+ * Trigger configuration
+ *
+ * It is <b>highly recommended</b> to keep a 1:1 relationship between triggers
+ * in the physical setup and instances of this structure. (i.e., do not re-use
+ * and change the same bladerf_trigger) for multiple triggers.)
+ */
+struct bladerf_trigger {
+ bladerf_channel channel; /**< RX/TX channel associated with trigger */
+ bladerf_trigger_role role; /**< Role of the device in a trigger chain */
+ bladerf_trigger_signal signal; /**< Pin or signal being used */
+ uint64_t options; /**< Reserved field for future options. This
+ * is unused and should be set to 0. */
+};
+
+/**
+ * Initialize a bladerf_trigger structure based upon the current configuration
+ * of the specified trigger signal.
+ *
+ * While it is possible to simply declare and manually fill in a bladerf_trigger
+ * structure, it is recommended to use this function to retrieve the current
+ * `role` and `options` values.
+ *
+ * @param dev Device to query
+ * @param[in] ch Channel
+ * @param[in] signal Trigger signal to query
+ * @param[out] trigger Updated to describe trigger
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_trigger_init(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_trigger_signal signal,
+ struct bladerf_trigger *trigger);
+
+/**
+ * Configure and (dis)arm a trigger on the specified device.
+ *
+ * @note If trigger->role is set to ::BLADERF_TRIGGER_ROLE_DISABLED, this will
+ * inherently disarm an armed trigger and clear any fire requests,
+ * regardless of the value of `arm`.
+ *
+ * @param dev Device to configure
+ * @param[in] trigger Trigger configure
+ * @param[in] arm (Re)Arm trigger if true, disarm if false
+ * @param[in] resv1 Reserved for future use. Set to 0.
+ * @param[in] resv2 Reserved for future use. Set to 0.
+ *
+ * @warning Configuring two devices in the trigger chain (or both RX and TX on a
+ * single device) as masters can damage the associated FPGA pins, as
+ * this would cause contention over the trigger signal. <b>Ensure only
+ * one device in the chain is configured as the master!</b>
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_trigger_arm(struct bladerf *dev,
+ const struct bladerf_trigger *trigger,
+ bool arm,
+ uint64_t resv1,
+ uint64_t resv2);
+
+/**
+ * Fire a trigger event.
+ *
+ * Calling this functiona with a trigger whose role is anything other than
+ * ::BLADERF_TRIGGER_REG_MASTER will yield a BLADERF_ERR_INVAL return value.
+ *
+ * @param dev Device handle
+ * @param[in] trigger Trigger to assert
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_trigger_fire(struct bladerf *dev,
+ const struct bladerf_trigger *trigger);
+
+/**
+ * Query the fire request status of a master trigger
+ *
+ * @param dev Device handle
+ * @param[in] trigger Trigger to query
+ * @param[out] is_armed Set to true if the trigger is armed, and false
+ * otherwise. May be NULL.
+ * @param[out] has_fired Set to true if the trigger has fired, and false
+ * otherwise. May be NULL.
+ * @param[out] fire_requested Only applicable to a trigger master.
+ * Set to true if a fire request has been
+ * previously submitted. May be NULL.
+ * @param[out] resv1 Reserved for future use.
+ * This field is written as 0 if not set to NULL.
+ * @param[out] resv2 Reserved for future use.
+ * This field is written as 0 if not set to NULL.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_trigger_state(struct bladerf *dev,
+ const struct bladerf_trigger *trigger,
+ bool *is_armed,
+ bool *has_fired,
+ bool *fire_requested,
+ uint64_t *resv1,
+ uint64_t *resv2);
+
+/** @} (End of FN_TRIG) */
+
+/**
+ * @defgroup FN_RECEIVE_MUX Receive Mux
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * RX Mux modes
+ *
+ * These values describe the source of samples to the RX FIFOs in the FPGA.
+ * They map directly to rx_mux_mode_t inside the FPGA's source code.
+ */
+typedef enum {
+ /** Invalid RX Mux mode selection */
+ BLADERF_RX_MUX_INVALID = -1,
+
+ /** Read baseband samples. This is the default mode of operation. */
+ BLADERF_RX_MUX_BASEBAND = 0x0,
+
+ /**
+ * Read samples from 12 bit counters.
+ *
+ * The I channel counts up while the Q channel counts down.
+ */
+ BLADERF_RX_MUX_12BIT_COUNTER = 0x1,
+
+ /**
+ * Read samples from a 32 bit up-counter.
+ *
+ * I and Q form a little-endian value.
+ */
+ BLADERF_RX_MUX_32BIT_COUNTER = 0x2,
+
+ /* RX_MUX setting 0x3 is reserved for future use */
+
+ /** Read samples from the baseband TX input to the FPGA (from the host) */
+ BLADERF_RX_MUX_DIGITAL_LOOPBACK = 0x4,
+} bladerf_rx_mux;
+
+/** @cond IGNORE */
+/* Backwards compatible mapping for `bladerf_rx_mux`. */
+#define BLADERF_RX_MUX_BASEBAND_LMS BLADERF_RX_MUX_BASEBAND
+/** @endcond */
+
+/**
+ * Set the current RX Mux mode
+ *
+ * @param dev Device handle
+ * @param[in] mux Mux mode.
+ *
+ * @returns 0 on success, value from \ref RETCODES list on failure.
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_rx_mux(struct bladerf *dev, bladerf_rx_mux mux);
+
+/**
+ * Gets the current RX Mux mode
+ *
+ * @param dev Device handle
+ * @param[out] mode Current RX Mux mode
+ *
+ * @returns 0 on success, value from \ref RETCODES list on failure.
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_rx_mux(struct bladerf *dev, bladerf_rx_mux *mode);
+
+/** @} (End of FN_RECEIVE_MUX) */
+
+/**
+ * @defgroup FN_SCHEDULED_TUNING Scheduled Tuning
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * @ingroup STREAMING
+ *
+ * Timestamp, in ticks
+ *
+ * A channel's timestamp typically increments at the sample rate.
+ *
+ * @see Format macros for fprintf() and fscanf(): `BLADERF_PRIuTS`,
+ * `BLADERF_PRIxTS`, `BLADERF_SCNuTS`, `BLADERF_SCNxTS`
+ */
+typedef uint64_t bladerf_timestamp;
+
+/**
+ * Specifies that scheduled retune should occur immediately when using
+ * bladerf_schedule_retune().
+ */
+#define BLADERF_RETUNE_NOW (bladerf_timestamp)0
+
+/**
+ * Quick Re-tune parameters.
+ *
+ * @note These parameters, which are associated with the RFIC's register values,
+ * are sensitive to changes in the operating environment (e.g.,
+ * temperature).
+ *
+ * This structure should be filled in via bladerf_get_quick_tune().
+ */
+struct bladerf_quick_tune {
+ union {
+ /* bladeRF1 quick tune parameters */
+ struct {
+ uint8_t freqsel; /**< Choice of VCO and VCO division factor */
+ uint8_t vcocap; /**< VCOCAP value */
+ uint16_t nint; /**< Integer portion of LO frequency value */
+ uint32_t nfrac; /**< Fractional portion of LO frequency value */
+ uint8_t flags; /**< Flag bits used internally by libbladeRF */
+ uint8_t xb_gpio; /**< Flag bits used to configure XB */
+ };
+ /* bladeRF2 quick tune parameters */
+ struct {
+ uint16_t nios_profile; /**< Profile number in Nios */
+ uint8_t rffe_profile; /**< Profile number in RFFE */
+ uint8_t port; /**< RFFE port settings */
+ uint8_t spdt; /**< External SPDT settings */
+ };
+ };
+};
+
+/**
+ * Schedule a frequency retune to occur at specified sample timestamp value.
+ *
+ * @pre bladerf_sync_config() must have been called with the
+ * \ref BLADERF_FORMAT_SC16_Q11_META format for the associated channel in
+ * order to enable timestamps. (The timestamped metadata format must be
+ * enabled in order to use this function.)
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] timestamp Channel's sample timestamp to perform the
+ * retune operation. If this value is in the past,
+ * the retune will occur immediately. To perform
+ * the retune immediately, specify
+ * ::BLADERF_RETUNE_NOW.
+ * @param[in] frequency Desired frequency, in Hz.
+ * @param[in] quick_tune If non-NULL, the provided "quick retune" values
+ * will be applied to the transceiver to tune it
+ * according to a previous state retrieved via
+ * bladerf_get_quick_tune().
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure.
+ *
+ * @note If the underlying queue of scheduled retune requests becomes full, \ref
+ * BLADERF_ERR_QUEUE_FULL will be returned. In this case, it should be
+ * possible to schedule a retune after the timestamp of one of the earlier
+ * requests occurs.
+
+ * @note NULL quick_tune parameters are not supported by the bladeRF 2.0 micro.
+ */
+API_EXPORT
+int CALL_CONV bladerf_schedule_retune(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_timestamp timestamp,
+ bladerf_frequency frequency,
+ struct bladerf_quick_tune *quick_tune);
+
+/**
+ * Cancel all pending scheduled retune operations for the specified channel.
+ *
+ * This will be done automatically during bladerf_close() to ensure that
+ * previously queued retunes do not continue to occur after closing and then
+ * later re-opening a device.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure.
+ */
+API_EXPORT
+int CALL_CONV bladerf_cancel_scheduled_retunes(struct bladerf *dev,
+ bladerf_channel ch);
+
+/**
+ * Fetch parameters used to tune the transceiver to the current frequency for
+ * use with bladerf_schedule_retune() to perform a "quick retune."
+ *
+ * This allows for a faster retune, with a potential trade off of increased
+ * phase noise.
+ *
+ * @note These parameters are sensitive to changes in the operating environment,
+ * and should be "refreshed" if planning to use the "quick retune"
+ * functionality over a long period of time.
+ *
+ * @pre bladerf_set_frequency() or bladerf_schedule_retune() have previously
+ * been used to retune to the desired frequency.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] quick_tune Quick retune parameters
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_quick_tune(struct bladerf *dev,
+ bladerf_channel ch,
+ struct bladerf_quick_tune *quick_tune);
+
+/**
+ * @brief Prints the quick retune parameters for a bladeRF device.
+ *
+ * Outputs the current quick retune parameters of a bladeRF device
+ * to standard output. It is useful for debugging and verifying the
+ * configuration of quick tune settings.
+ *
+ * @note supported devices: bladeRF1, bladeRF2
+ *
+ * @param[in] dev Device handle. Must not be NULL.
+ * @param[in] qt Pointer to the `bladerf_quick_tune` structure containing
+ * the quick retune parameters. Must not be NULL.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int bladerf_print_quick_tune(struct bladerf *dev,
+ const struct bladerf_quick_tune *qt);
+
+/** @} (End of FN_SCHEDULED_TUNING) */
+
+/**
+ * @defgroup FN_CORR Correction
+ *
+ * This group provides routines for applying manual offset, gain, and phase
+ * corrections.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Correction value, in arbitrary units
+ *
+ * @see ::bladerf_correction
+ * @see bladerf_get_correction()
+ * @see bladerf_set_correction()
+ */
+typedef int16_t bladerf_correction_value;
+
+/**
+ * Correction parameter selection
+ *
+ * These values specify the correction parameter to modify or query when calling
+ * bladerf_set_correction() or bladerf_get_correction(). Note that the meaning
+ * of the `value` parameter to these functions depends upon the correction
+ * parameter.
+ *
+ */
+typedef enum {
+ /**
+ * Adjusts the in-phase DC offset. Valid values are [-2048, 2048], which are
+ * scaled to the available control bits.
+ */
+ BLADERF_CORR_DCOFF_I,
+
+ /**
+ * Adjusts the quadrature DC offset. Valid values are [-2048, 2048], which
+ * are scaled to the available control bits.
+ */
+ BLADERF_CORR_DCOFF_Q,
+
+ /**
+ * Adjusts phase correction of [-10, 10] degrees, via a provided count value
+ * of [-4096, 4096].
+ */
+ BLADERF_CORR_PHASE,
+
+ /**
+ * Adjusts gain correction value in [-1.0, 1.0], via provided values in the
+ * range of [-4096, 4096].
+ */
+ BLADERF_CORR_GAIN
+} bladerf_correction;
+
+/** @cond IGNORE */
+/* Backwards compatible mapping to `bladerf_correction`. */
+#define BLADERF_CORR_LMS_DCOFF_I BLADERF_CORR_DCOFF_I
+#define BLADERF_CORR_LMS_DCOFF_Q BLADERF_CORR_DCOFF_Q
+#define BLADERF_CORR_FPGA_PHASE BLADERF_CORR_PHASE
+#define BLADERF_CORR_FPGA_GAIN BLADERF_CORR_GAIN
+/** @endcond */
+
+/**
+ * Set the value of the specified configuration parameter
+ *
+ * @see The ::bladerf_correction description for the valid ranges of the `value`
+ * parameter.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] corr Correction type
+ * @param[in] value Value to apply
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_correction(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_correction corr,
+ bladerf_correction_value value);
+
+/**
+ * Obtain the current value of the specified configuration parameter
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] corr Correction type
+ * @param[out] value Current value
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_correction(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_correction corr,
+ bladerf_correction_value *value);
+
+/** @} (End of FN_CORR) */
+
+/** @} (End of FN_CHANNEL) */
+
+/**
+ * @defgroup STREAMING Streaming
+ *
+ * This section defines the streaming APIs.
+ *
+ * @{
+ */
+
+/** printf format for timestamps in unsigned decimal */
+#define BLADERF_PRIuTS PRIu64
+/** printf format for timestamps in hexadecimal */
+#define BLADERF_PRIxTS PRIx64
+/** scanf format for timestamps in unsigned decimal */
+#define BLADERF_SCNuTS SCNu64
+/** scanf format for timestamps in hexadecimal */
+#define BLADERF_SCNxTS SCNx64
+
+/**
+ * @defgroup STREAMING_FORMAT Formats
+ *
+ * This section defines the available sample formats and metadata flags.
+ *
+ * @{
+ */
+
+/**
+ * Sample format
+ */
+typedef enum {
+ /**
+ * Signed, Complex 16-bit Q11. This is the native format of the DAC data.
+ *
+ * Values in the range [-2048, 2048) are used to represent [-1.0, 1.0).
+ * Note that the lower bound here is inclusive, and the upper bound is
+ * exclusive. Ensure that provided samples stay within [-2048, 2047].
+ *
+ * Samples consist of interleaved IQ value pairs, with I being the first
+ * value in the pair. Each value in the pair is a right-aligned,
+ * little-endian int16_t. The FPGA ensures that these values are
+ * sign-extended.
+ *
+ * <pre>
+ * .--------------.--------------.
+ * | Bits 31...16 | Bits 15...0 |
+ * +--------------+--------------+
+ * | Q[15..0] | I[15..0] |
+ * `--------------`--------------`
+ * </pre>
+ *
+ * When using this format the minimum required buffer size, in bytes, is:
+ *
+ * \f$
+ * buffer\_size\_min = (2 \times num\_samples \times num\_channels \times
+ * sizeof(int16\_t))
+ * \f$
+ *
+ * For example, to hold 2048 samples for one channel, a buffer must be at
+ * least 8192 bytes large.
+ *
+ * When a multi-channel ::bladerf_channel_layout is selected, samples
+ * will be interleaved per channel. For example, with ::BLADERF_RX_X2
+ * or ::BLADERF_TX_X2 (x2 MIMO), the buffer is structured like:
+ *
+ * <pre>
+ * .-------------.--------------.--------------.------------------.
+ * | Byte offset | Bits 31...16 | Bits 15...0 | Description |
+ * +-------------+--------------+--------------+------------------+
+ * | 0x00 | Q0[0] | I0[0] | Ch 0, sample 0 |
+ * | 0x04 | Q1[0] | I1[0] | Ch 1, sample 0 |
+ * | 0x08 | Q0[1] | I0[1] | Ch 0, sample 1 |
+ * | 0x0c | Q1[1] | I1[1] | Ch 1, sample 1 |
+ * | ... | ... | ... | ... |
+ * | 0xxx | Q0[n] | I0[n] | Ch 0, sample n |
+ * | 0xxx | Q1[n] | I1[n] | Ch 1, sample n |
+ * `-------------`--------------`--------------`------------------`
+ * </pre>
+ *
+ * Per the `buffer_size_min` formula above, 2048 samples for two channels
+ * will generate 4096 total samples, and require at least 16384 bytes.
+ *
+ * Implementors may use the interleaved buffers directly, or may use
+ * bladerf_deinterleave_stream_buffer() / bladerf_interleave_stream_buffer()
+ * if contiguous blocks of samples are desired.
+ */
+ BLADERF_FORMAT_SC16_Q11,
+
+ /**
+ * This format is the same as the ::BLADERF_FORMAT_SC16_Q11 format, except
+ * the first 4 samples in every <i>block*</i> of samples are replaced with
+ * metadata organized as follows. All fields are little-endian byte order.
+ *
+ * <pre>
+ * .-------------.------------.----------------------------------.
+ * | Byte offset | Type | Description |
+ * +-------------+------------+----------------------------------+
+ * | 0x00 | uint16_t | Reserved |
+ * | 0x02 | uint8_t | Stream flags |
+ * | 0x03 | uint8_t | Meta version ID |
+ * | 0x04 | uint64_t | 64-bit Timestamp |
+ * | 0x0c | uint32_t | BLADERF_META_FLAG_* flags |
+ * | 0x10..end | | Payload |
+ * `-------------`------------`----------------------------------`
+ * </pre>
+ *
+ * For IQ sample meta mode, the Meta version ID and Stream flags should
+ * currently be set to values 0x00 and 0x00, respectively.
+ *
+ * <i>*</i>The number of samples in a <i>block</i> is dependent upon
+ * the USB speed being used:
+ * - USB 2.0 Hi-Speed: 256 samples
+ * - USB 3.0 SuperSpeed: 512 samples
+ *
+ * When using the bladerf_sync_rx() and bladerf_sync_tx() functions, the
+ * above details are entirely transparent; the caller need not be concerned
+ * with these details. These functions take care of packing/unpacking the
+ * metadata into/from the underlying stream and convey this information
+ * through the ::bladerf_metadata structure.
+ *
+ * However, when using the \ref FN_STREAMING_ASYNC interface, the user is
+ * responsible for manually packing/unpacking the above metadata into/from
+ * their samples.
+ *
+ * @see STREAMING_FORMAT_METADATA
+ * @see The `src/streaming/metadata.h` header in the libbladeRF codebase.
+ */
+ BLADERF_FORMAT_SC16_Q11_META,
+
+ /**
+ * This format is for exchanging packets containing digital payloads with
+ * the FPGA. A packet is generall a digital payload, that the FPGA then
+ * processes to either modulate, demodulate, filter, etc.
+ *
+ * All fields are little-endian byte order.
+ *
+ * <pre>
+ * .-------------.------------.----------------------------------.
+ * | Byte offset | Type | Description |
+ * +-------------+------------+----------------------------------+
+ * | 0x00 | uint16_t | Packet length (in 32bit DWORDs) |
+ * | 0x02 | uint8_t | Packet flags |
+ * | 0x03 | uint8_t | Packet core ID |
+ * | 0x04 | uint64_t | 64-bit Timestamp |
+ * | 0x0c | uint32_t | BLADERF_META_FLAG_* flags |
+ * | 0x10..end | | Payload |
+ * `-------------`------------`----------------------------------`
+ * </pre>
+ *
+ * A target core (for example a modem) must be specified when calling the
+ * bladerf_sync_rx() and bladerf_sync_tx() functions.
+ *
+ * When in packet mode, lengths for all functions and data formats are
+ * expressed in number of 32-bit DWORDs. As an example, a 12 byte packet
+ * is considered to be 3 32-bit DWORDs long.
+ *
+ * This packet format does not send or receive raw IQ samples. The digital
+ * payloads contain configurations, and digital payloads that are specific
+ * to the digital core to which they are addressed. It is the FPGA core
+ * that should generate, interpret, and process the digital payloads.
+ *
+ * With the exception of packet lenghts, no difference should exist between
+ * USB 2.0 Hi-Speed or USB 3.0 SuperSpeed for packets for this streaming
+ * format.
+ *
+ * @see STREAMING_FORMAT_METADATA
+ * @see The `src/streaming/metadata.h` header in the libbladeRF codebase.
+ */
+ BLADERF_FORMAT_PACKET_META,
+
+ /**
+ * Signed, Complex 8-bit Q8. This is the native format of the DAC data.
+ *
+ * Values in the range [-128, 128) are used to represent [-1.0, 1.0).
+ * Note that the lower bound here is inclusive, and the upper bound is
+ * exclusive. Ensure that provided samples stay within [-128, 127].
+ *
+ * Samples consist of interleaved IQ value pairs, with I being the first
+ * value in the pair. Each value in the pair is a right-aligned int8_t.
+ * The FPGA ensures that these values are sign-extended.
+ *
+ * <pre>
+ * .--------------.--------------.
+ * | Bits 15...8 | Bits 7...0 |
+ * +--------------+--------------+
+ * | Q[7..0] | I[7..0] |
+ * `--------------`--------------`
+ * </pre>
+ *
+ * When using this format the minimum required buffer size, in bytes, is:
+ *
+ * \f$
+ * buffer\_size\_min = (2 \times num\_samples \times num\_channels \times
+ * sizeof(int8\_t))
+ * \f$
+ *
+ * For example, to hold 2048 samples for one channel, a buffer must be at
+ * least 4096 bytes large.
+ *
+ * When a multi-channel ::bladerf_channel_layout is selected, samples
+ * will be interleaved per channel. For example, with ::BLADERF_RX_X2
+ * or ::BLADERF_TX_X2 (x2 MIMO), the buffer is structured like:
+ *
+ * <pre>
+ * .-------------.--------------.--------------.------------------.
+ * | Byte offset | Bits 15...8 | Bits 7...0 | Description |
+ * +-------------+--------------+--------------+------------------+
+ * | 0x00 | Q0[0] | I0[0] | Ch 0, sample 0 |
+ * | 0x02 | Q1[0] | I1[0] | Ch 1, sample 0 |
+ * | 0x04 | Q0[1] | I0[1] | Ch 0, sample 1 |
+ * | 0x06 | Q1[1] | I1[1] | Ch 1, sample 1 |
+ * | ... | ... | ... | ... |
+ * | 0xxx | Q0[n] | I0[n] | Ch 0, sample n |
+ * | 0xxx | Q1[n] | I1[n] | Ch 1, sample n |
+ * `-------------`--------------`--------------`------------------`
+ * </pre>
+ *
+ * Per the `buffer_size_min` formula above, 2048 samples for two channels
+ * will generate 4096 total samples, and require at least 8192 bytes.
+ *
+ * Implementors may use the interleaved buffers directly, or may use
+ * bladerf_deinterleave_stream_buffer() / bladerf_interleave_stream_buffer()
+ * if contiguous blocks of samples are desired.
+ */
+ BLADERF_FORMAT_SC8_Q7,
+
+ /**
+ * This format is the same as the ::BLADERF_FORMAT_SC8_Q7 format, except
+ * the first 4 samples in every <i>block*</i> of samples are replaced with
+ * metadata organized as follows. All fields are little-endian byte order.
+ *
+ * <pre>
+ * .-------------.------------.----------------------------------.
+ * | Byte offset | Type | Description |
+ * +-------------+------------+----------------------------------+
+ * | 0x00 | uint16_t | Reserved |
+ * | 0x02 | uint8_t | Stream flags |
+ * | 0x03 | uint8_t | Meta version ID |
+ * | 0x04 | uint64_t | 64-bit Timestamp |
+ * | 0x0c | uint32_t | BLADERF_META_FLAG_* flags |
+ * | 0x10..end | | Payload |
+ * `-------------`------------`----------------------------------`
+ * </pre>
+ *
+ * For IQ sample meta mode, the Meta version ID and Stream flags should
+ * currently be set to values 0x00 and 0x00, respectively.
+ *
+ * <i>*</i>The number of samples in a <i>block</i> is dependent upon
+ * the USB speed being used:
+ * - USB 2.0 Hi-Speed: 256 samples
+ * - USB 3.0 SuperSpeed: 512 samples
+ *
+ * When using the bladerf_sync_rx() and bladerf_sync_tx() functions, the
+ * above details are entirely transparent; the caller need not be concerned
+ * with these details. These functions take care of packing/unpacking the
+ * metadata into/from the underlying stream and convey this information
+ * through the ::bladerf_metadata structure.
+ *
+ * However, when using the \ref FN_STREAMING_ASYNC interface, the user is
+ * responsible for manually packing/unpacking the above metadata into/from
+ * their samples.
+ *
+ * @see STREAMING_FORMAT_METADATA
+ * @see The `src/streaming/metadata.h` header in the libbladeRF codebase.
+ */
+ BLADERF_FORMAT_SC8_Q7_META,
+} bladerf_format;
+
+/**
+ * @defgroup STREAMING_FORMAT_METADATA Metadata structure and flags
+ *
+ * @{
+ */
+
+/*
+ * Metadata status bits
+ *
+ * These are used in conjunction with the bladerf_metadata structure's `status`
+ * field.
+ */
+
+/**
+ * A sample overrun has occurred.
+ *
+ * This indicates that either the host (more likely) or the FPGA is not keeping
+ * up with the incoming samples.
+ */
+#define BLADERF_META_STATUS_OVERRUN (1 << 0)
+
+/**
+ * A sample underrun has occurred.
+ *
+ * This generally only occurs on the TX channel when the FPGA is starved of
+ * samples.
+ *
+ * @note libbladeRF does not report this status. It is here for future use.
+ */
+#define BLADERF_META_STATUS_UNDERRUN (1 << 1)
+
+/*
+ * Metadata flags
+ *
+ * These are used in conjunction with the bladerf_metadata structure's `flags`
+ * field.
+ */
+
+/**
+ * Mark the associated buffer as the start of a burst transmission.
+ *
+ * @note This is only used for the bladerf_sync_tx() call.
+ *
+ * When using this flag, the bladerf_metadata::timestamp field should contain
+ * the timestamp at which samples should be sent.
+ *
+ * Between specifying the ::BLADERF_META_FLAG_TX_BURST_START and
+ * ::BLADERF_META_FLAG_TX_BURST_END flags, there is no need for the user to the
+ * bladerf_metadata::timestamp field because the library will ensure the
+ * correct value is used, based upon the timestamp initially provided and
+ * the number of samples that have been sent.
+ */
+#define BLADERF_META_FLAG_TX_BURST_START (1 << 0)
+
+/**
+ * Mark the associated buffer as the end of a burst transmission. This will
+ * flush the remainder of the sync interface's current working buffer and
+ * enqueue samples into the hardware's transmit FIFO.
+ *
+ * As of libbladeRF v1.3.0, it is no longer necessary for the API user to ensure
+ * that the final 3 samples of a burst are \f$0 + 0 j\f$. libbladeRF now ensures
+ * this hardware requirement is upheld.
+ *
+ * Specifying this flag and flushing the sync interface's working buffer implies
+ * that the next timestamp that can be transmitted is the current timestamp plus
+ * the duration of the burst that this flag is ending <b>and</b> the remaining
+ * length of the remaining buffer that is flushed. (The buffer size, in this
+ * case, is the `buffer_size` value passed to the previous bladerf_sync_config()
+ * call.)
+ *
+ * Rather than attempting to keep track of the number of samples sent with
+ * respect to buffer sizes, it is easiest to always assume 1 buffer's worth of
+ * time is required between bursts. In this case "buffer" refers to the
+ * `buffer_size` parameter provided to bladerf_sync_config().) If this is too
+ * much time, consider using the ::BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP
+ * flag.
+ *
+ * @note This is only used for the bladerf_sync_tx() call. It is ignored by the
+ * bladerf_sync_rx() call.
+ */
+#define BLADERF_META_FLAG_TX_BURST_END (1 << 1)
+
+/**
+ * Use this flag in conjunction with ::BLADERF_META_FLAG_TX_BURST_START to
+ * indicate that the burst should be transmitted as soon as possible, as opposed
+ * to waiting for a specific timestamp.
+ *
+ * When this flag is used, there is no need to set the
+ * bladerf_metadata::timestamp field.
+ */
+#define BLADERF_META_FLAG_TX_NOW (1 << 2)
+
+/**
+ * Use this flag within a burst (i.e., between the use of
+ * ::BLADERF_META_FLAG_TX_BURST_START and ::BLADERF_META_FLAG_TX_BURST_END) to
+ * specify that bladerf_sync_tx() should read the bladerf_metadata::timestamp
+ * field and zero-pad samples up to the specified timestamp. The provided
+ * samples will then be transmitted at that timestamp.
+ *
+ * Use this flag when potentially flushing an entire buffer via the
+ * ::BLADERF_META_FLAG_TX_BURST_END would yield an unacceptably large gap in the
+ * transmitted samples.
+ *
+ * In some applications where a transmitter is constantly transmitting with
+ * extremely small gaps (less than a buffer), users may end up using a single
+ * ::BLADERF_META_FLAG_TX_BURST_START, and then numerous calls to
+ * bladerf_sync_tx() with the ::BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP flag set.
+ * The ::BLADERF_META_FLAG_TX_BURST_END would only be used to end the stream
+ * when shutting down.
+ */
+#define BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP (1 << 3)
+
+/**
+ * This flag indicates that calls to bladerf_sync_rx should return any available
+ * samples, rather than wait until the timestamp indicated in the
+ * bladerf_metadata timestamp field.
+ */
+#define BLADERF_META_FLAG_RX_NOW (1 << 31)
+
+/**
+ * This flag is asserted in bladerf_metadata.status by the hardware when an
+ * underflow is detected in the sample buffering system on the device.
+ */
+#define BLADERF_META_FLAG_RX_HW_UNDERFLOW (1 << 0)
+
+/**
+ * This flag is asserted in bladerf_metadata.status by the hardware if mini
+ * expansion IO pin 1 is asserted.
+ */
+#define BLADERF_META_FLAG_RX_HW_MINIEXP1 (1 << 16)
+
+/**
+ * This flag is asserted in bladerf_metadata.status by the hardware if mini
+ * expansion IO pin 2 is asserted.
+ */
+#define BLADERF_META_FLAG_RX_HW_MINIEXP2 (1 << 17)
+
+/**
+ * Sample metadata
+ *
+ * This structure is used in conjunction with the ::BLADERF_FORMAT_SC16_Q11_META
+ * format to TX scheduled bursts or retrieve timestamp information about
+ * received samples.
+ */
+struct bladerf_metadata {
+ /**
+ * Free-running FPGA counter that monotonically increases at the sample rate
+ * of the associated channel.
+ */
+ bladerf_timestamp timestamp;
+
+ /**
+ * Input bit field to control the behavior of the call that the metadata
+ * structure is passed to. API calls read this field from the provided data
+ * structure, and do not modify it.
+ *
+ * Valid flags include
+ * ::BLADERF_META_FLAG_TX_BURST_START,
+ * ::BLADERF_META_FLAG_TX_BURST_END,
+ * ::BLADERF_META_FLAG_TX_NOW,
+ * ::BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP, and
+ * ::BLADERF_META_FLAG_RX_NOW
+ */
+ uint32_t flags;
+
+ /**
+ * Output bit field to denoting the status of transmissions/receptions. API
+ * calls will write this field.
+ *
+ * Possible status flags include ::BLADERF_META_STATUS_OVERRUN and
+ * ::BLADERF_META_STATUS_UNDERRUN.
+ */
+ uint32_t status;
+
+ /**
+ * This output parameter is updated to reflect the actual number of
+ * contiguous samples that have been populated in an RX buffer during a
+ * bladerf_sync_rx() call.
+ *
+ * This will not be equal to the requested count in the event of a
+ * discontinuity (i.e., when the status field has the
+ * ::BLADERF_META_STATUS_OVERRUN flag set). When an overrun occurs, it is
+ * important not to read past the number of samples specified by this value,
+ * as the remaining contents of the buffer are undefined.
+ *
+ * @note This parameter is not currently used by bladerf_sync_tx().
+ */
+ unsigned int actual_count;
+
+ /**
+ * Reserved for future use. This is not used by any functions. It is
+ * recommended that users zero out this field.
+ */
+ uint8_t reserved[32];
+};
+
+/** @} (End of STREAMING_FORMAT_METADATA) */
+
+/**
+ * Interleaves contiguous blocks of samples in preparation for MIMO TX.
+ *
+ * Given a `buffer` loaded with data as such:
+ *
+ * <pre>
+ * .-------------------.--------------.--------------.------------------.
+ * | Byte offset | Bits 31...16 | Bits 15...0 | Description |
+ * +-------------------+--------------+--------------+------------------+
+ * | 0x00 + 0*chsize | Q0[0] | I0[0] | Ch 0, sample 0 |
+ * | 0x04 + 0*chsize | Q0[1] | I0[1] | Ch 0, sample 1 |
+ * | 0x08 + 0*chsize | Q0[2] | I0[2] | Ch 0, sample 2 |
+ * | 0x0c + 0*chsize | Q0[3] | I0[3] | Ch 0, sample 3 |
+ * | ... | ... | ... | ... |
+ * | 0x00 + 1*chsize | Q1[0] | I1[0] | Ch 1, sample 0 |
+ * | 0x04 + 1*chsize | Q1[1] | I1[1] | Ch 1, sample 1 |
+ * | 0x08 + 1*chsize | Q1[2] | I1[2] | Ch 1, sample 2 |
+ * | 0x0c + 1*chsize | Q1[3] | I1[3] | Ch 1, sample 3 |
+ * | ... | ... | ... | ... |
+ * `-------------------`--------------`--------------`------------------`
+ * </pre>
+ *
+ * where \f$chsize = \frac{sizeof(buffer)}{num\_channels}\f$.
+ *
+ * This function interleaves the samples in the manner described by the
+ * ::BLADERF_FORMAT_SC16_Q11 format, in place. Each channel must have
+ * \f$buffer\_size / num\_channels\f$ samples, and they must be concatenated in
+ * order.
+ *
+ * If the ::BLADERF_FORMAT_SC16_Q11_META format is specified, the first 16 bytes
+ * will skipped.
+ *
+ * This function's inverse is bladerf_deinterleave_stream_buffer().
+ *
+ * @param[in] layout Stream direction and layout
+ * @param[in] format Data format to use
+ * @param[in] buffer_size The size of the buffer, in samples. Note that this
+ * is the entire buffer, not just a single channel.
+ * @param samples Buffer to process. The user is responsible for
+ * ensuring this buffer contains exactly
+ * `buffer_size` samples.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_interleave_stream_buffer(bladerf_channel_layout layout,
+ bladerf_format format,
+ unsigned int buffer_size,
+ void *samples);
+
+/**
+ * Deinterleaves samples into contiguous blocks after MIMO RX.
+ *
+ * This function deinterleaves a multi-channel interleaved buffer, as described
+ * by the ::BLADERF_FORMAT_SC16_Q11 format. The output is in the format
+ * described as the input to this function's inverse,
+ * bladerf_interleave_stream_buffer().
+ *
+ * If the ::BLADERF_FORMAT_SC16_Q11_META format is specified, the first 16 bytes
+ * will skipped.
+ *
+ * @param[in] layout Stream direction and layout
+ * @param[in] format Data format to use
+ * @param[in] buffer_size The size of the buffer, in samples. Note that
+ * this is the entire buffer, not just a single
+ * channel.
+ * @param samples Buffer to process. The user is responsible for
+ * ensuring this buffer contains exactly
+ * `buffer_size` samples.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_deinterleave_stream_buffer(bladerf_channel_layout layout,
+ bladerf_format format,
+ unsigned int buffer_size,
+ void *samples);
+
+/** @} (End of STREAMING_FORMAT) */
+
+/**
+ * Enable or disable the RF front end of the specified direction.
+ *
+ * RF front ends must always be enabled prior to streaming samples on the
+ * associated interface.
+ *
+ * When a synchronous stream is associated with the specified channel, this will
+ * shut down the underlying asynchronous stream when `enable` = false.
+ *
+ * When transmitting samples, be sure to provide ample time for TX samples reach
+ * the RF front-end before calling this function with `enable` = false. (This
+ * can be achieved easily when using metadata, as shown on
+ * \link sync_tx_meta_bursts.html this page\endlink.)
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] enable true to enable, false to disable
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_enable_module(struct bladerf *dev,
+ bladerf_channel ch,
+ bool enable);
+
+/**
+ * Retrieve the specified stream's current timestamp counter value from the
+ * FPGA.
+ *
+ * This function is only intended to be used to retrieve a coarse estimate of
+ * the current timestamp when starting up a stream. It <b>should not</b> be used
+ * as a means to accurately retrieve the current timestamp of individual samples
+ * within a running stream. The reasons for this are:
+ * - The timestamp counter will have advanced during the time that the captured
+ * value is propagated back from the FPGA to the host
+ * - The value retrieved in this manner is not tightly-coupled with
+ * specific sample positions in the stream.
+ *
+ * When actively receiving a sample stream, instead use the
+ * ::bladerf_metadata::timestamp field (provided when using the
+ * ::BLADERF_FORMAT_SC16_Q11_META format) to retrieve the timestamp value
+ * associated with a block of samples. See the \link sync_rx_meta.html RX with
+ * metadata\endlink page for examples of this.
+ *
+ * An example use-case of this function is to schedule an initial TX burst in a
+ * set of bursts:
+ *
+ * - Configure and start a TX stream using the ::BLADERF_FORMAT_SC16_Q11_META
+ * format.
+ * - Retrieve timestamp \f$T\f$, a coarse estimate the TX's current timestamp
+ * via this function.
+ * - Schedule the first burst, \f$F\f$ to occur in the future: \f$F = T + N\f$.
+ * Generally, adding \f$N\f$ in tens to low hundreds of milliseconds is
+ * sufficient to account for timestamp retrieval overhead and stream
+ * startup.
+ * - Schedule additional bursts relative to the first burst \f$F\f$.
+ *
+ * Examples of the above are shown on the \link sync_tx_meta_bursts.html TX
+ * with metadata\endlink page.
+ *
+ * @param dev Device handle
+ * @param[in] dir Stream direction
+ * @param[out] timestamp Coarse timestamp value
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_timestamp(struct bladerf *dev,
+ bladerf_direction dir,
+ bladerf_timestamp *timestamp);
+
+/**
+ * @defgroup FN_STREAMING_SYNC Synchronous API
+ *
+ * This group of functions presents synchronous, blocking calls (with optional
+ * timeouts) for transmitting and receiving samples.
+ *
+ * The synchronous interface is built atop the asynchronous interface, and is
+ * generally less complex and easier to work with. It alleviates the need to
+ * explicitly spawn threads (it is done under the hood) and manually manage
+ * sample buffers.
+ *
+ * Under the hood, this interface spawns worker threads to handle an
+ * asynchronous stream and perform thread-safe buffer management.
+ *
+ * These functions are thread-safe.
+ *
+ * The following pages provide additional information and example usage:
+ *
+ * - \link sync_no_meta.html Basic usage without metadata\endlink
+ * - \link sync_rx_meta.html Synchronous RX with metadata\endlink
+ * - \link sync_tx_meta_bursts.html Synchronous TX with metadata\endlink
+ *
+ * @{
+ */
+
+/**
+ * (Re)Configure a device for synchronous transmission or reception
+ *
+ * This function sets up the device for the specified format and initializes
+ * the underlying asynchronous stream parameters
+ *
+ * This function does not call bladerf_enable_module(). The API user is
+ * responsible for enabling/disable streams when desired.
+ *
+ * Note that (re)configuring the TX direction does not affect the RX direction,
+ * and vice versa. This call configures each direction independently.
+ *
+ * Memory allocated by this function will be deallocated when bladerf_close()
+ * is called.
+ *
+ * @see The bladerf_init_stream() documentation for information on determining
+ * appropriate values for `buffers_size`, `num_transfers`, and
+ * `stream_timeout`.
+ *
+ * @note The `num_buffers` parameter should generally be increased as the amount
+ * of work done between bladerf_sync_rx() or bladerf_sync_tx() calls
+ * increases.
+ *
+ * @param dev Device to configure
+ * @param[in] layout Stream direction and layout
+ * @param[in] format Format to use in synchronous data transfers
+ * @param[in] num_buffers The number of buffers to use in the underlying
+ * data stream. This must be greater than the
+ * `num_xfers` parameter.
+ * @param[in] buffer_size The size of the underlying stream buffers, in
+ * samples. This value must be a multiple of 1024.
+ * Note that samples are only transferred when a
+ * buffer of this size is filled.
+ * @param[in] num_transfers The number of active USB transfers that may be
+ * in-flight at any given time. If unsure of what
+ * to use here, try values of 4, 8, or 16.
+ * @param[in] stream_timeout Timeout (milliseconds) for transfers in the
+ * underlying data stream.
+ *
+ * @return 0 on success,
+ * ::BLADERF_ERR_UNSUPPORTED if libbladeRF is not built with support
+ * for this functionality,
+ * or a value from \ref RETCODES list on failures.
+ */
+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);
+
+/**
+ * Transmit IQ samples.
+ *
+ * Under the hood, this call starts up an underlying asynchronous stream as
+ * needed. This stream can be stopped by disabling the TX channel. (See
+ * bladerf_enable_module for more details.)
+ *
+ * Samples will only be sent to the FPGA when a buffer have been filled. The
+ * number of samples required to fill a buffer corresponds to the `buffer_size`
+ * parameter passed to bladerf_sync_config().
+ *
+ * @pre A bladerf_sync_config() call has been to configure the device for
+ * synchronous data transfer.
+ *
+ * @note A call to bladerf_enable_module() should be made before attempting to
+ * transmit samples. Failing to do this may result in timeouts and other
+ * errors.
+ *
+ * @param dev Device handle
+ * @param[in] samples Array of samples
+ * @param[in] num_samples Number of samples to write
+ * @param[in] metadata Sample metadata. This must be provided when using
+ * the ::BLADERF_FORMAT_SC16_Q11_META format, but may
+ * be NULL when the interface is configured for
+ * the ::BLADERF_FORMAT_SC16_Q11 format.
+ * @param[in] timeout_ms Timeout (milliseconds) for this call to complete.
+ * Zero implies "infinite."
+ *
+ * @return 0 on success,
+ * ::BLADERF_ERR_UNSUPPORTED if libbladeRF is not built with support
+ * for this functionality,
+ * or a value from \ref RETCODES list on failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_sync_tx(struct bladerf *dev,
+ const void *samples,
+ unsigned int num_samples,
+ struct bladerf_metadata *metadata,
+ unsigned int timeout_ms);
+
+/**
+ * Receive IQ samples.
+ *
+ * Under the hood, this call starts up an underlying asynchronous stream as
+ * needed. This stream can be stopped by disabling the RX channel. (See
+ * bladerf_enable_module for more details.)
+ *
+ * @pre A bladerf_sync_config() call has been to configure the device for
+ * synchronous data transfer.
+ *
+ * @note A call to bladerf_enable_module() should be made before attempting to
+ * receive samples. Failing to do this may result in timeouts and other
+ * errors.
+ *
+ * @param dev Device handle
+ * @param[out] samples Buffer to store samples in. The caller is
+ * responsible for ensuring this buffer is sufficiently
+ * large for the number of samples requested,
+ * considering the size of the sample format being
+ * used.
+ * @param[in] num_samples Number of samples to read
+ * @param[out] metadata Sample metadata. This must be provided when using
+ * the ::BLADERF_FORMAT_SC16_Q11_META format, but may
+ * be NULL when the interface is configured for
+ * the ::BLADERF_FORMAT_SC16_Q11 format.
+ * @param[in] timeout_ms Timeout (milliseconds) for this call to complete.
+ * Zero implies "infinite."
+ *
+ * @return 0 on success,
+ * ::BLADERF_ERR_UNSUPPORTED if libbladeRF is not built with support
+ * for this functionality,
+ * or a value from \ref RETCODES list on failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_sync_rx(struct bladerf *dev,
+ void *samples,
+ unsigned int num_samples,
+ struct bladerf_metadata *metadata,
+ unsigned int timeout_ms);
+
+
+/** @} (End of FN_STREAMING_SYNC) */
+
+/**
+ * @defgroup FN_STREAMING_ASYNC Asynchronous API
+ *
+ * This interface gives the API user full control over the stream and buffer
+ * management, at the cost of added complexity.
+ *
+ * @note New users are recommended to first evaluate the \ref FN_STREAMING_SYNC
+ * interface, and to only use this interface if the former is found to not
+ * yield suitable performance.
+ *
+ * These functions are either thread-safe or may be used in a thread-safe
+ * manner (per the details noted in the function description).
+ *
+ * @{
+ */
+
+/**
+ * Use this as a return value in callbacks or as the buffer parameter to
+ * bladerf_submit_stream_buffer() to shutdown a stream.
+ */
+#define BLADERF_STREAM_SHUTDOWN (NULL)
+
+/**
+ * Use this value in a stream callback to indicate that no buffer is being
+ * provided. In this case, buffers are expected to be provided via
+ * bladerf_submit_stream_buffer().
+ */
+#define BLADERF_STREAM_NO_DATA ((void *)(-1))
+
+/** This opaque structure is used to keep track of stream information */
+struct bladerf_stream;
+
+/**
+ * This typedef represents a callback function that is executed in response to
+ * this interface's asynchronous events.
+ *
+ * Stream callbacks <b>must not</b> block or perform long-running operations.
+ * Otherwise, timeouts may occur. If this cannot be guaranteed, consider
+ * returning ::BLADERF_STREAM_NO_DATA in callbacks and later submit a buffer
+ * using bladerf_submit_stream_buffer(). However, callbacks should always take
+ * a single approach of returning buffers <b>or</b> returning
+ * ::BLADERF_STREAM_NO_DATA and submitting buffers later -- <b>but not both</b>.
+ *
+ * When running in a full-duplex mode of operation with simultaneous TX and RX
+ * stream threads, be aware that one stream's callback may occur in the context
+ * of another stream's thread. The API user is responsible for ensuring their
+ * callbacks are thread safe. For example, when managing access to sample
+ * buffers, the caller must ensure that if one thread is processing samples in a
+ * buffer, that this buffer is not returned via the callback's return value.
+ *
+ * As of libbladeRF v0.15.0, is guaranteed that only one callback from a stream
+ * will occur at a time. (i.e., a second TX callback will not fire while one is
+ * currently being handled.) To achieve this, while a callback is executing, a
+ * per-stream lock is held. It is important to consider this when thinking about
+ * the order of lock acquisitions both in the callbacks, and the code
+ * surrounding bladerf_submit_stream_buffer().
+ *
+ * @note Do not call bladerf_submit_stream_buffer() from a callback.
+ *
+ * For both RX and TX, the stream callback receives:
+ * - dev: Device structure
+ * - stream: The associated stream
+ * - metadata: For future support - do not attempt to read/write this
+ * in the current library implementation.
+ * - user_data: User data provided when initializing stream
+ *
+ * For TX callbacks:
+ * - samples: Pointer to buffer of samples that was sent
+ * - num_samples: Number of sent in last transfer and to send in next transfer
+ * - Return value: The user specifies the address of the next buffer to send,
+ * ::BLADERF_STREAM_SHUTDOWN, or ::BLADERF_STREAM_NO_DATA.
+ *
+ * For RX callbacks:
+ * - samples: Buffer filled with received data
+ * - num_samples: Number of samples received and size of next buffers
+ * - Return value: The user specifies the next buffer to fill with RX data,
+ * which should be `num_samples` in size,
+ * ::BLADERF_STREAM_SHUTDOWN, or ::BLADERF_STREAM_NO_DATA.
+ */
+typedef void *(*bladerf_stream_cb)(struct bladerf *dev,
+ struct bladerf_stream *stream,
+ struct bladerf_metadata *meta,
+ void *samples,
+ size_t num_samples,
+ void *user_data);
+
+/**
+ * Initialize a stream for use with asynchronous routines.
+ *
+ * This function will internally allocate data buffers, which will be provided
+ * to the API user in callback functions.
+ *
+ * The `buffers` output parameter populates a pointer to the list of allocated
+ * buffers. This allows the API user to implement a buffer management scheme to
+ * best suit his or her specific use case.
+ *
+ * Generally, one will want to set the `buffers` parameter to a value larger
+ * than the `num_transfers` parameter, and keep track of which buffers are
+ * currently "in-flight", versus those available for use.
+ *
+ * For example, for a transmit stream, modulated data can be actively written
+ * into free buffers while transfers of other buffers are occurring. Once a
+ * buffer has been filled with data, it can be marked 'in-flight' and be
+ * returned in a successive callback to transmit.
+ *
+ * The choice of values for the `num_transfers` and `buffer_size` should be
+ * made based upon the desired samplerate, and the stream timeout value
+ * specified via bladerf_set_stream_timeout(), which defaults to 1 second.
+ *
+ * For a given sample rate, the below relationship must be upheld to transmit or
+ * receive data without timeouts or dropped data.
+ *
+ * @f[
+ * Sample\ Rate > \frac{\#\ Transfers}{Timeout} \times Buffer\ Size
+ * @f]
+ *
+ * ...where Sample Rate is in samples per second, and Timeout is in seconds.
+ *
+ * To account for general system overhead, it is recommended to multiply the
+ * righthand side by 1.1 to 1.25.
+ *
+ * While increasing the number of buffers available provides additional
+ * elasticity, be aware that it also increases latency.
+ *
+ * @param[out] stream Upon success, this will be updated to contain
+ * a stream handle (i.e., address)
+ * @param dev Device to associate with the stream
+ * @param[in] callback Callback routine to handle asynchronous events
+ * @param[out] buffers This will be updated to point to a dynamically
+ * allocated array of buffer pointers.
+ * @param[in] num_buffers Number of buffers to allocate and return. This
+ * value must >= the `num_transfers` parameter.
+ * @param[in] format Sample data format
+ * @param[in] samples_per_buffer Size of allocated buffers, in units of
+ * samples Note that the physical size of the
+ * buffer is a function of this and the format
+ * parameter.
+ * @param[in] num_transfers Maximum number of transfers that may be
+ * in-flight simultaneously. This must be <= the
+ * `num_buffers` parameter.
+ * @param[in] user_data Caller-provided data that will be provided
+ * in stream callbacks
+ *
+ * @note This call should be later followed by a call to
+ * bladerf_deinit_stream() to avoid memory leaks.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_init_stream(struct bladerf_stream **stream,
+ struct bladerf *dev,
+ bladerf_stream_cb callback,
+ void ***buffers,
+ size_t num_buffers,
+ bladerf_format format,
+ size_t samples_per_buffer,
+ size_t num_transfers,
+ void *user_data);
+
+/**
+ * Begin running a stream. This call will block until the stream completes.
+ *
+ * Only 1 RX stream and 1 TX stream may be running at a time. Attempting to
+ * call bladerf_stream() with more than one stream will yield unexpected (and
+ * most likely undesirable) results.
+ *
+ * @note See the ::bladerf_stream_cb description for additional thread-safety
+ * caveats.
+ *
+ * @pre This function should be preceded by a call to bladerf_enable_module()
+ * to enable the associated RX or TX directions before attempting to use
+ * it to stream data.
+ *
+ * @param stream A stream handle that has been successfully been
+ * initialized via bladerf_init_stream()
+ * @param[in] layout Stream direction and channel layout
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_stream(struct bladerf_stream *stream,
+ bladerf_channel_layout layout);
+
+/**
+ * Submit a buffer to a stream from outside of a stream callback function.
+ * Use this only when returning BLADERF_STREAM_NO_DATA from callbacks. <b>Do
+ * not</b> use this function if the associated callback functions will be
+ * returning buffers for submission.
+ *
+ * This call may block if the device is not ready to submit a buffer for
+ * transfer. Use the `timeout_ms` to place an upper limit on the time this
+ * function can block.
+ *
+ * To safely submit buffers from outside the stream callback flow, this function
+ * internally acquires a per-stream lock (the same one that is held during the
+ * execution of a stream callback). Therefore, it is important to be aware of
+ * locks that may be held while making this call, especially those acquired
+ * during execution of the associated stream callback function. (i.e., be wary
+ * of the order of lock acquisitions, including the internal per-stream lock.)
+ *
+ * @param stream Stream to submit buffer to
+ * @param[inout] buffer Buffer to fill (RX) or containing data (TX).
+ * This buffer is assumed to be the size specified
+ * in the associated bladerf_init_stream() call.
+ * @param[in] timeout_ms Milliseconds to timeout in, if this call blocks.
+ * 0 implies an "infinite" wait.
+ *
+ * @return 0 on success, ::BLADERF_ERR_TIMEOUT upon a timeout, or a value from
+ * \ref RETCODES list on other failures
+ */
+API_EXPORT
+int CALL_CONV bladerf_submit_stream_buffer(struct bladerf_stream *stream,
+ void *buffer,
+ unsigned int timeout_ms);
+
+/**
+ * This is a non-blocking variant of bladerf_submit_stream_buffer(). All of the
+ * caveats and important notes from bladerf_submit_stream_buffer() apply.
+ *
+ * In the event that this call would need to block in order to submit a buffer,
+ * it returns BLADERF_ERR_WOULD_BLOCK. In this case, the caller could either
+ * wait and try again or defer buffer submission to the asynchronous callback.
+ *
+ * @param stream Stream to submit buffer to
+ * @param[inout] buffer Buffer to fill (RX) or containing data (TX).
+ * This buffer is assumed to be the size specified
+ * in the associated bladerf_init_stream() call.
+ *
+ * @return 0 on success, ::BLADERF_ERR_WOULD_BLOCK if the call would have to
+ * block to succeed, or another value from \ref RETCODES upon other
+ * failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_submit_stream_buffer_nb(struct bladerf_stream *stream,
+ void *buffer);
+
+
+/**
+ * Deinitialize and deallocate stream resources.
+ *
+ * @pre Stream is no longer being used (via bladerf_submit_stream_buffer() or
+ * bladerf_stream() calls.)
+ *
+ * @post Stream is deallocated and may no longer be used.
+ *
+ * @param stream Stream to deinitialize. This function does nothing if
+ * stream is `NULL`.
+ */
+API_EXPORT
+void CALL_CONV bladerf_deinit_stream(struct bladerf_stream *stream);
+
+/**
+ * Set stream transfer timeout in milliseconds
+ *
+ * @param dev Device handle
+ * @param[in] dir Stream direction
+ * @param[in] timeout Timeout in milliseconds
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_stream_timeout(struct bladerf *dev,
+ bladerf_direction dir,
+ unsigned int timeout);
+
+/**
+ * Get transfer timeout in milliseconds
+ *
+ * @param dev Device handle
+ * @param[in] dir Stream direction
+ * @param[out] timeout On success, updated with current transfer
+ * timeout value. Undefined on failure.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_stream_timeout(struct bladerf *dev,
+ bladerf_direction dir,
+ unsigned int *timeout);
+
+/** @} (End of FN_STREAMING_ASYNC) */
+
+/** @} (End of STREAMING) */
+
+/**
+ * @defgroup FN_PROG Firmware and FPGA
+ *
+ * These functions provide the ability to load and program devices on the
+ * bladeRF board.
+ *
+ * Care should be taken with bootloader recovery functions to ensure that
+ * devices operated on are indeed a bladeRF, as opposed to another FX3-based
+ * device running in bootloader mode.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Write FX3 firmware to the bladeRF's SPI flash
+ *
+ * @note This will require a power cycle to take effect
+ *
+ * @param dev Device handle
+ * @param[in] firmware Full path to firmware file
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_flash_firmware(struct bladerf *dev, const char *firmware);
+
+/**
+ * Load device's FPGA.
+ *
+ * @note This FPGA configuration will be reset at the next power cycle.
+ *
+ * @param dev Device handle
+ * @param[in] fpga Full path to FPGA bitstream
+ *
+ * @return 0 upon successfully, or a value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_load_fpga(struct bladerf *dev, const char *fpga);
+
+/**
+ * Write the provided FPGA image to the bladeRF's SPI flash and enable FPGA
+ * loading from SPI flash at power on (also referred to within this project as
+ * FPGA "autoloading").
+ *
+ * @param dev Device handle
+ * @param[in] fpga_image Full path to FPGA file
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_flash_fpga(struct bladerf *dev, const char *fpga_image);
+
+/**
+ * Erase the FPGA region of SPI flash, effectively disabling FPGA autoloading
+ *
+ * @param dev Device handle
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_erase_stored_fpga(struct bladerf *dev);
+
+/**
+ * Reset the device, causing it to reload its firmware from flash
+ *
+ * @param dev Device handle
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_device_reset(struct bladerf *dev);
+
+/**
+ * Read firmware log data and write it to the specified file
+ *
+ * @param dev Device to read firmware log from
+ * @param[in] filename Filename to write log information to. If set to
+ * `NULL`, log data will be printed to stdout.
+ *
+ * @return 0 upon success, or a value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_fw_log(struct bladerf *dev, const char *filename);
+
+/**
+ * Clear out a firmware signature word in flash and jump to FX3 bootloader.
+ *
+ * The device will continue to boot into the FX3 bootloader across power cycles
+ * until new firmware is written to the device.
+ *
+ * @param dev Device handle
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_jump_to_bootloader(struct bladerf *dev);
+
+/**
+ * Get a list of devices that are running the FX3 bootloader.
+ *
+ * After obtaining this list, identify the device that you would like to load
+ * firmware onto. Save the bus and address values so that you can provide them
+ * to bladerf_load_fw_from_bootloader(), and then free this list via
+ * bladerf_free_device_list().
+ *
+ * @param[out] list Upon finding devices, this will be updated to point
+ * to a list of bladerf_devinfo structures that
+ * describe the identified devices.
+ *
+ * @return Number of items populated in `list`,
+ * or an error value from the \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_bootloader_list(struct bladerf_devinfo **list);
+
+/**
+ * Download firmware to the specified device that is enumarating an FX3
+ * bootloader, and begin executing the firmware from RAM.
+ *
+ * @note This function <b>does not</b> write the firmware to SPI flash. If this
+ * is desired, open the newly enumerated device with bladerf_open() and use
+ * bladerf_flash_firmware().
+ *
+ * @param[in] device_identifier Device identifier string describing the
+ * backend to use via the
+ * `<backend>:device=<bus>:<addr>` syntax. If
+ * this is NULL, the backend, bus, and addr
+ * arguments will be used instead.
+ * @param[in] backend Backend to use. This is only used if
+ * device_identifier is `NULL`.
+ * @param[in] bus Bus number the device is located on. This
+ * is only used if device_identifier is `NULL`.
+ * @param[in] addr Bus address the device is located on. This
+ * is only used if device_identifier is `NULL`.
+ * @param[in] file Filename of the firmware image to boot
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_load_fw_from_bootloader(const char *device_identifier,
+ bladerf_backend backend,
+ uint8_t bus,
+ uint8_t addr,
+ const char *file);
+
+/** @} (End of FN_PROG) */
+
+/**
+ * @defgroup FN_IMAGE Flash image format
+ *
+ * This section contains a file format and associated routines for storing
+ * and loading flash contents with metadata.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/** Type of data stored in a flash image */
+typedef enum {
+ BLADERF_IMAGE_TYPE_INVALID = -1, /**< Used to denote invalid value */
+ BLADERF_IMAGE_TYPE_RAW, /**< Misc. raw data */
+ BLADERF_IMAGE_TYPE_FIRMWARE, /**< Firmware data */
+ BLADERF_IMAGE_TYPE_FPGA_40KLE, /**< FPGA bitstream for 40 KLE device */
+ BLADERF_IMAGE_TYPE_FPGA_115KLE, /**< FPGA bitstream for 115 KLE device */
+ BLADERF_IMAGE_TYPE_FPGA_A4, /**< FPGA bitstream for A4 device */
+ BLADERF_IMAGE_TYPE_FPGA_A9, /**< FPGA bitstream for A9 device */
+ BLADERF_IMAGE_TYPE_CALIBRATION, /**< Board calibration */
+ BLADERF_IMAGE_TYPE_RX_DC_CAL, /**< RX DC offset calibration table */
+ BLADERF_IMAGE_TYPE_TX_DC_CAL, /**< TX DC offset calibration table */
+ BLADERF_IMAGE_TYPE_RX_IQ_CAL, /**< RX IQ balance calibration table */
+ BLADERF_IMAGE_TYPE_TX_IQ_CAL, /**< TX IQ balance calibration table */
+ BLADERF_IMAGE_TYPE_FPGA_A5, /**< FPGA bitstream for A5 device */
+ BLADERF_IMAGE_TYPE_GAIN_CAL, /**< Gain calibration */
+} bladerf_image_type;
+
+/** Size of the magic signature at the beginning of bladeRF image files */
+#define BLADERF_IMAGE_MAGIC_LEN 7
+
+/** Size of bladeRF flash image checksum */
+#define BLADERF_IMAGE_CHECKSUM_LEN 32
+
+/** Size of reserved region of flash image */
+#define BLADERF_IMAGE_RESERVED_LEN 128
+
+/**
+ * Image format for backing up and restoring bladeRF flash contents
+ *
+ * The on disk format generated by the bladerf_image_write function is a
+ * serialized version of this structure and its contents. When written to disk,
+ * values are converted to big-endian byte order, for ease of reading in a hex
+ * editor.
+ *
+ * When creating and using a bladerf_image of type ::BLADERF_IMAGE_TYPE_RAW,
+ * the address and length fields must be erase-block aligned.
+ */
+struct bladerf_image {
+ /**
+ * Magic value used to identify image file format.
+ *
+ * Note that an extra character is added to store a `NUL`-terminator,
+ * to allow this field to be printed. This `NUL`-terminator is *NOT*
+ * written in the serialized image.
+ */
+ char magic[BLADERF_IMAGE_MAGIC_LEN + 1];
+
+ /**
+ * SHA256 checksum of the flash image. This is computed over the entire
+ * image, with this field filled with 0's.
+ */
+ uint8_t checksum[BLADERF_IMAGE_CHECKSUM_LEN];
+
+ /**
+ * Image format version. Only the major, minor, and patch fields are
+ * written to the disk; the describe field is not used. The version is
+ * serialized as: [major | minor | patch]
+ */
+ struct bladerf_version version;
+
+ /** UTC image timestamp, in seconds since the Unix Epoch */
+ uint64_t timestamp;
+
+ /**
+ * Serial number of the device that the image was obtained from. This
+ * field should be all '\0' if irrelevant.
+ *
+ * The +1 here is actually extraneous; ::BLADERF_SERIAL_LENGTH already
+ * accounts for a `NUL` terminator. However, this is left here to avoid
+ * breaking backwards compatibility.
+ */
+ char serial[BLADERF_SERIAL_LENGTH + 1];
+
+ /**
+ * Reserved for future metadata. Should be 0's.
+ */
+ char reserved[BLADERF_IMAGE_RESERVED_LEN];
+
+ /**
+ * Type of data contained in the image. Serialized as a uint32_t.
+ */
+ bladerf_image_type type;
+
+ /**
+ * Address of the flash data in this image. A value of `0xffffffff`
+ * implies that this field is left unspecified (i.e., "don't care").
+ */
+ uint32_t address;
+
+ /** Length of the data contained in the image */
+ uint32_t length;
+
+ /** Image data */
+ uint8_t *data;
+};
+
+/**
+ * Allocate and initialize an image structure.
+ *
+ * This following bladerf_image fields are populated: `magic`, `version`,
+ * `timestamp`, `type`, `address`, and `length`
+ *
+ * The following bladerf_image fields are zeroed out: `checksum`, `serial`, and
+ * `reserved`
+ *
+ * If the `length` parameter is not 0, the ::bladerf_image `data` field will be
+ * dynamically allocated. Otherwise, `data` will be set to NULL.
+ *
+ * @note A non-zero `length` should be use only with bladerf_image_write();
+ * bladerf_image_read() allocates and sets `data` based upon size of the
+ * image contents, and does not attempt to free() the `data` field before
+ * setting it.
+ *
+ * The `address` and `length` fields should be set 0 when reading an image from
+ * a file.
+ *
+ * @param[in] dev Device handle
+ * @param[in] type Image type to be created, represented by `bladerf_image_type`
+ * @param[in] address Address in flash memory where the image is stored. Use 0xffffffff if not applicable.
+ * @param[in] length Length of the image data in bytes
+ *
+ * @return Pointer to allocated and initialized structure on success,
+ * `NULL` on memory allocation failure or invalid address/length.
+ */
+API_EXPORT
+struct bladerf_image *CALL_CONV bladerf_alloc_image(struct bladerf *dev,
+ bladerf_image_type type,
+ uint32_t address,
+ uint32_t length);
+
+/**
+ * Create a flash image initialized to contain a calibration data region.
+ *
+ * This is intended to be used in conjunction with bladerf_image_write(), or a
+ * write of the image's `data` field to flash.
+ *
+ * @param[in] dev Device handle
+ * @param[in] fpga_size Target FPGA size
+ * @param[in] vctcxo_trim VCTCXO oscillator trim value.
+ *
+ * @return Pointer to allocated and initialized structure on success,
+ * `NULL` on memory allocation failure
+ */
+API_EXPORT
+struct bladerf_image *CALL_CONV bladerf_alloc_cal_image(
+ struct bladerf *dev, bladerf_fpga_size fpga_size, uint16_t vctcxo_trim);
+
+/**
+ * Free a bladerf_image previously obtained via bladerf_alloc_image.
+ *
+ * If the bladerf_image's `data` field is non-`NULL`, it will be freed.
+ *
+ * @param[inout] image Flash image
+ */
+API_EXPORT
+void CALL_CONV bladerf_free_image(struct bladerf_image *image);
+
+/**
+ * @brief Prints the metadata of a bladeRF image structure.
+ *
+ * This function displays the metadata of a provided `bladerf_image` structure.
+ * It includes information such as the magic number, version, timestamp, serial number,
+ * address, and length of the image. The function will return an error code if the
+ * provided image pointer is `NULL`.
+ *
+ * @pre The image should have been allocated using bladerf_alloc_image().
+ *
+ * @note This function only prints the metadata of the image and does not
+ * perform any operations on the image data itself.
+ *
+ * @param[in] image Pointer to the `bladerf_image` structure whose metadata is to be printed.
+ * It should not be `NULL`.
+ *
+ * @return 0 on success, BLADERF_ERR_MEM if the image pointer is `NULL`.
+ */
+API_EXPORT
+int CALL_CONV bladerf_image_print_metadata(const struct bladerf_image *image);
+
+/**
+ * @brief Converts a bladeRF image type to its corresponding string representation.
+ *
+ * This function maps a `bladerf_image_type` enumeration value to a human-readable
+ * string. It is useful for logging, debugging, or displaying the image type
+ * to an end user.
+ *
+ * @param[in] type The `bladerf_image_type` enumeration value to be converted.
+ *
+ * @return A pointer to a string representing the image type. Returns "Unknown Type"
+ * for any unrecognized or out-of-range values.
+ */
+const char* bladerf_image_type_to_string(bladerf_image_type type);
+
+/**
+ * Write a flash image to a file.
+ *
+ * This function will fill in the checksum field before writing the contents to
+ * the specified file. The user-supplied contents of this field are ignored.
+ *
+ * @pre `image` has been initialized using bladerf_alloc_image()
+ * @post `image->checksum` will be populated if this function succeeds
+ *
+ * @param[in] dev Device handle
+ * @param[in] image Flash image
+ * @param[in] file File to write the flash image to
+ *
+ * @return 0 upon success, or a value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_image_write(struct bladerf *dev,
+ struct bladerf_image *image,
+ const char *file);
+
+/**
+ * Read flash image from a file.
+ *
+ * @pre The `image` parameter has been obtained via a call to
+ * bladerf_alloc_image(), with a `length` of 0.
+ *
+ * @post The `image` fields will be populated upon success, overwriting any
+ * previous values.
+ *
+ * @note The contents of the `image` parameter should not be used if this
+ * function fails.
+ *
+ * @param[out] image Flash image structure to populate.
+ * @param[in] file File to read image from.
+ *
+ * @return 0 upon success,
+ * ::BLADERF_ERR_CHECKSUM upon detecting a checksum mismatch,
+ * ::BLADERF_ERR_INVAL if any image fields are invalid,
+ * ::BLADERF_ERR_IO on a file I/O error,
+ * or a value from \ref RETCODES list on any other failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_image_read(struct bladerf_image *image, const char *file);
+
+/** @} (End of FN_IMAGE) */
+
+/**
+ * @defgroup FN_LOW_LEVEL Low-level Functions
+ *
+ * This section defines low-level APIs.
+ *
+ * @{
+ */
+
+/**
+ * @defgroup FN_VCTCXO_TAMER VCTCXO Tamer Mode
+ *
+ * This group provides routines for controlling the VTCTXO tamer.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * VCTCXO Tamer mode selection
+ *
+ * These values control the use of header J71 pin 1 for taming the
+ * on-board VCTCXO to improve or sustain frequency accuracy.
+ *
+ * When supplying input into the VCTCXO tamer, a 1.8V signal must be provided.
+ *
+ * @warning IMPORTANT: Exceeding 1.8V on J71-1 can damage the associated FPGA
+ * I/O bank. Ensure that you provide only a 1.8V signal!
+ */
+typedef enum {
+ /** Denotes an invalid selection or state */
+ BLADERF_VCTCXO_TAMER_INVALID = -1,
+
+ /** Do not attempt to tame the VCTCXO with an input source. */
+ BLADERF_VCTCXO_TAMER_DISABLED = 0,
+
+ /** Use a 1 pps input source to tame the VCTCXO. */
+ BLADERF_VCTCXO_TAMER_1_PPS = 1,
+
+ /** Use a 10 MHz input source to tame the VCTCXO. */
+ BLADERF_VCTCXO_TAMER_10_MHZ = 2
+} bladerf_vctcxo_tamer_mode;
+
+/**
+ * Set the VCTCXO tamer mode.
+ *
+ * @param dev Device handle
+ * @param[in] mode VCTCXO taming mode
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_vctcxo_tamer_mode(struct bladerf *dev,
+ bladerf_vctcxo_tamer_mode mode);
+
+/**
+ * Get the current VCTCXO tamer mode
+ *
+ * @param dev Device handle
+ * @param[out] mode Current VCTCXO taming mode or
+ * ::BLADERF_VCTCXO_TAMER_INVALID if a failure
+ * occurs.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_vctcxo_tamer_mode(struct bladerf *dev,
+ bladerf_vctcxo_tamer_mode *mode);
+
+/** @} (End of FN_VCTCXO_TAMER) */
+
+/**
+ * @defgroup FN_VCTCXO_TRIM_DAC VCTCXO Trim DAC
+ *
+ * These functions provide the ability to manipulate the VCTCXO Trim DAC.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Query a device's VCTCXO calibration trim
+ *
+ * @param dev Device handle
+ * @param[out] trim VCTCXO calibration trim
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_vctcxo_trim(struct bladerf *dev, uint16_t *trim);
+
+/**
+ * Write value to VCTCXO trim DAC.
+ *
+ * @note This should not be used when the VCTCXO tamer is enabled.
+ *
+ * @param dev Device handle
+ * @param[in] val Desired VCTCXO trim DAC value
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_trim_dac_write(struct bladerf *dev, uint16_t val);
+
+/**
+ * Read value from VCTCXO trim DAC.
+ *
+ * This is similar to bladerf_get_vctcxo_trim(), except that it returns the
+ * current trim DAC value, as opposed to the calibration value read from flash.
+ *
+ * Use this if you are trying to query the value after having previously made
+ * calls to bladerf_trim_dac_write().
+ *
+ * @param dev Device handle
+ * @param[out] val Current VCTCXO trim DAC value
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_trim_dac_read(struct bladerf *dev, uint16_t *val);
+
+/** @} (End of FN_VCTCXO_TRIM_DAC) */
+
+/**
+ * @defgroup FN_TUNING_MODE Tuning Mode
+ *
+ * These functions provide the ability to select the tuning mode.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Frequency tuning modes
+ *
+ * The default tuning mode, `BLADERF_TUNING_MODE_HOST`, can be overridden by
+ * setting a BLADERF_DEFAULT_TUNING_MODE environment variable to `host` or `fpga`.
+ *
+ * ::BLADERF_TUNING_MODE_HOST is the default tuning mode.
+ *
+ * ::BLADERF_TUNING_MODE_FPGA requirements:
+ * - libbladeRF >= v1.3.0
+ * - FPGA >= v0.2.0
+ *
+ * @note Overriding this value with a mode not supported by the FPGA will result
+ * in failures or unexpected behavior.
+ */
+typedef enum {
+ /** Indicates an invalid mode is set */
+ BLADERF_TUNING_MODE_INVALID = -1,
+
+ /**
+ * Perform tuning algorithm on the host. This is slower, but provides
+ * easier accessiblity to diagnostic information.
+ */
+ BLADERF_TUNING_MODE_HOST,
+
+ /** Perform tuning algorithm on the FPGA for faster tuning. */
+ BLADERF_TUNING_MODE_FPGA,
+} bladerf_tuning_mode;
+
+/**
+ * Set the device's tuning mode
+ *
+ * @param dev Device handle
+ * @param[in] mode Desired tuning mode. Note that the available modes
+ * depends on the FPGA version.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_tuning_mode(struct bladerf *dev,
+ bladerf_tuning_mode mode);
+
+/**
+ * Get the device's current tuning mode
+ *
+ * @param dev Device handle
+ * @param[in] mode Tuning mode
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_tuning_mode(struct bladerf *dev,
+ bladerf_tuning_mode *mode);
+
+/** @} (End of FN_TUNING_MODE) */
+
+/**
+ * @defgroup FN_TRIGGER_CONTROL Trigger Control
+ *
+ * These functions provide the ability to read and write the trigger control
+ * registers.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Trigger control register "Arm" bit
+ *
+ * This bit arms (i.e., enables) the trigger controller when set to 1. Samples
+ * will be gated until the "Fire" bit has been asserted.
+ *
+ * A 0 in this bit disables the trigger controller. Samples will continue to
+ * flow as they normally do in this state.
+ */
+#define BLADERF_TRIGGER_REG_ARM ((uint8_t)(1 << 0))
+
+/**
+ * Trigger control register "Fire" bit
+ *
+ * For a master, this bit causes a trigger to be sent to all slave devices. Once
+ * this trigger is received (the master "receives" it immediately as well),
+ * devices begin streaming samples.
+ *
+ * This bit has no effect on slave devices.
+ */
+#define BLADERF_TRIGGER_REG_FIRE ((uint8_t)(1 << 1))
+
+/**
+ * Trigger control register "Master" bit
+ *
+ * Selects whether the device is a trigger master (1) or trigger slave (0). The
+ * trigger master drives the trigger signal as an output.
+ *
+ * Slave devices configure the trigger signal as an input.
+ */
+#define BLADERF_TRIGGER_REG_MASTER ((uint8_t)(1 << 2))
+
+/**
+ * Trigger control registers "line" bit
+ *
+ * This is a read-only register bit that denotes the current state of the the
+ * trigger signal.
+ */
+#define BLADERF_TRIGGER_REG_LINE ((uint8_t)(1 << 3))
+
+/**
+ * Read trigger control register
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] signal Trigger signal (control register) to read from
+ * @param[out] val Pointer to variable that register is read into See
+ * the BLADERF_TRIGGER_REG_* macros for the meaning of
+ * each bit.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_read_trigger(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_trigger_signal signal,
+ uint8_t *val);
+
+/**
+ * Write trigger control register
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] signal Trigger signal to configure
+ * @param[in] val Data to write into the trigger control register.
+ * See the BLADERF_TRIGGER_REG_* macros for options.
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_write_trigger(struct bladerf *dev,
+ bladerf_channel ch,
+ bladerf_trigger_signal signal,
+ uint8_t val);
+
+/** @} (End of FN_TRIGGER_CONTROL) */
+
+/**
+ * @defgroup FN_WISHBONE_MASTER Wishbone bus master
+ *
+ * These functions provide the ability to read and write to the wishbone peripheral bus,
+ * which is reserved for modem
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Read a specific Wishbone Master address
+ *
+ * @param dev Device handle
+ * @param addr Wishbone Master address
+ * @param[out] data Wishbone Master data
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_wishbone_master_read(struct bladerf *dev, uint32_t addr, uint32_t *data);
+
+/**
+ * Write value to a specific Wishbone Master address
+ *
+ *
+ * @param dev Device handle
+ * @param addr Wishbone Master address
+ * @param data Wishbone Master data
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_wishbone_master_write(struct bladerf *dev, uint32_t addr, uint32_t val);
+
+/** @} (End of FN_WISHBONE_MASTER) */
+
+
+/**
+ * @defgroup FN_CONFIG_GPIO Configuration GPIO
+ *
+ * These functions provide the ability to read and write the configuration
+ * GPIO.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Read the configuration GPIO register.
+ *
+ * @param dev Device handle
+ * @param[out] val Current configuration GPIO value
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_config_gpio_read(struct bladerf *dev, uint32_t *val);
+
+/**
+ * Write the configuration GPIO register.
+ *
+ * @note Callers should be sure to perform a read-modify-write sequence to
+ * avoid accidentally clearing other GPIO bits that may be set by the
+ * library internally.
+ *
+ * @param dev Device handle
+ * @param[out] val Desired configuration GPIO value
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_config_gpio_write(struct bladerf *dev, uint32_t val);
+
+/** @} (End of FN_CONFIG_GPIO) */
+
+/**
+ * @defgroup FN_SPI_FLASH SPI Flash
+ *
+ * These functions provide the ability to erase, read, and write the SPI flash.
+ *
+ * @warning Use of SPI flash functions requires an understanding of the
+ * underlying SPI flash device, and the bladeRF's flash memory map. Be
+ * sure to review the following page and the associated flash datasheet
+ * before using these functions:
+ * https://github.com/nuand/bladeRF/wiki/FX3-Firmware#spi-flash-layout
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Erase regions of the bladeRF's SPI flash
+ *
+ * @note This function operates in units of 64 KiB erase blocks
+ * @note Not recommended for new designs. Consider using the
+ * `bladerf_erase_flash_bytes()` function instead. It will perform the
+ * necessary conversion from bytes to pages based on the specific
+ * flash architecture found on the board.
+ *
+ * @param dev Device handle
+ * @param[in] erase_block Erase block from which to start erasing
+ * @param[in] count Number of blocks to erase
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `erase_block` or `count` value,
+ * or a value from \ref RETCODES list on other failures
+ */
+API_EXPORT
+int CALL_CONV bladerf_erase_flash(struct bladerf *dev,
+ uint32_t erase_block,
+ uint32_t count);
+
+/**
+ * Erase regions of the bladeRF's SPI flash
+ *
+ * @note This function operates in units of bytes
+ *
+ * @param dev Device handle
+ * @param[in] address Address at which to start erasing
+ * @param[in] length Number of bytes to erase
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `address` or `length` value,
+ * or a value from \ref RETCODES list on other failures
+ */
+API_EXPORT
+int CALL_CONV bladerf_erase_flash_bytes(struct bladerf *dev,
+ uint32_t address,
+ uint32_t length);
+
+/**
+ * Read data from the bladeRF's SPI flash
+ *
+ * @note This function operates in units of flash pages.
+ * @note Not recommended for new designs. Consider using the
+ * `bladerf_read_flash_bytes()` function instead. It will perform the
+ * necessary conversion from bytes to pages based on the specific
+ * flash architecture found on the board.
+ *
+ * @param dev Device handle
+ * @param[in] buf Buffer to read data into. Must be `count` *
+ * flash-page-size bytes or larger.
+ * @param[in] page Page to begin reading from
+ * @param[in] count Number of pages to read
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `page` or `count` value,
+ * or a value from \ref RETCODES list on other failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_read_flash(struct bladerf *dev,
+ uint8_t *buf,
+ uint32_t page,
+ uint32_t count);
+
+/**
+ * Read data from the bladeRF's SPI flash
+ *
+ * @note This function operates in units of bytes.
+ *
+ * @param dev Device handle
+ * @param[in] buf Buffer to read data into. Must be `bytes`
+ * bytes or larger.
+ * @param[in] address Address to begin reading from
+ * @param[in] bytes Number of bytes to read
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `address` or `bytes` value,
+ * or a value from \ref RETCODES list on other failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_read_flash_bytes(struct bladerf *dev,
+ uint8_t *buf,
+ uint32_t address,
+ uint32_t bytes);
+
+/**
+ * Write data to the bladeRF's SPI flash device
+ *
+ * @note This function operates in units of flash pages.
+ * @note Not recommended for new designs. Consider using the
+ * `bladerf_write_flash_bytes()` function instead. It will perform the
+ * necessary conversion from bytes to pages based on the specific
+ * flash architecture found on the board.
+ *
+ * @param dev Device handle
+ * @param[in] buf Data to write to flash
+ * @param[in] page Page to begin writing at
+ * @param[in] count Number of pages to write
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `page` or `count` value,
+ * or a value from \ref RETCODES list on other failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_write_flash(struct bladerf *dev,
+ const uint8_t *buf,
+ uint32_t page,
+ uint32_t count);
+
+/**
+ * Write data to the bladeRF's SPI flash device
+ *
+ * @note This function operates in units of bytes.
+ *
+ * @param dev Device handle
+ * @param[in] buf Data to write to flash
+ * @param[in] address Address to begin writing at
+ * @param[in] length Number of bytes to write
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `address` or `length` value,
+ * or a value from \ref RETCODES list on other failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_write_flash_bytes(struct bladerf *dev,
+ const uint8_t *buf,
+ uint32_t address,
+ uint32_t length);
+
+/**
+ * Lock the bladeRF's OTP
+ *
+ * @param dev Device handle
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `page` or `count` value,
+ * or a value from \ref RETCODES list on other failures.
+ */
+
+API_EXPORT
+int CALL_CONV bladerf_lock_otp(struct bladerf *dev);
+
+/**
+ * Read data from the bladeRF's SPI flash OTP
+ *
+ * @note This function operates solely on the first 256 byte page of the OTP
+ *
+ * @param dev Device handle
+ * @param[in] buf Buffer to read OTP data into
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `page` or `count` value,
+ * or a value from \ref RETCODES list on other failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_read_otp(struct bladerf *dev,
+ uint8_t *buf);
+
+/**
+ * Write data to the bladeRF's SPI flash OTP device
+ *
+ * @note This function operates solely on the first 256 byte page of the OTP
+ *
+ * @param dev Device handle
+ * @param[in] buf Data to write to OTP
+ *
+ * @return 0 on success,
+ * or ::BLADERF_ERR_INVAL on an invalid `page` or `count` value,
+ * or a value from \ref RETCODES list on other failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_write_otp(struct bladerf *dev,
+ uint8_t *buf);
+
+/** @} (End of FN_SPI_FLASH) */
+
+/**
+ * @defgroup FN_RF_PORTS RF Ports
+ *
+ * These functions provide the ability to select various RF ports for RX and TX
+ * channels. This is normally handled automatically.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Set the RF port
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[in] port RF port name
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_set_rf_port(struct bladerf *dev,
+ bladerf_channel ch,
+ const char *port);
+
+/**
+ * Get the RF port
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] port RF port name
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_rf_port(struct bladerf *dev,
+ bladerf_channel ch,
+ const char **port);
+
+/**
+ * Get available RF ports
+ *
+ * This function may be called with `NULL` for `ports`, or 0 for `count`, to
+ * determine the number of RF ports.
+ *
+ * @param dev Device handle
+ * @param[in] ch Channel
+ * @param[out] ports RF port names
+ * @param[out] count Number to populate
+ *
+ * @return Number of RF ports on success, value from \ref RETCODES list on
+ * failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_rf_ports(struct bladerf *dev,
+ bladerf_channel ch,
+ const char **ports,
+ unsigned int count);
+
+/** @} (End of FN_RF_PORTS) */
+
+/** @} (End of FN_LOW_LEVEL) */
+
+/**
+ * @defgroup FN_SF Features
+ *
+ * This group of functions provides the ability to set features available
+ * to bladeRF devices.
+ *
+ * @{
+ */
+
+/**
+ * Feature Set
+ */
+typedef enum {
+ BLADERF_FEATURE_DEFAULT = 0, /**< No feature enabled */
+ BLADERF_FEATURE_OVERSAMPLE /**< Enforces AD9361 OC and 8bit mode */
+} bladerf_feature;
+
+/**
+ * Enables a feature.
+ *
+ * @param dev Device handle
+ * @param[out] feature Feature
+ * @param[in] enable true to enable, false to disable
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_enable_feature(struct bladerf *dev,
+ bladerf_feature feature,
+ bool enable);
+
+/**
+ * Gets currently enabled feature.
+ *
+ * @param dev Device handle
+ * @param[out] feature Feature
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_feature(struct bladerf *dev,
+ bladerf_feature* feature);
+
+/** @} (End of FN_SF) */
+
+/**
+ * @defgroup FN_CAL Gain Calibration
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * @brief Individual gain calibration entry. Each entry associates a frequency
+ * with a corresponding gain correction factor.
+ */
+struct bladerf_gain_cal_entry {
+ bladerf_frequency freq; /**< Frequency (Hz) */
+ double gain_corr; /**< Gain correction factor */
+};
+
+/**
+ * @brief Gain calibration table. The table contains a series of
+ * entries, each associating a frequency with a gain correction factor. Entries
+ * are sorted by frequency, from start_freq to stop_freq.
+ */
+struct bladerf_gain_cal_tbl {
+ struct bladerf_version version; /**< Table format version */
+ bladerf_channel ch; /**< Channel */
+ bool enabled; /**< Whether gain calibration is enabled. */
+ uint32_t n_entries; /**< Number of entries */
+ bladerf_frequency start_freq; /**< Start frequency (Hz) */
+ bladerf_frequency stop_freq; /**< Stop frequency (Hz) */
+ struct bladerf_gain_cal_entry *entries; /**< Sorted calibration entries */
+ bladerf_gain gain_target; /**< Compensated gain */
+ size_t file_path_len; /**< Length of the file path string. */
+ char *file_path; /**< Path to the file from which the table was loaded. */
+ enum gain_cal_state {
+ BLADERF_GAIN_CAL_UNINITIALIZED,
+ BLADERF_GAIN_CAL_LOADED,
+ BLADERF_GAIN_CAL_UNLOADED
+ } state; /**< Calibration state */
+};
+
+
+/**
+ * @brief Loads and applies gain calibration for a specified channel from a
+ * file.
+ *
+ * This function adjusts the specified channel's gain settings on the bladeRF
+ * device using calibration data from the provided file path. It supports
+ * calibration files in CSV format, automatically converting them to binary
+ * format as required by the device. This ensures the device operates with
+ * optimized gain settings across its frequency range. The operation is
+ * protected by mutex locks to maintain thread safety.
+ *
+ * @param[in] dev Pointer to the initialized bladeRF device.
+ * @param[in] ch The target channel (RX or TX) for gain calibration.
+ * @param[in] cal_file_loc Path to the calibration file, either in CSV or binary
+ * format. CSV files are converted to binary format during the process.
+ *
+ * @return 0 on success, indicating that the calibration data was successfully
+ * applied to the channel. Returns BLADERF_ERR_UNSUPPORTED if the device or
+ * channel does not support gain calibration. Other BLADERF_ERR_* error codes
+ * indicate specific failures, such as file access issues or conversion errors.
+ */
+API_EXPORT
+int CALL_CONV bladerf_load_gain_calibration(struct bladerf *dev,
+ bladerf_channel ch,
+ const char* cal_file_loc);
+
+/**
+ * @brief Displays gain calibration details for a specified channel.
+ *
+ * Outputs the gain calibration information to the console. The level of detail
+ * is adjustable via `with_entries`.
+ *
+ * @note This operation is thread-safe.
+ *
+ * @param[in] dev Non-NULL pointer to a bladeRF device.
+ * @param[in] ch Channel to display gain calibration for. Use
+ * `bladerf_channel`.
+ * @param[in] with_entries Set to `true` to print all calibration entries, or
+ * `false` for a summary only.
+ *
+ * @return 0 on success, BLADERF_ERR_UNSUPPORTED if calibration is not supported
+ * on the device, or other BLADERF_ERR_* codes for different failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_print_gain_calibration(struct bladerf *dev,
+ bladerf_channel ch,
+ bool with_entries);
+
+/**
+ * @brief Toggles gain calibration for a specified channel.
+ *
+ * Enables or disables automatic gain adjustment based on a preloaded
+ * calibration table for the specified channel. This operation is thread-safe.
+
+ *
+ * @note Gain calibration mode persists until device reset or power cycle.
+ * Ensure a calibration table is loaded before enabling.
+
+ *
+ * @param[in] dev Non-NULL pointer to the bladeRF device.
+ * @param[in] ch Channel (`BLADERF_CHANNEL_RX(0)`, `BLADERF_CHANNEL_TX(0)`,
+ * etc.) to set gain calibration for.
+ * @param[in] en `true` to enable or `false` to disable gain calibration.
+ *
+ * @return 0 on success, or a `BLADERF_ERR_*` code on failure (e.g., if
+ * calibration table is not initialized).
+ */
+API_EXPORT
+int CALL_CONV bladerf_enable_gain_calibration(struct bladerf *dev,
+ bladerf_channel ch,
+ bool en);
+
+/**
+ * @brief Provides read-only access to a channel's gain calibration table.
+ *
+ * Returns a read-only pointer to a specified channel's gain calibration table,
+ * preventing modification. Access is thread-safe, protected by device mutexes.
+ *
+ * @param[in] dev Non-NULL pointer to a BladeRF device structure.
+ * @param[in] ch Channel to retrieve the gain calibration table for.
+ * @param[out] tbl On success, updated to point to the read-only gain
+ * calibration table.
+ *
+ * @return 0 on success, BLADERF_ERR_UNEXPECTED if the table is not loaded, or
+ * BLADERF_ERR_INVAL for invalid inputs.
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain_calibration(struct bladerf *dev, bladerf_channel ch, const struct bladerf_gain_cal_tbl **tbl);
+
+/**
+ * @brief Computes the gain target for a specified channel, incorporating
+ * calibration corrections.
+ *
+ * For a channel, this calculates the target gain considering the current gain
+ * setting and calibration corrections, if available. In MGC mode, it returns
+ * the target gain from the calibration table. In AGC mode, it adjusts the
+ * target based on the calibration correction for the current frequency.
+ *
+ * @note Access to device and calibration data is thread-safe.
+ *
+ * @param[in] dev Non-NULL pointer to a BladeRF device.
+ * @param[in] ch Channel (RX/TX) for querying the gain target.
+ * @param[out] gain_target Where to store the computed gain target. Reflects
+ * current gain and calibration corrections.
+ *
+ * @return 0 if successful, with `gain_target` updated. On failure, returns
+ * BLADERF_ERR_UNEXPECTED if calibration is uninitialized, or other error codes
+ * for different failures.
+ */
+API_EXPORT
+int CALL_CONV bladerf_get_gain_target(struct bladerf *dev, bladerf_channel ch, int *gain_target);
+
+/** @} (End of FN_CAL) */
+
+/**
+ * @defgroup FN_XB Expansion board support
+ *
+ * This group of functions provides the ability to attach and detach expansion
+ * boards.
+ *
+ * In general, one should call bladerf_expansion_attach() immediately after
+ * opening the device.
+ *
+ * @note Hotplug and expansion board removal is not supported. It is expected
+ * that the expansion boards are attached at power-on and remain attached
+ * until power is removed.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Expansion boards
+ */
+typedef enum {
+ BLADERF_XB_NONE = 0, /**< No expansion boards attached */
+ BLADERF_XB_100, /**< XB-100 GPIO expansion board.
+ * This device is not yet supported in
+ * libbladeRF, and is here as a placeholder
+ * for future support. */
+ BLADERF_XB_200, /**< XB-200 Transverter board */
+ BLADERF_XB_300 /**< XB-300 Amplifier board */
+} bladerf_xb;
+
+/**
+ * Attach and enable an expansion board's features
+ *
+ * @param dev Device handle
+ * @param[in] xb Expansion board
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_expansion_attach(struct bladerf *dev, bladerf_xb xb);
+
+/**
+ * Determine which expansion board is attached
+ *
+ * @param dev Device handle
+ * @param[out] xb Expansion board
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+API_EXPORT
+int CALL_CONV bladerf_expansion_get_attached(struct bladerf *dev,
+ bladerf_xb *xb);
+
+/** @} (End of FN_XB) */
+
+/**
+ * @defgroup FN_LOGGING Logging
+ *
+ * This section contains various helper/utility functions for library logging
+ * facilities.
+ *
+ * These functions are thread-safe.
+ *
+ * @{
+ */
+
+/**
+ * Severity levels for logging functions
+ */
+typedef enum {
+ BLADERF_LOG_LEVEL_VERBOSE, /**< Verbose level logging */
+ BLADERF_LOG_LEVEL_DEBUG, /**< Debug level logging */
+ BLADERF_LOG_LEVEL_INFO, /**< Information level logging */
+ BLADERF_LOG_LEVEL_WARNING, /**< Warning level logging */
+ BLADERF_LOG_LEVEL_ERROR, /**< Error level logging */
+ BLADERF_LOG_LEVEL_CRITICAL, /**< Fatal error level logging */
+ BLADERF_LOG_LEVEL_SILENT /**< No output */
+} bladerf_log_level;
+
+/**
+ * Sets the filter level for displayed log messages.
+ *
+ * Messages that are at or above the specified log level will be printed, while
+ * messages with a lower log level will be suppressed.
+ *
+ * @param[in] level The new log level filter value
+ */
+API_EXPORT
+void CALL_CONV bladerf_log_set_verbosity(bladerf_log_level level);
+
+/** @} (End of FN_LOGGING) */
+
+/**
+ * @defgroup FN_LIBRARY_VERSION Library version
+ *
+ * @{
+ */
+
+/**
+ * Get libbladeRF version information
+ *
+ * @param[out] version libbladeRF version information
+ */
+API_EXPORT
+void CALL_CONV bladerf_version(struct bladerf_version *version);
+
+/** @} (End of FN_LIBRARY_VERSION) */
+
+/**
+ * @defgroup RETCODES Error codes
+ *
+ * bladeRF library routines return negative values to indicate errors.
+ * Values >= 0 are used to indicate success.
+ *
+ * @code
+ * int status = bladerf_set_gain(dev, BLADERF_CHANNEL_RX(0), 2);
+ *
+ * if (status < 0) {
+ * handle_error();
+ * }
+ * @endcode
+ *
+ * @{
+ */
+// clang-format off
+#define BLADERF_ERR_UNEXPECTED (-1) /**< An unexpected failure occurred */
+#define BLADERF_ERR_RANGE (-2) /**< Provided parameter is out of range */
+#define BLADERF_ERR_INVAL (-3) /**< Invalid operation/parameter */
+#define BLADERF_ERR_MEM (-4) /**< Memory allocation error */
+#define BLADERF_ERR_IO (-5) /**< File/Device I/O error */
+#define BLADERF_ERR_TIMEOUT (-6) /**< Operation timed out */
+#define BLADERF_ERR_NODEV (-7) /**< No device(s) available */
+#define BLADERF_ERR_UNSUPPORTED (-8) /**< Operation not supported */
+#define BLADERF_ERR_MISALIGNED (-9) /**< Misaligned flash access */
+#define BLADERF_ERR_CHECKSUM (-10) /**< Invalid checksum */
+#define BLADERF_ERR_NO_FILE (-11) /**< File not found */
+#define BLADERF_ERR_UPDATE_FPGA (-12) /**< An FPGA update is required */
+#define BLADERF_ERR_UPDATE_FW (-13) /**< A firmware update is requied */
+#define BLADERF_ERR_TIME_PAST (-14) /**< Requested timestamp is in the past */
+#define BLADERF_ERR_QUEUE_FULL (-15) /**< Could not enqueue data into
+ * full queue */
+#define BLADERF_ERR_FPGA_OP (-16) /**< An FPGA operation reported failure */
+#define BLADERF_ERR_PERMISSION (-17) /**< Insufficient permissions for the
+ * requested operation */
+#define BLADERF_ERR_WOULD_BLOCK (-18) /**< Operation would block, but has been
+ * requested to be non-blocking. This
+ * indicates to a caller that it may
+ * need to retry the operation later.
+ */
+#define BLADERF_ERR_NOT_INIT (-19) /**< Device insufficiently initialized
+ * for operation */
+// clang-format on
+
+/**
+ * Obtain a textual description of a value from the \ref RETCODES list
+ *
+ * @param[in] error Error value to look up
+ *
+ * @return Error string
+ */
+API_EXPORT
+const char *CALL_CONV bladerf_strerror(int error);
+
+/** @} (End RETCODES) */
+
+#include "bladeRF1.h"
+#include "bladeRF2.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBBLADERF_H_ */