diff options
-rw-r--r-- | common/motion_calibrate.c | 1 | ||||
-rw-r--r-- | common/motion_sense.c | 149 | ||||
-rw-r--r-- | driver/accel_kxcj9.c | 219 | ||||
-rw-r--r-- | driver/accel_kxcj9.h | 27 | ||||
-rw-r--r-- | driver/accelgyro_lsm6ds0.c | 139 | ||||
-rw-r--r-- | driver/accelgyro_lsm6ds0.h | 14 | ||||
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | include/accelerometer.h | 87 | ||||
-rw-r--r-- | include/accelgyro.h | 111 | ||||
-rw-r--r-- | include/ec_commands.h | 1 | ||||
-rw-r--r-- | include/motion_sense.h | 16 | ||||
-rw-r--r-- | test/math_util.c | 39 | ||||
-rw-r--r-- | test/motion_sense.c | 79 |
13 files changed, 496 insertions, 387 deletions
diff --git a/common/motion_calibrate.c b/common/motion_calibrate.c index 9819f12d28..f0b7d5ade3 100644 --- a/common/motion_calibrate.c +++ b/common/motion_calibrate.c @@ -5,7 +5,6 @@ /* Motion sensor calibration code. */ -#include "accelerometer.h" #include "common.h" #include "console.h" #include "math_util.h" diff --git a/common/motion_sense.c b/common/motion_sense.c index 3564c06d4e..0dd0b7e07a 100644 --- a/common/motion_sense.c +++ b/common/motion_sense.c @@ -5,7 +5,7 @@ /* Motion sense module to read from various motion sensors. */ -#include "accelerometer.h" +#include "accelgyro.h" #include "common.h" #include "console.h" #include "hooks.h" @@ -24,6 +24,9 @@ /* Minimum time in between running motion sense task loop. */ #define MIN_MOTION_SENSE_WAIT_TIME (1 * MSEC) +static const struct motion_sensor_t *base; +static const struct motion_sensor_t *lid; + /* Current acceleration vectors and current lid angle. */ static vector_3_t acc_lid_raw, acc_lid, acc_base; static vector_3_t acc_lid_host, acc_base_host; @@ -186,6 +189,7 @@ void motion_sense_task(void) uint8_t *lpc_status; uint16_t *lpc_data; int sample_id = 0; + int i; lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS); lpc_data = (uint16_t *)host_get_memmap(EC_MEMMAP_ACC_DATA); @@ -193,14 +197,25 @@ void motion_sense_task(void) /* * 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. + * one accel in the base, one in the lid. Eventually, these + * assumptions will have to be removed when we have other + * configurations of motion sensors. */ + for (i = 0; i < motion_sensor_count; ++i) { + if (motion_sensors[i].location == LOCATION_LID) + lid = &motion_sensors[i]; + else if (motion_sensors[i].location == LOCATION_BASE) + base = &motion_sensors[i]; + } + + if (lid == NULL || base == NULL) { + CPRINTS("Invalid motion_sensors list, lid and base required"); + return; + } /* Initialize accelerometers. */ - ret = accel_init(ACCEL_LID); - ret |= accel_init(ACCEL_BASE); + ret = lid->drv->init(lid->drv_data, lid->i2c_addr); + ret |= base->drv->init(base->drv_data, base->i2c_addr); /* If accelerometers do not initialize, then end task. */ if (ret != EC_SUCCESS) { @@ -212,12 +227,12 @@ void motion_sense_task(void) 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); + lid->drv->set_range(lid->drv_data, 2, 1); + lid->drv->set_resolution(lid->drv_data, 12, 1); + lid->drv->set_datarate(lid->drv_data, 100000, 1); + base->drv->set_range(base->drv_data, 2, 1); + base->drv->set_resolution(base->drv_data, 12, 1); + base->drv->set_datarate(base->drv_data, 100000, 1); /* Write to status byte to represent that accelerometers are present. */ *lpc_status |= EC_MEMMAP_ACC_STATUS_PRESENCE_BIT; @@ -226,9 +241,9 @@ void motion_sense_task(void) ts0 = get_time(); /* Read all accelerations. */ - accel_read(ACCEL_LID, &acc_lid_raw[X], &acc_lid_raw[Y], + lid->drv->read(lid->drv_data, &acc_lid_raw[X], &acc_lid_raw[Y], &acc_lid_raw[Z]); - accel_read(ACCEL_BASE, &acc_base[X], &acc_base[Y], + base->drv->read(base->drv_data, &acc_base[X], &acc_base[Y], &acc_base[Z]); /* @@ -333,32 +348,27 @@ void accel_int_base(enum gpio_signal signal) /*****************************************************************************/ /* Host commands */ -/** - * Temporary function to map host sensor IDs to EC sensor IDs. - * - * TODO(crosbug.com/p/27320): Eventually we need a board specific table - * specifying which motion sensors are attached and which driver to use to - * access that sensor. Once we have this, this function should be able to go - * away. - */ -static int host_sensor_id_to_ec_sensor_id(int host_id) +/* Function to map host sensor IDs to motion sensor. */ +static const struct motion_sensor_t + *host_sensor_id_to_motion_sensor(int host_id) { switch (host_id) { case EC_MOTION_SENSOR_ACCEL_BASE: - return ACCEL_BASE; + return base; case EC_MOTION_SENSOR_ACCEL_LID: - return ACCEL_LID; + return lid; } /* If no match then the EC currently doesn't support ID received. */ - return -1; + return NULL; } 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; + const struct motion_sensor_t *sensor; + int data; switch (in->cmd) { case MOTIONSENSE_CMD_DUMP: @@ -390,24 +400,25 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) * use some motion_sense data structure from the board file to * help fill in this response. */ - id = host_sensor_id_to_ec_sensor_id(in->sensor_odr.sensor_num); - if (id < 0) + sensor = host_sensor_id_to_motion_sensor( + in->sensor_odr.sensor_num); + if (sensor == NULL) return EC_RES_INVALID_PARAM; - switch (id) { - case ACCEL_BASE: + if (sensor->drv->sensor_type == SENSOR_ACCELEROMETER) out->info.type = MOTIONSENSE_TYPE_ACCEL; + else if (sensor->drv->sensor_type == SENSOR_GYRO) + out->info.type = MOTIONSENSE_TYPE_GYRO; + + if (sensor->location == LOCATION_BASE) out->info.location = MOTIONSENSE_LOC_BASE; - out->info.chip = MOTIONSENSE_CHIP_KXCJ9; - break; - case ACCEL_LID: - out->info.type = MOTIONSENSE_TYPE_ACCEL; + else if (sensor->location == LOCATION_LID) out->info.location = MOTIONSENSE_LOC_LID; + + if (sensor->drv->chip_type == CHIP_KXCJ9) out->info.chip = MOTIONSENSE_CHIP_KXCJ9; - break; - default: - return EC_RES_INVALID_PARAM; - } + else if (sensor->drv->chip_type == CHIP_LSM6DS0) + out->info.chip = MOTIONSENSE_CHIP_LSM6DS0; args->response_size = sizeof(out->info); break; @@ -436,21 +447,24 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_SENSOR_ODR: /* Verify sensor number is valid. */ - id = host_sensor_id_to_ec_sensor_id(in->sensor_odr.sensor_num); - if (id < 0) + sensor = host_sensor_id_to_motion_sensor( + in->sensor_odr.sensor_num); + if (sensor == NULL) return EC_RES_INVALID_PARAM; /* 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) { + if (sensor->drv->set_datarate(sensor->drv_data, + in->sensor_odr.data, + in->sensor_odr.roundup) + != EC_SUCCESS) { CPRINTS("MS bad sensor rate %d", in->sensor_odr.data); return EC_RES_INVALID_PARAM; } } - accel_get_datarate(id, &data); + sensor->drv->get_datarate(sensor->drv_data, &data); out->sensor_odr.ret = data; args->response_size = sizeof(out->sensor_odr); @@ -458,21 +472,24 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_SENSOR_RANGE: /* Verify sensor number is valid. */ - id = host_sensor_id_to_ec_sensor_id(in->sensor_odr.sensor_num); - if (id < 0) + sensor = host_sensor_id_to_motion_sensor( + in->sensor_odr.sensor_num); + if (sensor == NULL) return EC_RES_INVALID_PARAM; /* 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) { + if (sensor->drv->set_range(sensor->drv_data, + in->sensor_range.data, + in->sensor_range.roundup) + != EC_SUCCESS) { CPRINTS("MS bad sensor range %d", in->sensor_range.data); return EC_RES_INVALID_PARAM; } } - accel_get_range(id, &data); + sensor->drv->get_range(sensor->drv_data, &data); out->sensor_range.ret = data; args->response_size = sizeof(out->sensor_range); @@ -548,14 +565,16 @@ static int command_accelrange(int argc, char **argv) { char *e; int id, data, round = 1; + struct motion_sensor_t *sensor; if (argc < 2 || argc > 4) return EC_ERROR_PARAM_COUNT; /* First argument is sensor id. */ id = strtoi(argv[1], &e, 0); - if (*e || id < 0 || id > ACCEL_COUNT) + if (*e || id < 0 || id > motion_sensor_count) return EC_ERROR_PARAM1; + sensor = motion_sensors[id]; if (argc >= 3) { /* Second argument is data to write. */ @@ -574,10 +593,12 @@ static int command_accelrange(int argc, char **argv) * Write new range, if it returns invalid arg, then return * a parameter error. */ - if (accel_set_range(id, data, round) == EC_ERROR_INVAL) + if (sensor->drv->set_range(sensor->drv_data, + data, + round) == EC_ERROR_INVAL) return EC_ERROR_PARAM2; } else { - accel_get_range(id, &data); + sensor->drv->get_range(sensor->drv_data, &data); ccprintf("Range for sensor %d: %d\n", id, data); } @@ -591,14 +612,16 @@ static int command_accelresolution(int argc, char **argv) { char *e; int id, data, round = 1; + struct motion_sensor_t *sensor; if (argc < 2 || argc > 4) return EC_ERROR_PARAM_COUNT; /* First argument is sensor id. */ id = strtoi(argv[1], &e, 0); - if (*e || id < 0 || id > ACCEL_COUNT) + if (*e || id < 0 || id > motion_sensor_count) return EC_ERROR_PARAM1; + sensor = motion_sensors[id]; if (argc >= 3) { /* Second argument is data to write. */ @@ -617,10 +640,11 @@ static int command_accelresolution(int argc, char **argv) * Write new resolution, if it returns invalid arg, then * return a parameter error. */ - if (accel_set_resolution(id, data, round) == EC_ERROR_INVAL) + if (sensor->drv->set_resolution(sensor->drv_data, data, round) + == EC_ERROR_INVAL) return EC_ERROR_PARAM2; } else { - accel_get_resolution(id, &data); + sensor->drv->get_resolution(sensor->drv_data, &data); ccprintf("Resolution for sensor %d: %d\n", id, data); } @@ -634,14 +658,16 @@ static int command_acceldatarate(int argc, char **argv) { char *e; int id, data, round = 1; + struct motion_sensor_t *sensor; if (argc < 2 || argc > 4) return EC_ERROR_PARAM_COUNT; /* First argument is sensor id. */ id = strtoi(argv[1], &e, 0); - if (*e || id < 0 || id > ACCEL_COUNT) + if (*e || id < 0 || id > motion_sensor_count) return EC_ERROR_PARAM1; + sensor = motion_sensors[id]; if (argc >= 3) { /* Second argument is data to write. */ @@ -660,10 +686,11 @@ static int command_acceldatarate(int argc, char **argv) * Write new data rate, if it returns invalid arg, then * return a parameter error. */ - if (accel_set_datarate(id, data, round) == EC_ERROR_INVAL) + if (sensor->drv->set_datarate(sensor->drv_data, data, round) + == EC_ERROR_INVAL) return EC_ERROR_PARAM2; } else { - accel_get_datarate(id, &data); + sensor->drv->get_datarate(sensor->drv_data, &data); ccprintf("Data rate for sensor %d: %d\n", id, data); } @@ -678,21 +705,23 @@ static int command_accelerometer_interrupt(int argc, char **argv) { char *e; int id, thresh; + struct motion_sensor_t *sensor; if (argc != 3) return EC_ERROR_PARAM_COUNT; /* First argument is id. */ id = strtoi(argv[1], &e, 0); - if (*e || id < 0 || id >= ACCEL_COUNT) + if (*e || id < 0 || id >= motion_sensor_count) return EC_ERROR_PARAM1; + sensor = motion_sensors[id]; /* Second argument is interrupt threshold. */ thresh = strtoi(argv[2], &e, 0); if (*e) return EC_ERROR_PARAM2; - accel_set_interrupt(id, thresh); + sensor->drv->set_interrupt(drv_data, thresh); return EC_SUCCESS; } diff --git a/driver/accel_kxcj9.c b/driver/accel_kxcj9.c index 1dc491151b..de05f85559 100644 --- a/driver/accel_kxcj9.c +++ b/driver/accel_kxcj9.c @@ -5,7 +5,7 @@ /* KXCJ9 gsensor module for Chrome EC */ -#include "accelerometer.h" +#include "accelgyro.h" #include "common.h" #include "console.h" #include "driver/accel_kxcj9.h" @@ -31,20 +31,20 @@ struct accel_param_pair { }; /* List of range values in +/-G's and their associated register values. */ -const struct accel_param_pair ranges[] = { +static const struct accel_param_pair ranges[] = { {2, KXCJ9_GSEL_2G}, {4, KXCJ9_GSEL_4G}, {8, KXCJ9_GSEL_8G_14BIT} }; /* List of resolution values in bits and their associated register values. */ -const struct accel_param_pair resolutions[] = { +static const struct accel_param_pair resolutions[] = { {8, KXCJ9_RES_8BIT}, {12, KXCJ9_RES_12BIT} }; /* List of ODR values in mHz and their associated register values. */ -const struct accel_param_pair datarates[] = { +static const struct accel_param_pair datarates[] = { {781, KXCJ9_OSA_0_781HZ}, {1563, KXCJ9_OSA_1_563HZ}, {3125, KXCJ9_OSA_3_125HZ}, @@ -59,24 +59,6 @@ const struct accel_param_pair datarates[] = { {1600000, KXCJ9_OSA_1600_HZ} }; -/* Current range of each accelerometer. The value is an index into ranges[]. */ -static int sensor_range[ACCEL_COUNT] = {0, 0}; - -/* - * Current resolution of each accelerometer. The value is an index into - * resolutions[]. - */ -static int sensor_resolution[ACCEL_COUNT] = {1, 1}; - -/* - * Current output data rate of each accelerometer. The value is an index into - * datarates[]. - */ -static int sensor_datarate[ACCEL_COUNT] = {6, 6}; - - -static struct mutex accel_mutex[ACCEL_COUNT]; - /** * Find index into a accel_param_pair that matches the given engineering value * passed in. The round_up flag is used to specify whether to round up or down. @@ -126,12 +108,12 @@ static int raw_write8(const int addr, const int reg, int data) * * Note: This is intended to be called in a pair with enable_sensor(). * - * @id Sensor index + * @data Pointer to motion sensor data * @ctrl1 Pointer to location to store KXCJ9_CTRL1 register after disabling * * @return EC_SUCCESS if successful, EC_ERROR_* otherwise */ -static int disable_sensor(const enum accel_id id, int *ctrl1) +static int disable_sensor(struct kxcj9_data *data, int *ctrl1) { int ret; @@ -139,7 +121,7 @@ static int disable_sensor(const enum accel_id id, int *ctrl1) * Read the current state of the ctrl1 register so that we can restore * it later. */ - ret = raw_read8(accel_addr[id], KXCJ9_CTRL1, ctrl1); + ret = raw_read8(data->accel_addr, KXCJ9_CTRL1, ctrl1); if (ret != EC_SUCCESS) return ret; @@ -147,13 +129,13 @@ static int disable_sensor(const enum accel_id id, int *ctrl1) * Before disabling the sensor, acquire mutex to prevent another task * from attempting to access accel parameters until we enable sensor. */ - mutex_lock(&accel_mutex[id]); + mutex_lock(&data->accel_mutex); /* Disable sensor. */ *ctrl1 &= ~KXCJ9_CTRL1_PC1; - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, *ctrl1); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, *ctrl1); if (ret != EC_SUCCESS) { - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); return ret; } @@ -165,178 +147,166 @@ static int disable_sensor(const enum accel_id id, int *ctrl1) * * Note: This is intended to be called in a pair with disable_sensor(). * - * @id Sensor index + * @data Pointer to motion sensor data * @ctrl1 Value of KXCJ9_CTRL1 register to write to sensor * * @return EC_SUCCESS if successful, EC_ERROR_* otherwise */ -static int enable_sensor(const enum accel_id id, const int ctrl1) +static int enable_sensor(struct kxcj9_data *data, const int ctrl1) { int i, ret; for (i = 0; i < SENSOR_ENABLE_ATTEMPTS; i++) { /* Enable accelerometer based on ctrl1 value. */ - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, ctrl1 | KXCJ9_CTRL1_PC1); /* On first success, we are done. */ if (ret == EC_SUCCESS) { - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); return EC_SUCCESS; } - } /* Release mutex. */ - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); /* Cannot enable accel, print warning and return an error. */ - CPRINTF("Error trying to enable accelerometer %d\n", id); + CPRINTF("Error trying to enable accelerometer\n"); return ret; } -int accel_set_range(const enum accel_id id, const int range, const int rnd) +static int accel_set_range(void *drv_data, + const int range, + const int rnd) { int ret, ctrl1, ctrl1_new, index; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Find index for interface pair matching the specified range. */ index = find_param_index(range, rnd, ranges, ARRAY_SIZE(ranges)); /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; /* Determine new value of CTRL1 reg and attempt to write it. */ ctrl1_new = (ctrl1 & ~KXCJ9_GSEL_ALL) | ranges[index].reg; - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, ctrl1_new); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, ctrl1_new); /* If successfully written, then save the range. */ if (ret == EC_SUCCESS) { - sensor_range[id] = index; + data->sensor_range = index; ctrl1 = ctrl1_new; } /* Re-enable the sensor. */ - if (enable_sensor(id, ctrl1) != EC_SUCCESS) + if (enable_sensor(data, ctrl1) != EC_SUCCESS) return EC_ERROR_UNKNOWN; return ret; } -int accel_get_range(const enum accel_id id, int * const range) +static int accel_get_range(void *drv_data, int * const range) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - - *range = ranges[sensor_range[id]].val; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; + *range = ranges[data->sensor_range].val; return EC_SUCCESS; } -int accel_set_resolution(const enum accel_id id, const int res, const int rnd) +static int accel_set_resolution(void *drv_data, + const int res, + const int rnd) { int ret, ctrl1, ctrl1_new, index; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Find index for interface pair matching the specified resolution. */ index = find_param_index(res, rnd, resolutions, ARRAY_SIZE(resolutions)); /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; /* Determine new value of CTRL1 reg and attempt to write it. */ ctrl1_new = (ctrl1 & ~KXCJ9_RES_12BIT) | resolutions[index].reg; - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, ctrl1_new); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, ctrl1_new); /* If successfully written, then save the range. */ if (ret == EC_SUCCESS) { - sensor_resolution[id] = index; + data->sensor_resolution = index; ctrl1 = ctrl1_new; } /* Re-enable the sensor. */ - if (enable_sensor(id, ctrl1) != EC_SUCCESS) + if (enable_sensor(data, ctrl1) != EC_SUCCESS) return EC_ERROR_UNKNOWN; return ret; } -int accel_get_resolution(const enum accel_id id, int * const res) +static int accel_get_resolution(void *drv_data, int * const res) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - - *res = resolutions[sensor_resolution[id]].val; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; + *res = resolutions[data->sensor_resolution].val; return EC_SUCCESS; } -int accel_set_datarate(const enum accel_id id, const int rate, const int rnd) +static int accel_set_datarate(void *drv_data, + const int rate, + const int rnd) { int ret, ctrl1, index; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Find index for interface pair matching the specified rate. */ index = find_param_index(rate, rnd, datarates, ARRAY_SIZE(datarates)); /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; /* Set output data rate. */ - ret = raw_write8(accel_addr[id], KXCJ9_DATA_CTRL, + ret = raw_write8(data->accel_addr, KXCJ9_DATA_CTRL, datarates[index].reg); /* If successfully written, then save the range. */ if (ret == EC_SUCCESS) - sensor_datarate[id] = index; + data->sensor_datarate = index; /* Re-enable the sensor. */ - if (enable_sensor(id, ctrl1) != EC_SUCCESS) + if (enable_sensor(data, ctrl1) != EC_SUCCESS) return EC_ERROR_UNKNOWN; return ret; } -int accel_get_datarate(const enum accel_id id, int * const rate) +static int accel_get_datarate(void *drv_data, int * const rate) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - - *rate = datarates[sensor_datarate[id]].val; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; + *rate = datarates[data->sensor_datarate].val; return EC_SUCCESS; } #ifdef CONFIG_ACCEL_INTERRUPTS -int accel_set_interrupt(const enum accel_id id, unsigned int threshold) +static int accel_set_interrupt(void *drv_data, unsigned int threshold) { int ctrl1, tmp, ret; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; /* Set interrupt timer to 1 so it wakes up immediately. */ - ret = raw_write8(accel_addr[id], KXCJ9_WAKEUP_TIMER, 1); + ret = raw_write8(data->accel_addr, KXCJ9_WAKEUP_TIMER, 1); if (ret != EC_SUCCESS) goto error_enable_sensor; @@ -345,7 +315,7 @@ int accel_set_interrupt(const enum accel_id id, unsigned int threshold) * first we need to divide by 16 to get the value to send. */ threshold >>= 4; - ret = raw_write8(accel_addr[id], KXCJ9_WAKEUP_THRESHOLD, threshold); + ret = raw_write8(data->accel_addr, KXCJ9_WAKEUP_THRESHOLD, threshold); if (ret != EC_SUCCESS) goto error_enable_sensor; @@ -354,11 +324,11 @@ int accel_set_interrupt(const enum accel_id id, unsigned int threshold) * function is called once, the interrupt stays enabled and it is * only necessary to clear KXCJ9_INT_REL to allow the next interrupt. */ - ret = raw_read8(accel_addr[id], KXCJ9_INT_CTRL1, &tmp); + ret = raw_read8(data->accel_addr, KXCJ9_INT_CTRL1, &tmp); if (ret != EC_SUCCESS) goto error_enable_sensor; if (!(tmp & KXCJ9_INT_CTRL1_IEN)) { - ret = raw_write8(accel_addr[id], KXCJ9_INT_CTRL1, + ret = raw_write8(data->accel_addr, KXCJ9_INT_CTRL1, tmp | KXCJ9_INT_CTRL1_IEN); if (ret != EC_SUCCESS) goto error_enable_sensor; @@ -369,41 +339,40 @@ int accel_set_interrupt(const enum accel_id id, unsigned int threshold) * Note: this register latches motion detected above threshold. Once * latched, no interrupt can occur until this register is cleared. */ - ret = raw_read8(accel_addr[id], KXCJ9_INT_REL, &tmp); + ret = raw_read8(data->accel_addr, KXCJ9_INT_REL, &tmp); error_enable_sensor: /* Re-enable the sensor. */ - if (enable_sensor(id, ctrl1) != EC_SUCCESS) + if (enable_sensor(data, ctrl1) != EC_SUCCESS) return EC_ERROR_UNKNOWN; return ret; } #endif -int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc, - int * const z_acc) +static int accel_read(void *drv_data, + int * const x_acc, + int * const y_acc, + int * const z_acc) { uint8_t acc[6]; uint8_t reg = KXCJ9_XOUT_L; int ret, multiplier; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Read 6 bytes starting at KXCJ9_XOUT_L. */ - mutex_lock(&accel_mutex[id]); + mutex_lock(&data->accel_mutex); i2c_lock(I2C_PORT_ACCEL, 1); - ret = i2c_xfer(I2C_PORT_ACCEL, accel_addr[id], ®, 1, acc, 6, + ret = i2c_xfer(I2C_PORT_ACCEL, data->accel_addr, ®, 1, acc, 6, I2C_XFER_SINGLE); i2c_lock(I2C_PORT_ACCEL, 0); - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); if (ret != EC_SUCCESS) return ret; /* Determine multiplier based on stored range. */ - switch (ranges[sensor_range[id]].reg) { + switch (ranges[data->sensor_range].reg) { case KXCJ9_GSEL_2G: multiplier = 1; break; @@ -436,17 +405,23 @@ int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc, return EC_SUCCESS; } -int accel_init(const enum accel_id id) +static int accel_init(void *drv_data, int i2c_addr) { int ret = EC_SUCCESS; int cnt = 0, ctrl1, ctrl2; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) + if (data == NULL) return EC_ERROR_INVAL; + memset(&data->accel_mutex, sizeof(struct mutex), 0); + data->sensor_range = 0; + data->sensor_datarate = 6; + data->sensor_resolution = 1; + data->accel_addr = i2c_addr; + /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; @@ -455,13 +430,13 @@ int accel_init(const enum accel_id id) * the sensor is unknown here. Initiate software reset to restore * sensor to default. */ - ret = raw_write8(accel_addr[id], KXCJ9_CTRL2, KXCJ9_CTRL2_SRST); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL2, KXCJ9_CTRL2_SRST); if (ret != EC_SUCCESS) return ret; /* Wait until software reset is complete or timeout. */ while (1) { - ret = raw_read8(accel_addr[id], KXCJ9_CTRL2, &ctrl2); + ret = raw_read8(data->accel_addr, KXCJ9_CTRL2, &ctrl2); /* Reset complete. */ if (ret == EC_SUCCESS && !(ctrl2 & KXCJ9_CTRL2_SRST)) @@ -476,23 +451,25 @@ int accel_init(const enum accel_id id) } /* Set resolution and range. */ - ctrl1 = resolutions[sensor_resolution[id]].reg | - ranges[sensor_range[id]].reg; + ctrl1 = resolutions[data->sensor_resolution].reg | + ranges[data->sensor_range].reg; #ifdef CONFIG_ACCEL_INTERRUPTS /* Enable wake up (motion detect) functionality. */ ctrl1 |= KXCJ9_CTRL1_WUFE; #endif - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, ctrl1); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, ctrl1); #ifdef CONFIG_ACCEL_INTERRUPTS /* Set interrupt polarity to rising edge and keep interrupt disabled. */ - ret |= raw_write8(accel_addr[id], KXCJ9_INT_CTRL1, KXCJ9_INT_CTRL1_IEA); + ret |= raw_write8(data->accel_addr, + KXCJ9_INT_CTRL1, + KXCJ9_INT_CTRL1_IEA); /* Set output data rate for wake-up interrupt function. */ - ret |= raw_write8(accel_addr[id], KXCJ9_CTRL2, KXCJ9_OWUF_100_0HZ); + ret |= raw_write8(data->accel_addr, KXCJ9_CTRL2, KXCJ9_OWUF_100_0HZ); /* Set interrupt to trigger on motion on any axis. */ - ret |= raw_write8(accel_addr[id], KXCJ9_INT_CTRL2, + ret |= raw_write8(data->accel_addr, KXCJ9_INT_CTRL2, KXCJ9_INT_SRC2_XNWU | KXCJ9_INT_SRC2_XPWU | KXCJ9_INT_SRC2_YNWU | KXCJ9_INT_SRC2_YPWU | KXCJ9_INT_SRC2_ZNWU | KXCJ9_INT_SRC2_ZPWU); @@ -506,11 +483,27 @@ int accel_init(const enum accel_id id) #endif /* Set output data rate. */ - ret |= raw_write8(accel_addr[id], KXCJ9_DATA_CTRL, - datarates[sensor_datarate[id]].reg); + ret |= raw_write8(data->accel_addr, KXCJ9_DATA_CTRL, + datarates[data->sensor_datarate].reg); /* Enable the sensor. */ - ret |= enable_sensor(id, ctrl1); + ret |= enable_sensor(data, ctrl1); return ret; } + +const struct accelgyro_info accel_kxcj9 = { + .chip_type = CHIP_KXCJ9, + .sensor_type = SENSOR_ACCELEROMETER, + .init = accel_init, + .read = accel_read, + .set_range = accel_set_range, + .get_range = accel_get_range, + .set_resolution = accel_set_resolution, + .get_resolution = accel_get_resolution, + .set_datarate = accel_set_datarate, + .get_datarate = accel_get_datarate, +#ifdef CONFIG_ACCEL_INTERRUPTS + .set_interrupt = accel_set_interrupt, +#endif +}; diff --git a/driver/accel_kxcj9.h b/driver/accel_kxcj9.h index ea15b6ec17..30bea0e737 100644 --- a/driver/accel_kxcj9.h +++ b/driver/accel_kxcj9.h @@ -8,6 +8,8 @@ #ifndef __CROS_EC_ACCEL_KXCJ9_H #define __CROS_EC_ACCEL_KXCJ9_H +#include "task.h" + /* * 7-bit address is 000111Xb. Where 'X' is determined * by the voltage on the ADDR pin. @@ -99,17 +101,18 @@ #define KXCJ9_OSA_800_0HZ 6 #define KXCJ9_OSA_1600_HZ 7 - -#ifdef CONFIG_ACCEL_INTERRUPTS -/** - * Setup a one-time accel interrupt. If the threshold is low enough, the - * interrupt may trigger due simply to noise and not any real motion. If the - * threshold is 0, the interrupt will fire immediately. - * - * @param id Target accelerometer - * @param threshold Threshold for interrupt in units of counts. - */ -int accel_set_interrupt(const enum accel_id id, unsigned int threshold); -#endif +struct kxcj9_data { + struct mutex accel_mutex; + /* Current range of accelerometer. */ + int sensor_range; + /* Current output data rate of accelerometer. */ + int sensor_datarate; + /* Current resolution of accelerometer. */ + int sensor_resolution; + /* Device address. */ + int accel_addr; +}; + +extern const struct accelgyro_info accel_kxcj9; #endif /* __CROS_EC_ACCEL_KXCJ9_H */ diff --git a/driver/accelgyro_lsm6ds0.c b/driver/accelgyro_lsm6ds0.c index 8c8bd76b49..313ec9a312 100644 --- a/driver/accelgyro_lsm6ds0.c +++ b/driver/accelgyro_lsm6ds0.c @@ -5,7 +5,7 @@ /* LSM6DS0 accelerometer and gyro module for Chrome EC */ -#include "accelerometer.h" +#include "accelgyro.h" #include "common.h" #include "console.h" #include "driver/accelgyro_lsm6ds0.h" @@ -24,14 +24,14 @@ struct accel_param_pair { }; /* List of range values in +/-G's and their associated register values. */ -const struct accel_param_pair ranges[] = { +static const struct accel_param_pair ranges[] = { {2, LSM6DS0_GSEL_2G}, {4, LSM6DS0_GSEL_4G}, {8, LSM6DS0_GSEL_8G} }; /* List of ODR values in mHz and their associated register values. */ -const struct accel_param_pair datarates[] = { +static const struct accel_param_pair datarates[] = { {10000, LSM6DS0_ODR_10HZ}, {50000, LSM6DS0_ODR_50HZ}, {119000, LSM6DS0_ODR_119HZ}, @@ -40,17 +40,6 @@ const struct accel_param_pair datarates[] = { {952000, LSM6DS0_ODR_982HZ} }; -/* Current range of each accelerometer. The value is an index into ranges[]. */ -static int sensor_range[ACCEL_COUNT] = {0, 0}; - -/* - * Current output data rate of each accelerometer. The value is an index into - * datarates[]. - */ -static int sensor_datarate[ACCEL_COUNT] = {1, 1}; - -static struct mutex accel_mutex[ACCEL_COUNT]; - /** * Find index into a accel_param_pair that matches the given engineering value * passed in. The round_up flag is used to specify whether to round up or down. @@ -94,9 +83,12 @@ static int raw_write8(const int addr, const int reg, int data) return i2c_write8(I2C_PORT_ACCEL, addr, reg, data); } -int accel_set_range(const enum accel_id id, const int range, const int rnd) +static int accel_set_range(void *drv_data, + const int range, + const int rnd) { int ret, index, ctrl_reg6; + struct lsm6ds0_data *data = (struct lsm6ds0_data *)drv_data; /* Find index for interface pair matching the specified range. */ index = find_param_index(range, rnd, ranges, ARRAY_SIZE(ranges)); @@ -105,61 +97,52 @@ int accel_set_range(const enum accel_id id, const int range, const int rnd) * Lock accel resource to prevent another task from attempting * to write accel parameters until we are done. */ - mutex_lock(&accel_mutex[id]); + mutex_lock(&data->accel_mutex); - ret = raw_read8(accel_addr[id], LSM6DS0_CTRL_REG6_XL, &ctrl_reg6); + ret = raw_read8(data->accel_addr, LSM6DS0_CTRL_REG6_XL, &ctrl_reg6); if (ret != EC_SUCCESS) goto accel_cleanup; ctrl_reg6 = (ctrl_reg6 & ~LSM6DS0_GSEL_ALL) | ranges[index].reg; - ret = raw_write8(accel_addr[id], LSM6DS0_CTRL_REG6_XL, ctrl_reg6); + ret = raw_write8(data->accel_addr, LSM6DS0_CTRL_REG6_XL, ctrl_reg6); accel_cleanup: /* Unlock accel resource and save new range if written successfully. */ - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); if (ret == EC_SUCCESS) - sensor_range[id] = index; + data->sensor_range = index; return EC_SUCCESS; } -int accel_get_range(const enum accel_id id, int * const range) +static int accel_get_range(void *drv_data, int * const range) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - - *range = ranges[sensor_range[id]].val; + struct lsm6ds0_data *data = (struct lsm6ds0_data *)drv_data; + *range = ranges[data->sensor_range].val; return EC_SUCCESS; } -int accel_set_resolution(const enum accel_id id, const int res, const int rnd) +static int accel_set_resolution(void *drv_data, + const int res, + const int rnd) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - /* Only one resolution, LSM6DS0_RESOLUTION, so nothing to do. */ return EC_SUCCESS; } -int accel_get_resolution(const enum accel_id id, int * const res) +static int accel_get_resolution(void *drv_data, + int * const res) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - *res = LSM6DS0_RESOLUTION; return EC_SUCCESS; } -int accel_set_datarate(const enum accel_id id, const int rate, const int rnd) +static int accel_set_datarate(void *drv_data, + const int rate, + const int rnd) { int ret, index, ctrl_reg6; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct lsm6ds0_data *data = (struct lsm6ds0_data *)drv_data; /* Find index for interface pair matching the specified range. */ index = find_param_index(rate, rnd, datarates, ARRAY_SIZE(datarates)); @@ -168,62 +151,64 @@ int accel_set_datarate(const enum accel_id id, const int rate, const int rnd) * Lock accel resource to prevent another task from attempting * to write accel parameters until we are done. */ - mutex_lock(&accel_mutex[id]); + mutex_lock(&data->accel_mutex); - ret = raw_read8(accel_addr[id], LSM6DS0_CTRL_REG6_XL, &ctrl_reg6); + ret = raw_read8(data->accel_addr, LSM6DS0_CTRL_REG6_XL, &ctrl_reg6); if (ret != EC_SUCCESS) goto accel_cleanup; ctrl_reg6 = (ctrl_reg6 & ~LSM6DS0_ODR_ALL) | datarates[index].reg; - ret = raw_write8(accel_addr[id], LSM6DS0_CTRL_REG6_XL, ctrl_reg6); + ret = raw_write8(data->accel_addr, LSM6DS0_CTRL_REG6_XL, ctrl_reg6); accel_cleanup: /* Unlock accel resource and save new ODR if written successfully. */ - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); if (ret == EC_SUCCESS) - sensor_datarate[id] = index; + data->sensor_datarate = index; return EC_SUCCESS; } -int accel_get_datarate(const enum accel_id id, int * const rate) +static int accel_get_datarate(void *drv_data, + int * const rate) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - - *rate = datarates[sensor_datarate[id]].val; + struct lsm6ds0_data *data = (struct lsm6ds0_data *)drv_data; + *rate = datarates[data->sensor_datarate].val; return EC_SUCCESS; } #ifdef CONFIG_ACCEL_INTERRUPTS -int accel_set_interrupt(const enum accel_id id, unsigned int threshold) +static int accel_set_interrupt(void *drv_data, + unsigned int threshold) { /* Currently unsupported. */ return EC_ERROR_UNKNOWN; } #endif -int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc, - int * const z_acc) +static int accel_read(void *drv_data, + int * const x_acc, + int * const y_acc, + int * const z_acc) { uint8_t acc[6]; uint8_t reg = LSM6DS0_OUT_X_L_XL; int ret, multiplier; + struct lsm6ds0_data *data = (struct lsm6ds0_data *)drv_data; /* Read 6 bytes starting at LSM6DS0_OUT_X_L_XL. */ - mutex_lock(&accel_mutex[id]); + mutex_lock(&data->accel_mutex); i2c_lock(I2C_PORT_ACCEL, 1); - ret = i2c_xfer(I2C_PORT_ACCEL, accel_addr[id], ®, 1, acc, 6, + ret = i2c_xfer(I2C_PORT_ACCEL, data->accel_addr, ®, 1, acc, 6, I2C_XFER_SINGLE); i2c_lock(I2C_PORT_ACCEL, 0); - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); if (ret != EC_SUCCESS) return ret; /* Determine multiplier based on stored range. */ - switch (ranges[sensor_range[id]].reg) { + switch (ranges[data->sensor_range].reg) { case LSM6DS0_GSEL_2G: multiplier = 1; break; @@ -254,32 +239,50 @@ int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc, return EC_SUCCESS; } -int accel_init(const enum accel_id id) +static int accel_init(void *drv_data, int i2c_addr) { int ret, ctrl_reg6; + struct lsm6ds0_data *data = (struct lsm6ds0_data *)drv_data; - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) + if (data == NULL) return EC_ERROR_INVAL; - mutex_lock(&accel_mutex[id]); + memset(&data->accel_mutex, sizeof(struct mutex), 0); + data->sensor_range = 0; + data->sensor_datarate = 1; + data->accel_addr = i2c_addr; /* * This sensor can be powered through an EC reboot, so the state of * the sensor is unknown here. Initiate software reset to restore * sensor to default. */ - ret = raw_write8(accel_addr[id], LSM6DS0_CTRL_REG8, 1); + ret = raw_write8(data->accel_addr, LSM6DS0_CTRL_REG8, 1); if (ret != EC_SUCCESS) goto accel_cleanup; /* Set ODR and range. */ - ctrl_reg6 = datarates[sensor_datarate[id]].reg | - ranges[sensor_range[id]].reg; + ctrl_reg6 = datarates[data->sensor_datarate].reg | + ranges[data->sensor_range].reg; - ret = raw_write8(accel_addr[id], LSM6DS0_CTRL_REG6_XL, ctrl_reg6); + ret = raw_write8(data->accel_addr, LSM6DS0_CTRL_REG6_XL, ctrl_reg6); accel_cleanup: - mutex_unlock(&accel_mutex[id]); return ret; } + +const struct accelgyro_info accel_lsm6ds0 = { + .chip_type = CHIP_LSM6DS0, + .sensor_type = SENSOR_ACCELEROMETER, + .init = accel_init, + .read = accel_read, + .set_range = accel_set_range, + .get_range = accel_get_range, + .set_resolution = accel_set_resolution, + .get_resolution = accel_get_resolution, + .set_datarate = accel_set_datarate, + .get_datarate = accel_get_datarate, +#ifdef CONFIG_ACCEL_INTERRUPTS + .set_interrupt = accel_set_interrupt, +#endif +}; diff --git a/driver/accelgyro_lsm6ds0.h b/driver/accelgyro_lsm6ds0.h index 6c34570b15..5f1b64ca31 100644 --- a/driver/accelgyro_lsm6ds0.h +++ b/driver/accelgyro_lsm6ds0.h @@ -8,6 +8,8 @@ #ifndef __CROS_EC_ACCEL_LSM6DS0_H #define __CROS_EC_ACCEL_LSM6DS0_H +#include "task.h" + /* * 7-bit address is 110101Xb. Where 'X' is determined * by the voltage on the ADDR pin. @@ -42,4 +44,16 @@ /* Sensor resolution in number of bits. This sensor has fixed resolution. */ #define LSM6DS0_RESOLUTION 16 +struct lsm6ds0_data { + struct mutex accel_mutex; + /* Current range of accelerometer. */ + int sensor_range; + /* Current output data rate of accelerometer. */ + int sensor_datarate; + /* Device address. */ + int accel_addr; +}; + +extern const struct accelgyro_info accel_lsm6ds0; + #endif /* __CROS_EC_ACCEL_LSM6DS0_H */ diff --git a/driver/build.mk b/driver/build.mk index d3872acf6e..a18deb2657 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -8,6 +8,7 @@ # Accelerometers driver-$(CONFIG_ACCEL_KXCJ9)+=accel_kxcj9.o +driver-$(CONFIG_ACCELGYRO_LSM6DS0)+=accelgyro_lsm6ds0.o # ALS drivers driver-$(CONFIG_ALS_ISL29035)+=als_isl29035.o diff --git a/include/accelerometer.h b/include/accelerometer.h deleted file mode 100644 index 0c8703f3ae..0000000000 --- a/include/accelerometer.h +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright (c) 2014 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. - */ - -#ifndef __CROS_EC_ACCELEROMETER_H -#define __CROS_EC_ACCELEROMETER_H - -/* Header file for accelerometer drivers. */ - -/* This array must be defined in board.c. */ -extern const int accel_addr[]; - -/* This enum must be defined in board.h. */ -enum accel_id; - -/* Number of counts from accelerometer that represents 1G acceleration. */ -#define ACCEL_G 1024 - -/** - * Read all three accelerations of an accelerometer. Note that all three - * accelerations come back in counts, where ACCEL_G can be used to convert - * counts to engineering units. - * - * @param id Target accelerometer - * @param x_acc Pointer to store X-axis acceleration (in counts). - * @param y_acc Pointer to store Y-axis acceleration (in counts). - * @param z_acc Pointer to store Z-axis acceleration (in counts). - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc, - int * const z_acc); - -/** - * Initialize accelerometers. - * - * @param id Target accelerometer - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int accel_init(const enum accel_id id); - -/** - * Setter and getter methods for the sensor range. The sensor range defines - * the maximum value that can be returned from accel_read(). As the range - * increases, the resolution gets worse. - * - * @param id Target accelerometer - * @param range Range (Units are +/- G's for accel, +/- deg/s for gyro) - * @param rnd Rounding flag. If true, it rounds up to nearest valid value. - * Otherwise, it rounds down. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int accel_set_range(const enum accel_id id, const int range, const int rnd); -int accel_get_range(const enum accel_id id, int * const range); - - -/** - * Setter and getter methods for the sensor resolution. - * - * @param id Target accelerometer - * @param range Resolution (Units are number of bits) - * param rnd Rounding flag. If true, it rounds up to nearest valid value. - * Otherwise, it rounds down. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int accel_set_resolution(const enum accel_id id, const int res, const int rnd); -int accel_get_resolution(const enum accel_id id, int * const res); - -/** - * Setter and getter methods for the sensor output data range. As the ODR - * increases, the LPF roll-off frequency also increases. - * - * @param id Target accelerometer - * @param rate Output data rate (units are mHz) - * @param rnd Rounding flag. If true, it rounds up to nearest valid value. - * Otherwise, it rounds down. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int accel_set_datarate(const enum accel_id id, const int rate, const int rnd); -int accel_get_datarate(const enum accel_id id, int * const rate); - -#endif /* __CROS_EC_ACCELEROMETER_H */ diff --git a/include/accelgyro.h b/include/accelgyro.h new file mode 100644 index 0000000000..2a4a458cfa --- /dev/null +++ b/include/accelgyro.h @@ -0,0 +1,111 @@ +/* Copyright (c) 2014 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. + */ + +#ifndef __CROS_EC_ACCELGYRO_H +#define __CROS_EC_ACCELGYRO_H + +/* Header file for accelerometer / gyro drivers. */ + +/* Number of counts from accelerometer that represents 1G acceleration. */ +#define ACCEL_G 1024 + +enum accelgyro_chip_t { + CHIP_TEST, + CHIP_KXCJ9, + CHIP_LSM6DS0, +}; + +enum accelgyro_sensor_t { + SENSOR_ACCELEROMETER, + SENSOR_GYRO, +}; + +struct accelgyro_info { + enum accelgyro_chip_t chip_type; + enum accelgyro_sensor_t sensor_type; + + /** + * Initialize accelerometers. + * @param drv_data Pointer to sensor data. + * @i2c_addr i2c slave device address + * @return EC_SUCCESS if successful, non-zero if error. + */ + int (*init)(void *drv_data, + int i2c_addr); + + /** + * Read all three accelerations of an accelerometer. Note that all + * three accelerations come back in counts, where ACCEL_G can be used + * to convert counts to engineering units. + * @param drv_data Pointer to sensor data. + * @param x_acc Pointer to store X-axis acceleration (in counts). + * @param y_acc Pointer to store Y-axis acceleration (in counts). + * @param z_acc Pointer to store Z-axis acceleration (in counts). + * @return EC_SUCCESS if successful, non-zero if error. + */ + int (*read)(void *drv_data, + int * const x_acc, + int * const y_acc, + int * const z_acc); + + /** + * Setter and getter methods for the sensor range. The sensor range + * defines the maximum value that can be returned from read(). As the + * range increases, the resolution gets worse. + * @param drv_data Pointer to sensor data. + * @param range Range (Units are +/- G's for accel, +/- deg/s for gyro) + * @param rnd Rounding flag. If true, it rounds up to nearest valid + * value. Otherwise, it rounds down. + * @return EC_SUCCESS if successful, non-zero if error. + */ + int (*set_range)(void *drv_data, + const int range, + const int rnd); + int (*get_range)(void *drv_data, + int * const range); + + /** + * Setter and getter methods for the sensor resolution. + * @param drv_data Pointer to sensor data. + * @param range Resolution (Units are number of bits) + * param rnd Rounding flag. If true, it rounds up to nearest valid + * value. Otherwise, it rounds down. + * @return EC_SUCCESS if successful, non-zero if error. + */ + int (*set_resolution)(void *drv_data, + const int res, + const int rnd); + int (*get_resolution)(void *drv_data, + int * const res); + + /** + * Setter and getter methods for the sensor output data range. As the + * ODR increases, the LPF roll-off frequency also increases. + * @param drv_data Pointer to sensor data. + * @param rate Output data rate (units are mHz) + * @param rnd Rounding flag. If true, it rounds up to nearest valid + * value. Otherwise, it rounds down. + * @return EC_SUCCESS if successful, non-zero if error. + */ + int (*set_datarate)(void *drv_data, + const int rate, + const int rnd); + int (*get_datarate)(void *drv_data, + int * const rate); + +#ifdef CONFIG_ACCEL_INTERRUPTS + /** + * Setup a one-time accel interrupt. If the threshold is low enough, the + * interrupt may trigger due simply to noise and not any real motion. + * If the threshold is 0, the interrupt will fire immediately. + * @param drv_data Pointer to sensor data. + * @param threshold Threshold for interrupt in units of counts. + */ + int (*set_interrupt)(void *drv_data, + unsigned int threshold); +#endif +}; + +#endif /* __CROS_EC_ACCELGYRO_H */ diff --git a/include/ec_commands.h b/include/ec_commands.h index d5d5590269..a8c9ab450b 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -1300,6 +1300,7 @@ enum motionsensor_location { /* List of motion sensor chips. */ enum motionsensor_chip { MOTIONSENSE_CHIP_KXCJ9 = 0, + MOTIONSENSE_CHIP_LSM6DS0 = 1, }; /* Module flag masks used for the dump sub-command. */ diff --git a/include/motion_sense.h b/include/motion_sense.h index 3a3b9b5121..0319514fd7 100644 --- a/include/motion_sense.h +++ b/include/motion_sense.h @@ -92,5 +92,21 @@ void accel_int_lid(enum gpio_signal signal); */ void accel_int_base(enum gpio_signal signal); +enum sensor_location_t { + LOCATION_BASE, + LOCATION_LID, +}; + +struct motion_sensor_t { + char *name; + enum sensor_location_t location; + const struct accelgyro_info *drv; + void *drv_data; + uint8_t i2c_addr; +}; + +/* Defined at board level. */ +extern const struct motion_sensor_t motion_sensors[]; +extern const unsigned int motion_sensor_count; #endif /* __CROS_EC_MOTION_SENSE_H */ diff --git a/test/math_util.c b/test/math_util.c index 5ace8d2a83..e69005fcbc 100644 --- a/test/math_util.c +++ b/test/math_util.c @@ -10,43 +10,12 @@ #include "math_util.h" #include "motion_sense.h" #include "test_util.h" +#include "util.h" /*****************************************************************************/ -/* Mock functions */ - -/* Need to define accelerometer functions just to compile. */ -int accel_init(enum accel_id id) -{ - return EC_SUCCESS; -} -int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc) -{ - return EC_SUCCESS; -} -int accel_set_range(const enum accel_id id, const int range, const int rnd) -{ - return EC_SUCCESS; -} -int accel_get_range(const enum accel_id id, int * const range) -{ - return EC_SUCCESS; -} -int accel_set_resolution(const enum accel_id id, const int res, const int rnd) -{ - return EC_SUCCESS; -} -int accel_get_resolution(const enum accel_id id, int * const res) -{ - return EC_SUCCESS; -} -int accel_set_datarate(const enum accel_id id, const int rate, const int rnd) -{ - return EC_SUCCESS; -} -int accel_get_datarate(const enum accel_id id, int * const rate) -{ - return EC_SUCCESS; -} +/* Need to define motion sensor globals just to compile. */ +const struct motion_sensor_t motion_sensors[] = {}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); /*****************************************************************************/ /* Test utilities */ diff --git a/test/motion_sense.c b/test/motion_sense.c index 1836a524fe..941b6cc9e7 100644 --- a/test/motion_sense.c +++ b/test/motion_sense.c @@ -7,12 +7,14 @@ #include <math.h> +#include "accelgyro.h" #include "common.h" #include "host_command.h" #include "motion_sense.h" #include "task.h" #include "test_util.h" #include "timer.h" +#include "util.h" /* Mock acceleration values for motion sense task to read in. */ int mock_x_acc[ACCEL_COUNT], mock_y_acc[ACCEL_COUNT], mock_z_acc[ACCEL_COUNT]; @@ -20,46 +22,101 @@ int mock_x_acc[ACCEL_COUNT], mock_y_acc[ACCEL_COUNT], mock_z_acc[ACCEL_COUNT]; /*****************************************************************************/ /* Mock functions */ -int accel_init(enum accel_id id) +static int accel_init(void *drv_data, int i2c_addr) { return EC_SUCCESS; } -int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc) +static int accel_read_base(void *drv_data, int *x_acc, int *y_acc, int *z_acc) { /* Return the mock values. */ - *x_acc = mock_x_acc[id]; - *y_acc = mock_y_acc[id]; - *z_acc = mock_z_acc[id]; + *x_acc = mock_x_acc[ACCEL_BASE]; + *y_acc = mock_y_acc[ACCEL_BASE]; + *z_acc = mock_z_acc[ACCEL_BASE]; return EC_SUCCESS; } -int accel_set_range(const enum accel_id id, const int range, const int rnd) +static int accel_read_lid(void *drv_data, int *x_acc, int *y_acc, int *z_acc) { + /* Return the mock values. */ + *x_acc = mock_x_acc[ACCEL_LID]; + *y_acc = mock_y_acc[ACCEL_LID]; + *z_acc = mock_z_acc[ACCEL_LID]; + return EC_SUCCESS; } -int accel_get_range(const enum accel_id id, int * const range) + +static int accel_set_range(void *drv_data, + const int range, + const int rnd) { return EC_SUCCESS; } -int accel_set_resolution(const enum accel_id id, const int res, const int rnd) + +static int accel_get_range(void *drv_data, + int * const range) { return EC_SUCCESS; } -int accel_get_resolution(const enum accel_id id, int * const res) + +static int accel_set_resolution(void *drv_data, + const int res, + const int rnd) { return EC_SUCCESS; } -int accel_set_datarate(const enum accel_id id, const int rate, const int rnd) + +static int accel_get_resolution(void *drv_data, + int * const res) { return EC_SUCCESS; } -int accel_get_datarate(const enum accel_id id, int * const rate) + +static int accel_set_datarate(void *drv_data, + const int rate, + const int rnd) +{ + return EC_SUCCESS; +} + +static int accel_get_datarate(void *drv_data, + int * const rate) { return EC_SUCCESS; } +const struct accelgyro_info test_motion_sense_base = { + .chip_type = CHIP_TEST, + .sensor_type = SENSOR_ACCELEROMETER, + .init = accel_init, + .read = accel_read_base, + .set_range = accel_set_range, + .get_range = accel_get_range, + .set_resolution = accel_set_resolution, + .get_resolution = accel_get_resolution, + .set_datarate = accel_set_datarate, + .get_datarate = accel_get_datarate, +}; + +const struct accelgyro_info test_motion_sense_lid = { + .chip_type = CHIP_TEST, + .sensor_type = SENSOR_ACCELEROMETER, + .init = accel_init, + .read = accel_read_lid, + .set_range = accel_set_range, + .get_range = accel_get_range, + .set_resolution = accel_set_resolution, + .get_resolution = accel_get_resolution, + .set_datarate = accel_set_datarate, + .get_datarate = accel_get_datarate, +}; + +const struct motion_sensor_t motion_sensors[] = { + {"test base sensor", LOCATION_BASE, &test_motion_sense_base, NULL, 0}, + {"test lid sensor", LOCATION_LID, &test_motion_sense_lid, NULL, 0}, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); /*****************************************************************************/ /* Test utilities */ |