summaryrefslogtreecommitdiff
path: root/Radio/HW/BladeRF/src/driver/ina219.c
diff options
context:
space:
mode:
Diffstat (limited to 'Radio/HW/BladeRF/src/driver/ina219.c')
-rw-r--r--Radio/HW/BladeRF/src/driver/ina219.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/Radio/HW/BladeRF/src/driver/ina219.c b/Radio/HW/BladeRF/src/driver/ina219.c
new file mode 100644
index 0000000..f3cd23b
--- /dev/null
+++ b/Radio/HW/BladeRF/src/driver/ina219.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the bladeRF project:
+ * http://www.github.com/nuand/bladeRF
+ *
+ * Copyright (C) 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
+ */
+
+#include <libbladeRF.h>
+
+#include "log.h"
+
+#include "ina219.h"
+
+#define INA219_REG_CONFIGURATION 0x00
+#define INA219_REG_SHUNT_VOLTAGE 0x01
+#define INA219_REG_BUS_VOLTAGE 0x02
+#define INA219_REG_POWER 0x03
+#define INA219_REG_CURRENT 0x04
+#define INA219_REG_CALIBRATION 0x05
+
+int ina219_init(struct bladerf *dev, float r_shunt)
+{
+ int status;
+ uint16_t value;
+
+ /* Soft-reset INA219 */
+ value = 0x8000;
+ status = dev->backend->ina219_write(dev, INA219_REG_CONFIGURATION, value);
+ if (status < 0) {
+ log_error("INA219 soft reset error: %d\n", status);
+ return status;
+ }
+
+ /* Poll until we're out of reset */
+ while (value & 0x8000) {
+ status = dev->backend->ina219_read(dev, INA219_REG_CONFIGURATION, &value);
+ if (status < 0) {
+ log_error("INA219 soft reset poll error: %d\n", status);
+ return status;
+ }
+ }
+
+ /* Write configuration register */
+ /* BRNG (13) = 0 for 16V FSR
+ PG (12-11) = 00 for 40mV
+ BADC (10-7) = 0011 for 12-bit / 532uS
+ SADC (6-3) = 0011 for 12-bit / 532uS
+ MODE (2-0) = 111 for continuous shunt & bus */
+ value = 0x019f;
+ status = dev->backend->ina219_write(dev, INA219_REG_CONFIGURATION, value);
+ if (status < 0) {
+ log_error("INA219 configuration error: %d\n", status);
+ return status;
+ }
+
+ log_debug("Configuration register: 0x%04x\n", value);
+
+ /* Write calibration register */
+ /* Current_LSB = 0.001 A / LSB */
+ /* Calibration = 0.04096 / (Current_LSB * r_shunt) */
+ value = (uint16_t)((0.04096 / (0.001 * r_shunt)) + 0.5);
+ status = dev->backend->ina219_write(dev, INA219_REG_CALIBRATION, value);
+ if (status < 0) {
+ log_error("INA219 calibration error: %d\n", status);
+ return status;
+ }
+
+ log_debug("Calibration register: 0x%04x\n", value);
+
+ return 0;
+}
+
+int ina219_read_shunt_voltage(struct bladerf *dev, float *voltage)
+{
+ int status;
+ uint16_t data;
+
+ status = dev->backend->ina219_read(dev, INA219_REG_SHUNT_VOLTAGE, &data);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Scale by 1e-5 LSB / Volt */
+ *voltage = ((float)((int16_t)data)) * 1e-5F;
+
+ return 0;
+}
+
+int ina219_read_bus_voltage(struct bladerf *dev, float *voltage)
+{
+ int status;
+ uint16_t data;
+
+ status = dev->backend->ina219_read(dev, INA219_REG_BUS_VOLTAGE, &data);
+ if (status < 0) {
+ return status;
+ }
+
+ /* If overflow flag is set */
+ if (data & 0x1) {
+ return BLADERF_ERR_UNEXPECTED;
+ }
+
+ /* Scale by 0.004 LSB / Volt */
+ *voltage = ((float)(data >> 3)) * 0.004F;
+
+ return 0;
+}
+
+int ina219_read_current(struct bladerf *dev, float *current)
+{
+ int status;
+ uint16_t data;
+
+ status = dev->backend->ina219_read(dev, INA219_REG_CURRENT, &data);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Scale by 0.001 LSB / Ampere */
+ *current = ((float)((int16_t)data)) * 0.001F;
+
+ return 0;
+}
+
+int ina219_read_power(struct bladerf *dev, float *power)
+{
+ int status;
+ uint16_t data;
+
+ status = dev->backend->ina219_read(dev, INA219_REG_POWER, &data);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Scale by 0.020 LSB / Watt */
+ *power = ((float)((int16_t)data)) * 0.020F;
+
+ return 0;
+}