summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2015-11-12 00:45:27 -0800
committerchrome-bot <chrome-bot@chromium.org>2015-11-15 07:16:37 -0800
commit96b65354878587df434becfbc5d707a687c85fa4 (patch)
treec1b18e7bff9cf87b15038f8efb9bfc5555eb231e
parentd68cb398ab9b76eeab57230c32dd7c476c5e3377 (diff)
downloadchrome-ec-96b65354878587df434becfbc5d707a687c85fa4.tar.gz
motion: fix oversampling formula
Overly complex previous formula could lead the EC to throw all samples between 2 timestamps and put 2 event within one timestamp. That would confuse the kernel. If the motion sense task is delayed while this happen, the delta between the 2 samples could be so long that CTS test cts.SingleSensorTests would fail. BRANCH=smaug BUG=b:24367625 TEST=Loops of cts.SingleSensorTests pass. Change-Id: I29e6bf354ccb7ecf741a91116854d6abe07558dc Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/312364 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--common/motion_sense.c70
-rw-r--r--include/motion_sense.h5
2 files changed, 33 insertions, 42 deletions
diff --git a/common/motion_sense.c b/common/motion_sense.c
index 7602d62334..ded4ad4832 100644
--- a/common/motion_sense.c
+++ b/common/motion_sense.c
@@ -94,49 +94,23 @@ void motion_sense_fifo_add_unit(struct ec_response_motion_sensor_data *data,
}
for (i = 0; i < valid_data; i++)
sensor->xyz[i] = data->data[i];
- mutex_unlock(&g_sensor_mutex);
/* For valid sensors, check if AP really needs this data */
if (valid_data) {
- /* Use Hz, conversion to FP will overflow with kHz */
- fp_t ap_odr =
- fp_div(BASE_ODR(sensor->config[SENSOR_CONFIG_AP].odr),
- 1000);
- fp_t rate = fp_div(sensor->drv->get_data_rate(sensor), 1000);
+ int removed;
- /*
- * If the AP does not want sensor info, skip.
- * It happens:
- * - only the EC needs the data
- * - when there is event waiting in the FIFO when the AP
- * put the sensor in suspend.
- */
- if (ap_odr == 0)
- return;
-
- /*
- * BM160 FIFO can return bad data (see chrome-os-partner:43339.
- * It looks like an accelerometer event.
- * It can happen if we are in middle of setting a new ODR
- * while we are processing the FIFO.
- */
- if (rate == 0) {
- CPRINTS("%s: unexpected event: 0x%04x", sensor->name,
- data->data[0]);
+ if (sensor->oversampling_ratio == 0) {
+ mutex_unlock(&g_sensor_mutex);
return;
}
-
- if (fp_mul(ap_odr, INT_TO_FP(2)) < rate) {
- /* Skip if sensor is significantly oversampling */
- if (sensor->oversampling < 0) {
- sensor->oversampling +=
- fp_div(INT_TO_FP(1), rate);
- return;
- }
- sensor->oversampling += fp_div(INT_TO_FP(1), rate) -
- fp_div(INT_TO_FP(1), ap_odr);
+ removed = sensor->oversampling++;
+ sensor->oversampling %= sensor->oversampling_ratio;
+ if (removed != 0) {
+ mutex_unlock(&g_sensor_mutex);
+ return;
}
}
+ mutex_unlock(&g_sensor_mutex);
if (data->flags & MOTIONSENSE_SENSOR_FLAG_WAKEUP) {
/*
* Fist, send a timestamp to be sure the event will not
@@ -219,7 +193,7 @@ static enum sensor_config motion_sense_get_ec_config(void)
*/
int motion_sense_set_data_rate(struct motion_sensor_t *sensor)
{
- int roundup = 0, ec_odr = 0, odr = 0;
+ int roundup, ap_odr = 0, ec_odr, odr, ret;
enum sensor_config config_id;
timestamp_t ts = get_time();
@@ -227,26 +201,40 @@ int motion_sense_set_data_rate(struct motion_sensor_t *sensor)
/* Check the AP setting first. */
if (sensor_active != SENSOR_ACTIVE_S5)
- odr = BASE_ODR(sensor->config[SENSOR_CONFIG_AP].odr);
+ ap_odr = BASE_ODR(sensor->config[SENSOR_CONFIG_AP].odr);
/* check if the EC set the sensor ODR at a higher frequency */
config_id = motion_sense_get_ec_config();
ec_odr = BASE_ODR(sensor->config[config_id].odr);
- if (ec_odr > odr)
+ if (ec_odr > ap_odr) {
odr = ec_odr;
- else
+ } else {
+ odr = ap_odr;
config_id = SENSOR_CONFIG_AP;
+ }
roundup = !!(sensor->config[config_id].odr & ROUND_UP_FLAG);
+ ret = sensor->drv->set_data_rate(sensor, odr, roundup);
+ if (ret)
+ return ret;
+
CPRINTS("%s ODR: %d - roundup %d from config %d [AP %d]",
sensor->name, odr, roundup, config_id,
BASE_ODR(sensor->config[SENSOR_CONFIG_AP].odr));
- sensor->oversampling = 0;
+ mutex_lock(&g_sensor_mutex);
+ if (ap_odr)
+ sensor->oversampling_ratio =
+ sensor->drv->get_data_rate(sensor) / ap_odr;
+ else
+ sensor->oversampling_ratio = 0;
+
/*
* Reset last collection: the last collection may be so much in the past
* it may appear to be in the future.
*/
sensor->last_collection = ts.le.lo;
- return sensor->drv->set_data_rate(sensor, odr, roundup);
+ sensor->oversampling = 0;
+ mutex_unlock(&g_sensor_mutex);
+ return 0;
}
static int motion_sense_select_ec_rate(
diff --git a/include/motion_sense.h b/include/motion_sense.h
index 7dd9fd747d..89203dd040 100644
--- a/include/motion_sense.h
+++ b/include/motion_sense.h
@@ -108,8 +108,11 @@ struct motion_sensor_t {
/*
* Allow EC to request an higher frequency for the sensors than the AP.
+ * We will downsample according to oversampling_ratio, or ignore the
+ * samples altogether if oversampling_ratio is 0.
*/
- fp_t oversampling;
+ uint16_t oversampling;
+ uint16_t oversampling_ratio;
/*
* How many vector events are lost in the FIFO since last time