diff options
Diffstat (limited to 'Radio/HW/BladeRF/src/board/bladerf2/common.h')
-rw-r--r-- | Radio/HW/BladeRF/src/board/bladerf2/common.h | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/Radio/HW/BladeRF/src/board/bladerf2/common.h b/Radio/HW/BladeRF/src/board/bladerf2/common.h new file mode 100644 index 0000000..5a88cb4 --- /dev/null +++ b/Radio/HW/BladeRF/src/board/bladerf2/common.h @@ -0,0 +1,494 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2018 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 BLADERF2_COMMON_H_ +#define BLADERF2_COMMON_H_ + +#if !defined(BLADERF_NIOS_BUILD) && !defined(BLADERF_NIOS_PC_SIMULATION) +#include "log.h" +#endif + +#include "bladerf2_common.h" +#include "helpers/version.h" +#include "streaming/sync.h" + + +/******************************************************************************/ +/* Types */ +/******************************************************************************/ + +enum bladerf2_vctcxo_trim_source { + TRIM_SOURCE_NONE, + TRIM_SOURCE_TRIM_DAC, + TRIM_SOURCE_PLL, + TRIM_SOURCE_AUXDAC +}; + +enum bladerf2_rfic_command_mode { + RFIC_COMMAND_HOST, /**< Host-based control */ + RFIC_COMMAND_FPGA, /**< FPGA-based control */ +}; + +struct controller_fns { + bool (*is_present)(struct bladerf *dev); + bool (*is_initialized)(struct bladerf *dev); + bool (*is_standby)(struct bladerf *dev); + int (*get_init_state)(struct bladerf *dev, bladerf_rfic_init_state *state); + + int (*initialize)(struct bladerf *dev); + int (*standby)(struct bladerf *dev); + int (*deinitialize)(struct bladerf *dev); + + int (*enable_module)(struct bladerf *dev, bladerf_channel ch, bool enable); + + int (*get_sample_rate)(struct bladerf *dev, + bladerf_channel ch, + bladerf_sample_rate *rate); + int (*set_sample_rate)(struct bladerf *dev, + bladerf_channel ch, + bladerf_sample_rate rate); + + int (*get_frequency)(struct bladerf *dev, + bladerf_channel ch, + bladerf_frequency *frequency); + int (*set_frequency)(struct bladerf *dev, + bladerf_channel ch, + bladerf_frequency frequency); + int (*select_band)(struct bladerf *dev, + bladerf_channel ch, + bladerf_frequency frequency); + + int (*get_bandwidth)(struct bladerf *dev, + bladerf_channel ch, + bladerf_bandwidth *bandwidth); + int (*set_bandwidth)(struct bladerf *dev, + bladerf_channel ch, + bladerf_bandwidth bandwidth, + bladerf_bandwidth *actual); + + int (*get_gain_mode)(struct bladerf *dev, + bladerf_channel ch, + bladerf_gain_mode *mode); + int (*set_gain_mode)(struct bladerf *dev, + bladerf_channel ch, + bladerf_gain_mode mode); + + int (*get_gain)(struct bladerf *dev, bladerf_channel ch, int *gain); + int (*set_gain)(struct bladerf *dev, bladerf_channel ch, int gain); + + int (*get_gain_stage)(struct bladerf *dev, + bladerf_channel ch, + char const *stage, + int *gain); + int (*set_gain_stage)(struct bladerf *dev, + bladerf_channel ch, + char const *stage, + int gain); + + int (*get_rssi)(struct bladerf *dev, + bladerf_channel ch, + int *pre_rssi, + int *sym_rssi); + + int (*get_filter)(struct bladerf *dev, + bladerf_channel ch, + bladerf_rfic_rxfir *rxfir, + bladerf_rfic_txfir *txfir); + int (*set_filter)(struct bladerf *dev, + bladerf_channel ch, + bladerf_rfic_rxfir rxfir, + bladerf_rfic_txfir txfir); + + int (*get_txmute)(struct bladerf *dev, bladerf_channel ch, bool *state); + int (*set_txmute)(struct bladerf *dev, bladerf_channel ch, bool state); + + int (*store_fastlock_profile)(struct bladerf *dev, + bladerf_channel ch, + uint32_t profile); + + int (*save_fastlock_profile)(struct bladerf *dev, + bladerf_channel ch, + uint32_t profile, + uint8_t *values); + + enum bladerf2_rfic_command_mode const command_mode; +}; + +struct bladerf2_board_data { + /* Board state */ + enum { + STATE_UNINITIALIZED, + STATE_FIRMWARE_LOADED, + STATE_FPGA_LOADED, + STATE_INITIALIZED, + } state; + + /* AD9361 PHY Handle */ + struct ad9361_rf_phy *phy; + + /* RFIC configuration parameters */ + void *rfic_init_params; + + /* Bitmask of capabilities determined by version numbers */ + uint64_t capabilities; + + /* Format currently being used with a module, or -1 if module is not used */ + bladerf_format module_format[NUM_MODULES]; + + /* Which mode of operation we use for tuning */ + bladerf_tuning_mode tuning_mode; + + /* Board properties */ + bladerf_fpga_size fpga_size; + /* Data message size */ + size_t msg_size; + + /* Version information */ + struct bladerf_version fpga_version; + struct bladerf_version fw_version; + char fpga_version_str[BLADERF_VERSION_STR_MAX + 1]; + char fw_version_str[BLADERF_VERSION_STR_MAX + 1]; + + /* Synchronous interface handles */ + struct bladerf_sync sync[2]; + + /* VCTCXO trim state */ + enum bladerf2_vctcxo_trim_source trim_source; + uint16_t trimdac_last_value; /**< saved running value */ + uint16_t trimdac_stored_value; /**< cached value read from SPI flash */ + + /* Quick Tune Profile Status */ + uint16_t quick_tune_tx_profile; + uint16_t quick_tune_rx_profile; + + /* RFIC backend command handling */ + struct controller_fns const *rfic; + + /* RFIC FIR Filter status */ + bladerf_rfic_rxfir rxfir; + bladerf_rfic_txfir txfir; + + /* If true, RFIC control will be fully de-initialized on close, instead of + * just put into a standby state. */ + bool rfic_reset_on_close; +}; + +struct bladerf_rfic_status_register { + bool rfic_initialized; + size_t write_queue_length; +}; + + +/******************************************************************************/ +/* Externs */ +/******************************************************************************/ + +extern AD9361_InitParam bladerf2_rfic_init_params; +extern AD9361_InitParam bladerf2_rfic_init_params_fastagc_burst; +extern AD9361_RXFIRConfig bladerf2_rfic_rx_fir_config; +extern AD9361_TXFIRConfig bladerf2_rfic_tx_fir_config; +extern AD9361_RXFIRConfig bladerf2_rfic_rx_fir_config_dec2; +extern AD9361_TXFIRConfig bladerf2_rfic_tx_fir_config_int2; +extern AD9361_RXFIRConfig bladerf2_rfic_rx_fir_config_dec4; +extern AD9361_TXFIRConfig bladerf2_rfic_tx_fir_config_int4; +extern const float ina219_r_shunt; + + +/******************************************************************************/ +/* Constants */ +/******************************************************************************/ + +extern char const *bladerf2_state_to_string[4]; + + +/******************************************************************************/ +/* Macros */ +/******************************************************************************/ + +/* Macro for logging and returning an error status. This should be used for + * errors defined in the \ref RETCODES list. */ +#define RETURN_ERROR_STATUS(_what, _status) \ + do { \ + log_error("%s: %s failed: %s\n", __FUNCTION__, _what, \ + bladerf_strerror(_status)); \ + return _status; \ + } while (0) + +/* Macro for converting, logging, and returning libad9361 error codes. */ +#define RETURN_ERROR_AD9361(_what, _status) \ + do { \ + RETURN_ERROR_STATUS(_what, errno_ad9361_to_bladerf(_status)); \ + } while (0) + +/* Macro for logging and returning ::BLADERF_ERR_INVAL */ +#define RETURN_INVAL_ARG(_what, _arg, _why) \ + do { \ + log_error("%s: %s '%s' invalid: %s\n", __FUNCTION__, _what, #_arg, \ + _why); \ + return BLADERF_ERR_INVAL; \ + } while (0) + +#define RETURN_INVAL(_what, _why) \ + do { \ + log_error("%s: %s invalid: %s\n", __FUNCTION__, _what, _why); \ + return BLADERF_ERR_INVAL; \ + } while (0) + +/** + * @brief Null test + * + * @param _var The variable to check + * + * @return RETURN_INVAL if _var is null, continues otherwise + */ +#define NULL_CHECK(_var) \ + do { \ + if (NULL == _var) { \ + RETURN_INVAL(#_var, "is null"); \ + } \ + } while (0) + +/** + * @brief Null test, with mutex unlock on failure + * + * @param _var The variable to check + * + * @return RETURN_INVAL if _var is null, continues otherwise + */ +#define NULL_CHECK_LOCKED(_var) \ + do { \ + NULL_CHECK(dev); \ + \ + if (NULL == _var) { \ + MUTEX_UNLOCK(__lock); \ + RETURN_INVAL(#_var, "is null"); \ + } \ + } while (0) + +/** + * @brief Board state check + * + * @param _state Minimum sufficient board state + * + * @return BLADERF_ERR_NOT_INIT if board's state is less than _state, continues + * otherwise + */ +#define CHECK_BOARD_STATE(_state) \ + do { \ + NULL_CHECK(dev); \ + NULL_CHECK(dev->board); \ + \ + struct bladerf2_board_data *_bd = dev->board_data; \ + \ + if (_bd->state < _state) { \ + log_error("%s: Board state insufficient for operation " \ + "(current \"%s\", requires \"%s\").\n", \ + __FUNCTION__, bladerf2_state_to_string[_bd->state], \ + bladerf2_state_to_string[_state]); \ + \ + return BLADERF_ERR_NOT_INIT; \ + } \ + } while (0) + +/** + * @brief Test if board is a bladeRF 2 + * + * @param _dev Device handle + * + * @return BLADERF_ERR_UNSUPPORTED if board is not a bladeRF 2, continues + * otherwise + */ +#define CHECK_BOARD_IS_BLADERF2(_dev) \ + do { \ + NULL_CHECK(_dev); \ + NULL_CHECK(_dev->board); \ + \ + if (_dev->board != &bladerf2_board_fns) { \ + log_error("%s: Board type \"%s\" not supported\n", __FUNCTION__, \ + _dev->board->name); \ + return BLADERF_ERR_UNSUPPORTED; \ + } \ + } while (0) + +/** + * @brief Call a function and return early if it fails + * + * @param _fn The function + * + * @return function return value if less than zero; continues otherwise + */ +#define CHECK_STATUS(_fn) \ + do { \ + int _s = _fn; \ + if (_s < 0) { \ + RETURN_ERROR_STATUS(#_fn, _s); \ + } \ + } while (0) + +/** + * @brief Call a function and goto error if it fails + * + * @param _fn The function + * + * @note `int status` must be declared in the including scope + */ +#define CHECK_STATUS_GOTO(_fn) \ + do { \ + status = _fn; \ + if (status < 0) { \ + log_error("%s: %i failed: %s\n", #_fn, status, \ + bladerf_strerror(status)); \ + goto error; \ + } \ + } while (0) + +/** + * @brief Call a function and, if it fails, unlock the mutex and return + * + * @param _fn The function + * + * @return function return value if less than zero; continues otherwise + */ +#define CHECK_STATUS_LOCKED(_fn) \ + do { \ + int _s = _fn; \ + if (_s < 0) { \ + MUTEX_UNLOCK(__lock); \ + RETURN_ERROR_STATUS(#_fn, _s); \ + } \ + } while (0) + +/** + * @brief Call a function and return early if it fails, with error translation + * from AD936x to bladeRF return codes + * + * @param _fn The function + * + * @return function return value if less than zero; continues otherwise + */ +#define CHECK_AD936X(_fn) \ + do { \ + int _s = _fn; \ + if (_s < 0) { \ + RETURN_ERROR_AD9361(#_fn, _s); \ + } \ + } while (0) + +/** + * @brief Call a function and, if it fails, unlock the mutex and return, with + * error translation from AD936x to bladeRF return codes + * + * @param _fn The function + * + * @return function return value if less than zero; continues otherwise + */ +#define CHECK_AD936X_LOCKED(_fn) \ + do { \ + int _s = _fn; \ + if (_s < 0) { \ + MUTEX_UNLOCK(__lock); \ + RETURN_ERROR_AD9361(#_fn, _s); \ + } \ + } while (0) + +/** + * @brief Execute a command block with a mutex lock + * + * @note Variables declared within the including scope must be declared + * one-per-line. + * + * @param _lock Lock to hold + * @param _thing Block to execute + */ +#define WITH_MUTEX(_lock, _thing) \ + do { \ + MUTEX *__lock = _lock; \ + \ + MUTEX_LOCK(__lock); \ + _thing; \ + MUTEX_UNLOCK(__lock); \ + } while (0) + +/** + * @brief Execute command block, conditional to _mode + * + * @param _dev Device handle + * @param _mode Command mode + * @param _thing Block to do if it happens + */ +#define IF_COMMAND_MODE(_dev, _mode, _thing) \ + do { \ + NULL_CHECK(_dev); \ + NULL_CHECK(_dev->board_data); \ + \ + struct bladerf2_board_data *bd = _dev->board_data; \ + \ + if (bd->rfic->command_mode == _mode) { \ + _thing; \ + }; \ + } while (0) + + +/******************************************************************************/ +/* Functions */ +/******************************************************************************/ + +/** + * Perform the neccessary device configuration for the specified format + * (e.g., enabling/disabling timestamp support), first checking that the + * requested format would not conflict with the other stream direction. + * + * @param dev Device handle + * @param[in] dir Direction that is currently being configured + * @param[in] format Format the channel is being configured for + * + * @return 0 on success, BLADERF_ERR_* on failure + */ +int perform_format_config(struct bladerf *dev, + bladerf_direction dir, + bladerf_format format); + +/** + * Deconfigure and update any state pertaining what a format that a stream + * direction is no longer using. + * + * @param dev Device handle + * @param[in] dir Direction that is currently being deconfigured + * + * @return 0 on success, BLADERF_ERR_* on failure + */ +int perform_format_deconfig(struct bladerf *dev, bladerf_direction dir); + +bool is_valid_fpga_size(struct bladerf *dev, + bladerf_fpga_size fpga, + size_t len); + +bool is_valid_fw_size(size_t len); + +bladerf_tuning_mode default_tuning_mode(struct bladerf *dev); + +bool check_total_sample_rate(struct bladerf *dev); + +bool does_rffe_dir_have_enabled_ch(uint32_t reg, bladerf_direction dir); + +int get_gain_offset(struct bladerf *dev, bladerf_channel ch, float *offset); + +#endif // BLADERF2_COMMON_H_ |