summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/accel_lis2dw12.h11
-rw-r--r--zephyr/emul/emul_lis2dw12.c86
-rw-r--r--zephyr/include/emul/emul_lis2dw12.h17
3 files changed, 114 insertions, 0 deletions
diff --git a/driver/accel_lis2dw12.h b/driver/accel_lis2dw12.h
index 71116cb13b..9d0be0ac0a 100644
--- a/driver/accel_lis2dw12.h
+++ b/driver/accel_lis2dw12.h
@@ -45,6 +45,11 @@
#define LIS2DW12_FIFO_THS_UP 0x80
#define LIS2DW12_OUT_X_L_ADDR 0x28
+#define LIS2DW12_OUT_X_H_ADDR 0x29
+#define LIS2DW12_OUT_Y_L_ADDR 0x2a
+#define LIS2DW12_OUT_Y_H_ADDR 0x2b
+#define LIS2DW12_OUT_Z_L_ADDR 0x2c
+#define LIS2DW12_OUT_Z_H_ADDR 0x2d
#define LIS2DW12_FIFO_CTRL_ADDR 0x2e
@@ -206,6 +211,12 @@ enum lis2dw12_fs {
*/
#define LIS2DW12_RESOLUTION 14
+/** Maximum possible sample */
+#define LIS2DW12_SAMPLE_MAX ((1<<(LIS2DW12_RESOLUTION-1))-1)
+
+/** Smallest possible sample */
+#define LIS2DW12_SAMPLE_MIN (-(1<<(LIS2DW12_RESOLUTION-1)))
+
#ifdef CONFIG_ZTEST
int lis2dw12_set_power_mode(const struct motion_sensor_t *s,
enum lis2sw12_mode mode,
diff --git a/zephyr/emul/emul_lis2dw12.c b/zephyr/emul/emul_lis2dw12.c
index 3a29b74816..a4e6b46413 100644
--- a/zephyr/emul/emul_lis2dw12.c
+++ b/zephyr/emul/emul_lis2dw12.c
@@ -35,8 +35,12 @@ struct lis2dw12_emul_data {
uint8_t ctrl2_reg;
/** Emulated ctrl6 register */
uint8_t ctrl6_reg;
+ /** Emulated status register */
+ uint8_t status_reg;
/** Soft reset count */
uint32_t soft_reset_count;
+ /** Current X, Y, and Z output data registers */
+ int16_t accel_data[3];
};
struct lis2dw12_emul_cfg {
@@ -63,8 +67,13 @@ void lis2dw12_emul_reset(const struct emul *emul)
i2c_common_emul_set_read_func(i2c_emul, NULL, NULL);
i2c_common_emul_set_write_func(i2c_emul, NULL, NULL);
data->who_am_i_reg = LIS2DW12_WHO_AM_I;
+ data->ctrl1_reg = 0;
data->ctrl2_reg = 0;
+ data->ctrl6_reg = 0;
+ data->status_reg = 0;
data->soft_reset_count = 0;
+
+ memset(data->accel_data, 0, sizeof(data->accel_data));
}
void lis2dw12_emul_set_who_am_i(const struct emul *emul, uint8_t who_am_i)
@@ -103,6 +112,38 @@ static int lis2dw12_emul_read_byte(struct i2c_emul *emul, int reg, uint8_t *val,
__ASSERT_NO_MSG(bytes == 0);
*val = data->ctrl6_reg;
break;
+ case LIS2DW12_STATUS_REG:
+ __ASSERT_NO_MSG(bytes == 0);
+ *val = data->status_reg;
+ break;
+ case LIS2DW12_OUT_X_L_ADDR:
+ case LIS2DW12_OUT_X_H_ADDR:
+ case LIS2DW12_OUT_Y_L_ADDR:
+ case LIS2DW12_OUT_Y_H_ADDR:
+ case LIS2DW12_OUT_Z_L_ADDR:
+ case LIS2DW12_OUT_Z_H_ADDR:
+ /* Allow multi-byte reads within this range of registers.
+ * `bytes` is actually an offset past the starting register
+ * `reg`.
+ */
+
+ __ASSERT_NO_MSG(LIS2DW12_OUT_X_L_ADDR + bytes <=
+ LIS2DW12_OUT_Z_H_ADDR);
+
+ /* 0 is OUT_X_L_ADDR .. 5 is OUT_Z_H_ADDR */
+ int offset_into_odrs = reg - LIS2DW12_OUT_X_L_ADDR + bytes;
+
+ /* Which of the 3 channels we're reading. 0 = X, 1 = Y, 2 = Z */
+ int channel = offset_into_odrs / 2;
+
+ if (offset_into_odrs % 2 == 0) {
+ /* Get the LSB (L reg) */
+ *val = data->accel_data[channel] & 0xFF;
+ } else {
+ /* Get the MSB (H reg) */
+ *val = (data->accel_data[channel] >> 8) & 0xFF;
+ }
+ break;
default:
__ASSERT(false, "No read handler for register 0x%02x", reg);
return -EINVAL;
@@ -175,6 +216,20 @@ static int lis2dw12_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val,
case LIS2DW12_CTRL6_ADDR:
data->ctrl6_reg = val;
break;
+ case LIS2DW12_STATUS_REG:
+ __ASSERT(false,
+ "Attempt to write to read-only status register");
+ return -EINVAL;
+ case LIS2DW12_OUT_X_L_ADDR:
+ case LIS2DW12_OUT_X_H_ADDR:
+ case LIS2DW12_OUT_Y_L_ADDR:
+ case LIS2DW12_OUT_Y_H_ADDR:
+ case LIS2DW12_OUT_Z_L_ADDR:
+ case LIS2DW12_OUT_Z_H_ADDR:
+ __ASSERT(false,
+ "Attempt to write to data output register 0x%02x",
+ reg);
+ return -EINVAL;
default:
__ASSERT(false, "No write handler for register 0x%02x", reg);
return -EINVAL;
@@ -199,6 +254,37 @@ static int emul_lis2dw12_init(const struct emul *emul,
return i2c_emul_register(parent, emul->dev_label, &data->common.emul);
}
+int lis2dw12_emul_set_accel_reading(const struct emul *emul, intv3_t reading)
+{
+ __ASSERT(emul, "emul is NULL");
+ struct lis2dw12_emul_data *data = emul->data;
+
+ for (int i = X; i <= Z; i++) {
+ /* Ensure we fit in a 14-bit signed integer */
+ if (reading[i] < LIS2DW12_SAMPLE_MIN ||
+ reading[i] > LIS2DW12_SAMPLE_MAX) {
+ return -EINVAL;
+ }
+ /* Readings are left-aligned, so shift over by 2 */
+ data->accel_data[i] = reading[i] * 4;
+ }
+
+ /* Set the DRDY (data ready) bit */
+ data->status_reg |= LIS2DW12_STS_DRDY_UP;
+
+ return 0;
+}
+
+void lis2dw12_emul_clear_accel_reading(const struct emul *emul)
+{
+ __ASSERT(emul, "emul is NULL");
+ struct lis2dw12_emul_data *data = emul->data;
+
+ /* Zero out the registers and reset DRDY bit */
+ memset(data->accel_data, 0, sizeof(data->accel_data));
+ data->status_reg &= ~LIS2DW12_STS_DRDY_UP;
+}
+
#define INIT_LIS2DW12(n) \
static struct lis2dw12_emul_data lis2dw12_emul_data_##n = { \
.common = { \
diff --git a/zephyr/include/emul/emul_lis2dw12.h b/zephyr/include/emul/emul_lis2dw12.h
index 91ad5c0948..0d630af215 100644
--- a/zephyr/include/emul/emul_lis2dw12.h
+++ b/zephyr/include/emul/emul_lis2dw12.h
@@ -80,4 +80,21 @@ uint8_t lis2dw12_emul_peek_mode(struct i2c_emul *emul);
*/
uint8_t lis2dw12_emul_peek_lpmode(struct i2c_emul *emul);
+/**
+ * @brief Updates the current 3-axis acceleromter reading and
+ * sets the DRDY (data ready) flag.
+ * @param emul Reference to current LIS2DW12 emulator.
+ * @param reading array of int X, Y, and Z readings.
+ * @return 0 on success, or -EINVAL if readings are out of bounds.
+ */
+int lis2dw12_emul_set_accel_reading(const struct emul *emul,
+ intv3_t reading);
+
+/**
+ * @brief Clears the current accelerometer reading and resets the
+ * DRDY (data ready) flag.
+ * @param emul Reference to current LIS2DW12 emulator.
+ */
+void lis2dw12_emul_clear_accel_reading(const struct emul *emul);
+
#endif /* ZEPHYR_INCLUDE_EMUL_EMUL_LIS2DW12_H_ */