예제 #1
0
/**
 *  @brief  An MPL wrapper for the main MPU Self Test API inv_factory_calibrate().
 *          See inv_factory_calibrate() function for more details.
 *
 *  @pre    inv_dmp_open() <b>must</b> have been called to populate the mldl_cfg
 *          data structure.
 *          On Windows, SetupPlatform() is also a madatory pre condition to
 *          ensure the accelerometer is properly configured before running the
 *          test.
 *
 *  @param  mlsl_handle
 *              serial interface handle to allow serial communication with the
 *              device, both gyro and accelerometer.
 *  @param  provide_result
 *              If 1:
 *              perform and analyze the offset, drive frequency, and noise
 *              calculation and compare it against set thresholds. Report
 *              also the final result using a bit-mask like error code as
 *              described in the inv_test_gyro_xxxx() functions.
 *              When 0:
 *              skip the noise and drive frequency calculation  and pass/fail
 *              assessment. It simply calculates the gyro and accel biases.
 *              NOTE: for MPU6050 devices, this parameter is currently
 *              ignored.
 *
 *  @return INV_SUCCESS or first non-zero error code otherwise.
 */
inv_error_t inv_self_test_factory_calibrate(void *mlsl_handle,
        unsigned char provide_result)
{
    INVENSENSE_FUNC_START;
    inv_error_t firstError = INV_SUCCESS;
    inv_error_t result;
    unsigned char initState = inv_get_state();

    if (initState < INV_STATE_DMP_OPENED) {
        MPL_LOGE("Self Test cannot run before inv_dmp_open()\n");
        return INV_ERROR_SM_IMPROPER_STATE;
    }

    /* obtain a pointer to the 'struct mldl_cfg' data structure. */
    mputestCfgPtr = inv_get_dl_config();

    if(initState == INV_STATE_DMP_STARTED) {
        result = inv_dmp_stop();
        ERROR_CHECK_FIRST(firstError, result);
    }

    result = inv_factory_calibrate(mlsl_handle, provide_result);
    ERROR_CHECK_FIRST(firstError, result);

    if(initState == INV_STATE_DMP_STARTED) {
        result = inv_dmp_start();
        ERROR_CHECK_FIRST(firstError, result);
    }

    return firstError;
}
예제 #2
0
/**
 *  @brief  umplStop stops the uMPL state machine. This function
 *          in turn calls the necessary MPL functions like inv_dmp_stop()
 *          and inv_dmp_close() to stop the motion processing algorithms.
 *
 *
 *  @pre    umplInit() and umplStartMPU() must have been called.
 *
 *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
 */
inv_error_t umplStop(void)
{
    inv_error_t result;
    if (umplState == UMPL_RUN)
    {
#ifndef UMPL_DISABLE_STORE_CAL
    result = inv_ustore_calibration();
    if (result != INV_SUCCESS)
        MPL_LOGE("inv_ustore_calibration failed with %d in umplStop\n",result);
#endif
    }
    if (umplState == UMPL_RUN ||  umplState == UMPL_ACCEL_ONLY ||
     umplState == UMPL_LPACCEL_ONLY)
    {
        result = inv_dmp_stop();
        if (result != INV_SUCCESS) return result;

        result = inv_dmp_close();
        if (result != INV_SUCCESS) return result;

        umplSetState(UMPL_STOP);
        return INV_SUCCESS;
    }
    return INV_ERROR_SM_IMPROPER_STATE;
}
MPLSensor::~MPLSensor()
{
    FUNC_LOG;
    pthread_mutex_lock(&mMplMutex);
    if (inv_dmp_stop() != INV_SUCCESS) {
        ALOGW("Error: could not stop the DMP correctly.\n");
    }

    if (inv_dmp_close() != INV_SUCCESS) {
        ALOGW("Error: could not close the DMP");
    }

    if (inv_serial_stop() != INV_SUCCESS) {
        ALOGW("Error : could not close the serial port");
    }
    pthread_mutex_unlock(&mMplMutex);
    pthread_mutex_destroy(&mMplMutex);
}
/* set the power states of the various sensors based on the bits set in the
 * enabled_sensors parameter.
 * this function modifies globalish state variables.  It must be called with the mMplMutex held. */
void MPLSensor::setPowerStates(int enabled_sensors)
{
    FUNC_LOG;
    bool irq_set[5] = { false, false, false, false, false };

    //ALOGV(" setPowerStates: %d dmp_started: %d", enabled_sensors, mDmpStarted);

    do {

        if (LA_ENABLED || GR_ENABLED || RV_ENABLED || O_ENABLED) {
            mLocalSensorMask = ALL_MPL_SENSORS_NP;
            break;
        }

        if (!A_ENABLED && !M_ENABLED && !GY_ENABLED) {
            mLocalSensorMask = 0;
            break;
        }

        if (GY_ENABLED) {
            mLocalSensorMask |= INV_THREE_AXIS_GYRO;
        } else {
            mLocalSensorMask &= ~INV_THREE_AXIS_GYRO;
        }

        if (A_ENABLED) {
            mLocalSensorMask |= (INV_THREE_AXIS_ACCEL);
        } else {
            mLocalSensorMask &= ~(INV_THREE_AXIS_ACCEL);
        }

        if (M_ENABLED) {
            mLocalSensorMask |= INV_THREE_AXIS_COMPASS;
        } else {
            mLocalSensorMask &= ~(INV_THREE_AXIS_COMPASS);
        }

    } while (0);

    //record the new sensor state
    inv_error_t rv;

    long sen_mask = mLocalSensorMask & mMasterSensorMask;

    bool changing_sensors = ((inv_get_dl_config()->requested_sensors
            != sen_mask) && (sen_mask != 0));
    bool restart = (!mDmpStarted) && (sen_mask != 0);

    if (changing_sensors || restart) {

        ALOGV_IF(EXTRA_VERBOSE, "cs:%d rs:%d ", changing_sensors, restart);

        if (mDmpStarted) {
            inv_dmp_stop();
            clearIrqData(irq_set);
            mDmpStarted = false;
        }

        if (sen_mask != inv_get_dl_config()->requested_sensors) {
            //ALOGV("setPowerStates: %lx", sen_mask);
            rv = inv_set_mpu_sensors(sen_mask);
            ALOGE_IF(rv != INV_SUCCESS,
                    "error: unable to set MPL sensor power states (sens=%ld retcode = %d)",
                    sen_mask, rv);
        }

        if (((mUsetimerIrqCompass && (sen_mask == INV_THREE_AXIS_COMPASS))
                || (mUseTimerIrqAccel && (sen_mask & INV_THREE_AXIS_ACCEL)))
                && ((sen_mask & INV_DMP_PROCESSOR) == 0)) {
            ALOGV_IF(EXTRA_VERBOSE, "Allowing TimerIRQ");
            mUseTimerirq = true;
        } else {
            if (mUseTimerirq) {
                ioctl(mIrqFds.valueFor(TIMERIRQ_FD), TIMERIRQ_STOP, 0);
                clearIrqData(irq_set);
            }
            ALOGV_IF(EXTRA_VERBOSE, "Not allowing TimerIRQ");
            mUseTimerirq = false;
        }

        if (!mDmpStarted) {
            if (mHaveGoodMpuCal || mHaveGoodCompassCal) {
                rv = inv_store_calibration();
                ALOGE_IF(rv != INV_SUCCESS,
                        "error: unable to store MPL calibration file");
                mHaveGoodMpuCal = false;
                mHaveGoodCompassCal = false;
            }
            //ALOGV("Starting DMP");
            rv = inv_dmp_start();
            ALOGE_IF(rv != INV_SUCCESS, "unable to start dmp");
            mDmpStarted = true;
        }
    }

    //check if we should stop the DMP
    if (mDmpStarted && (sen_mask == 0)) {
        //ALOGV("Stopping DMP");
        rv = inv_dmp_stop();
        ALOGE_IF(rv != INV_SUCCESS, "error: unable to stop DMP (retcode = %d)",
                rv);
        if (mUseTimerirq) {
            ioctl(mIrqFds.valueFor(TIMERIRQ_FD), TIMERIRQ_STOP, 0);
        }
        clearIrqData(irq_set);

        mDmpStarted = false;
        mPollTime = -1;
        mCurFifoRate = -1;
    }

}
/**
 *  @brief  The main entry point of the MPU Self Test, triggering the run of
 *          the single tests, for gyros and accelerometers.
 *          Prepares the MPU for the test, taking the device out of low power
 *          state if necessary, switching the MPU secondary I2C interface into
 *          bypass mode and restoring the original power state at the end of
 *          the test.
 *          This function is also responsible for encoding the output of each
 *          test in the correct format as it is stored on the file/medium of
 *          choice (according to inv_serial_write_cal() function).
 *          The format needs to stay perfectly consistent with the one expected
 *          by the corresponding loader in ml_stored_data.c; currectly the
 *          loaded in use is inv_load_cal_V1 (record type 1 - initial
 *          calibration).
 *
 *  @param  mlsl_handle
 *              serial interface handle to allow serial communication with the
 *              device, both gyro and accelerometer.
 *  @param  perform_full_test
 *              If 1:
 *              Complete calibration test:
 *              Calculate offset, drive frequency, and noise and compare it
 *              against set thresholds.
 *              When 0:
 *              Skip the noise and drive frequency calculation,
 *              simply calculate the gyro biases.
 *  @param  provide_result
 *              If 1:
 *              Report the final result using a bit-mask like error code as
 *              described in the test_gyro() function.
 *
 *  @return 0 on success.  A non-zero error code on error.
 *          Propagates the errors from the tests up to the caller.
 */
int inv_device_test(void *mlsl_handle,
                    uint_fast8_t sensor_mask,
                    uint_fast8_t perform_full_test,
                    uint_fast8_t provide_result)
{
    int result = 0, gyro_test_result = 0, accel_test_result = 0;
    short temp_avg = 0;
    short gyro_biases[3] = {0, 0, 0};
    short accel_biases[3] = {0, 0, 0};
    long accel_sens[3] = {0};
    unsigned long saved_sensor_mask;
    unsigned char saved_state = inv_get_state();

    mldl_cfg = inv_get_dl_config();
    saved_sensor_mask = mldl_cfg->inv_mpu_cfg->requested_sensors;

    if (sensor_mask & (INV_THREE_AXIS_GYRO & ~INV_DMP_PROCESSOR)) {
        result = inv_set_mpu_sensors(INV_THREE_AXIS_GYRO & ~INV_DMP_PROCESSOR);
        if (result) {
            LOG_RESULT_LOCATION(result);
            return -1;
        }
        if (saved_state < INV_STATE_DMP_STARTED) {
            result = inv_dmp_start();
            if (result) {
                LOG_RESULT_LOCATION(result);
                return -1;
            }
        }
#ifdef TRACK_IDS
        result = get_mpu_unique_id(mlsl_handle);
        if (result != INV_SUCCESS) {
            MPL_LOGI("Could not read the device's unique ID\n");
            MPL_LOGI("\n");
            return -1;
        }
#endif
        MPL_LOGI("Collecting one group of %d ms samples for each axis\n",
            (perform_full_test ? DEF_PERIOD_CAL : DEF_PERIOD_SELF));
        MPL_LOGI("\n");

        /* adjust the gyro sensitivity according to the gyro_sens_trim value */
        adj_gyro_sens = test_setup.gyro_sens *
            mldl_cfg->mpu_chip_info->gyro_sens_trim / 131.072f;
        test_setup.gyro_fs = (int)(32768.f / adj_gyro_sens);

        /* collect gyro and temperature data, test gyro, report result */
        gyro_test_result = test_gyro(mlsl_handle,
                                gyro_biases, &temp_avg, perform_full_test);
        MPL_LOGI("\n");
        if (gyro_test_result == 0) {
            MPL_LOGI_IF(provide_result, "Test : PASSED\n");
        } else {
            MPL_LOGI_IF(provide_result, "Test : FAILED %d/%04X - Biases NOT stored\n",
                        gyro_test_result, gyro_test_result);
            goto gyro_test_failed;
        }
        MPL_LOGI_IF(provide_result, "\n");
    }

    if (sensor_mask & INV_THREE_AXIS_ACCEL) {
        if (!mldl_cfg->slave[EXT_SLAVE_TYPE_ACCEL]) {
            MPL_LOGI("\n");
            MPL_LOGI("No accelerometer configured\n");
        } else {
            result = inv_set_mpu_sensors(INV_THREE_AXIS_ACCEL);
            if (result)
                return -1;
            if (inv_get_state() < INV_STATE_DMP_STARTED) {
                result = inv_dmp_start();
                if (result)
                    return -1;
            }

            get_accel_sensitivity(accel_sens);
            /* collect accel data.  if this step is skipped,
               ensure the array still contains zeros. */
            accel_test_result =
                test_accel(mlsl_handle, sensor_mask >> 4,
                           accel_biases, accel_sens[Z],
                           perform_full_test);
            if (accel_test_result)
                goto accel_test_failed;

            /* if only Z accel is requested,
               clear out the biases from the other 2 axes */
            if ((sensor_mask & INV_THREE_AXIS_ACCEL) == INV_Z_ACCEL)
                    accel_biases[X] = accel_biases[Y] = 0;
        }
    }

	
	ALOGE("in %s: accel_bias is %d %d %d", __func__, accel_biases[0],
			accel_biases[1], accel_biases[2]);
    result = populate_data_store(sensor_mask, temp_avg, gyro_biases,
                                     accel_biases, accel_sens);
    if (result)
        return -1;
    result = inv_serial_write_cal(data_store, ML_INIT_CAL_LEN);
    if (result) {
        MPL_LOGI("Error : cannot write calibration on file - error %d\n",
            result);
        LOG_RESULT_LOCATION(result);
        return -1;
    }

gyro_test_failed:
accel_test_failed:
    /* restore the setting had at the beginning */
    mldl_cfg->inv_mpu_state->status |= MPU_GYRO_NEEDS_CONFIG;
    result = inv_set_mpu_sensors(saved_sensor_mask);
    if (result) {
        LOG_RESULT_LOCATION(result);
        return -1;
    }
    /* turn off only if it was off when the function was called */
    if (saved_state < INV_STATE_DMP_STARTED) {
        result = inv_dmp_stop();
        if (result) {
            LOG_RESULT_LOCATION(result);
            return -1;
        }
    }

    if (gyro_test_result)
        return gyro_test_result;
    if (accel_test_result)
        return accel_test_result;

    return result;
}