diff options
author | Ching-Kang Yen <chingkang@chromium.org> | 2020-01-16 16:11:40 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-06-23 23:02:04 +0000 |
commit | 606acbd904635e08344c7050097232f2e50f4e52 (patch) | |
tree | d764c28192b155f8f0a418b47b025b62e1736d3e | |
parent | 6e211171f1e787811f155826db82ce16ec263cbd (diff) | |
download | chrome-ec-606acbd904635e08344c7050097232f2e50f4e52.tar.gz |
driver: bmi160: Fix rounding error in set_offset() and get_offset()
The original set_offset() and get_offset() codes in the
driver/accelgyro_bmi160 use simple divisions to write the data.
The more times the set_offset() and get_offset() is used, the
data will get closer to 0.
Fixing it by replacing simple division to round_divide(), division
that round to nearest, in the common/math_util.c.
BRANCH=octopus
BUG=b:146823505
TEST=Testing on octopus:ampton on branch [firmware-octopus-11297.B].
Checking the data did not rounding to 0.
Change-Id: Ide9df9e32fc501e63d6f952cb8254df7662afd23
Signed-off-by: Ching-Kang Yen <chingkang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2002998
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Commit-Queue: Gwendal Grignou <gwendal@chromium.org>
(cherry picked from commit 036e9f7b214b763524497550aae0ee94df8fd536)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2247976
Reviewed-by: Inno.Park <ih.yoo.park@samsung.corp-partner.google.com>
Tested-by: Inno.Park <ih.yoo.park@samsung.corp-partner.google.com>
Commit-Queue: Bob Moragues <moragues@chromium.org>
-rw-r--r-- | common/math_util.c | 8 | ||||
-rw-r--r-- | driver/accelgyro_bmi160.c | 21 | ||||
-rw-r--r-- | include/math_util.h | 5 |
3 files changed, 26 insertions, 8 deletions
diff --git a/common/math_util.c b/common/math_util.c index ad98aecdf5..813847344b 100644 --- a/common/math_util.c +++ b/common/math_util.c @@ -238,3 +238,11 @@ void rotate_inv(const vector_3_t v, const matrix_3x3_t R, vector_3_t res) res[1] = FP_TO_INT(fp_div(t[1], deter)); res[2] = FP_TO_INT(fp_div(t[2], deter)); } + +/* division that round to the nearest integer */ +int round_divide(int64_t dividend, int divisor) +{ + return (dividend > 0) ^ (divisor > 0) ? + (dividend - divisor / 2) / divisor : + (dividend + divisor / 2) / divisor; +} diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c index 601073ce27..8f956aeeb2 100644 --- a/driver/accelgyro_bmi160.c +++ b/driver/accelgyro_bmi160.c @@ -502,8 +502,10 @@ static int get_offset(const struct motion_sensor_t *s, &val); if (val > 0x7f) val = -256 + val; - v[i] = val * BMI160_OFFSET_ACC_MULTI_MG / - BMI160_OFFSET_ACC_DIV_MG; + v[i] = round_divide( + (int64_t)val * BMI160_OFFSET_ACC_MULTI_MG, + BMI160_OFFSET_ACC_DIV_MG); + } break; case MOTIONSENSE_TYPE_GYRO: @@ -521,8 +523,9 @@ static int get_offset(const struct motion_sensor_t *s, val |= ((val98 >> (2 * i)) & 0x3) << 8; if (val > 0x1ff) val = -1024 + val; - v[i] = val * BMI160_OFFSET_GYRO_MULTI_MDS / - BMI160_OFFSET_GYRO_DIV_MDS; + v[i] = round_divide( + (int64_t)val * BMI160_OFFSET_GYRO_MULTI_MDS, + BMI160_OFFSET_GYRO_DIV_MDS); } break; #ifdef CONFIG_MAG_BMI160_BMM150 @@ -559,8 +562,9 @@ static int set_offset(const struct motion_sensor_t *s, switch (s->type) { case MOTIONSENSE_TYPE_ACCEL: for (i = X; i <= Z; i++) { - val = v[i] * BMI160_OFFSET_ACC_DIV_MG / - BMI160_OFFSET_ACC_MULTI_MG; + val = round_divide( + (int64_t)v[i] * BMI160_OFFSET_ACC_DIV_MG, + BMI160_OFFSET_ACC_MULTI_MG); if (val > 127) val = 127; if (val < -128) @@ -575,8 +579,9 @@ static int set_offset(const struct motion_sensor_t *s, break; case MOTIONSENSE_TYPE_GYRO: for (i = X; i <= Z; i++) { - val = v[i] * BMI160_OFFSET_GYRO_DIV_MDS / - BMI160_OFFSET_GYRO_MULTI_MDS; + val = round_divide( + (int64_t)v[i] * BMI160_OFFSET_GYRO_DIV_MDS, + BMI160_OFFSET_GYRO_MULTI_MDS); if (val > 511) val = 511; if (val < -512) diff --git a/include/math_util.h b/include/math_util.h index 385c044c6f..46981af05f 100644 --- a/include/math_util.h +++ b/include/math_util.h @@ -150,4 +150,9 @@ void rotate(const vector_3_t v, const matrix_3x3_t R, vector_3_t res); */ void rotate_inv(const vector_3_t v, const matrix_3x3_t R, vector_3_t res); +/** + * Divide dividend by divisor and round it to the nearest integer. + */ +int round_divide(int64_t dividend, int divisor); + #endif /* __CROS_EC_MATH_UTIL_H */ |