motion: Add sample frequency per sensor

Store at which frequency each sensor should be sampled.
This frequency is different from the sensor frequency:
- sensor frequency: frequency at which the sensor produce information.
- sensor sampling frequency: frequency at the which the EC gater
information.
If 2 sensors must be sampled at very different frequency,
we don't want to oversample the slow one, and filling the
software FIFO unnecessarily.

BRANCH=smaug
TEST=Unit test. Check that frequency is correct when sensor
frequencies change from IIO driver.
BUG=chrome-os-partner:39900

Change-Id: I4272963413f53d4ca004e26639dc7a2affd317eb
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/284616
Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
Gwendal Grignou
2015-06-26 16:15:37 -07:00
committed by ChromeOS Commit Bot
parent 3b55292cdb
commit c0f78b4c0a
10 changed files with 245 additions and 149 deletions

View File

@@ -113,7 +113,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &base_standard_ref,
.default_config = {
.odr = 100000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
{.name = "Lid",
@@ -128,7 +129,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &lid_standard_ref,
.default_config = {
.odr = 100000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
};

View File

@@ -190,7 +190,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &base_standard_ref,
.default_config = {
.odr = 100000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
{.name = "Lid Accel",
@@ -205,7 +206,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &lid_standard_ref,
.default_config = {
.odr = 100000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
};

View File

@@ -296,6 +296,7 @@ struct motion_sensor_t motion_sensors[] = {
.default_config = {
.odr = 100000,
.range = 8,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
@@ -310,8 +311,9 @@ struct motion_sensor_t motion_sensors[] = {
.i2c_addr = BMI160_ADDR0,
.rot_standard_ref = NULL,
.default_config = {
.odr = 100000,
.range = 2000
.odr = 0,
.range = 2000,
.ec_rate = MAX_MOTION_SENSE_WAIT_TIME,
}
},
@@ -326,8 +328,9 @@ struct motion_sensor_t motion_sensors[] = {
.i2c_addr = BMI160_ADDR0,
.rot_standard_ref = NULL,
.default_config = {
.odr = 25000,
.range = 1
.odr = 0,
.range = 1,
.ec_rate = MAX_MOTION_SENSE_WAIT_TIME,
}
},
};

View File

@@ -59,7 +59,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = NULL,
.default_config = {
.odr = 119000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
@@ -75,7 +76,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = NULL,
.default_config = {
.odr = 119000,
.range = 2000
.range = 2000,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},

View File

@@ -309,7 +309,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &base_standard_ref,
.default_config = {
.odr = 119000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
@@ -325,7 +326,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &lid_standard_ref,
.default_config = {
.odr = 100000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
@@ -341,7 +343,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = NULL,
.default_config = {
.odr = 119000,
.range = 2000
.range = 2000,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},

View File

@@ -130,7 +130,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &base_standard_ref,
.default_config = {
.odr = 100000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
{.name = "Lid Accel",
@@ -145,7 +146,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &lid_standard_ref,
.default_config = {
.odr = 100000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
};

View File

@@ -30,48 +30,24 @@
#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ## args)
#define CPRINTF(format, args...) cprintf(CC_MOTION_SENSE, format, ## args)
/* Minimum time in between running motion sense task loop. */
#define MIN_MOTION_SENSE_WAIT_TIME (1 * MSEC)
/* Time to wait in between failed attempts to initialize sensors */
#define TASK_MOTION_SENSE_WAIT_TIME (500 * MSEC)
/* Bounds for setting the sensor polling interval. */
#define MIN_POLLING_INTERVAL_MS 1
/* Define sensor sampling interval in suspend. */
#ifdef CONFIG_GESTURE_DETECTION
#define SUSPEND_SAMPLING_INTERVAL (CONFIG_GESTURE_SAMPLING_INTERVAL_MS * MSEC)
#elif defined(CONFIG_ACCEL_FIFO)
#define SUSPEND_SAMPLING_INTERVAL (1000 * MSEC)
#else
#define SUSPEND_SAMPLING_INTERVAL (100 * MSEC)
#endif
/* Accelerometer polling intervals based on chipset state. */
#ifdef CONFIG_ACCEL_FIFO
/*
* TODO(crbug.com/498352):
* For now, we collect the data every accel_interval.
* For non-FIFO sensor, we should set accel_interval at a lower value.
* But if we have a mix a FIFO and non FIFO sensors, setting it
* to low will increase the number of interrupts.
*/
static int accel_interval_ap_on = 1000 * MSEC;
#else
static int accel_interval_ap_on = 10 * MSEC;
#endif
/*
* Sampling interval for measuring acceleration and calculating lid angle.
* Set to accel_interval_ap_on when ap is on.
*/
static int accel_interval;
unsigned accel_interval;
#ifdef CONFIG_CMD_ACCEL_INFO
static int accel_disp;
#endif
#define SENSOR_EC_RATE(_sensor) \
((_sensor)->active == SENSOR_ACTIVE_S0 ? \
(_sensor)->runtime_config.ec_rate : \
(_sensor)->default_config.ec_rate)
/* Minimal amount of time since last collection before triggering a new one */
#define SENSOR_EC_RATE_THRES(_sensor) \
(SENSOR_EC_RATE(_sensor) * 9 / 10)
/*
* Mutex to protect sensor values between host command task and
* motion sense task:
@@ -132,6 +108,54 @@ static void motion_sense_get_fifo_info(
}
#endif
/*
* motion_sense_set_accel_interval
*
* Set the wake up interval for the motion sense thread.
* It is set to the highest frequency one of the sensors need to be polled at.
*
* driving_sensor: In S0, indicates which sensor has its EC sampling rate
* changed. In S3, it is hard coded, so in S3 driving_sensor should be NULL.
*
* Note: Not static to be tested.
*/
int motion_sense_set_accel_interval(
struct motion_sensor_t *driving_sensor,
unsigned data)
{
int i;
struct motion_sensor_t *sensor;
if (driving_sensor)
driving_sensor->runtime_config.ec_rate = data;
for (i = 0; i < motion_sensor_count; ++i) {
sensor = &motion_sensors[i];
if (sensor == driving_sensor)
continue;
if (SENSOR_EC_RATE(sensor) < data)
data = SENSOR_EC_RATE(sensor);
}
accel_interval = data;
return data;
}
static void motion_sense_startup(void)
{
int i;
struct motion_sensor_t *sensor;
for (i = 0; i < motion_sensor_count; ++i) {
sensor = &motion_sensors[i];
sensor->state = SENSOR_NOT_INITIALIZED;
sensor->active = SENSOR_ACTIVE_S5;
memcpy(&sensor->runtime_config, &sensor->default_config,
sizeof(sensor->runtime_config));
}
motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
}
DECLARE_HOOK(HOOK_INIT, motion_sense_startup,
MOTION_SENSE_HOOK_PRIO);
static void motion_sense_shutdown(void)
{
int i;
@@ -140,14 +164,15 @@ static void motion_sense_shutdown(void)
for (i = 0; i < motion_sensor_count; i++) {
sensor = &motion_sensors[i];
sensor->active = SENSOR_ACTIVE_S5;
sensor->runtime_config.odr = sensor->default_config.odr;
sensor->runtime_config.range = sensor->default_config.range;
memcpy(&sensor->runtime_config, &sensor->default_config,
sizeof(sensor->runtime_config));
if ((sensor->state == SENSOR_INITIALIZED) &&
!(sensor->active_mask & sensor->active)) {
sensor->drv->set_data_rate(sensor, 0, 0);
sensor->state = SENSOR_NOT_INITIALIZED;
}
}
motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
}
DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, motion_sense_shutdown,
MOTION_SENSE_HOOK_PRIO);
@@ -157,14 +182,12 @@ static void motion_sense_suspend(void)
int i;
struct motion_sensor_t *sensor;
accel_interval = SUSPEND_SAMPLING_INTERVAL;
for (i = 0; i < motion_sensor_count; i++) {
sensor = &motion_sensors[i];
/* if it is in s5, don't enter suspend */
/* if we are comming from S5, don't enter suspend */
if (sensor->active == SENSOR_ACTIVE_S5)
continue;
return;
sensor->active = SENSOR_ACTIVE_S3;
@@ -175,6 +198,7 @@ static void motion_sense_suspend(void)
sensor->state = SENSOR_NOT_INITIALIZED;
}
}
motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
}
DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, motion_sense_suspend,
MOTION_SENSE_HOOK_PRIO);
@@ -184,8 +208,6 @@ static void motion_sense_resume(void)
int i;
struct motion_sensor_t *sensor;
accel_interval = accel_interval_ap_on;
for (i = 0; i < motion_sensor_count; i++) {
sensor = &motion_sensors[i];
sensor->active = SENSOR_ACTIVE_S0;
@@ -195,6 +217,7 @@ static void motion_sense_resume(void)
sensor->runtime_config.odr, 1);
}
}
motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
}
DECLARE_HOOK(HOOK_CHIPSET_RESUME, motion_sense_resume,
MOTION_SENSE_HOOK_PRIO);
@@ -258,10 +281,13 @@ static inline void motion_sense_init(struct motion_sensor_t *sensor)
ret = sensor->drv->init(sensor);
} while ((ret != EC_SUCCESS) && (--cnt > 0));
if (ret != EC_SUCCESS)
if (ret != EC_SUCCESS) {
sensor->state = SENSOR_INIT_ERROR;
else
} else {
timestamp_t ts = get_time();
sensor->state = SENSOR_INITIALIZED;
sensor->last_collection = ts.val;
}
}
static int motion_sense_read(struct motion_sensor_t *sensor)
@@ -275,6 +301,7 @@ static int motion_sense_read(struct motion_sensor_t *sensor)
static int motion_sense_process(struct motion_sensor_t *sensor,
uint32_t event,
const timestamp_t *ts,
int *flush_needed)
{
int ret = EC_SUCCESS;
@@ -288,13 +315,18 @@ static int motion_sense_process(struct motion_sensor_t *sensor,
if (sensor->drv->load_fifo != NULL) {
/* Load fifo is filling raw_xyz sensor vector */
sensor->drv->load_fifo(sensor);
} else {
} else if (ts->val - sensor->last_collection >=
SENSOR_EC_RATE_THRES(sensor)) {
struct ec_response_motion_sensor_data vector;
sensor->last_collection = ts->val;
ret = motion_sense_read(sensor);
/* Put data in fifo.
* Depending on the frequency on that particular sensor,
* we may not do it all the time.
* TODO(chromium:498352)
*/
vector.flags = 0;
vector.data[X] = sensor->raw_xyz[X];
vector.data[Y] = sensor->raw_xyz[Y];
vector.data[Z] = sensor->raw_xyz[Z];
motion_sense_fifo_add_unit(&vector, sensor);
} else {
ret = EC_ERROR_BUSY;
}
if (event & TASK_EVENT_MOTION_FLUSH_PENDING) {
int flush_pending;
@@ -305,8 +337,14 @@ static int motion_sense_process(struct motion_sensor_t *sensor,
}
}
#else
/* Get latest data for local calculation */
ret = motion_sense_read(sensor);
if (ts->val - sensor->last_collection >=
SENSOR_EC_RATE_THRES(sensor)) {
sensor->last_collection = ts->val;
/* Get latest data for local calculation */
ret = motion_sense_read(sensor);
} else {
ret = EC_ERROR_BUSY;
}
#endif
return ret;
}
@@ -321,48 +359,26 @@ static int motion_sense_process(struct motion_sensor_t *sensor,
void motion_sense_task(void)
{
int i, ret, wait_us, fifo_flush_needed = 0;
static timestamp_t ts_begin_task, ts_end_task;
timestamp_t ts_begin_task, ts_end_task;
uint8_t *lpc_status;
uint16_t *lpc_data;
uint32_t event;
uint32_t event = 0;
int sample_id = 0;
int rd_cnt;
struct motion_sensor_t *sensor;
#ifdef CONFIG_ACCEL_FIFO
static timestamp_t ts_last_int;
timestamp_t ts_last_int;
#endif
lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS);
lpc_data = (uint16_t *)host_get_memmap(EC_MEMMAP_ACC_DATA);
for (i = 0; i < motion_sensor_count; ++i) {
sensor = &motion_sensors[i];
sensor->state = SENSOR_NOT_INITIALIZED;
sensor->runtime_config.odr = sensor->default_config.odr;
sensor->runtime_config.range = sensor->default_config.range;
}
set_present(lpc_status);
if (chipset_in_state(CHIPSET_STATE_ON)) {
/* Update the sensor current active state to S0. */
for (i = 0; i < motion_sensor_count; ++i) {
sensor = &motion_sensors[i];
sensor->active = SENSOR_ACTIVE_S0;
}
accel_interval = accel_interval_ap_on;
} else {
/* sensor->active already initializes to SENSOR_ACTIVE_S5 */
accel_interval = SUSPEND_SAMPLING_INTERVAL;
}
wait_us = accel_interval;
#ifdef CONFIG_ACCEL_FIFO
ts_last_int = get_time();
#endif
while ((event = task_wait_event(wait_us))) {
do {
ts_begin_task = get_time();
rd_cnt = 0;
for (i = 0; i < motion_sensor_count; ++i) {
@@ -374,7 +390,9 @@ void motion_sense_task(void)
if (sensor->state == SENSOR_NOT_INITIALIZED)
motion_sense_init(sensor);
ts_begin_task = get_time();
ret = motion_sense_process(sensor, event,
&ts_begin_task,
&fifo_flush_needed);
if (ret != EC_SUCCESS)
continue;
@@ -462,8 +480,7 @@ void motion_sense_task(void)
*/
if (wait_us < MIN_MOTION_SENSE_WAIT_TIME)
wait_us = MIN_MOTION_SENSE_WAIT_TIME;
}
} while ((event = task_wait_event(wait_us)));
}
#ifdef CONFIG_ACCEL_FIFO
@@ -561,21 +578,24 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
break;
case MOTIONSENSE_CMD_EC_RATE:
sensor = host_sensor_id_to_motion_sensor(
in->sensor_odr.sensor_num);
if (sensor == NULL)
return EC_RES_INVALID_PARAM;
/*
* Set new sensor sampling rate when AP is on, if the data arg
* has a value.
*/
if (in->ec_rate.data != EC_MOTION_SENSE_NO_VALUE) {
/* Bound the new sampling rate. */
data = in->ec_rate.data;
if (data < MIN_POLLING_INTERVAL_MS)
data = MIN_POLLING_INTERVAL_MS;
accel_interval_ap_on = data * MSEC;
accel_interval = data * MSEC;
motion_sense_set_accel_interval(
sensor,
MAX(in->ec_rate.data * MSEC,
MIN_MOTION_SENSE_WAIT_TIME));
}
out->ec_rate.ret = accel_interval_ap_on / MSEC;
out->ec_rate.ret = sensor->runtime_config.ec_rate / MSEC;
args->response_size = sizeof(out->ec_rate);
break;
@@ -597,14 +617,15 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
in->sensor_odr.data);
return EC_RES_INVALID_PARAM;
}
/*
* To be sure timestamps are calculated properly,
* Send an event to have a timestamp inserted in the
* FIFO.
*/
task_set_event(TASK_ID_MOTIONSENSE,
TASK_EVENT_MOTION_ODR_CHANGE, 0);
}
/* To be sure timestamps are calculated properly,
* Send an event to have a timestamp inserted in the FIFO.
*/
task_set_event(TASK_ID_MOTIONSENSE,
TASK_EVENT_MOTION_ODR_CHANGE, 0);
sensor->drv->get_data_rate(sensor, &data);
/* Save configuration parameter: ODR */
@@ -671,6 +692,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
in->sensor_odr.sensor_num);
if (sensor == NULL)
return EC_RES_INVALID_PARAM;
atomic_add(&sensor->flush_pending, 1);
task_set_event(TASK_ID_MOTIONSENSE,

View File

@@ -1629,7 +1629,13 @@ enum motionsense_command {
/*
* EC Rate command is a setter/getter command for the EC sampling rate
* of all motion sensors in milliseconds.
* in milliseconds.
* It is per sensor, the EC run sample task at the minimum of all
* sensors EC_RATE.
* For sensors without hardware FIFO, EC_RATE should be equals to 1/ODR
* to collect all the sensor samples.
* For sensor with hardware FIFO, EC_RATE is used as the maximal delay
* to process of all motion sensors in milliseconds.
*/
MOTIONSENSE_CMD_EC_RATE = 2,
@@ -1787,16 +1793,14 @@ struct ec_params_motion_sense {
} dump;
/*
* Used for MOTIONSENSE_CMD_EC_RATE and
* MOTIONSENSE_CMD_KB_WAKE_ANGLE.
* Used for MOTIONSENSE_CMD_KB_WAKE_ANGLE.
*/
struct {
/* Data to set or EC_MOTION_SENSE_NO_VALUE to read.
* ec_rate: polling rate in ms.
* kb_wake_angle: angle to wakup AP.
*/
int16_t data;
} ec_rate, kb_wake_angle;
} kb_wake_angle;
/* Used for MOTIONSENSE_CMD_INFO, MOTIONSENSE_CMD_DATA
* and MOTIONSENSE_CMD_PERFORM_CALIB. */
@@ -1805,8 +1809,8 @@ struct ec_params_motion_sense {
} info, data, fifo_flush, perform_calib;
/*
* Used for MOTIONSENSE_CMD_SENSOR_ODR and
* MOTIONSENSE_CMD_SENSOR_RANGE.
* Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR
* and MOTIONSENSE_CMD_SENSOR_RANGE.
*/
struct {
uint8_t sensor_num;
@@ -1818,7 +1822,7 @@ struct ec_params_motion_sense {
/* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */
int32_t data;
} sensor_odr, sensor_range;
} ec_rate, sensor_odr, sensor_range;
/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
struct __attribute__((__packed__)) {

View File

@@ -28,11 +28,35 @@ enum sensor_state {
#define SENSOR_ACTIVE_S0_S3 (SENSOR_ACTIVE_S3 | SENSOR_ACTIVE_S0)
#define SENSOR_ACTIVE_S0_S3_S5 (SENSOR_ACTIVE_S0_S3 | SENSOR_ACTIVE_S5)
/* Events the motion sense task may have to process.*/
#define TASK_EVENT_MOTION_FLUSH_PENDING TASK_EVENT_CUSTOM(1)
#define TASK_EVENT_MOTION_INTERRUPT TASK_EVENT_CUSTOM(2)
#define TASK_EVENT_MOTION_ODR_CHANGE TASK_EVENT_CUSTOM(4)
/* Define sensor sampling interval in suspend. */
#ifdef CONFIG_GESTURE_DETECTION
#define SUSPEND_SAMPLING_INTERVAL (CONFIG_GESTURE_SAMPLING_INTERVAL_MS * MSEC)
#elif defined(CONFIG_ACCEL_FIFO)
#define SUSPEND_SAMPLING_INTERVAL (1000 * MSEC)
#else
#define SUSPEND_SAMPLING_INTERVAL (100 * MSEC)
#endif
/* Minimum time in between running motion sense task loop. */
#define MIN_MOTION_SENSE_WAIT_TIME (3 * MSEC)
#define MAX_MOTION_SENSE_WAIT_TIME (60000 * MSEC)
struct motion_data_t {
/* data rate the sensor will measure, in mHz */
int odr;
/* range of measurement in SI */
int range;
/* delay between collection by EC, in ms.
* For non FIFO sensor, should be nead 1e6/odr to
* collect events.
* For sensor with FIFO, can be much longer.
*/
unsigned ec_rate;
};
struct motion_sensor_t {
@@ -68,11 +92,26 @@ struct motion_sensor_t {
* FIFO info has been transmitted.
*/
uint16_t lost;
/*
* Time since iast collection:
* For sensor with hardware FIFO, time since last sample
* has move from the hardware FIFO to the FIFO (used if fifo rate != 0).
* For sensor without FIFO, time since the last event was collect
* from sensor registers.
*/
int last_collection;
};
/* Defined at board level. */
extern struct motion_sensor_t motion_sensors[];
extern const unsigned int motion_sensor_count;
extern const unsigned motion_sensor_count;
/* For testing purposes: export the sampling interval. */
extern unsigned accel_interval;
int motion_sense_set_accel_interval(
struct motion_sensor_t *driving_sensor,
unsigned data);
/*
* Priority of the motion sense resume/suspend hooks, to be sure associated
@@ -103,10 +142,4 @@ void motion_sense_fifo_add_unit(struct ec_response_motion_sensor_data *data,
const struct motion_sensor_t *sensor);
#endif
/* Events the motion sense task may have to process.*/
#define TASK_EVENT_MOTION_FLUSH_PENDING TASK_EVENT_CUSTOM(1)
#define TASK_EVENT_MOTION_INTERRUPT TASK_EVENT_CUSTOM(2)
#define TASK_EVENT_MOTION_ODR_CHANGE TASK_EVENT_CUSTOM(4)
#endif /* __CROS_EC_MOTION_SENSE_H */

View File

@@ -19,6 +19,18 @@
#include "timer.h"
#include "util.h"
/*
* Period in us for the motion task period.
* The task will read the vectors at that interval
*/
#define TEST_LID_EC_RATE (SUSPEND_SAMPLING_INTERVAL / 10)
/*
* Time in ms to wait for the task to read the vectors.
*/
#define TEST_LID_SLEEP_RATE (TEST_LID_EC_RATE / (5 * MSEC))
/*****************************************************************************/
/* Mock functions */
static int accel_init(const struct motion_sensor_t *s)
@@ -109,10 +121,11 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &base_standard_ref,
.default_config = {
.odr = 119000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
{.name = "base",
{.name = "lid",
.active_mask = SENSOR_ACTIVE_S0,
.chip = MOTIONSENSE_CHIP_KXCJ9,
.type = MOTIONSENSE_TYPE_ACCEL,
@@ -124,7 +137,8 @@ struct motion_sensor_t motion_sensors[] = {
.rot_standard_ref = &lid_standard_ref,
.default_config = {
.odr = 119000,
.range = 2
.range = 2,
.ec_rate = SUSPEND_SAMPLING_INTERVAL,
}
},
};
@@ -132,19 +146,38 @@ const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors);
/*****************************************************************************/
/* Test utilities */
static void wait_for_valid_sample(void)
{
uint8_t sample;
uint8_t *lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS);
sample = *lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
msleep(TEST_LID_EC_RATE/MSEC);
task_wake(TASK_ID_MOTIONSENSE);
while ((*lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK) == sample)
msleep(TEST_LID_SLEEP_RATE);
}
static int test_lid_angle(void)
{
uint8_t *lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS);
uint8_t sample;
struct motion_sensor_t *base = &motion_sensors[0];
struct motion_sensor_t *lid = &motion_sensors[1];
/* Go to S3 state */
hook_notify(HOOK_CHIPSET_STARTUP);
TEST_ASSERT(accel_interval == SUSPEND_SAMPLING_INTERVAL);
TEST_ASSERT(motion_sensors[0].active == SENSOR_ACTIVE_S5);
/* Go to S0 state */
hook_notify(HOOK_CHIPSET_RESUME);
TEST_ASSERT(accel_interval == SUSPEND_SAMPLING_INTERVAL);
TEST_ASSERT(motion_sensors[0].active == SENSOR_ACTIVE_S0);
motion_sense_set_accel_interval(base, TEST_LID_EC_RATE);
TEST_ASSERT(accel_interval == TEST_LID_EC_RATE);
motion_sense_set_accel_interval(lid, TEST_LID_EC_RATE);
TEST_ASSERT(accel_interval == TEST_LID_EC_RATE);
/*
* Set the base accelerometer as if it were sitting flat on a desk
@@ -156,32 +189,28 @@ static int test_lid_angle(void)
lid->xyz[X] = 0;
lid->xyz[Y] = 0;
lid->xyz[Z] = 1000;
sample = *lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
/* Initial wake up, like init does */
task_wake(TASK_ID_MOTIONSENSE);
msleep(5);
/* wait for the EC sampling period to expire */
msleep(TEST_LID_EC_RATE/MSEC);
task_wake(TASK_ID_MOTIONSENSE);
while ((*lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK) == sample)
msleep(5);
wait_for_valid_sample();
TEST_ASSERT(motion_lid_get_angle() == 0);
/* Set lid open to 90 degrees. */
lid->xyz[X] = -1000;
lid->xyz[Y] = 0;
lid->xyz[Z] = 0;
sample = *lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
task_wake(TASK_ID_MOTIONSENSE);
while ((*lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK) == sample)
msleep(5);
wait_for_valid_sample();
TEST_ASSERT(motion_lid_get_angle() == 90);
/* Set lid open to 225. */
lid->xyz[X] = 500;
lid->xyz[Y] = 0;
lid->xyz[Z] = -500;
sample = *lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
task_wake(TASK_ID_MOTIONSENSE);
while ((*lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK) == sample)
msleep(5);
wait_for_valid_sample();
TEST_ASSERT(motion_lid_get_angle() == 225);
/*
@@ -191,10 +220,7 @@ static int test_lid_angle(void)
base->xyz[X] = 0;
base->xyz[Y] = 1000;
base->xyz[Z] = 0;
sample = *lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
task_wake(TASK_ID_MOTIONSENSE);
while ((*lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK) == sample)
msleep(5);
wait_for_valid_sample();
TEST_ASSERT(motion_lid_get_angle() == LID_ANGLE_UNRELIABLE);
/*
@@ -207,10 +233,7 @@ static int test_lid_angle(void)
lid->xyz[X] = -500;
lid->xyz[Y] = -400;
lid->xyz[Z] = -300;
sample = *lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
task_wake(TASK_ID_MOTIONSENSE);
while ((*lpc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK) == sample)
msleep(5);
wait_for_valid_sample();
TEST_ASSERT(motion_lid_get_angle() == 180);
return EC_SUCCESS;