diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2015-08-30 20:55:40 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2015-09-21 01:13:54 -0700 |
commit | 8139114897c2eab41fd71e66368d861f9e5db2ba (patch) | |
tree | 80088b7be806602ecf0f3f337e8f7f70f03a03e2 /driver | |
parent | 1d8fcfcd0d1b93d04ea5adcb980ffac38bd3d140 (diff) | |
download | chrome-ec-8139114897c2eab41fd71e66368d861f9e5db2ba.tar.gz |
driver: bmi160: Add Significant motion support.
Add support for significant motion.
BRANCH=smaug
BUG=b:23570481
TEST=On Ryu, check significant motion (not still) is detected.
Change-Id: I5760a1ba3624490a0297de82371b1d15f05df5dc
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/296214
Diffstat (limited to 'driver')
-rw-r--r-- | driver/accelgyro_bmi160.c | 94 | ||||
-rw-r--r-- | driver/accelgyro_bmi160.h | 22 |
2 files changed, 116 insertions, 0 deletions
diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c index cbbb78f7cb..325398f011 100644 --- a/driver/accelgyro_bmi160.c +++ b/driver/accelgyro_bmi160.c @@ -628,6 +628,81 @@ void normalize(const struct motion_sensor_t *s, vector_3_t v, uint8_t *data) rotate(v, *s->rot_standard_ref, v); } +/* + * Manage gesture recognition. + * Defined even if host interface is not defined, to enable double tap even + * when the host does not deal with gesture. + */ +int manage_activity(struct motion_sensor_t *s, + enum motionsensor_activity activity, + int enable, + struct ec_motion_sense_activity *param) +{ + int ret; + struct bmi160_drv_data_t *data = BMI160_GET_DATA(s); + + switch (activity) { +#ifdef CONFIG_GESTURE_SIGMO + case MOTIONSENSE_ACTIVITY_SIG_MOTION: { + int tmp; + /* Set double tap interrupt and fifo*/ + ret = raw_read8(s->addr, BMI160_INT_EN_0, &tmp); + if (ret) + return ret; + if (enable) { + /* We should use paramters from caller */ + raw_write8(s->addr, BMI160_INT_MOTION_3, + BMI160_MOTION_PROOF_TIME( + CONFIG_GESTURE_SIGMO_PROOF_MS) << + BMI160_MOTION_PROOF_OFF | + BMI160_MOTION_SKIP_TIME( + CONFIG_GESTURE_SIGMO_SKIP_MS) << + BMI160_MOTION_SKIP_OFF | + BMI160_MOTION_SIG_MOT_SEL); + raw_write8(s->addr, BMI160_INT_MOTION_1, + BMI160_MOTION_TH(s, + CONFIG_GESTURE_SIGMO_THRES_MG)); + tmp |= BMI160_INT_ANYMO_X_EN | + BMI160_INT_ANYMO_Y_EN | + BMI160_INT_ANYMO_Z_EN; + } else { + tmp &= ~(BMI160_INT_ANYMO_X_EN | + BMI160_INT_ANYMO_Y_EN | + BMI160_INT_ANYMO_Z_EN); + } + ret = raw_write8(s->addr, BMI160_INT_EN_0, tmp); + if (ret) + ret = EC_RES_UNAVAILABLE; + break; + } +#endif + default: + ret = EC_RES_INVALID_PARAM; + } + if (ret == EC_RES_SUCCESS) { + if (enable) { + data->enabled_activities |= 1 << activity; + data->disabled_activities &= ~(1 << activity); + } else { + data->enabled_activities &= ~(1 << activity); + data->disabled_activities |= 1 << activity; + } + } + return ret; +} + +#ifdef CONFIG_GESTURE_HOST_DETECTION +int list_activities(struct motion_sensor_t *s, + uint32_t *enabled, + uint32_t *disabled) +{ + struct bmi160_drv_data_t *data = BMI160_GET_DATA(s); + *enabled = data->enabled_activities; + *disabled = data->disabled_activities; + return EC_RES_SUCCESS; +} +#endif + #ifdef CONFIG_ACCEL_INTERRUPTS /** * bmi160_interrupt - called when the sensor activate the interrupt line. @@ -668,6 +743,9 @@ static int config_interrupt(const struct motion_sensor_t *s) /* Map activity interrupt to int 1 */ tmp = 0; +#ifdef CONFIG_GESTURE_SIGMO + tmp |= BMI160_INT_ANYMOTION; +#endif #ifdef CONFIG_GESTURE_SENSOR_BATTERY_TAP tmp |= BMI160_INT_D_TAP; #endif @@ -721,6 +799,10 @@ static int irq_handler(struct motion_sensor_t *s, uint32_t *event) if (interrupt & BMI160_D_TAP_INT) *event |= CONFIG_GESTURE_TAP_EVENT; #endif +#ifdef CONFIG_GESTURE_SIGMO + if (interrupt & BMI160_SIGMOT_INT) + *event |= CONFIG_GESTURE_SIGMO_EVENT; +#endif /* * No need to read the FIFO here, motion sense task is * doing it on every interrupt. @@ -963,6 +1045,14 @@ static int init(const struct motion_sensor_t *s) data->flags &= ~(BMI160_FLAG_SEC_I2C_ENABLED | (BMI160_FIFO_ALL_MASK << BMI160_FIFO_FLAG_OFFSET)); +#ifdef CONFIG_GESTURE_HOST_DETECTION + data->enabled_activities = 0; + data->disabled_activities = 0; +#ifdef CONFIG_GESTURE_SIGMO + data->disabled_activities |= + 1 << MOTIONSENSE_ACTIVITY_SIG_MOTION; +#endif +#endif /* To avoid gyro wakeup */ raw_write8(s->addr, BMI160_PMU_TRIGGER, 0); } @@ -1073,6 +1163,10 @@ const struct accelgyro_drv bmi160_drv = { #ifdef CONFIG_ACCEL_FIFO .load_fifo = load_fifo, #endif +#ifdef CONFIG_GESTURE_HOST_DETECTION + .manage_activity = manage_activity, + .list_activities = list_activities, +#endif }; struct bmi160_drv_data_t g_bmi160_data = { diff --git a/driver/accelgyro_bmi160.h b/driver/accelgyro_bmi160.h index 0d6103a14c..ee44f9262e 100644 --- a/driver/accelgyro_bmi160.h +++ b/driver/accelgyro_bmi160.h @@ -296,8 +296,28 @@ enum fifo_header { #define BMI160_INT_MOTION_0 0x5f #define BMI160_INT_MOTION_1 0x60 +/* + * The formula is defined in 2.11.25 (any motion interrupt [1]). + * + * if we want threshold at a (in mg), the register should be x, where + * x * 7.81mg = a, assuming a range of 4G, which is + * x * 4 * 1.953 = a so + * x = a * 1000 / range * 1953 + */ +#define BMI160_MOTION_TH(_s, _mg) \ + (MIN(((_mg) * 1000) / ((_s)->drv->get_range(_s) * 1953), 0xff)) #define BMI160_INT_MOTION_2 0x61 #define BMI160_INT_MOTION_3 0x62 +#define BMI160_MOTION_NO_MOT_SEL (1 << 0) +#define BMI160_MOTION_SIG_MOT_SEL (1 << 1) +#define BMI160_MOTION_SKIP_OFF 2 +#define BMI160_MOTION_SKIP_MASK 0x3 +#define BMI160_MOTION_SKIP_TIME(_ms) \ + (MIN(__fls((_ms) / 1500), BMI160_MOTION_SKIP_MASK)) +#define BMI160_MOTION_PROOF_OFF 4 +#define BMI160_MOTION_PROOF_MASK 0x3 +#define BMI160_MOTION_PROOF_TIME(_ms) \ + (MIN(__fls((_ms) / 250), BMI160_MOTION_PROOF_MASK)) #define BMI160_INT_TAP_0 0x63 #define BMI160_INT_TAP_1 0x64 @@ -409,6 +429,8 @@ enum bmi160_running_mode { struct bmi160_drv_data_t { struct accelgyro_saved_data_t saved_data[3]; uint8_t flags; + uint8_t enabled_activities; + uint8_t disabled_activities; #ifdef CONFIG_MAG_BMI160_BMM150 struct bmm150_comp_registers comp_regs; #endif |