diff options
Diffstat (limited to 'Radio/HW/BladeRF/src/expansion/xb300.c')
-rw-r--r-- | Radio/HW/BladeRF/src/expansion/xb300.c | 299 |
1 files changed, 299 insertions, 0 deletions
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; + +} |