summaryrefslogtreecommitdiff
path: root/common/motion_sense.c
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-03-24 10:03:56 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-04-05 03:25:47 +0000
commit529548208cad436232cfba2c0b802523ddaf5383 (patch)
tree74e7b6febda2d30599ab72204befc8d61e0c3d7c /common/motion_sense.c
parentf06ad7e2ab4fa1a03c2e48a8bca3fdf2abbdffa9 (diff)
downloadchrome-ec-529548208cad436232cfba2c0b802523ddaf5383.tar.gz
accel: add host command to modify accel params and add ectool command
Created a host command to set/get various motion sensor parameters and added an ectool command to use that host command. The host command is created such that the first argument is a sub-command. Sub-commands created include: dump: dumps all current motion sensor data info: returns general information about each motion sensor ec_rate: set/get the EC sampling rate of sensors sensor_range: set/get the sensor range (ie +/- 2G,4G,8G) sensor_odr: set/get the sensor output data rate (ie 50Hz, 100Hz, ...) For sensor_range and sensor_odr parameters, since the host doesn't know what are valid values for the parameter, the host can specify to round up or down to the nearest valid value. For example, the host can specify to set the output data rate to at least 100Hz, and the EC will return the closest valid output data rate that is at least 100Hz. BUG=chrome-os-partner:27321 BRANCH=rambi TEST=Test on a glimmer using ectool from vt-2 prompt: > ectool motionsense help Usage: motionsense - dump all motion data motionsense info NUM - print sensor info motionsense ec_rate [RATE_MS] - set/get sample rate motionsense odr NUM [ODR [ROUNDUP]] - set/get sensor ODR motionsense range NUM [RANGE [ROUNDUP]]- set/get sensor range > > ectool motionsense Sensor 0: 0, 0, 1024 Sensor 1: 1024, 0, 0 Sensor 2: None > ectool motionsense info 0 Type: accel Location: base Chip: kxcj9 > ectool motionsense ec_rate 10 > ectool motionsense ec_rate 1000 1000 > ectool motionsense odr 0 100000 > ectool motionsense odr 0 40000 1 50000 > ectool motionsense range 0 8 8 After running this I verified on the EC console that all the parameters were set appropriately. I tested the EC sampling rate was 1000ms by running lidangle on and making sure samples were displayed roughly every second. I verified the sensor odr and range by defining CONFIG_CMD_ACCELS and typing: > accelrange 0 8 > accelrate 0 50000 Change-Id: I444e2f0eafabd607f1c7aa78b5c4e91f6cb06387 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/192064 Reviewed-on: https://chromium-review.googlesource.com/193307 Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'common/motion_sense.c')
-rw-r--r--common/motion_sense.c176
1 files changed, 165 insertions, 11 deletions
diff --git a/common/motion_sense.c b/common/motion_sense.c
index 5dad6db1cf..8629fa7588 100644
--- a/common/motion_sense.c
+++ b/common/motion_sense.c
@@ -30,9 +30,13 @@ static vector_3_t acc_lid_host, acc_base_host;
static float lid_angle_deg;
static int lid_angle_is_reliable;
+/* Bounds for setting the sensor polling interval. */
+#define MIN_POLLING_INTERVAL_MS 5
+#define MAX_POLLING_INTERVAL_MS 1000
+
/* Accelerometer polling intervals based on chipset state. */
-#define ACCEL_INTERVAL_AP_ON_MS 10
-#define ACCEL_INTERVAL_AP_SUSPEND_MS 100
+static int accel_interval_ap_on_ms = 10;
+static const int accel_interval_ap_suspend_ms = 100;
/*
* Angle threshold for how close the hinge aligns with gravity before
@@ -43,7 +47,7 @@ static int lid_angle_is_reliable;
#define HINGE_ALIGNED_WITH_GRAVITY_THRESHOLD 0.96593F
/* Sampling interval for measuring acceleration and calculating lid angle. */
-static int accel_interval_ms = ACCEL_INTERVAL_AP_SUSPEND_MS;
+static int accel_interval_ms;
#ifdef CONFIG_CMD_LID_ANGLE
static int accel_disp;
@@ -153,19 +157,17 @@ void motion_get_accel_base(vector_3_t *v)
}
#endif
-/* Lower accel polling rate on chipset suspend. */
-static void set_slow_accel_polling(void)
+static void set_ap_suspend_polling(void)
{
- accel_interval_ms = ACCEL_INTERVAL_AP_SUSPEND_MS;
+ accel_interval_ms = accel_interval_ap_suspend_ms;
}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, set_slow_accel_polling, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, set_ap_suspend_polling, HOOK_PRIO_DEFAULT);
-/* Raise accel polling rate on chipset resume. */
-static void set_fast_accel_polling(void)
+static void set_ap_on_polling(void)
{
- accel_interval_ms = ACCEL_INTERVAL_AP_ON_MS;
+ accel_interval_ms = accel_interval_ap_on_ms;
}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, set_fast_accel_polling, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_CHIPSET_RESUME, set_ap_on_polling, HOOK_PRIO_DEFAULT);
void motion_sense_task(void)
@@ -180,6 +182,14 @@ void motion_sense_task(void)
lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS);
lpc_data = (uint16_t *)host_get_memmap(EC_MEMMAP_ACC_DATA);
+ /*
+ * TODO(crosbug.com/p/27320): The motion_sense task currently assumes
+ * one configuration of motion sensors. Namely, it assumes there is
+ * one accel in the base, one in the lid, and they both use the same
+ * driver. Eventually, all of these assumptions will have to be removed
+ * when we have other configurations of motion sensors.
+ */
+
/* Initialize accelerometers. */
ret = accel_init(ACCEL_LID);
ret |= accel_init(ACCEL_BASE);
@@ -191,6 +201,17 @@ void motion_sense_task(void)
return;
}
+ /* Initialize sampling interval. */
+ accel_interval_ms = accel_interval_ap_suspend_ms;
+
+ /* Set default accelerometer parameters. */
+ accel_set_range(ACCEL_LID, 2, 1);
+ accel_set_range(ACCEL_BASE, 2, 1);
+ accel_set_resolution(ACCEL_LID, 12, 1);
+ accel_set_resolution(ACCEL_BASE, 12, 1);
+ accel_set_datarate(ACCEL_LID, 100000, 1);
+ accel_set_datarate(ACCEL_BASE, 100000, 1);
+
/* Write to status byte to represent that accelerometers are present. */
*lpc_status |= EC_MEMMAP_ACC_STATUS_PRESENCE_BIT;
@@ -299,6 +320,139 @@ void accel_int_base(enum gpio_signal signal)
}
/*****************************************************************************/
+/* Host commands */
+
+static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_motion_sense *in = args->params;
+ struct ec_response_motion_sense *out = args->response;
+ int id, data;
+
+ switch (in->cmd) {
+ case MOTIONSENSE_CMD_DUMP:
+ /*
+ * TODO(crosbug.com/p/27320): Need to remove hard coding and
+ * use some motion_sense data structure from the board file to
+ * help fill in this response.
+ */
+ out->dump.sensor_presence[0] = 1;
+ out->dump.sensor_presence[1] = 1;
+ out->dump.sensor_presence[2] = 0;
+ out->dump.data[0] = acc_base_host[X];
+ out->dump.data[1] = acc_base_host[Y];
+ out->dump.data[2] = acc_base_host[Z];
+ out->dump.data[3] = acc_lid_host[X];
+ out->dump.data[4] = acc_lid_host[Y];
+ out->dump.data[5] = acc_lid_host[Z];
+
+ args->response_size = sizeof(out->dump);
+ break;
+
+ case MOTIONSENSE_CMD_INFO:
+ /*
+ * TODO(crosbug.com/p/27320): Need to remove hard coding and
+ * use some motion_sense data structure from the board file to
+ * help fill in this response.
+ */
+ switch (in->sensor_odr.sensor_num) {
+ case ACCEL_BASE:
+ out->info.type = MOTIONSENSE_TYPE_ACCEL;
+ out->info.location = MOTIONSENSE_LOC_BASE;
+ out->info.chip = MOTIONSENSE_CHIP_KXCJ9;
+ break;
+ case ACCEL_LID:
+ out->info.type = MOTIONSENSE_TYPE_ACCEL;
+ out->info.location = MOTIONSENSE_LOC_LID;
+ out->info.chip = MOTIONSENSE_CHIP_KXCJ9;
+ break;
+ default:
+ return EC_RES_INVALID_PARAM;
+ }
+
+ args->response_size = sizeof(out->info);
+ break;
+
+ case MOTIONSENSE_CMD_EC_RATE:
+ /*
+ * 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) {
+ if (in->ec_rate.data >= MIN_POLLING_INTERVAL_MS &&
+ in->ec_rate.data <= MAX_POLLING_INTERVAL_MS) {
+ accel_interval_ap_on_ms = in->ec_rate.data;
+ accel_interval_ms = accel_interval_ap_on_ms;
+ } else {
+ CPRINTF("[%T MS bad EC sampling rate %d]\n",
+ in->ec_rate.data);
+ return EC_RES_INVALID_PARAM;
+ }
+ }
+
+ out->ec_rate.ret = accel_interval_ap_on_ms;
+
+ args->response_size = sizeof(out->ec_rate);
+ break;
+
+ case MOTIONSENSE_CMD_SENSOR_ODR:
+ /* Verify sensor number is valid. */
+ if (in->sensor_odr.sensor_num >= ACCEL_COUNT)
+ return EC_RES_INVALID_PARAM;
+
+ id = in->sensor_odr.sensor_num;
+
+ /* Set new datarate if the data arg has a value. */
+ if (in->sensor_odr.data != EC_MOTION_SENSE_NO_VALUE) {
+ if (accel_set_datarate(id, in->sensor_odr.data,
+ in->sensor_odr.roundup) != EC_SUCCESS) {
+ CPRINTF("[%T MS bad sensor rate %d]\n",
+ in->sensor_odr.data);
+ return EC_RES_INVALID_PARAM;
+ }
+ }
+
+ accel_get_datarate(id, &data);
+ out->sensor_odr.ret = data;
+
+ args->response_size = sizeof(out->sensor_odr);
+ break;
+
+ case MOTIONSENSE_CMD_SENSOR_RANGE:
+ /* Verify sensor number is valid. */
+ if (in->sensor_odr.sensor_num >= ACCEL_COUNT)
+ return EC_RES_INVALID_PARAM;
+
+ id = in->sensor_odr.sensor_num;
+
+ /* Set new datarate if the data arg has a value. */
+ if (in->sensor_range.data != EC_MOTION_SENSE_NO_VALUE) {
+ if (accel_set_range(id, in->sensor_range.data,
+ in->sensor_range.roundup) != EC_SUCCESS) {
+ CPRINTF("[%T MS bad sensor range %d]\n",
+ in->sensor_range.data);
+ return EC_RES_INVALID_PARAM;
+ }
+ }
+
+ accel_get_range(id, &data);
+ out->sensor_range.ret = data;
+
+ args->response_size = sizeof(out->sensor_range);
+ break;
+
+ default:
+ CPRINTF("[%T MS bad cmd 0x%x]\n", in->cmd);
+ return EC_RES_INVALID_PARAM;
+ }
+
+ return EC_RES_SUCCESS;
+}
+
+DECLARE_HOST_COMMAND(EC_CMD_MOTION_SENSE_CMD,
+ host_cmd_motion_sense,
+ EC_VER_MASK(0));
+
+/*****************************************************************************/
/* Console commands */
#ifdef CONFIG_CMD_LID_ANGLE
static int command_ctrl_print_lid_angle_calcs(int argc, char **argv)