[firmware] Add support for Zedmon v2.
Because v2 uses the ina233 which is not interface compatible with the
ina231, some refactoring was needed.
Change-Id: I0cb5fcd0bedf982b8e76ec299acec5303c80d6c4
diff --git a/firmware/app/zedmon/ina.c b/firmware/app/zedmon/ina.c
new file mode 100644
index 0000000..2bb3238
--- /dev/null
+++ b/firmware/app/zedmon/ina.c
@@ -0,0 +1,112 @@
+#include <app/zedmon/ina.h>
+
+#include <app/zedmon/usb.h>
+#include <assert.h>
+#include <err.h>
+#include <dev/i2c.h>
+#include <lib/cbuf.h>
+#include <lib/console.h>
+#include <platform.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <target/gpioconfig.h>
+
+#include "ina231.h"
+#include "ina233.h"
+
+typedef struct __attribute__((packed)) {
+ lk_bigtime_t time;
+ uint8_t channel;
+} ina_alert_event_t;
+
+static cbuf_t ina_alert_events;
+
+static bool (*ina_sample)(uint16_t *v_shunt, uint16_t *v_bus);
+static bool ina_initialized = false;
+
+static uint32_t ina_errors;
+static uint32_t ina_samples;
+static uint16_t ina_v_shunt;
+static uint16_t ina_v_bus;
+
+
+bool ina_alert_irq(int index, uint64_t timestamp) {
+ // We only handle a single channel right now.
+ assert(index == 0);
+
+ if (!ina_initialized) {
+ return false;
+ }
+
+ ina_alert_event_t event = {
+ .channel = 0,
+ .time = timestamp,
+ };
+
+ // This won't race because we're in interrupt context.
+ if (cbuf_space_avail(&ina_alert_events) >= sizeof(event)) {
+ cbuf_write(&ina_alert_events, &event, sizeof(event), false);
+ return true;
+ }
+ return false;
+}
+
+void ina_init(void) {
+ cbuf_initialize(&ina_alert_events, 32);
+
+ if (ina233_init()) {
+ printf("ina233 found\n");
+ ina_sample = ina233_sample;
+ } else if (ina231_init()) {
+ printf("ina231 found\n");
+ ina_sample = ina231_sample;
+ }
+
+ ina_initialized = true;
+
+ // call sample once to unstick the conversion ready flag.
+ uint16_t v_shunt;
+ uint16_t v_bus;
+ ina_sample(&v_shunt, &v_bus);
+}
+
+
+void ina_loop(void) {
+ while (true) {
+ ina_alert_event_t event;
+ cbuf_read(&ina_alert_events, &event, sizeof(event), true);
+
+ if (ina_sample == NULL) {
+ continue;
+ }
+
+ uint16_t v_shunt;
+ uint16_t v_bus;
+
+ if (!ina_sample(&v_shunt, &v_bus)) {
+ ina_errors++;
+ continue;
+ }
+
+ ina_v_shunt = v_shunt;
+ ina_v_bus = v_bus;
+ ina_samples++;
+ zedmon_usb_add_sample(event.time, v_shunt, v_bus);
+ }
+}
+
+static int cmd_ina_status(int argc, const cmd_args *argv) {
+ float v_shunt = ina_v_shunt * 0.0025;
+ float v_bus = ina_v_bus * 0.00125;
+
+ printf("samples: %u\n", ina_samples);
+ printf("errors: %u\n", ina_errors);
+ printf("v_bus: %f V \n", v_bus);
+ printf("v_shunt: %f mV\n", v_shunt);
+ return 0;
+}
+
+STATIC_COMMAND_START
+STATIC_COMMAND("ina_status", "ina status", &cmd_ina_status)
+STATIC_COMMAND_END(ina);
+
diff --git a/firmware/app/zedmon/ina231.c b/firmware/app/zedmon/ina231.c
index dd45bc7..3d0dd53 100644
--- a/firmware/app/zedmon/ina231.c
+++ b/firmware/app/zedmon/ina231.c
@@ -1,4 +1,4 @@
-#include <app/zedmon/ina231.h>
+#include "ina231.h"
#include <app/zedmon/usb.h>
#include <assert.h>
@@ -77,32 +77,16 @@
INA231_ME_SOL = 1 << 15, // Assert Alert on Shunt Over Voltage Limit.
};
-typedef struct __attribute__((packed)) {
- lk_bigtime_t time;
- uint8_t channel;
-} ina231_alert_event_t;
-
-static cbuf_t ina231_alert_events;
-static stm32_timer_capture_t ina231_tc;
static const uint8_t INA231_ADDR = 0x40;
-
-static const float INA231_SHUNT_R = 0.010; // [Ohms]
-static lk_bigtime_t ina231_start_time;
static uint32_t ina231_errors;
-static uint32_t ina231_samples;
-static uint16_t ina231_v_shunt;
-static uint16_t ina231_v_bus;
-
-static bool ina231_initialized = false;
-
static status_t ina231_write(uint8_t reg, uint16_t val) {
uint8_t data[2];
data[0] = val >> 8;
data[1] = val & 0xff;
- status_t ret = i2c_write_reg_bytes(INA231_BUS, INA231_ADDR, reg, data, 2);
+ status_t ret = i2c_write_reg_bytes(INA_BUS, INA231_ADDR, reg, data, 2);
if (ret != NO_ERROR) {
return ret;
}
@@ -113,7 +97,7 @@
static status_t ina231_read(uint8_t reg, uint16_t *val) {
uint8_t data[2];
- status_t ret = i2c_read_reg_bytes(INA231_BUS, INA231_ADDR, reg, data, 2);
+ status_t ret = i2c_read_reg_bytes(INA_BUS, INA231_ADDR, reg, data, 2);
if (ret != NO_ERROR) {
return ret;
}
@@ -122,46 +106,11 @@
return NO_ERROR;
}
-bool ina231_alert_irq(int index, uint64_t timestamp) {
- // We only handle a single channel right now.
- assert(index == 0);
-
- if (!ina231_initialized) {
- return false;
- }
-
- ina231_alert_event_t event = {
- .channel = 0,
- .time = timestamp,
- };
-
- // This won't race because we're in interrupt context.
- if (cbuf_space_avail(&ina231_alert_events) >= sizeof(event)) {
- cbuf_write(&ina231_alert_events, &event, sizeof(event), false);
- return true;
- }
- return false;
-}
-
-static bool ina231_alert0_capture_irq(uint64_t val) {
- return ina231_alert_irq(0, val);
-}
-
-void ina231_init() {
- cbuf_initialize(&ina231_alert_events, 32);
-
- if (false) {
- ina231_tc.chan[0] = (stm32_timer_capture_channel_t){
- .flags = STM32_TIMER_CAPTURE_CHAN_FLAG_FALLING | STM32_TIMER_CAPTURE_CHAN_FLAG_ENABLE,
- .cb = ina231_alert0_capture_irq,
- };
-
- stm32_timer_capture_setup(&ina231_tc, 3, 48);
- }
+bool ina231_init() {
status_t ret = ina231_write(INA231_REG_MASK_ENABLE, INA231_ME_CNVR);
if (ret != NO_ERROR) {
- printf("Error configuring ina231: %d\n", ret);
+ return false;
}
ret = ina231_write(INA231_REG_CONFIG,
@@ -170,117 +119,37 @@
| INA231_CONFIG_V_BUS_CT_332_US
| INA231_CONFIG_AVG_1);
if (ret != NO_ERROR) {
- printf("Error configuring ina231: %d\n", ret);
+ return false;
}
- ina231_start_time = current_time_hires();
- ina231_initialized = true;
+ return true;
}
-void ina231_loop(void) {
- while (true) {
- ina231_alert_event_t event;
- cbuf_read(&ina231_alert_events, &event, sizeof(event), true);
- status_t ret;
-
- uint16_t status;
- ret = ina231_read(INA231_REG_MASK_ENABLE, &status);
- if (ret != NO_ERROR) {
- ina231_errors++;
- continue;
- }
-
- if (!(status & INA231_ME_CRVF)) {
- printf("alert with no crvf!\n");
- continue;
- }
-
- uint16_t v_shunt;
- uint16_t v_bus;
- ret = ina231_read(INA231_REG_SHUNT_VOLTAGE, &v_shunt);
- if (ret != NO_ERROR) {
- ina231_errors++;
- continue;
- }
-
- ret = ina231_read(INA231_REG_BUS_VOLTAGE, &v_bus);
- if (ret != NO_ERROR) {
- ina231_errors++;
- continue;
- }
-
- ina231_v_shunt = v_shunt;
- ina231_v_bus = v_bus;
-
- ina231_samples++;
- zedmon_usb_add_sample(event.time, v_shunt, v_bus);
- }
-}
-
-uint64_t ina231_get_current_time(void) {
- return stm32_timer_capture_get_counter(&ina231_tc);
-}
-
-static int cmd_ina231_status(int argc, const cmd_args *argv) {
- lk_bigtime_t delta = current_time_hires() - ina231_start_time;
- float samples_per_sec = (float) ina231_samples / delta * 1000000.0f;
-
- float v_shunt = ina231_v_shunt * 0.0025;
- float v_bus = ina231_v_bus * 0.00125;
- float i_shunt = v_shunt / INA231_SHUNT_R;
- float power = i_shunt * v_bus;
-
- printf("samples: %u\n", ina231_samples);
- printf("samples/sec: %f\n", samples_per_sec);
- printf("errors: %u\n", ina231_errors);
- printf("v_bus: %f V \n", v_bus);
- printf("v_shunt: %f mV\n", v_shunt);
- printf("i_shunt: %f mA\n", i_shunt);
- printf("power: %f mW\n", power);
- return 0;
-}
-
-static int cmd_ina231_dump(int argc, const cmd_args *argv) {
- int i;
-
- for (i = 0; i < 8; i++) {
- uint16_t data;
- status_t ret = ina231_read(i, &data);
- printf("%d: ", i);
-
- if (ret != NO_ERROR) {
- printf("error %d\n", ret);
- } else {
- printf("%04x\n", data);
- }
- }
-
- return 0;
-}
-
-static int cmd_ina231_read(int argc, const cmd_args *argv) {
- if (argc != 2) {
- printf("usage: ina_231_read <reg>\n");
- return 1;
- }
-
- uint8_t reg = argv[1].u;
- uint16_t data;
-
- status_t ret = ina231_read(reg, &data);
+bool ina231_sample(uint16_t *v_shunt, uint16_t *v_bus) {
+ status_t ret;
+ uint16_t status;
+ ret = ina231_read(INA231_REG_MASK_ENABLE, &status);
if (ret != NO_ERROR) {
- printf("error: %d\n", ret);
- return 1;
+ ina231_errors++;
+ return false;
}
- printf("%02x: %04x\n", reg, data);
- return 0;
+ if (!(status & INA231_ME_CRVF)) {
+ printf("alert with no crvf!\n");
+ return false;
+ }
+
+ ret = ina231_read(INA231_REG_SHUNT_VOLTAGE, v_shunt);
+ if (ret != NO_ERROR) {
+ ina231_errors++;
+ return false;
+ }
+
+ ret = ina231_read(INA231_REG_BUS_VOLTAGE, v_bus);
+ if (ret != NO_ERROR) {
+ ina231_errors++;
+ return false;
+ }
+ return true;
}
-
-STATIC_COMMAND_START
-STATIC_COMMAND("ina231_read", "read an ina231 register", &cmd_ina231_read)
-STATIC_COMMAND("ina231_dump", "dump ina231 registers", &cmd_ina231_dump)
-STATIC_COMMAND("ina231_status", "ina231 status", &cmd_ina231_status)
-STATIC_COMMAND_END(ina231);
-
diff --git a/firmware/app/zedmon/include/app/zedmon/ina231.h b/firmware/app/zedmon/ina231.h
similarity index 86%
copy from firmware/app/zedmon/include/app/zedmon/ina231.h
copy to firmware/app/zedmon/ina231.h
index bbf42a9..6bc2220 100644
--- a/firmware/app/zedmon/include/app/zedmon/ina231.h
+++ b/firmware/app/zedmon/ina231.h
@@ -25,16 +25,12 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+//
#pragma once
#include <stdbool.h>
#include <stdint.h>
-void ina231_init(void);
-void ina231_loop(void);
-uint64_t ina231_get_current_time(void);
+bool ina231_init(void);
+bool ina231_sample(uint16_t *v_shunt, uint16_t *v_bus);
-// Target specific code should call this when it gets a falling edge on the
-// alert line (from interrupt context).
-bool ina231_alert_irq(int index, uint64_t timestamp);
diff --git a/firmware/app/zedmon/ina233.c b/firmware/app/zedmon/ina233.c
new file mode 100644
index 0000000..bc04930
--- /dev/null
+++ b/firmware/app/zedmon/ina233.c
@@ -0,0 +1,275 @@
+#include "ina233.h"
+
+#include <app/zedmon/usb.h>
+#include <assert.h>
+#include <err.h>
+#include <dev/i2c.h>
+#include <lib/cbuf.h>
+#include <lib/console.h>
+#include <platform.h>
+#include <platform/timer_capture.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <target/gpioconfig.h>
+
+enum {
+ INA233_RER_CLEAR_FAULTS = 0x03,
+ INA233_REG_RESTORE_DEFAULT_ALL = 0x12,
+ INA233_REG_CAPABILITY = 0x19,
+ INA233_REG_IOUT_OC_WARN_LIMIT = 0x4a,
+ INA233_REG_VIN_OV_WARN_LIMIT = 0x57,
+ INA233_REG_VIN_UV_WARN_LIMIT = 0x58,
+ INA233_REG_PIN_OP_WANR_LIMIT = 0x6B,
+ INA233_REG_STATUS_BYTE = 0x78,
+ INA233_REG_STATUS_WORD = 0x79,
+ INA233_REF_STATUS_IOUT = 0x7b,
+ INA233_REG_STATUS_INPUT = 0x7c,
+ INA233_REG_STATUS_CML = 0x7e,
+ INA233_REG_STATUS_MFR_SPECIFIC = 0x80,
+ INA233_REG_READ_EIN = 0x86,
+ INA233_REG_READ_VIN = 0x88,
+ INA233_REG_READ_IN = 0x89,
+ INA233_REG_READ_VOUT = 0x8b,
+ INA233_REG_READ_IOUT = 0x8c,
+ INA233_REG_READ_POUT = 0x96,
+ INA233_REG_READ_PIN = 0x97,
+ INA233_REG_MFR_ID = 0x99,
+ INA233_REG_MFR_MODEL = 0x9A,
+ INA233_REG_MFR_REVISION = 0x9b,
+ INA233_REG_MFR_ADC_CONFIG = 0xd0,
+ INA233_REG_MFR_READ_VSHUNT = 0xd1,
+ INA233_REG_MFR_ALERT_MASK = 0xd2,
+ INA233_REG_MFR_CALIBRATION = 0xd4,
+ INA233_REG_MFR_DEVICE_CONFIG = 0xd5,
+ INA233_REG_CLEAR_EIN = 0xd6,
+ INA233_REG_TI_MFR_ID = 0xe0,
+ INA233_REG_TI_MFR_MODEL = 0xe1,
+ INA233_REF_TI_MFR_REVISION = 0xe2,
+};
+
+enum {
+ INA233_ADC_CONFIG_MODE_POWER_DOWN = 0 << 0,
+ INA233_ADC_CONFIG_MODE_TRIG_SHUNT = 1 << 0,
+ INA233_ADC_CONFIG_MODE_TRIG_BUS = 2 << 0,
+ INA233_ADC_CONFIG_MODE_TRIG_SHUNT_BUS = 3 << 0,
+ INA233_ADC_CONFIG_MODE_POWER_DOWN2 = 4 << 0,
+ INA233_ADC_CONFIG_MODE_CONT_SHUNT = 5 << 0,
+ INA233_ADC_CONFIG_MODE_CONT_BUS = 6 << 0,
+ INA233_ADC_CONFIG_MODE_CONT_SHUNT_BUS = 7 << 0,
+
+ INA233_ADC_CONFIG_V_SHUNT_CT_140_US = 0 << 3,
+ INA233_ADC_CONFIG_V_SHUNT_CT_204_US = 1 << 3,
+ INA233_ADC_CONFIG_V_SHUNT_CT_332_US = 2 << 3,
+ INA233_ADC_CONFIG_V_SHUNT_CT_588_US = 3 << 3,
+ INA233_ADC_CONFIG_V_SHUNT_CT_1100_US = 4 << 3,
+ INA233_ADC_CONFIG_V_SHUNT_CT_2116_US = 5 << 3,
+ INA233_ADC_CONFIG_V_SHUNT_CT_4156_US = 6 << 3,
+ INA233_ADC_CONFIG_V_SHUNT_CT_8244_US = 7 << 3,
+
+ INA233_ADC_CONFIG_V_BUS_CT_140_US = 0 << 6,
+ INA233_ADC_CONFIG_V_BUS_CT_204_US = 1 << 6,
+ INA233_ADC_CONFIG_V_BUS_CT_332_US = 2 << 6,
+ INA233_ADC_CONFIG_V_BUS_CT_588_US = 3 << 6,
+ INA233_ADC_CONFIG_V_BUS_CT_1100_US = 4 << 6,
+ INA233_ADC_CONFIG_V_BUS_CT_2116_US = 5 << 6,
+ INA233_ADC_CONFIG_V_BUS_CT_4156_US = 6 << 6,
+ INA233_ADC_CONFIG_V_BUS_CT_8244_US = 7 << 6,
+
+ INA233_ADC_CONFIG_AVG_1 = 0 << 9,
+ INA233_ADC_CONFIG_AVG_4 = 1 << 9,
+ INA233_ADC_CONFIG_AVG_16 = 2 << 9,
+ INA233_ADC_CONFIG_AVG_64 = 3 << 9,
+ INA233_ADC_CONFIG_AVG_128 = 4 << 9,
+ INA233_ADC_CONFIG_AVG_256 = 5 << 9,
+ INA233_ADC_CONFIG_AVG_512 = 6 << 9,
+ INA233_ADC_CONFIG_AVG_1024 = 7 << 9,
+
+ INA233_ADC_CONFIG_RESERVED = 1 << 14,
+};
+
+enum {
+ INA233_STATUS_MFR_IN_UV_WARNING = 1 << 0,
+ INA233_STATUS_MFR_IN_OV_WARNING = 1 << 1,
+ INA233_STATUS_MFR_IN_OC_WARNING = 1 << 2,
+ INA233_STATUS_MFR_IN_OP_WARNING = 1 << 3,
+ INA233_STATUS_MFR_COMM_FAILURE = 1 << 4,
+ INA233_STATUS_MFR_POR = 1 << 5,
+ INA233_STATUS_MFR_ADC_OVERFLOW = 1 << 6,
+ INA233_STATUS_MFR_CONVERSION_READY = 1 << 7,
+};
+
+enum {
+ INA233_ALERT_MASK_IN_UV_WARNING = 1 << 0,
+ INA233_ALERT_MASK_IN_OV_WARNING = 1 << 1,
+ INA233_ALERT_MASK_IN_OC_WARNING = 1 << 2,
+ INA233_ALERT_MASK_IN_OP_WARNING = 1 << 3,
+ INA233_ALERT_MASK_COMM_FAILURE = 1 << 4,
+ INA233_ALERT_MASK_POR = 1 << 5,
+ INA233_ALERT_MASK_ADC_OVERFLOW = 1 << 6,
+ INA233_ALERT_MASK_CONVERSION_READY = 1 << 7,
+};
+
+static const uint16_t INA233_MFR_ID = 0x5449;
+static const uint16_t INA233_MFR_MODEL = 0x3333;
+static const uint8_t INA233_ADDR = 0x40;
+
+static uint32_t ina233_errors;
+
+static status_t ina233_write16(uint8_t reg, uint16_t val) {
+ uint8_t data[2];
+ data[1] = val >> 8;
+ data[0] = val & 0xff;
+
+ status_t ret = i2c_write_reg_bytes(INA_BUS, INA233_ADDR, reg, data, 2);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ return NO_ERROR;
+}
+
+static status_t ina233_write8(uint8_t reg, uint8_t val) {
+ status_t ret = i2c_write_reg_bytes(INA_BUS, INA233_ADDR, reg, &val, 1);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ return NO_ERROR;
+}
+
+static status_t ina233_read8(uint8_t reg, uint8_t *val) {
+ status_t ret = i2c_read_reg_bytes(INA_BUS, INA233_ADDR, reg, val, 1);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ return NO_ERROR;
+}
+
+static status_t ina233_read16(uint8_t reg, uint16_t *val) {
+ uint8_t data[2];
+
+ status_t ret = i2c_read_reg_bytes(INA_BUS, INA233_ADDR, reg, data, 2);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ *val = data[1] << 8 | data[0];
+ return NO_ERROR;
+}
+
+bool ina233_init(void) {
+ status_t ret;
+
+ // Try to read TI_MFR_ID and TI_MFR_MODEL to detect device
+ uint16_t mfr_id;
+ ret = ina233_read16(INA233_REG_TI_MFR_ID, &mfr_id);
+ if (ret != NO_ERROR || mfr_id != INA233_MFR_ID) {
+ return false;
+ }
+
+ uint16_t mfr_model;
+ ret = ina233_read16(INA233_REG_TI_MFR_MODEL, &mfr_model);
+ if (ret != NO_ERROR || mfr_model != INA233_MFR_MODEL) {
+ return false;
+ }
+
+ // At this point we know we're speaking to an ina233.
+ ret = ina233_write16(INA233_REG_MFR_ADC_CONFIG,
+ INA233_ADC_CONFIG_MODE_CONT_SHUNT_BUS
+ | INA233_ADC_CONFIG_V_SHUNT_CT_332_US
+ | INA233_ADC_CONFIG_V_BUS_CT_332_US
+ | INA233_ADC_CONFIG_AVG_1
+ | INA233_ADC_CONFIG_RESERVED);
+ if (ret != NO_ERROR) {
+ return false;
+ }
+
+ ret = ina233_write8(INA233_REG_MFR_ALERT_MASK,
+ ~INA233_ALERT_MASK_CONVERSION_READY);
+ if (ret != NO_ERROR) {
+ return false;
+ }
+
+ ret = ina233_write8(INA233_REG_STATUS_MFR_SPECIFIC, 0xff);
+ if (ret != NO_ERROR) {
+ return false;
+ }
+
+ return true;
+}
+
+
+bool ina233_sample(uint16_t *v_shunt, uint16_t *v_bus) {
+ status_t ret;
+
+ uint8_t status;
+ ret = ina233_read8(INA233_REG_STATUS_MFR_SPECIFIC, &status);
+ if (ret != NO_ERROR) {
+ ina233_errors++;
+ return false;
+ }
+
+ // Ack the status.
+ ret = ina233_write8(INA233_REG_STATUS_MFR_SPECIFIC, status);
+ if (ret != NO_ERROR) {
+ ina233_errors++;
+ return false;
+ }
+
+ ret = ina233_read16(INA233_REG_MFR_READ_VSHUNT, v_shunt);
+ if (ret != NO_ERROR) {
+ ina233_errors++;
+ return false;
+ }
+
+ ret = ina233_read16(INA233_REG_READ_VIN, v_bus);
+ if (ret != NO_ERROR) {
+ ina233_errors++;
+ return false;
+ }
+
+ return true;
+}
+
+static int cmd_ina_read16(int argc, const cmd_args *argv) {
+ if (argc != 2) {
+ printf("usage: ina_233_read <reg>\n");
+ return 1;
+ }
+
+ uint8_t reg = argv[1].u;
+ uint16_t data;
+
+ status_t ret = ina233_read16(reg, &data);
+ if (ret != NO_ERROR) {
+ printf("error: %d\n", ret);
+ return 1;
+ }
+
+ printf("%02x: %04x\n", reg, data);
+ return 0;
+}
+
+static int cmd_ina_read8(int argc, const cmd_args *argv) {
+ if (argc != 2) {
+ printf("usage: ina_233_read <reg>\n");
+ return 1;
+ }
+
+ uint8_t reg = argv[1].u;
+ uint8_t data;
+
+ status_t ret = ina233_read8(reg, &data);
+ if (ret != NO_ERROR) {
+ printf("error: %d\n", ret);
+ return 1;
+ }
+
+ printf("%02x: %02x\n", reg, data);
+ return 0;
+}
+
+STATIC_COMMAND_START
+STATIC_COMMAND("ina_read8", "read an ina233 register", &cmd_ina_read8)
+STATIC_COMMAND("ina_read16", "read an ina233 register", &cmd_ina_read16)
+STATIC_COMMAND_END(ina233);
diff --git a/firmware/app/zedmon/include/app/zedmon/ina231.h b/firmware/app/zedmon/ina233.h
similarity index 85%
copy from firmware/app/zedmon/include/app/zedmon/ina231.h
copy to firmware/app/zedmon/ina233.h
index bbf42a9..efeca06 100644
--- a/firmware/app/zedmon/include/app/zedmon/ina231.h
+++ b/firmware/app/zedmon/ina233.h
@@ -25,16 +25,11 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+//
#pragma once
#include <stdbool.h>
#include <stdint.h>
-void ina231_init(void);
-void ina231_loop(void);
-uint64_t ina231_get_current_time(void);
-
-// Target specific code should call this when it gets a falling edge on the
-// alert line (from interrupt context).
-bool ina231_alert_irq(int index, uint64_t timestamp);
+bool ina233_init(void);
+bool ina233_sample(uint16_t *v_shunt, uint16_t *v_bus);
diff --git a/firmware/app/zedmon/include/app/zedmon/ina231.h b/firmware/app/zedmon/include/app/zedmon/ina.h
similarity index 87%
rename from firmware/app/zedmon/include/app/zedmon/ina231.h
rename to firmware/app/zedmon/include/app/zedmon/ina.h
index bbf42a9..ca998c1 100644
--- a/firmware/app/zedmon/include/app/zedmon/ina231.h
+++ b/firmware/app/zedmon/include/app/zedmon/ina.h
@@ -31,10 +31,13 @@
#include <stdbool.h>
#include <stdint.h>
-void ina231_init(void);
-void ina231_loop(void);
-uint64_t ina231_get_current_time(void);
+void ina_init(void);
+void ina_loop(void);
// Target specific code should call this when it gets a falling edge on the
// alert line (from interrupt context).
-bool ina231_alert_irq(int index, uint64_t timestamp);
+bool ina_alert_irq(int index, uint64_t timestamp);
+
+// Target specific code that returns the current time in the same time domain
+// as ina_alert_irq()s timestamp field.
+uint64_t ina_get_current_time(void);
diff --git a/firmware/app/zedmon/main.c b/firmware/app/zedmon/main.c
index 289e10a..0e35140 100644
--- a/firmware/app/zedmon/main.c
+++ b/firmware/app/zedmon/main.c
@@ -1,5 +1,5 @@
#include <app.h>
-#include <app/zedmon/ina231.h>
+#include <app/zedmon/ina.h>
#include <dev/gpio.h>
#include <kernel/thread.h>
#include <lib/console.h>
@@ -9,14 +9,14 @@
static void zedmon_init(const struct app_descriptor *app) {
- ina231_init();
+ ina_init();
printf("zedmon app initialized\n");
}
static void zedmon_entry(const struct app_descriptor *app, void *args)
{
printf("zedmon app started\n");
- ina231_loop();
+ ina_loop();
}
static int cmd_relay(int argc, const cmd_args *argv) {
diff --git a/firmware/app/zedmon/rules.mk b/firmware/app/zedmon/rules.mk
index 24651ef..c7b2d78 100644
--- a/firmware/app/zedmon/rules.mk
+++ b/firmware/app/zedmon/rules.mk
@@ -3,7 +3,9 @@
MODULE := $(LOCAL_DIR)
MODULE_SRCS += \
+ $(LOCAL_DIR)/ina.c \
$(LOCAL_DIR)/ina231.c \
+ $(LOCAL_DIR)/ina233.c \
$(LOCAL_DIR)/main.c \
$(LOCAL_DIR)/usb.c
diff --git a/firmware/app/zedmon/usb.c b/firmware/app/zedmon/usb.c
index 6b31556..96f0b7e 100644
--- a/firmware/app/zedmon/usb.c
+++ b/firmware/app/zedmon/usb.c
@@ -1,7 +1,7 @@
#include <app/zedmon/usb.h>
#include <assert.h>
-#include <app/zedmon/ina231.h>
+#include <app/zedmon/ina.h>
#include <app/zedmon/usb_proto.h>
#include <compiler.h>
#include <debug.h>
@@ -254,7 +254,7 @@
break;
case ZEDMON_USB_PACKET_QUERY_TIME:
zedmon_usb_timestamp_packet.packet_type = ZEDMON_USB_PACKET_TIMESTAMP;
- zedmon_usb_timestamp_packet.timestamp = ina231_get_current_time();
+ zedmon_usb_timestamp_packet.timestamp = ina_get_current_time();
queue_tx(&zedmon_usb_timestamp_packet, sizeof(zedmon_usb_timestamp_packet));
break;
case ZEDMON_USB_PACKET_ENABLE_REPORTING:
diff --git a/firmware/target/twinkie/include/target/gpioconfig.h b/firmware/target/twinkie/include/target/gpioconfig.h
index 0d95432..784804f 100644
--- a/firmware/target/twinkie/include/target/gpioconfig.h
+++ b/firmware/target/twinkie/include/target/gpioconfig.h
@@ -40,5 +40,5 @@
#define GPIO_UART_TX GPIO(GPIO_PORT_A, 9)
#define GPIO_UART_RX GPIO(GPIO_PORT_A, 10)
-#define INA231_BUS 1
+#define INA_BUS 1
#endif
diff --git a/firmware/target/twinkie/init.c b/firmware/target/twinkie/init.c
index f52e0ef..7ea8645 100644
--- a/firmware/target/twinkie/init.c
+++ b/firmware/target/twinkie/init.c
@@ -26,7 +26,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <app/zedmon/ina231.h>
+#include <app/zedmon/ina.h>
#include <err.h>
#include <debug.h>
#include <target.h>
@@ -45,9 +45,14 @@
int irqs;
bool stm32_exti2_irq(void) {
irqs++;
- return ina231_alert_irq(0, current_time_hires());
+ return ina_alert_irq(0, current_time_hires());
}
+uint64_t ina_get_current_time(void) {
+ return current_time_hires();
+}
+
+
void target_early_init(void)
{
gpio_config(GPIO_UART_TX, GPIO_STM32_AF | GPIO_STM32_AFn(1));
diff --git a/firmware/target/zedmon/include/target/gpioconfig.h b/firmware/target/zedmon/include/target/gpioconfig.h
index de251bd..3d955c5 100644
--- a/firmware/target/zedmon/include/target/gpioconfig.h
+++ b/firmware/target/zedmon/include/target/gpioconfig.h
@@ -44,6 +44,6 @@
#define GPIO_POWER_ENABLE_J GPIO(GPIO_PORT_B, 12)
-#define INA231_BUS 2
+#define INA_BUS 2
#endif
diff --git a/firmware/target/zedmon/init.c b/firmware/target/zedmon/init.c
index 9ca5d08..b4cc607 100644
--- a/firmware/target/zedmon/init.c
+++ b/firmware/target/zedmon/init.c
@@ -26,20 +26,31 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <app/zedmon/ina.h>
#include <err.h>
#include <debug.h>
-#include <target.h>
#include <compiler.h>
#include <dev/gpio.h>
#include <dev/i2c.h>
#include <lib/console.h>
#include <platform/gpio.h>
#include <platform/stm32.h>
+#include <platform/timer_capture.h>
#include <platform/usbc.h>
+#include <target.h>
#include <target/gpioconfig.h>
#include <target/usb.h>
static uint8_t board_id;
+static stm32_timer_capture_t zedmon_alert_tc;
+
+static bool zedmon_alert0_capture_irq(uint64_t val) {
+ return ina_alert_irq(0, val);
+}
+
+uint64_t ina_get_current_time(void) {
+ return stm32_timer_capture_get_counter(&zedmon_alert_tc);
+}
void target_early_init(void)
{
@@ -51,10 +62,10 @@
gpio_config(GPIO_ALERT_HIGH, GPIO_STM32_AF | GPIO_STM32_AFn(1));
gpio_config(GPIO_ALERT_LOW, GPIO_STM32_AF | GPIO_STM32_AFn(1));
- gpio_config(GPIO_BOARD_ID0, GPIO_INPUT);
- gpio_config(GPIO_BOARD_ID1, GPIO_INPUT);
- gpio_config(GPIO_BOARD_ID2, GPIO_INPUT);
- gpio_config(GPIO_BOARD_ID3, GPIO_INPUT);
+ gpio_config(GPIO_BOARD_ID0, GPIO_INPUT | GPIO_PULLDOWN);
+ gpio_config(GPIO_BOARD_ID1, GPIO_INPUT | GPIO_PULLDOWN);
+ gpio_config(GPIO_BOARD_ID2, GPIO_INPUT | GPIO_PULLDOWN);
+ gpio_config(GPIO_BOARD_ID3, GPIO_INPUT | GPIO_PULLDOWN);
gpio_set(GPIO_LED_RED, 1);
gpio_set(GPIO_LED_GREEN, 1);
@@ -74,6 +85,13 @@
stm32_debug_early_init();
i2c_init_early();
+
+ zedmon_alert_tc.chan[0] = (stm32_timer_capture_channel_t){
+ .flags = STM32_TIMER_CAPTURE_CHAN_FLAG_FALLING | STM32_TIMER_CAPTURE_CHAN_FLAG_ENABLE,
+ .cb = zedmon_alert0_capture_irq,
+ };
+
+ stm32_timer_capture_setup(&zedmon_alert_tc, 3, 48);
}
void target_init(void)
@@ -81,6 +99,7 @@
stm32_debug_init();
i2c_init();
stm32_usbc_init();
+
target_usb_setup();
printf("zedmon online. board_id=%1x\n", board_id);