summaryrefslogtreecommitdiff
path: root/Radio/HW/BladeRF/src/expansion/xb300.c
diff options
context:
space:
mode:
Diffstat (limited to 'Radio/HW/BladeRF/src/expansion/xb300.c')
-rw-r--r--Radio/HW/BladeRF/src/expansion/xb300.c299
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;
+
+}