diff options
Diffstat (limited to 'Radio/HW/BladeRF/src/expansion')
-rw-r--r-- | Radio/HW/BladeRF/src/expansion/xb100.c | 98 | ||||
-rw-r--r-- | Radio/HW/BladeRF/src/expansion/xb100.h | 47 | ||||
-rw-r--r-- | Radio/HW/BladeRF/src/expansion/xb200.c | 543 | ||||
-rw-r--r-- | Radio/HW/BladeRF/src/expansion/xb200.h | 105 | ||||
-rw-r--r-- | Radio/HW/BladeRF/src/expansion/xb300.c | 299 | ||||
-rw-r--r-- | Radio/HW/BladeRF/src/expansion/xb300.h | 94 |
6 files changed, 1186 insertions, 0 deletions
diff --git a/Radio/HW/BladeRF/src/expansion/xb100.c b/Radio/HW/BladeRF/src/expansion/xb100.c new file mode 100644 index 0000000..b432616 --- /dev/null +++ b/Radio/HW/BladeRF/src/expansion/xb100.c @@ -0,0 +1,98 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 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 + */ + +#include "xb100.h" + +#include "log.h" + +int xb100_attach(struct bladerf *dev) +{ + return 0; +} + +void xb100_detach(struct bladerf *dev) +{ +} + +int xb100_enable(struct bladerf *dev, bool enable) +{ + int status = 0; + + const uint32_t mask = + BLADERF_XB100_LED_D1 | + BLADERF_XB100_LED_D2 | + BLADERF_XB100_LED_D3 | + BLADERF_XB100_LED_D4 | + BLADERF_XB100_LED_D5 | + BLADERF_XB100_LED_D6 | + BLADERF_XB100_LED_D7 | + BLADERF_XB100_LED_D8 | + BLADERF_XB100_TLED_RED | + BLADERF_XB100_TLED_GREEN | + BLADERF_XB100_TLED_BLUE; + + const uint32_t outputs = mask; + const uint32_t default_values = mask; + + if (enable) { + status = dev->backend->expansion_gpio_dir_write(dev, mask, outputs); + if (status == 0) { + status = dev->backend->expansion_gpio_write(dev, mask, default_values); + } + } + + return status; +} + +int xb100_init(struct bladerf *dev) +{ + return 0; +} + +int xb100_gpio_read(struct bladerf *dev, uint32_t *val) +{ + return dev->backend->expansion_gpio_read(dev, val); +} + +int xb100_gpio_write(struct bladerf *dev, uint32_t val) +{ + return dev->backend->expansion_gpio_write(dev, 0xffffffff, val); +} + +int xb100_gpio_masked_write(struct bladerf *dev, uint32_t mask, uint32_t val) +{ + return dev->backend->expansion_gpio_write(dev, mask, val); +} + +int xb100_gpio_dir_read(struct bladerf *dev, uint32_t *val) +{ + return dev->backend->expansion_gpio_dir_read(dev, val); +} + +int xb100_gpio_dir_write(struct bladerf *dev, uint32_t val) +{ + return xb100_gpio_dir_masked_write(dev, 0xffffffff, val); +} + +int xb100_gpio_dir_masked_write(struct bladerf *dev, uint32_t mask, uint32_t val) +{ + return dev->backend->expansion_gpio_dir_write(dev, mask, val); +} diff --git a/Radio/HW/BladeRF/src/expansion/xb100.h b/Radio/HW/BladeRF/src/expansion/xb100.h new file mode 100644 index 0000000..2a49830 --- /dev/null +++ b/Radio/HW/BladeRF/src/expansion/xb100.h @@ -0,0 +1,47 @@ +/** + * @file xb.h + * + * @brief XB-100 support + * + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 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 EXPANSION_XB100_H_ +#define EXPANSION_XB100_H_ + +#include <stdbool.h> +#include <stdint.h> + +#include "board/board.h" + +int xb100_attach(struct bladerf *dev); +void xb100_detach(struct bladerf *dev); +int xb100_enable(struct bladerf *dev, bool enable); +int xb100_init(struct bladerf *dev); +int xb100_gpio_read(struct bladerf *dev, uint32_t *val); +int xb100_gpio_write(struct bladerf *dev, uint32_t val); +int xb100_gpio_masked_write(struct bladerf *dev, uint32_t mask, uint32_t val); +int xb100_gpio_dir_read(struct bladerf *dev, uint32_t *val); +int xb100_gpio_dir_write(struct bladerf *dev, uint32_t val); +int xb100_gpio_dir_masked_write(struct bladerf *dev, + uint32_t mask, + uint32_t val); + +#endif diff --git a/Radio/HW/BladeRF/src/expansion/xb200.c b/Radio/HW/BladeRF/src/expansion/xb200.c new file mode 100644 index 0000000..1e6dba2 --- /dev/null +++ b/Radio/HW/BladeRF/src/expansion/xb200.c @@ -0,0 +1,543 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 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 + */ + +#include "xb200.h" + +#include "driver/si5338.h" +#include "lms.h" +#include "rel_assert.h" +#include "log.h" + +#define BLADERF_XB_CONFIG_TX_PATH_MIX 0x04 +#define BLADERF_XB_CONFIG_TX_PATH_BYPASS 0x08 +#define BLADERF_XB_CONFIG_TX_BYPASS 0x04 +#define BLADERF_XB_CONFIG_TX_BYPASS_N 0x08 +#define BLADERF_XB_CONFIG_TX_BYPASS_MASK 0x0C +#define BLADERF_XB_CONFIG_RX_PATH_MIX 0x10 +#define BLADERF_XB_CONFIG_RX_PATH_BYPASS 0x20 +#define BLADERF_XB_CONFIG_RX_BYPASS 0x10 +#define BLADERF_XB_CONFIG_RX_BYPASS_N 0x20 +#define BLADERF_XB_CONFIG_RX_BYPASS_MASK 0x30 + +#define BLADERF_XB_RF_ON 0x0800 +#define BLADERF_XB_TX_ENABLE 0x1000 +#define BLADERF_XB_RX_ENABLE 0x2000 + +#define BLADERF_XB_TX_RF_SW2 0x04000000 +#define BLADERF_XB_TX_RF_SW1 0x08000000 +#define BLADERF_XB_TX_MASK 0x0C000000 +#define BLADERF_XB_TX_SHIFT 26 + +#define BLADERF_XB_RX_RF_SW2 0x10000000 +#define BLADERF_XB_RX_RF_SW1 0x20000000 +#define BLADERF_XB_RX_MASK 0x30000000 +#define BLADERF_XB_RX_SHIFT 28 + +struct xb200_xb_data { + /* Track filterbank selection for RX and TX auto-selection */ + bladerf_xb200_filter auto_filter[2]; +}; + +int xb200_attach(struct bladerf *dev) +{ + struct xb200_xb_data *xb_data; + int status = 0; + uint32_t val; + uint8_t val8; + unsigned int muxout = 6; + const char *mux_lut[] = { "THREE-STATE OUTPUT", + "DVdd", + "DGND", + "R COUNTER OUTPUT", + "N DIVIDER OUTPUT", + "ANALOG LOCK DETECT", + "DIGITAL LOCK DETECT", + "RESERVED" }; + + xb_data = calloc(1, sizeof(struct xb200_xb_data)); + if (xb_data == NULL) { + return BLADERF_ERR_MEM; + } + + xb_data->auto_filter[BLADERF_CHANNEL_RX(0)] = -1; + xb_data->auto_filter[BLADERF_CHANNEL_TX(0)] = -1; + + dev->xb_data = xb_data; + + log_debug(" Attaching transverter board\n"); + status = dev->backend->si5338_read(dev, 39, &val8); + if (status < 0) { + goto error; + } + val8 |= 2; + if ((status = dev->backend->si5338_write(dev, 39, val8))) { + goto error; + } + if ((status = dev->backend->si5338_write(dev, 34, 0x22))) { + goto error; + } + if ((status = dev->backend->config_gpio_read(dev, &val))) { + goto error; + } + val |= 0x80000000; + if ((status = dev->backend->config_gpio_write(dev, val))) { + goto error; + } + if ((status = dev->backend->expansion_gpio_read(dev, &val))) { + goto error; + } + + if ((status = dev->backend->expansion_gpio_dir_write(dev, 0xffffffff, + 0x3C00383E))) { + goto error; + } + + if ((status = dev->backend->expansion_gpio_write(dev, 0xffffffff, 0x800))) { + goto error; + } + + // Load ADF4351 registers via SPI + // Refer to ADF4351 reference manual for register set + // The LO is set to a Int-N 1248MHz +3dBm tone + // Registers are written in order from 5 downto 0 + if ((status = dev->backend->xb_spi(dev, 0x580005))) { + goto error; + } + if ((status = dev->backend->xb_spi(dev, 0x99A16C))) { + goto error; + } + if ((status = dev->backend->xb_spi(dev, 0xC004B3))) { + goto error; + } + log_debug(" MUXOUT: %s\n", mux_lut[muxout]); + + if ((status = dev->backend->xb_spi(dev, 0x60008E42 | (1 << 8) | + (muxout << 26)))) { + goto error; + } + if ((status = dev->backend->xb_spi(dev, 0x08008011))) { + goto error; + } + if ((status = dev->backend->xb_spi(dev, 0x00410000))) { + goto error; + } + + status = dev->backend->expansion_gpio_read(dev, &val); + if (!status && (val & 0x1)) + log_debug(" MUXOUT Bit set: OK\n"); + else { + log_debug(" MUXOUT Bit not set: FAIL\n"); + } + if ((status = + dev->backend->expansion_gpio_write(dev, 0xffffffff, 0x3C000800))) { + goto error; + } + + return 0; + +error: + free(dev->xb_data); + dev->xb_data = NULL; + return status; +} + +void xb200_detach(struct bladerf *dev) +{ + if (dev->xb_data) { + free(dev->xb_data); + dev->xb_data = NULL; + } +} + +int xb200_enable(struct bladerf *dev, bool enable) +{ + int status; + uint32_t val, orig; + + status = dev->backend->expansion_gpio_read(dev, &orig); + if (status) + return status; + + val = orig; + if (enable) + val |= BLADERF_XB_RF_ON; + else + val &= ~BLADERF_XB_RF_ON; + + if (status || (val == orig)) + return status; + + return dev->backend->expansion_gpio_write(dev, 0xffffffff, val); +} + +int xb200_init(struct bladerf *dev) +{ + int status; + + log_verbose( "Setting RX path\n" ); + status = xb200_set_path(dev, BLADERF_CHANNEL_RX(0), BLADERF_XB200_BYPASS); + if (status != 0) { + return status; + } + + log_verbose( "Setting TX path\n" ); + status = xb200_set_path(dev, BLADERF_CHANNEL_TX(0), BLADERF_XB200_BYPASS); + if (status != 0) { + return status; + } + + log_verbose( "Setting RX filter\n" ); + status = xb200_set_filterbank(dev, BLADERF_CHANNEL_RX(0), BLADERF_XB200_AUTO_1DB); + if (status != 0) { + return status; + } + + log_verbose( "Setting TX filter\n" ); + status = xb200_set_filterbank(dev, BLADERF_CHANNEL_TX(0), BLADERF_XB200_AUTO_1DB); + if (status != 0) { + return status; + } + + return 0; +} + +/** + * Validate XB-200 filter selection + * + * @param[in] f Filter supplied by API user. + * + * @return 0 for a valid enumeration value, BLADERF_ERR_INVAL otherwise. + */ +static int check_xb200_filter(bladerf_xb200_filter f) +{ + int status; + + switch (f) { + case BLADERF_XB200_50M: + case BLADERF_XB200_144M: + case BLADERF_XB200_222M: + case BLADERF_XB200_CUSTOM: + case BLADERF_XB200_AUTO_3DB: + case BLADERF_XB200_AUTO_1DB: + status = 0; + break; + + default: + log_debug("Invalid XB200 filter: %d\n", f); + status = BLADERF_ERR_INVAL; + break; + } + + return status; +} + +/** + * Validate XB-200 path selection + * + * @param[in] p Path supplied by API user. + * + * @return 0 for a valid enumeration value, BLADERF_ERR_INVAL otherwise. + */ +static int check_xb200_path(bladerf_xb200_path p) +{ + int status; + + switch (p) { + case BLADERF_XB200_BYPASS: + case BLADERF_XB200_MIX: + status = 0; + break; + + default: + status = BLADERF_ERR_INVAL; + log_debug("Invalid XB200 path: %d\n", p); + break; + } + + return status; +} +int xb200_get_filterbank(struct bladerf *dev, bladerf_channel ch, + bladerf_xb200_filter *filter) { + int status; + uint32_t val; + unsigned int shift; + + if (ch != BLADERF_CHANNEL_RX(0) && ch != BLADERF_CHANNEL_TX(0)) + return BLADERF_ERR_INVAL; + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status != 0) { + return status; + } + + if (ch == BLADERF_CHANNEL_RX(0)) { + shift = BLADERF_XB_RX_SHIFT; + } else { + shift = BLADERF_XB_TX_SHIFT; + } + + *filter = (val >> shift) & 3; + + status = check_xb200_filter(*filter); + if (status != 0) { + log_debug("Read back invalid GPIO state: 0x%08x\n", val); + status = BLADERF_ERR_UNEXPECTED; + } + + return status; +} + +static int set_filterbank_mux(struct bladerf *dev, bladerf_channel ch, bladerf_xb200_filter filter) +{ + int status; + uint32_t orig, val, mask; + unsigned int shift; + static const char *filters[] = { "50M", "144M", "222M", "custom" }; + + assert(filter >= 0); + assert(filter < ARRAY_SIZE(filters)); + + if (ch == BLADERF_CHANNEL_RX(0)) { + mask = BLADERF_XB_RX_MASK; + shift = BLADERF_XB_RX_SHIFT; + } else { + mask = BLADERF_XB_TX_MASK; + shift = BLADERF_XB_TX_SHIFT; + } + + status = dev->backend->expansion_gpio_read(dev, &orig); + if (status != 0) { + return status; + } + + val = orig & ~mask; + val |= filter << shift; + + if (orig != val) { + log_debug("Engaging %s band XB-200 %s filter\n", filters[filter], + mask == BLADERF_XB_TX_MASK ? "TX" : "RX"); + + status = dev->backend->expansion_gpio_write(dev, 0xffffffff, val); + if (status != 0) { + return status; + } + } + + + return 0; +} + +int xb200_set_filterbank(struct bladerf *dev, + bladerf_channel ch, + bladerf_xb200_filter filter) +{ + struct xb200_xb_data *xb_data = dev->xb_data; + uint64_t frequency; + + int status = 0; + + if (ch != BLADERF_CHANNEL_RX(0) && ch != BLADERF_CHANNEL_TX(0)) { + return BLADERF_ERR_INVAL; + } + + if (NULL == xb_data) { + log_error("xb_data is null (do you need to xb200_attach?)\n"); + return BLADERF_ERR_INVAL; + } + + status = check_xb200_filter(filter); + if (status != 0) { + return status; + } + + if (filter == BLADERF_XB200_AUTO_1DB || filter == BLADERF_XB200_AUTO_3DB) { + /* Save which soft auto filter mode we're in */ + xb_data->auto_filter[ch] = filter; + + status = dev->board->get_frequency(dev, ch, &frequency); + if (status == 0) { + status = xb200_auto_filter_selection(dev, ch, frequency); + } + + } else { + /* Invalidate the soft auto filter mode entry */ + xb_data->auto_filter[ch] = -1; + + status = set_filterbank_mux(dev, ch, filter); + } + + return status; +} + +int xb200_auto_filter_selection(struct bladerf *dev, + bladerf_channel ch, + uint64_t frequency) +{ + struct xb200_xb_data *xb_data = dev->xb_data; + bladerf_xb200_filter filter; + + int status = 0; + + if (frequency >= 300000000u) { + return 0; + } + + if (ch != BLADERF_CHANNEL_RX(0) && ch != BLADERF_CHANNEL_TX(0)) { + return BLADERF_ERR_INVAL; + } + + if (NULL == xb_data) { + log_error("xb_data is null (do you need to xb200_attach?)\n"); + return BLADERF_ERR_INVAL; + } + + if (xb_data->auto_filter[ch] == BLADERF_XB200_AUTO_1DB) { + if (37774405 <= frequency && frequency <= 59535436) { + filter = BLADERF_XB200_50M; + } else if (128326173 <= frequency && frequency <= 166711171) { + filter = BLADERF_XB200_144M; + } else if (187593160 <= frequency && frequency <= 245346403) { + filter = BLADERF_XB200_222M; + } else { + filter = BLADERF_XB200_CUSTOM; + } + + status = set_filterbank_mux(dev, ch, filter); + } else if (xb_data->auto_filter[ch] == BLADERF_XB200_AUTO_3DB) { + if (34782924 <= frequency && frequency <= 61899260) { + filter = BLADERF_XB200_50M; + } else if (121956957 <= frequency && frequency <= 178444099) { + filter = BLADERF_XB200_144M; + } else if (177522675 <= frequency && frequency <= 260140935) { + filter = BLADERF_XB200_222M; + } else { + filter = BLADERF_XB200_CUSTOM; + } + + status = set_filterbank_mux(dev, ch, filter); + } + + return status; +} + +#define LMS_RX_SWAP 0x40 +#define LMS_TX_SWAP 0x08 + +int xb200_set_path(struct bladerf *dev, + bladerf_channel ch, bladerf_xb200_path path) { + int status; + uint32_t val; + uint32_t mask; + uint8_t lval, lorig = 0; + + if (ch != BLADERF_CHANNEL_RX(0) && ch != BLADERF_CHANNEL_TX(0)) + return BLADERF_ERR_INVAL; + + status = check_xb200_path(path); + if (status != 0) { + return status; + } + + status = LMS_READ(dev, 0x5A, &lorig); + if (status != 0) { + return status; + } + + lval = lorig; + + if (path == BLADERF_XB200_MIX) { + lval |= (ch == BLADERF_CHANNEL_RX(0)) ? LMS_RX_SWAP : LMS_TX_SWAP; + } else { + lval &= ~((ch == BLADERF_CHANNEL_RX(0)) ? LMS_RX_SWAP : LMS_TX_SWAP); + } + + status = LMS_WRITE(dev, 0x5A, lval); + if (status != 0) { + return status; + } + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status != 0) { + return status; + } + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status != 0) { + return status; + } + + if (!(val & BLADERF_XB_RF_ON)) { + status = xb200_attach(dev); + if (status != 0) { + return status; + } + } + + if (ch == BLADERF_CHANNEL_RX(0)) { + mask = (BLADERF_XB_CONFIG_RX_BYPASS_MASK | BLADERF_XB_RX_ENABLE); + } else { + mask = (BLADERF_XB_CONFIG_TX_BYPASS_MASK | BLADERF_XB_TX_ENABLE); + } + + val |= BLADERF_XB_RF_ON; + val &= ~mask; + + if (ch == BLADERF_CHANNEL_RX(0)) { + if (path == BLADERF_XB200_MIX) { + val |= (BLADERF_XB_RX_ENABLE | BLADERF_XB_CONFIG_RX_PATH_MIX); + } else { + val |= BLADERF_XB_CONFIG_RX_PATH_BYPASS; + } + } else { + if (path == BLADERF_XB200_MIX) { + val |= (BLADERF_XB_TX_ENABLE | BLADERF_XB_CONFIG_TX_PATH_MIX); + } else { + val |= BLADERF_XB_CONFIG_TX_PATH_BYPASS; + } + } + + return dev->backend->expansion_gpio_write(dev, 0xffffffff, val); +} + +int xb200_get_path(struct bladerf *dev, + bladerf_channel ch, bladerf_xb200_path *path) { + int status; + uint32_t val; + + if (ch != BLADERF_CHANNEL_RX(0) && ch != BLADERF_CHANNEL_TX(0)) + return BLADERF_ERR_INVAL; + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status != 0) { + return status; + } + + if (ch == BLADERF_CHANNEL_RX(0)) { + *path = (val & BLADERF_XB_CONFIG_RX_BYPASS) ? + BLADERF_XB200_MIX : BLADERF_XB200_BYPASS; + + } else if (ch == BLADERF_CHANNEL_TX(0)) { + *path = (val & BLADERF_XB_CONFIG_TX_BYPASS) ? + BLADERF_XB200_MIX : BLADERF_XB200_BYPASS; + } + + return 0; +} diff --git a/Radio/HW/BladeRF/src/expansion/xb200.h b/Radio/HW/BladeRF/src/expansion/xb200.h new file mode 100644 index 0000000..3234a7c --- /dev/null +++ b/Radio/HW/BladeRF/src/expansion/xb200.h @@ -0,0 +1,105 @@ +/** + * @file xb.h + * + * @brief XB-200 support + * + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 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 EXPANSION_XB200_H_ +#define EXPANSION_XB200_H_ + +#include <stdbool.h> + +#include <libbladeRF.h> + +#include "board/board.h" + +int xb200_attach(struct bladerf *dev); +void xb200_detach(struct bladerf *dev); +int xb200_enable(struct bladerf *dev, bool enable); +int xb200_init(struct bladerf *dev); + +/** + * Select an XB-200 filterbank + * + * @param dev Device handle + * @param[in] ch Channel + * @param[in] filter XB200 filterbank + * + * @return 0 on success, BLADERF_ERR_* value on failure + */ +int xb200_set_filterbank(struct bladerf *dev, + bladerf_channel ch, + bladerf_xb200_filter filter); + +/** + * Select an appropriate filterbank, based upon the specified frequency + * + * @param dev Device handle + * @param[in] ch Channel + * @param[in] frequency Frequency + * + * @return 0 on success, BLADERF_ERR_* value on failure + */ +int xb200_auto_filter_selection(struct bladerf *dev, + bladerf_channel ch, + uint64_t frequency); + +/** + * Get the current selected XB-200 filterbank + * + * @param dev Device handle + * @param[in] ch Channel + * @param[out] filter Pointer to filterbank, only updated if return value + * is 0. + * + * @return 0 on success, BLADERF_ERR_* value on failure + */ +int xb200_get_filterbank(struct bladerf *dev, + bladerf_channel ch, + bladerf_xb200_filter *filter); +/** + * Configure the XB-200 signal path + * + * @param dev Device handle + * @param[in] ch Channel + * @param[in] path Desired XB-200 signal path + * + * @return 0 on success, BLADERF_ERR_* value on failure + */ +int xb200_set_path(struct bladerf *dev, + bladerf_channel ch, + bladerf_xb200_path path); + +/** + * Get the current XB-200 signal path + * + * @param dev Device handle + * @param[in] ch Channel + * @param[out] path Pointer to XB200 signal path + * + * @return 0 on success, value from \ref RETCODES list on failure + */ +int xb200_get_path(struct bladerf *dev, + bladerf_channel ch, + bladerf_xb200_path *path); + +#endif diff --git a/Radio/HW/BladeRF/src/expansion/xb300.c b/Radio/HW/BladeRF/src/expansion/xb300.c new file mode 100644 index 0000000..15a099d --- /dev/null +++ b/Radio/HW/BladeRF/src/expansion/xb300.c @@ -0,0 +1,299 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 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 + */ + +#include "xb300.h" + +#include "log.h" + +#define BLADERF_XB_AUX_EN 0x000002 +#define BLADERF_XB_TX_LED 0x000010 +#define BLADERF_XB_RX_LED 0x000020 +#define BLADERF_XB_TRX_TXn 0x000040 +#define BLADERF_XB_TRX_RXn 0x000080 +#define BLADERF_XB_TRX_MASK 0x0000c0 +#define BLADERF_XB_PA_EN 0x000200 +#define BLADERF_XB_LNA_ENn 0x000400 +#define BLADERF_XB_CS 0x010000 +#define BLADERF_XB_CSEL 0x040000 +#define BLADERF_XB_DOUT 0x100000 +#define BLADERF_XB_SCLK 0x400000 + +int xb300_attach(struct bladerf *dev) { + int status; + uint32_t val; + + val = BLADERF_XB_TX_LED | BLADERF_XB_RX_LED | BLADERF_XB_TRX_MASK; + val |= BLADERF_XB_PA_EN | BLADERF_XB_LNA_ENn; + val |= BLADERF_XB_CSEL | BLADERF_XB_SCLK | BLADERF_XB_CS; + + if ((status = dev->backend->expansion_gpio_dir_write(dev, 0xffffffff, val))) + return status; + + val = BLADERF_XB_CS | BLADERF_XB_LNA_ENn; + if ((status = dev->backend->expansion_gpio_write(dev, 0xffffffff, val))) + return status; + + return status; +} + +void xb300_detach(struct bladerf *dev) +{ +} + +int xb300_enable(struct bladerf *dev, bool enable) +{ + int status; + uint32_t val; + float pwr; + + val = BLADERF_XB_CS | BLADERF_XB_CSEL | BLADERF_XB_LNA_ENn; + if ((status = dev->backend->expansion_gpio_write(dev, 0xffffffff, val))) + return status; + + status = xb300_get_output_power(dev, &pwr); + + return status; +} + +int xb300_init(struct bladerf *dev) +{ + int status; + + log_verbose( "Setting TRX path to TX\n" ); + status = xb300_set_trx(dev, BLADERF_XB300_TRX_TX); + if (status != 0) { + return status; + } + + return 0; +} + +int xb300_set_trx(struct bladerf *dev, bladerf_xb300_trx trx) +{ + int status; + uint32_t val; + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status != 0) { + return status; + } + + val &= ~(BLADERF_XB_TRX_MASK); + + switch (trx) { + case BLADERF_XB300_TRX_RX: + val |= BLADERF_XB_TRX_RXn; + break; + + case BLADERF_XB300_TRX_TX: + val |= BLADERF_XB_TRX_TXn; + break; + + case BLADERF_XB300_TRX_UNSET: + break; + + default: + log_debug("Invalid TRX option: %d\n", trx); + return BLADERF_ERR_INVAL; + } + + status = dev->backend->expansion_gpio_write(dev, 0xffffffff, val); + return status; +} + +int xb300_get_trx(struct bladerf *dev, bladerf_xb300_trx *trx) +{ + int status; + uint32_t val; + + *trx = BLADERF_XB300_TRX_INVAL; + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status != 0) { + return status; + } + + val &= BLADERF_XB_TRX_MASK; + + if (!val) { + *trx = BLADERF_XB300_TRX_UNSET; + } else { + *trx = (val & BLADERF_XB_TRX_RXn) ? BLADERF_XB300_TRX_RX : BLADERF_XB300_TRX_TX; + } + + /* Sanity check */ + switch (*trx) { + case BLADERF_XB300_TRX_TX: + case BLADERF_XB300_TRX_RX: + case BLADERF_XB300_TRX_UNSET: + break; + + default: + log_debug("Read back invalid TRX setting value: %d\n", *trx); + status = BLADERF_ERR_INVAL; + } + + return status; +} + +int xb300_set_amplifier_enable(struct bladerf *dev, + bladerf_xb300_amplifier amp, bool enable) { + int status; + uint32_t val; + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status != 0) { + return status; + } + + switch (amp) { + case BLADERF_XB300_AMP_PA: + if (enable) { + val |= BLADERF_XB_TX_LED; + val |= BLADERF_XB_PA_EN; + } else { + val &= ~BLADERF_XB_TX_LED; + val &= ~BLADERF_XB_PA_EN; + } + break; + + case BLADERF_XB300_AMP_LNA: + if (enable) { + val |= BLADERF_XB_RX_LED; + val &= ~BLADERF_XB_LNA_ENn; + } else { + val &= ~BLADERF_XB_RX_LED; + val |= BLADERF_XB_LNA_ENn; + } + break; + + case BLADERF_XB300_AMP_PA_AUX: + if (enable) { + val |= BLADERF_XB_AUX_EN; + } else { + val &= ~BLADERF_XB_AUX_EN; + } + break; + + default: + log_debug("Invalid amplifier selection: %d\n", amp); + return BLADERF_ERR_INVAL; + } + + status = dev->backend->expansion_gpio_write(dev, 0xffffffff, val); + + return status; +} + +int xb300_get_amplifier_enable(struct bladerf *dev, + bladerf_xb300_amplifier amp, bool *enable) +{ + int status; + uint32_t val; + + *enable = false; + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status != 0) { + return status; + } + + switch (amp) { + case BLADERF_XB300_AMP_PA: + *enable = (val & BLADERF_XB_PA_EN); + break; + + case BLADERF_XB300_AMP_LNA: + *enable = !(val & BLADERF_XB_LNA_ENn); + break; + + case BLADERF_XB300_AMP_PA_AUX: + *enable = (val & BLADERF_XB_AUX_EN); + break; + + default: + log_debug("Read back invalid amplifier setting: %d\n", amp); + status = BLADERF_ERR_INVAL; + } + + return status; +} + +int xb300_get_output_power(struct bladerf *dev, float *pwr) +{ + uint32_t val, rval; + int i; + int ret = 0; + int status; + float volt, volt2, volt3, volt4; + + status = dev->backend->expansion_gpio_read(dev, &val); + if (status) { + return status; + } + + val &= ~(BLADERF_XB_CS | BLADERF_XB_SCLK | BLADERF_XB_CSEL); + + status = dev->backend->expansion_gpio_write(dev, 0xffffffff, BLADERF_XB_SCLK | val); + if (status) { + return status; + } + + status = dev->backend->expansion_gpio_write(dev, 0xffffffff, BLADERF_XB_CS | BLADERF_XB_SCLK | val); + if (status) { + return status; + } + + for (i = 1; i <= 14; i++) { + status = dev->backend->expansion_gpio_write(dev, 0xffffffff, val); + if (status) { + return status; + } + + status = dev->backend->expansion_gpio_write(dev, 0xffffffff, BLADERF_XB_SCLK | val); + if (status) { + return status; + } + + status = dev->backend->expansion_gpio_read(dev, &rval); + if (status) { + return status; + } + + if (i >= 2 && i <= 11) { + ret |= (!!(rval & BLADERF_XB_DOUT)) << (11 - i); + } + } + + volt = (1.8f/1024.0f) * ret; + volt2 = volt * volt; + volt3 = volt2 * volt; + volt4 = volt3 * volt; + + *pwr = -503.933f * volt4 + + 1409.489f * volt3 - + 1487.84f * volt2 + + 722.9793f * volt - + 114.7529f; + + return 0; + +} diff --git a/Radio/HW/BladeRF/src/expansion/xb300.h b/Radio/HW/BladeRF/src/expansion/xb300.h new file mode 100644 index 0000000..5fe50de --- /dev/null +++ b/Radio/HW/BladeRF/src/expansion/xb300.h @@ -0,0 +1,94 @@ +/** + * @file xb.h + * + * @brief XB-300 support + * + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 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 EXPANSION_XB300_H_ +#define EXPANSION_XB300_H_ + +#include <stdbool.h> + +#include <libbladeRF.h> + +#include "board/board.h" + +int xb300_attach(struct bladerf *dev); +void xb300_detach(struct bladerf *dev); +int xb300_enable(struct bladerf *dev, bool enable); +int xb300_init(struct bladerf *dev); + +/** + * Configure the XB-300 TRX path + * + * @param dev Device handle + * @param[in] trx Desired XB-300 TRX setting + * + * @return 0 on success, BLADERF_ERR_* value on failure + */ +int xb300_set_trx(struct bladerf *dev, bladerf_xb300_trx trx); + +/** + * Get the current XB-300 signal path + * + * @param dev Device handle + * @param[out] trx XB300 TRX antenna setting + * + * @return 0 on success, BLADERF_ERR_* value on failure + */ +int xb300_get_trx(struct bladerf *dev, bladerf_xb300_trx *trx); + +/** + * Enable or disable selected XB-300 amplifier + * + * @param dev Device handle + * @param[in] amp XB-300 amplifier + * @param[in] enable Set true to enable or false to disable + * + * @return 0 on success, BLADERF_ERR_* value on failure + */ +int xb300_set_amplifier_enable(struct bladerf *dev, + bladerf_xb300_amplifier amp, + bool enable); +/** + * Get state of selected XB-300 amplifier + * + * @param dev Device handle + * @param[in] amp XB-300 amplifier + * @param[out] enable Set true to enable or false to disable + * + * @return 0 on success, BLADERF_ERR_* value on failure + */ +int xb300_get_amplifier_enable(struct bladerf *dev, + bladerf_xb300_amplifier amp, + bool *enable); +/** + * Get current PA PDET output power in dBm + * + * @param dev Device handle + * @param[out] val Output power in dBm + * + * @return 0 on success, value from \ref RETCODES list on failure + */ +int xb300_get_output_power(struct bladerf *dev, float *val); + +#endif |