1 /* 2 $License: 3 Copyright 2011 InvenSense, Inc. 4 5 Licensed under the Apache License, Version 2.0 (the "License"); 6 you may not use this file except in compliance with the License. 7 You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11 Unless required by applicable law or agreed to in writing, software 12 distributed under the License is distributed on an "AS IS" BASIS, 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 See the License for the specific language governing permissions and 15 limitations under the License. 16 $ 17 */ 18 19 /****************************************************************************** 20 * 21 * $Id: mldmp.c 5629 2011-06-11 03:13:08Z mcaramello $ 22 * 23 *****************************************************************************/ 24 25 /** 26 * @addtogroup MLDMP 27 * 28 * @{ 29 * @file mldmp.c 30 * @brief Shared functions between all the different DMP versions 31 **/ 32 33 #include <stdio.h> 34 35 #include "mltypes.h" 36 #include "mlinclude.h" 37 #include "mltypes.h" 38 #include "ml.h" 39 #include "mldl_cfg.h" 40 #include "mldl.h" 41 #include "compass.h" 42 #include "mlSetGyroBias.h" 43 #include "mlsl.h" 44 #include "mlFIFO.h" 45 #include "mldmp.h" 46 #include "mlstates.h" 47 #include "dmpDefault.h" 48 #include "mlFIFOHW.h" 49 #include "mlsupervisor.h" 50 51 #include "log.h" 52 #undef MPL_LOG_TAG 53 #define MPL_LOG_TAG "MPL-dmp" 54 55 /** 56 * @brief Open the default motion sensor engine. 57 * This function is used to open the default MPL engine, 58 * featuring, for example, sensor fusion (6 axes and 9 axes), 59 * sensor calibration, accelerometer data byte swapping, among 60 * others. 61 * Compare with the other provided engines. 62 * 63 * @pre inv_serial_start() must have been called to instantiate the serial 64 * communication. 65 * 66 * Example: 67 * @code 68 * result = inv_dmp_open( ); 69 * if (INV_SUCCESS != result) { 70 * // Handle the error case 71 * } 72 * @endcode 73 * 74 * @return Zero on success; Error Code on any failure. 75 * 76 */ 77 inv_error_t inv_dmp_open(void) 78 { 79 INVENSENSE_FUNC_START; 80 inv_error_t result; 81 unsigned char state = inv_get_state(); 82 struct mldl_cfg *mldl_cfg; 83 unsigned long requested_sensors; 84 85 /************************************************************* 86 * Common operations before calling DMPOpen 87 ************************************************************/ 88 if (state == INV_STATE_DMP_OPENED) 89 return INV_SUCCESS; 90 91 if (state == INV_STATE_DMP_STARTED) { 92 return inv_dmp_stop(); 93 } 94 95 result = inv_state_transition(INV_STATE_DMP_OPENED); 96 if (result) { 97 LOG_RESULT_LOCATION(result); 98 return result; 99 } 100 101 result = inv_dl_open(inv_get_serial_handle()); 102 if (result) { 103 LOG_RESULT_LOCATION(result); 104 return result; 105 } 106 #ifdef ML_USE_DMP_SIM 107 do { 108 void setup_univ(); 109 setup_univ(); /* hijack the read and write paths 110 and re-direct them to the simulator */ 111 } while (0); 112 #endif 113 114 result = inv_setup_dmp(); 115 if (result) { 116 LOG_RESULT_LOCATION(result); 117 return result; 118 } 119 120 // Init vars. 121 inv_init_ml(); 122 123 result = inv_init_fifo_param(); 124 if (result) { 125 LOG_RESULT_LOCATION(result); 126 return result; 127 } 128 result = inv_enable_set_bias(); 129 if (result) { 130 LOG_RESULT_LOCATION(result); 131 return result; 132 } 133 inv_init_fifo_hardare(); 134 mldl_cfg = inv_get_dl_config(); 135 requested_sensors = INV_THREE_AXIS_GYRO; 136 if (mldl_cfg->accel && mldl_cfg->accel->resume) 137 requested_sensors |= INV_THREE_AXIS_ACCEL; 138 139 if (mldl_cfg->compass && mldl_cfg->compass->resume) 140 requested_sensors |= INV_THREE_AXIS_COMPASS; 141 142 if (mldl_cfg->pressure && mldl_cfg->pressure->resume) 143 requested_sensors |= INV_THREE_AXIS_PRESSURE; 144 145 result = inv_init_requested_sensors(requested_sensors); 146 if (result) { 147 LOG_RESULT_LOCATION(result); 148 return result; 149 } 150 result = inv_apply_calibration(); 151 if (result) { 152 LOG_RESULT_LOCATION(result); 153 return result; 154 } 155 if (NULL != mldl_cfg->accel){ 156 result = inv_apply_endian_accel(); 157 } 158 159 return result; 160 } 161 162 /** 163 * @brief Start the DMP. 164 * 165 * @pre inv_dmp_open() must have been called. 166 * 167 * @code 168 * result = inv_dmp_start(); 169 * if (INV_SUCCESS != result) { 170 * // Handle the error case 171 * } 172 * @endcode 173 * 174 * @return INV_SUCCESS if successful, or Non-zero error code otherwise. 175 */ 176 inv_error_t inv_dmp_start(void) 177 { 178 INVENSENSE_FUNC_START; 179 inv_error_t result; 180 181 if (inv_get_state() == INV_STATE_DMP_STARTED) 182 return INV_SUCCESS; 183 184 result = inv_state_transition(INV_STATE_DMP_STARTED); 185 if (result) { 186 LOG_RESULT_LOCATION(result); 187 return result; 188 } 189 inv_init_sensor_fusion_supervisor(); 190 result = inv_dl_start(inv_get_dl_config()->requested_sensors); 191 if (result) { 192 LOG_RESULT_LOCATION(result); 193 return result; 194 } 195 /* This is done after the start since it will modify DMP memory, which 196 * will cause a full reset is most cases */ 197 result = inv_reset_motion(); 198 if (result) { 199 LOG_RESULT_LOCATION(result); 200 return result; 201 } 202 203 return result; 204 } 205 206 /** 207 * @brief Stops the DMP and puts it in low power. 208 * 209 * @pre inv_dmp_start() must have been called. 210 * 211 * @return INV_SUCCESS, Non-zero error code otherwise. 212 */ 213 inv_error_t inv_dmp_stop(void) 214 { 215 INVENSENSE_FUNC_START; 216 inv_error_t result; 217 218 if (inv_get_state() == INV_STATE_DMP_OPENED) 219 return INV_SUCCESS; 220 221 result = inv_state_transition(INV_STATE_DMP_OPENED); 222 if (result) { 223 LOG_RESULT_LOCATION(result); 224 return result; 225 } 226 result = inv_dl_stop(INV_ALL_SENSORS); 227 if (result) { 228 LOG_RESULT_LOCATION(result); 229 return result; 230 } 231 232 return result; 233 } 234 235 /** 236 * @brief Closes the motion sensor engine. 237 * Does not close the serial communication. To do that, 238 * call inv_serial_stop(). 239 * After calling inv_dmp_close() another DMP module can be 240 * loaded in the MPL with the corresponding necessary 241 * intialization and configurations, via any of the 242 * MLDmpXXXOpen functions. 243 * 244 * @pre inv_dmp_open() must have been called. 245 * 246 * @code 247 * result = inv_dmp_close(); 248 * if (INV_SUCCESS != result) { 249 * // Handle the error case 250 * } 251 * @endcode 252 * 253 * @return INV_SUCCESS, Non-zero error code otherwise. 254 */ 255 inv_error_t inv_dmp_close(void) 256 { 257 INVENSENSE_FUNC_START; 258 inv_error_t result; 259 inv_error_t firstError = INV_SUCCESS; 260 261 if (inv_get_state() <= INV_STATE_DMP_CLOSED) 262 return INV_SUCCESS; 263 264 result = inv_disable_set_bias(); 265 ERROR_CHECK_FIRST(firstError, result); 266 267 result = inv_dl_stop(INV_ALL_SENSORS); 268 ERROR_CHECK_FIRST(firstError, result); 269 270 result = inv_close_fifo(); 271 ERROR_CHECK_FIRST(firstError, result); 272 273 result = inv_dl_close(); 274 ERROR_CHECK_FIRST(firstError, result); 275 276 result = inv_state_transition(INV_STATE_SERIAL_OPENED); 277 ERROR_CHECK_FIRST(firstError, result); 278 279 return result; 280 } 281 282 /** 283 * @} 284 */ 285