diff options
author | Arturs Artamonovs <arturs.artamonovs@protonmail.com> | 2024-11-03 15:56:55 +0000 |
---|---|---|
committer | Arturs Artamonovs <arturs.artamonovs@protonmail.com> | 2024-11-03 15:56:55 +0000 |
commit | cf4444e7390365df43ecbd3d130015c1e06ef88f (patch) | |
tree | 8a6eb114135a04d5efd5af213577b4fac47532ae /Radio/HW/BladeRF/include/libbladeRF.h | |
parent | ca50c0f64f1b2fce46b4cb83ed111854bac13852 (diff) | |
download | PrySDR-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.h | 4501 |
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_ */ |