198 lines
5.6 KiB
C
198 lines
5.6 KiB
C
/*
|
|
$License:
|
|
Copyright 2011 InvenSense, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
$
|
|
*/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* $Id:$
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "mlSetGyroBias.h"
|
|
#include "mlFIFO.h"
|
|
#include "ml.h"
|
|
#include <string.h>
|
|
#include "mldl.h"
|
|
#include "mlMathFunc.h"
|
|
|
|
typedef struct {
|
|
int needToSetBias;
|
|
short currentBias[3];
|
|
int mode;
|
|
int motion;
|
|
} tSGB;
|
|
|
|
tSGB sgb;
|
|
|
|
/** Records a motion event that may cause a callback when the priority for this
|
|
* feature is met.
|
|
*/
|
|
void inv_set_motion_state(int motion)
|
|
{
|
|
sgb.motion = motion;
|
|
}
|
|
|
|
/** Converts from internal DMP gyro bias registers to external hardware gyro bias by
|
|
* applying scaling and transformation.
|
|
*/
|
|
void inv_convert_bias(const unsigned char *regs, short *bias)
|
|
{
|
|
long biasTmp2[3], biasTmp[3], biasPrev[3];
|
|
int i;
|
|
int sf;
|
|
struct mldl_cfg *mldl_cfg = inv_get_dl_config();
|
|
|
|
if (mldl_cfg->gyro_sens_trim != 0) {
|
|
sf = 2000 * 131 / mldl_cfg->gyro_sens_trim;
|
|
} else {
|
|
sf = 2000;
|
|
}
|
|
for (i = 0; i < 3; i++) {
|
|
biasTmp2[i] = inv_big8_to_int32(®s[i * 4]);
|
|
}
|
|
// Rotate bias vector by the transpose of the orientation matrix
|
|
for (i = 0; i < 3; ++i) {
|
|
biasTmp[i] = inv_q30_mult(biasTmp2[0], inv_obj.gyro_orient[i]) +
|
|
inv_q30_mult(biasTmp2[1], inv_obj.gyro_orient[i + 3]) +
|
|
inv_q30_mult(biasTmp2[2], inv_obj.gyro_orient[i + 6]);
|
|
}
|
|
|
|
for (i = 0; i < GYRO_NUM_AXES; i++) {
|
|
biasTmp[i] = (long)(biasTmp[i] * 1.39882274201861f / sf);
|
|
biasPrev[i] = (long)mldl_cfg->offset[i];
|
|
if (biasPrev[i] > 32767)
|
|
biasPrev[i] -= 65536L;
|
|
}
|
|
|
|
for (i = 0; i < GYRO_NUM_AXES; i++) {
|
|
bias[i] = (short)(biasPrev[i] - biasTmp[i]);
|
|
}
|
|
}
|
|
|
|
/** Records hardware biases in format as used by hardware gyro registers.
|
|
* Note, the hardware will add this value to the measured gyro data.
|
|
*/
|
|
inv_error_t inv_set_gyro_bias_in_hw_unit(const short *bias, int mode)
|
|
{
|
|
if (sgb.currentBias[0] != bias[0])
|
|
sgb.needToSetBias = 1;
|
|
if (sgb.currentBias[1] != bias[1])
|
|
sgb.needToSetBias = 1;
|
|
if (sgb.currentBias[2] != bias[2])
|
|
sgb.needToSetBias = 1;
|
|
if (sgb.needToSetBias) {
|
|
memcpy(sgb.currentBias, bias, sizeof(sgb.currentBias));
|
|
sgb.mode = mode;
|
|
}
|
|
return INV_SUCCESS;
|
|
}
|
|
|
|
/** Records gyro biases
|
|
* @param[in] bias Bias where 1dps is 2^16. In chip frame.
|
|
*/
|
|
inv_error_t inv_set_gyro_bias_in_dps(const long *bias, int mode)
|
|
{
|
|
struct mldl_cfg *mldl_cfg = inv_get_dl_config();
|
|
int sf, i;
|
|
long biasTmp;
|
|
short offset[3];
|
|
inv_error_t result;
|
|
|
|
if (mldl_cfg->gyro_sens_trim != 0) {
|
|
sf = 2000 * 131 / mldl_cfg->gyro_sens_trim;
|
|
} else {
|
|
sf = 2000;
|
|
}
|
|
|
|
for (i = 0; i < GYRO_NUM_AXES; i++) {
|
|
biasTmp = -bias[i] / sf;
|
|
if (biasTmp < 0)
|
|
biasTmp += 65536L;
|
|
offset[i] = (short)biasTmp;
|
|
}
|
|
result = inv_set_gyro_bias_in_hw_unit(offset, mode);
|
|
return result;
|
|
}
|
|
|
|
inv_error_t inv_set_gyro_bias_in_dps_float(const float *bias, int mode)
|
|
{
|
|
long biasL[3];
|
|
inv_error_t result;
|
|
|
|
biasL[0] = (long)(bias[0] * (1L << 16));
|
|
biasL[1] = (long)(bias[1] * (1L << 16));
|
|
biasL[2] = (long)(bias[2] * (1L << 16));
|
|
result = inv_set_gyro_bias_in_dps(biasL, mode);
|
|
return result;
|
|
}
|
|
|
|
inv_error_t MLSetGyroBiasCB(struct inv_obj_t * inv_obj)
|
|
{
|
|
inv_error_t result = INV_SUCCESS;
|
|
if (sgb.needToSetBias) {
|
|
result = inv_set_offset(sgb.currentBias);
|
|
sgb.needToSetBias = 0;
|
|
}
|
|
|
|
// Check if motion state has changed
|
|
if (sgb.motion == INV_MOTION) {
|
|
// We are moving
|
|
if (inv_obj->motion_state == INV_NO_MOTION) {
|
|
//Trigger motion callback
|
|
inv_obj->motion_state = INV_MOTION;
|
|
inv_obj->flags[INV_MOTION_STATE_CHANGE] = INV_MOTION;
|
|
if (inv_params_obj.motion_cb_func) {
|
|
inv_params_obj.motion_cb_func(INV_MOTION);
|
|
}
|
|
}
|
|
} else if (sgb.motion == INV_NO_MOTION){
|
|
// We are not moving
|
|
if (inv_obj->motion_state == INV_MOTION) {
|
|
//Trigger no motion callback
|
|
inv_obj->motion_state = INV_NO_MOTION;
|
|
inv_obj->got_no_motion_bias = TRUE;
|
|
inv_obj->flags[INV_MOTION_STATE_CHANGE] = INV_NO_MOTION;
|
|
if (inv_params_obj.motion_cb_func) {
|
|
inv_params_obj.motion_cb_func(INV_NO_MOTION);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
inv_error_t inv_enable_set_bias(void)
|
|
{
|
|
inv_error_t result;
|
|
memset(&sgb, 0, sizeof(sgb));
|
|
|
|
sgb.motion = inv_obj.motion_state;
|
|
|
|
result =
|
|
inv_register_fifo_rate_process(MLSetGyroBiasCB,
|
|
INV_PRIORITY_SET_GYRO_BIASES);
|
|
if (result == INV_ERROR_INVALID_PARAMETER)
|
|
result = INV_SUCCESS; /* We already registered this */
|
|
return result;
|
|
}
|
|
|
|
inv_error_t inv_disable_set_bias(void)
|
|
{
|
|
inv_error_t result;
|
|
result = inv_unregister_fifo_rate_process(MLSetGyroBiasCB);
|
|
return INV_SUCCESS; // FIXME need to disable
|
|
}
|