summaryrefslogtreecommitdiff
path: root/zephyr/include/emul/emul_bmi.h
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/include/emul/emul_bmi.h')
-rw-r--r--zephyr/include/emul/emul_bmi.h518
1 files changed, 518 insertions, 0 deletions
diff --git a/zephyr/include/emul/emul_bmi.h b/zephyr/include/emul/emul_bmi.h
new file mode 100644
index 0000000000..81d889a301
--- /dev/null
+++ b/zephyr/include/emul/emul_bmi.h
@@ -0,0 +1,518 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * @file
+ *
+ * @brief Backend API for BMI emulator
+ */
+
+#ifndef __EMUL_BMI_H
+#define __EMUL_BMI_H
+
+#include <emul.h>
+#include <drivers/i2c.h>
+#include <drivers/i2c_emul.h>
+
+/**
+ * @brief BMI emulator backend API
+ * @defgroup bmi_emul BMI emulator
+ * @{
+ *
+ * BMI emulator supports responses to all write and read I2C messages.
+ * Accelerometer and gyroscope registers are obtained from internal emulator
+ * state, range register and offset. FIFO is fully simulated. Emulator can be
+ * extended to support more models of BMI.
+ * Application may alter emulator state:
+ *
+ * - define a Device Tree overlay file to set which inadvisable driver behaviour
+ * should be treated as errors and which model is emulated
+ * - call @ref bmi_emul_set_read_func and @ref bmi_emul_set_write_func to setup
+ * custom handlers for I2C messages
+ * - call @ref bmi_emul_set_reg and @ref bmi_emul_get_reg to set and get value
+ * of BMI registers
+ * - call @ref bmi_emul_set_off and @ref bmi_emul_get_off to set and get
+ * internal offset value
+ * - call @ref bmi_emul_set_value and @ref bmi_emul_get_value to set and get
+ * accelerometer or gyroscope value
+ * - call bmi_emul_set_err_* to change emulator behaviour on inadvisable driver
+ * behaviour
+ * - call @ref bmi_emul_simulate_cmd_exec_time to enable or disable simulation
+ * of command execution time
+ * - call @ref bmi_emul_set_read_fail_reg and @ref bmi_emul_set_write_fail_reg
+ * to configure emulator to fail on given register read or write
+ * - call @ref bmi_emul_append_frame to add frame to FIFO
+ * - call @reg bmi_emul_set_skipped_frames to generate skip frame on next access
+ * to FIFO
+ */
+
+/**
+ * Axis argument used in @ref bmi_emul_set_value @ref bmi_emul_get_value
+ * @ref bmi_emul_set_off and @ref bmi_emul_get_off
+ */
+enum bmi_emul_axis {
+ BMI_EMUL_ACC_X,
+ BMI_EMUL_ACC_Y,
+ BMI_EMUL_ACC_Z,
+ BMI_EMUL_GYR_X,
+ BMI_EMUL_GYR_Y,
+ BMI_EMUL_GYR_Z,
+};
+
+/** BMI emulator models */
+#define BMI_EMUL_160 1
+
+/** Last register supported by emulator */
+#define BMI_EMUL_MAX_REG 0x80
+/** Maximum number of registers that can be backed in NVM */
+#define BMI_EMUL_MAX_NVM_REGS 10
+
+/** Headers used in FIFO frames */
+#define BMI_EMUL_FIFO_HEAD_SKIP 0x40
+#define BMI_EMUL_FIFO_HEAD_TIME 0x44
+#define BMI_EMUL_FIFO_HEAD_CONFIG 0x48
+#define BMI_EMUL_FIFO_HEAD_EMPTY 0x80
+#define BMI_EMUL_FIFO_HEAD_DATA 0x80
+#define BMI_EMUL_FIFO_HEAD_DATA_MAG BIT(4)
+#define BMI_EMUL_FIFO_HEAD_DATA_GYR BIT(3)
+#define BMI_EMUL_FIFO_HEAD_DATA_ACC BIT(2)
+#define BMI_EMUL_FIFO_HEAD_DATA_TAG_MASK 0x03
+
+/**
+ * Acceleration 1g in internal emulator units. It is helpful for using
+ * functions @ref bmi_emul_set_value @ref bmi_emul_get_value
+ * @ref bmi_emul_set_off and @ref bmi_emul_get_off
+ */
+#define BMI_EMUL_1G BIT(14)
+/**
+ * Gyroscope 125°/s in internal emulator units. It is helpful for using
+ * functions @ref bmi_emul_set_value @ref bmi_emul_get_value
+ * @ref bmi_emul_set_off and @ref bmi_emul_get_off
+ */
+#define BMI_EMUL_125_DEG_S BIT(15)
+
+/** Type of frames that can be added to the emulator frames list */
+#define BMI_EMUL_FRAME_CONFIG BIT(0)
+#define BMI_EMUL_FRAME_ACC BIT(1)
+#define BMI_EMUL_FRAME_MAG BIT(2)
+#define BMI_EMUL_FRAME_GYR BIT(3)
+
+/**
+ * Code returned by model specific handle_read and handle_write functions, when
+ * RO register is accessed on write or WO register is accessed on read
+ */
+#define BMI_EMUL_ACCESS_E 1
+
+/**
+ * Special register values used in @ref bmi_emul_set_read_fail_reg and
+ * @ref bmi_emul_set_write_fail_reg
+ */
+#define BMI_EMUL_FAIL_ALL_REG (-1)
+#define BMI_EMUL_NO_FAIL_REG (-2)
+
+/** Structure used to describe single FIFO frame */
+struct bmi_emul_frame {
+ /** Type of frame */
+ uint8_t type;
+ /** Tag added to data frame */
+ uint8_t tag;
+ /** Value used in config frame */
+ uint8_t config;
+ /** Accelerometer sensor values in internal emulator units */
+ int32_t acc_x;
+ int32_t acc_y;
+ int32_t acc_z;
+ /** Gyroscope sensor values in internal emulator units */
+ int32_t gyr_x;
+ int32_t gyr_y;
+ int32_t gyr_z;
+ /** Magnetometer/other sensor values in internal emulator units */
+ int32_t mag_x;
+ int32_t mag_y;
+ int32_t mag_z;
+ int32_t rhall;
+
+ /** Pointer to next frame or NULL */
+ struct bmi_emul_frame *next;
+};
+
+/** Structure describing specific BMI model */
+struct bmi_emul_type_data {
+ /** Indicate if time frame should follow config frame */
+ bool sensortime_follow_config_frame;
+
+ /**
+ * @brief Model specific write function. It should modify state of
+ * emulator if required. @p reg value should be updated to
+ * register which is acctually accessed.
+ *
+ * @param regs Pointer to array of emulator's registers
+ * @param emul Pointer to BMI emulator
+ * @param reg Pointer to accessed reg. If different reg is accessed,
+ * this value should be modified.
+ * @param byte Number of handled bytes in this write command
+ * @param val Value that is being written
+ *
+ * @return 0 on success
+ * @return BMI_EMUL_ACCESS_E on RO register access
+ * @return other on error
+ */
+ int (*handle_write)(uint8_t *regs, struct i2c_emul *emul, int *reg,
+ int byte, uint8_t val);
+ /**
+ * @brief Model specific read function. It should modify state of
+ * emulator if required. @p reg value should be updated to
+ * register which is acctually accessed. @p buf should be
+ * set to response value.
+ *
+ * @param regs Pointer to array of emulator's registers
+ * @param emul Pointer to BMI emulator
+ * @param reg Pointer to accessed reg. If different reg is accessed,
+ * this value should be modified.
+ * @param byte Byte which is accessed during block read
+ * @param buf Pointer where read byte should be stored
+ *
+ * @return 0 on success
+ * @return BMI_EMUL_ACCESS_E on WO register access
+ * @return other on error
+ */
+ int (*handle_read)(uint8_t *regs, struct i2c_emul *emul, int *reg,
+ int byte, char *buf);
+ /**
+ * @brief Model specific reset function. It should modify state of
+ * emulator to imitate after reset conditions.
+ *
+ * @param regs Pointer to array of emulator's registers
+ * @param emul Pointer to BMI emulator
+ */
+ void (*reset)(uint8_t *regs, struct i2c_emul *emul);
+
+ /** Array of reserved bits mask for each register */
+ const uint8_t *rsvd_mask;
+
+ /** Array of registers that are backed in NVM */
+ const int *nvm_reg;
+ /** Number of registers backed in NVM */
+ int nvm_len;
+
+ /** Gyroscope X axis register */
+ int gyr_off_reg;
+ /** Accelerometer X axis register */
+ int acc_off_reg;
+ /** Gyroscope 9 and 8 bits register */
+ int gyr98_off_reg;
+};
+
+/**
+ * @brief Get BMI160 model specific structure.
+ *
+ * @return Pointer to BMI160 specific structure
+ */
+const struct bmi_emul_type_data *get_bmi160_emul_type_data(void);
+
+/**
+ * @brief Get pointer to BMI emulator using device tree order number.
+ *
+ * @param ord Device tree order number obtained from DT_DEP_ORD macro
+ *
+ * @return Pointer to BMI emulator
+ */
+struct i2c_emul *bmi_emul_get(int ord);
+
+/**
+ * @brief Custom function type that is used as user-defined callback in read
+ * I2C messages handling.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param reg Address which is now accessed by read command
+ * @param byte Byte which is accessed during block read
+ * @param data Pointer to custom user data
+ *
+ * @return 0 on success. Value of @p reg should be set by @ref bmi_emul_set_reg
+ * @return 1 continue with normal BMI emulator handler
+ * @return negative on error
+ */
+typedef int (*bmi_emul_read_func)(struct i2c_emul *emul, int reg, int byte,
+ void *data);
+
+/**
+ * @brief Custom function type that is used as user-defined callback in write
+ * I2C messages handling.
+ *
+ * @param emul Pointer to BMA255 emulator
+ * @param reg Address which is now accessed by write command
+ * @param byte Number of handled bytes in this write command. It does include
+ * first byte containing accessed register address.
+ * @param val Value which is being written to @p reg
+ * @param data Pointer to custom user data
+ *
+ * @return 0 on success
+ * @return 1 continue with normal BMI emulator handler
+ * @return negative on error
+ */
+typedef int (*bmi_emul_write_func)(struct i2c_emul *emul, int reg, int byte,
+ uint8_t val, void *data);
+
+/**
+ * @brief Lock access to BMI properties. After acquiring lock, user
+ * may change emulator behaviour in multi-thread setup.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param timeout Timeout in getting lock
+ *
+ * @return k_mutex_lock return code
+ */
+int bmi_emul_lock_data(struct i2c_emul *emul, k_timeout_t timeout);
+
+/**
+ * @brief Unlock access to BMI properties.
+ *
+ * @param emul Pointer to BMI emulator
+ *
+ * @return k_mutex_unlock return code
+ */
+int bmi_emul_unlock_data(struct i2c_emul *emul);
+
+/**
+ * @brief Set write handler for I2C messages. This function is called before
+ * generic handler.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param func Pointer to custom function
+ * @param data User data passed on call of custom function
+ */
+void bmi_emul_set_write_func(struct i2c_emul *emul, bmi_emul_write_func func,
+ void *data);
+
+/**
+ * @brief Set read handler for I2C messages. This function is called before
+ * generic handler.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param func Pointer to custom function
+ * @param data User data passed on call of custom function
+ */
+void bmi_emul_set_read_func(struct i2c_emul *emul, bmi_emul_read_func func,
+ void *data);
+
+/**
+ * @brief Set value of given register of BMI
+ *
+ * @param emul Pointer to BMI emulator
+ * @param reg Register address which value will be changed
+ * @param val New value of the register
+ */
+void bmi_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val);
+
+/**
+ * @brief Get value of given register of BMI
+ *
+ * @param emul Pointer to BMI emulator
+ * @param reg Register address
+ *
+ * @return Value of the register
+ */
+uint8_t bmi_emul_get_reg(struct i2c_emul *emul, int reg);
+
+/**
+ * @brief Setup fail on read of given register of BMI
+ *
+ * @param emul Pointer to BMI emulator
+ * @param reg Register address or one of special values (BMI_EMUL_FAIL_ALL_REG,
+ * BMI_EMUL_NO_FAIL_REG)
+ */
+void bmi_emul_set_read_fail_reg(struct i2c_emul *emul, int reg);
+
+/**
+ * @brief Setup fail on write of given register of BMI
+ *
+ * @param emul Pointer to BMI emulator
+ * @param reg Register address or one of special values (BMI_EMUL_FAIL_ALL_REG,
+ * BMI_EMUL_NO_FAIL_REG)
+ */
+void bmi_emul_set_write_fail_reg(struct i2c_emul *emul, int reg);
+
+/**
+ * @brief Get internal value of offset for given axis and sensor
+ *
+ * @param emul Pointer to BMI emulator
+ * @param axis Axis to access
+ *
+ * @return Offset of given axis. LSB for accelerometer is 0.061mg and for
+ * gyroscope is 0.0037°/s.
+ */
+int16_t bmi_emul_get_off(struct i2c_emul *emul, enum bmi_emul_axis axis);
+
+/**
+ * @brief Set internal value of offset for given axis and sensor
+ *
+ * @param emul Pointer to BMI emulator
+ * @param axis Axis to access
+ * @param val New value of given axis. LSB for accelerometer is 0.061mg and for
+ * gyroscope is 0.0037°/s.
+ */
+void bmi_emul_set_off(struct i2c_emul *emul, enum bmi_emul_axis axis,
+ int16_t val);
+
+/**
+ * @brief Get internal value of sensor for given axis
+ *
+ * @param emul Pointer to BMI emulator
+ * @param axis Axis to access
+ *
+ * @return Sensor value of given axis. LSB for accelerometer is 0.061mg and for
+ * gyroscope is 0.0037°/s.
+ */
+int32_t bmi_emul_get_value(struct i2c_emul *emul, enum bmi_emul_axis axis);
+
+/**
+ * @brief Set internal value of sensor for given axis
+ *
+ * @param emul Pointer to BMI emulator
+ * @param axis Axis to access
+ * @param val New value of given axis. LSB for accelerometer is 0.061mg and for
+ * gyroscope is 0.0037°/s.
+ */
+void bmi_emul_set_value(struct i2c_emul *emul, enum bmi_emul_axis axis,
+ int32_t val);
+
+/**
+ * @brief Set if error should be generated when read only register is being
+ * written
+ *
+ * @param emul Pointer to BMI emulator
+ * @param set Check for this error
+ */
+void bmi_emul_set_err_on_ro_write(struct i2c_emul *emul, bool set);
+
+/**
+ * @brief Set if error should be generated when reserved bits of register are
+ * not set to 0 on write I2C message
+ *
+ * @param emul Pointer to BMI emulator
+ * @param set Check for this error
+ */
+void bmi_emul_set_err_on_rsvd_write(struct i2c_emul *emul, bool set);
+
+/**
+ * @brief Set if error should be generated when write only register is read
+ *
+ * @param emul Pointer to BMI emulator
+ * @param set Check for this error
+ */
+void bmi_emul_set_err_on_wo_read(struct i2c_emul *emul, bool set);
+
+/**
+ * @brief Set if effect of simulated command should take place after simulated
+ * time pass from issuing command.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param set Simulate command execution time
+ */
+void bmi_emul_simulate_cmd_exec_time(struct i2c_emul *emul, bool set);
+
+/**
+ * @brief Set number of skipped frames. It will generate skip frame on next
+ * access to FIFO. After that number of skipped frames is reset to 0.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param skip Number of skipped frames
+ */
+void bmi_emul_set_skipped_frames(struct i2c_emul *emul, uint8_t skip);
+
+/**
+ * @brief Clear all FIFO frames, set current frame to empty and reset fifo_skip
+ * counter
+ *
+ * @param emul Pointer to BMI emulator
+ * @param tag_time Indicate if sensor time should be included in empty frame
+ * @param header Indicate if header should be included in frame
+ */
+void bmi_emul_flush_fifo(struct i2c_emul *emul, bool tag_time, bool header);
+
+/**
+ * @brief Restore registers backed by NVM, reset sensor time and flush FIFO
+ *
+ * @param emul Pointer to BMI emulator
+ */
+void bmi_emul_reset_common(struct i2c_emul *emul, bool tag_time, bool header);
+
+/**
+ * @brief Set command end time to @p time ms from now
+ *
+ * @param emul Pointer to BMI emulator
+ * @param time After this amount of ms command should end
+ */
+void bmi_emul_set_cmd_end_time(struct i2c_emul *emul, int time);
+
+/**
+ * @brief Check if command should end
+ *
+ * @param emul Pointer to BMI emulator
+ */
+bool bmi_emul_is_cmd_end(struct i2c_emul *emul);
+
+/**
+ * @brief Append FIFO @p frame to the emulator list of frames. It can be read
+ * using I2C interface.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param frame Pointer to new FIFO frame. Pointed data has to be valid while
+ * emulator may use this frame (until flush of FIFO or reading
+ * it out through I2C)
+ */
+void bmi_emul_append_frame(struct i2c_emul *emul, struct bmi_emul_frame *frame);
+
+/**
+ * @brief Get length of all frames that are on the emulator list of frames.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param tag_time Indicate if sensor time should be included in empty frame
+ * @param header Indicate if header should be included in frame
+ */
+uint16_t bmi_emul_fifo_len(struct i2c_emul *emul, bool tag_time, bool header);
+
+/**
+ * @brief Get next byte that should be returned on FIFO data access.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param byte Which byte of block read command is currently handled
+ * @param tag_time Indicate if sensor time should be included in empty frame
+ * @param header Indicate if header should be included in frame
+ * @param acc_shift How many bits should be right shifted from accelerometer
+ * data
+ * @param gyr_shift How many bits should be right shifted from gyroscope data
+ *
+ * @return FIFO data byte
+ */
+uint8_t bmi_emul_get_fifo_data(struct i2c_emul *emul, int byte,
+ bool tag_time, bool header, int acc_shift,
+ int gyr_shift);
+
+/**
+ * @brief Saves current internal state of sensors to emulator's registers.
+ *
+ * @param emul Pointer to BMI emulator
+ * @param acc_shift How many bits should be right shifted from accelerometer
+ * data
+ * @param gyr_shift How many bits should be right shifted from gyroscope data
+ * @param acc_reg Register which holds LSB of accelerometer sensor
+ * @param gyr_reg Register which holds LSB of gyroscope sensor
+ * @param sensortime_reg Register which holds LSB of sensor time
+ * @param acc_off_en Indicate if accelerometer offset should be included to
+ * sensor data value
+ * @param gyr_off_en Indicate if gyroscope offset should be included to
+ * sensor data value
+ */
+void bmi_emul_state_to_reg(struct i2c_emul *emul, int acc_shift,
+ int gyr_shift, int acc_reg, int gyr_reg,
+ int sensortime_reg, bool acc_off_en,
+ bool gyr_off_en);
+
+/**
+ * @}
+ */
+
+#endif /* __EMUL_BMI_H */