PageRenderTime 58ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/EDVSBoardOS/src/mpu9150.c

https://bitbucket.org/rui_araujo/edvsboardos
C | 416 lines | 298 code | 47 blank | 71 comment | 17 complexity | 3fb951b9c95680ff9d60c442ee3b5b54 MD5 | raw file
  1. /*
  2. * mpu9150.c
  3. *
  4. * Created on: Apr 7, 2014
  5. * Author: raraujo
  6. */
  7. #include "chip.h"
  8. #include "config.h"
  9. #include "mpu9105.h"
  10. #include "inv_mpu.h"
  11. #include "inv_mpu_dmp_motion_driver.h"
  12. #include "invensense.h"
  13. #include "invensense_adv.h"
  14. #include "eMPL_outputs.h"
  15. #include "xprintf.h"
  16. #include "sensors.h"
  17. #include "fixedptc.h"
  18. #include "utils.h"
  19. #include "extra_pins.h"
  20. #include <string.h>
  21. #include <stdbool.h>
  22. #if USE_IMU_DATA
  23. /* Starting sampling rate. */
  24. #define DEFAULT_MPU_HZ (40)
  25. // P3.1 VBAT reset signal
  26. #define MPU_INT_GND_PORT_GPIO (5)
  27. #define MPU_INT_GND_PIN_GPIO (8)
  28. #define MPU_INT_GND_PORT (3)
  29. #define MPU_INT_GND_PIN (1)
  30. #define SFSI2C0_CONFIGURE_STANDARD_FAST_MODE_PLUS (1<<3 | 3<<10)
  31. #define FAST_MODE_BAUD ((uint32_t)400000)
  32. #define FAST_MODE_PLUS_BAUD ((uint32_t)1000000)
  33. static long temperature;/* Temperature sensor output */
  34. static short gyrometer_data[3];/* 3 axis gyrometer data from the IMU*/
  35. static short accelerometer_data[3];/* 3 axis accelerometer data from the IMU*/
  36. static short magnometer_data[3];/* 3 axis compass data from the IMU*/
  37. static long quaternion[4];/* 4d quaternion data from the IMU DMP*/
  38. static unsigned long sensor_timestamp;
  39. static bool mpuEnabled = false;
  40. /* Platform-specific information. Kinda like a boardfile. */
  41. struct platform_data_s {
  42. signed char orientation[9];
  43. };
  44. unsigned char *mpl_key = (unsigned char*) "eMPL 5.1";
  45. /* The sensors can be mounted onto the board in any orientation. The mounting
  46. * matrix seen below tells the MPL how to rotate the raw data from the
  47. * driver(s).
  48. */
  49. static struct platform_data_s gyro_pdata = { .orientation = { 1, 0, 0, 0, 1, 0, 0, 0, 1 } };
  50. static struct platform_data_s compass_pdata = { .orientation = { 0, 1, 0, 1, 0, 0, 0, 0, -1 } };
  51. #define MAX_NUMBER_STRING_SIZE 32
  52. static void printLongHexData(long *data, int length) {
  53. for (int i = 0; i < length; ++i) {
  54. xprintf(" %X", data[i]);
  55. }
  56. }
  57. static void printShortData(short *data, int length) {
  58. for (int i = 0; i < length; ++i) {
  59. xprintf(" %d", data[i]);
  60. }
  61. }
  62. union ufloat {
  63. float f;
  64. long u;
  65. };
  66. /* ---------------------------------------------------------------------------*/
  67. /* Get data from MPL.
  68. */
  69. static void readFromMpl(uint8_t sensorId) {
  70. long data[9];
  71. int8_t accuracy;
  72. inv_time_t timestamp;
  73. xprintf("-S%d", sensorId);
  74. switch (sensorId) {
  75. case RAW_GYRO: {
  76. printShortData(gyrometer_data, 3);
  77. xputc('\n');
  78. break;
  79. }
  80. case RAW_ACCEL: {
  81. printShortData(accelerometer_data, 3);
  82. xputc('\n');
  83. break;
  84. }
  85. case RAW_COMPASS: {
  86. printShortData(magnometer_data, 3);
  87. xputc('\n');
  88. break;
  89. }
  90. case CAL_GYRO: {
  91. inv_get_sensor_type_gyro(data, &accuracy, &timestamp);
  92. printLongHexData(data, 3);
  93. xprintf(" %d\n", timestamp);
  94. break;
  95. }
  96. case CAL_ACCEL: {
  97. inv_get_sensor_type_accel(data, &accuracy, &timestamp);
  98. printLongHexData(data, 3);
  99. xputc('\n');
  100. break;
  101. }
  102. case CAL_COMPASS: {
  103. inv_get_sensor_type_compass(data, &accuracy, &timestamp);
  104. printLongHexData(data, 3);
  105. xputc('\n');
  106. break;
  107. }
  108. case QUARTERNION: {
  109. inv_get_sensor_type_quat(data, &accuracy, &timestamp);
  110. printLongHexData(data, 4);
  111. xputc('\n');
  112. break;
  113. }
  114. case EULER_ANGLES: {
  115. inv_get_sensor_type_euler(data, &accuracy, &timestamp);
  116. printLongHexData(data, 4);
  117. xputc('\n');
  118. break;
  119. }
  120. case ROTATION_MATRIX: {
  121. inv_get_sensor_type_rot_mat(data, &accuracy, &timestamp);
  122. printLongHexData(data, 9);
  123. xputc('\n');
  124. break;
  125. }
  126. case HEADING: {
  127. inv_get_sensor_type_heading(data, &accuracy, &timestamp);
  128. xprintf(" %X\n", data[0]);
  129. break;
  130. }
  131. case LINEAR_ACCEL: {
  132. float float_data[3] = { 0 };
  133. inv_get_sensor_type_linear_acceleration(float_data, &accuracy, &timestamp);
  134. union ufloat converter;
  135. for (int i = 0; i < 3; ++i) {
  136. converter.f = float_data[i];
  137. xprintf(" %X", converter.u);
  138. }
  139. xputc('\n');
  140. break;
  141. }
  142. case STATUS: {
  143. xprintf(" %s %d\n", fixedpt_cstr(temperature, 3, false), sensor_timestamp);
  144. break;
  145. }
  146. }
  147. }
  148. void RawGyroReport() {
  149. readFromMpl(RAW_GYRO);
  150. }
  151. void RawAccelerometerReport() {
  152. readFromMpl(RAW_ACCEL);
  153. }
  154. void RawCompassReport() {
  155. readFromMpl(RAW_COMPASS);
  156. }
  157. void CalGyroReport() {
  158. readFromMpl(CAL_GYRO);
  159. }
  160. void CalAccelerometerReport() {
  161. readFromMpl(CAL_ACCEL);
  162. }
  163. void CalCompassReport() {
  164. readFromMpl(CAL_COMPASS);
  165. }
  166. void IMUStatusReport() {
  167. readFromMpl(STATUS);
  168. }
  169. void QuaternionReport() {
  170. readFromMpl(QUARTERNION);
  171. }
  172. void EulerAnglesReport() {
  173. readFromMpl(EULER_ANGLES);
  174. }
  175. void RotationMatrixReport() {
  176. readFromMpl(ROTATION_MATRIX);
  177. }
  178. void HeadingReport() {
  179. readFromMpl(HEADING);
  180. }
  181. void LinearAccelReport() {
  182. readFromMpl(LINEAR_ACCEL);
  183. }
  184. void updateIMUData() {
  185. short sensors;
  186. unsigned char more;
  187. if (mpuEnabled && Chip_GPIO_ReadPortBit(LPC_GPIO_PORT, MPU_INT_GND_PORT_GPIO, MPU_INT_GND_PIN_GPIO)) {
  188. if (dmp_read_fifo(gyrometer_data, accelerometer_data, quaternion, &sensor_timestamp, &sensors, &more)) {
  189. return;
  190. }
  191. /* Push the new data to the MPL. */
  192. inv_build_gyro(gyrometer_data, sensor_timestamp);
  193. mpu_get_temperature(&temperature, &sensor_timestamp);
  194. inv_build_temp(temperature, sensor_timestamp);
  195. long converter[3];
  196. for (int i = 0; i < 3; i++) {
  197. converter[i] = accelerometer_data[i];
  198. }
  199. inv_build_accel(converter, 0, sensor_timestamp);
  200. inv_build_quat(quaternion, 0, sensor_timestamp);
  201. for (int i = 0; i < 3; i++) {
  202. converter[i] = magnometer_data[i];
  203. }
  204. mpu_get_compass_reg(magnometer_data, &sensor_timestamp);
  205. inv_build_compass((long*) magnometer_data, 0, sensor_timestamp);
  206. inv_execute_on_data();
  207. }
  208. }
  209. int32_t MPU9105Init() {
  210. Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, MPU_INT_GND_PORT_GPIO, MPU_INT_GND_PIN_GPIO);
  211. Chip_SCU_PinMuxSet(MPU_INT_GND_PORT, MPU_INT_GND_PIN,
  212. SCU_MODE_INBUFF_EN | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN);
  213. mpuEnabled = false;
  214. Chip_I2C_Init(I2C0);
  215. Chip_I2C_SetClockRate(I2C0, FAST_MODE_BAUD);
  216. Chip_I2C_SetMasterEventHandler(I2C0, Chip_I2C_EventHandlerPolling);
  217. LPC_SCU->SFSI2C0 = SFSI2C0_CONFIGURE_STANDARD_FAST_MODE_PLUS;
  218. /* Set up gyro.
  219. * Every function preceded by mpu_ is a driver function and can be found
  220. * in inv_mpu.h.
  221. */
  222. if (mpu_init(NULL)) {
  223. Chip_I2C_DeInit(I2C0);
  224. return MPU_ERROR;
  225. }
  226. bool mplInitialized = false;
  227. if (inv_init_mpl() == INV_SUCCESS) {
  228. mplInitialized = true;
  229. /* Compute 6-axis and 9-axis quaternions. */
  230. inv_enable_quaternion();
  231. inv_enable_9x_sensor_fusion();
  232. inv_9x_fusion_use_timestamps(1);
  233. /* Update gyro biases when not in motion.
  234. */
  235. inv_enable_fast_nomot();
  236. /* Update gyro biases when temperature changes. */
  237. inv_enable_gyro_tc();
  238. /* This algorithm updates the accel biases when in motion. A more accurate
  239. * bias measurement can be made when running the self-test but this algorithm
  240. * can be enabled if the self-test can't be executed in your application.
  241. */
  242. inv_enable_in_use_auto_calibration();
  243. /* Compass calibration algorithms. */
  244. inv_enable_vector_compass_cal();
  245. inv_enable_magnetic_disturbance();
  246. /* If you need to estimate your heading before the compass is calibrated,
  247. * enable this algorithm. It becomes useless after a good figure-eight is
  248. * detected, so we'll just leave it out to save memory.
  249. *
  250. */
  251. inv_enable_heading_from_gyro();
  252. /* Allows use of the MPL APIs in read_from_mpl. */
  253. inv_enable_eMPL_outputs();
  254. inv_start_mpl();
  255. }
  256. /* Get/set hardware configuration. Start gyro. */
  257. /* Wake up all sensors. */
  258. mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL | INV_XYZ_COMPASS);
  259. /* Push both gyro and accel data into the FIFO. */
  260. mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL);
  261. mpu_set_sample_rate(DEFAULT_MPU_HZ);
  262. /* The compass sampling rate can be less than the gyro/accel sampling rate.
  263. * Use this function for proper power management.
  264. */
  265. mpu_set_compass_sample_rate(DEFAULT_MPU_HZ);
  266. unsigned char accel_fsr = 0;
  267. unsigned short gyro_rate = 0, gyro_fsr = 0, compass_fsr = 0;
  268. /* Read back configuration in case it was set improperly. */
  269. mpu_get_sample_rate(&gyro_rate);
  270. mpu_get_gyro_fsr(&gyro_fsr);
  271. mpu_get_accel_fsr(&accel_fsr);
  272. mpu_get_compass_fsr(&compass_fsr);
  273. if (mplInitialized) {
  274. /* Sync driver configuration with MPL. */
  275. /* Sample rate expected in microseconds. */
  276. inv_set_gyro_sample_rate(1000000L / gyro_rate);
  277. inv_set_accel_sample_rate(1000000L / gyro_rate);
  278. /* The compass rate is independent of the gyro and accel rates. As long as
  279. * inv_set_compass_sample_rate is called with the correct value, the 9-axis
  280. * fusion algorithm's compass correction gain will work properly.
  281. */
  282. inv_set_compass_sample_rate(1000000L / gyro_rate);
  283. /* Set chip-to-body orientation matrix.
  284. * Set hardware units to dps/g's/degrees scaling factor.
  285. */
  286. inv_set_gyro_orientation_and_scale(inv_orientation_matrix_to_scalar(gyro_pdata.orientation),
  287. (long) gyro_fsr << 15);
  288. inv_set_accel_orientation_and_scale(inv_orientation_matrix_to_scalar(gyro_pdata.orientation),
  289. (long) accel_fsr << 15);
  290. inv_set_compass_orientation_and_scale(inv_orientation_matrix_to_scalar(compass_pdata.orientation),
  291. (long) compass_fsr << 15);
  292. }
  293. mpu_set_int_level(0);
  294. mpu_set_int_latched(ENABLE);
  295. dmp_load_motion_driver_firmware();
  296. dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_pdata.orientation));
  297. /*
  298. * Known Bug -
  299. * DMP when enabled will sample sensor data at 200Hz and output to FIFO at the rate
  300. * specified in the dmp_set_fifo_rate API. The DMP will then sent an interrupt once
  301. * a sample has been put into the FIFO. Therefore if the dmp_set_fifo_rate is at 25Hz
  302. * there will be a 25Hz interrupt from the MPU device.
  303. *
  304. * There is a known issue in which if you do not enable DMP_FEATURE_TAP
  305. * then the interrupts will be at 200Hz even if fifo rate
  306. * is set at a different rate. To avoid this issue include the DMP_FEATURE_TAP
  307. *
  308. * DMP sensor fusion works only with gyro at +-2000dps and accel +-2G
  309. */
  310. dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
  311. DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
  312. DMP_FEATURE_GYRO_CAL);
  313. dmp_set_fifo_rate(DEFAULT_MPU_HZ);
  314. mpu_set_dmp_state(ENABLE);
  315. Chip_I2C_SetClockRate(I2C0, FAST_MODE_PLUS_BAUD);
  316. mpuEnabled = true;
  317. //Register the sensors
  318. sensorsTimers[STATUS].refresh = IMUStatusReport;
  319. sensorsTimers[RAW_ACCEL].refresh = RawAccelerometerReport;
  320. sensorsTimers[RAW_GYRO].refresh = RawGyroReport;
  321. sensorsTimers[RAW_COMPASS].refresh = RawCompassReport;
  322. if (!mplInitialized) {
  323. return MPL_ERROR;
  324. }
  325. //Otherwise register the calculated sensors
  326. sensorsTimers[CAL_ACCEL].refresh = CalAccelerometerReport;
  327. sensorsTimers[CAL_GYRO].refresh = CalGyroReport;
  328. sensorsTimers[CAL_COMPASS].refresh = CalCompassReport;
  329. sensorsTimers[QUARTERNION].refresh = QuaternionReport;
  330. sensorsTimers[EULER_ANGLES].refresh = EulerAnglesReport;
  331. sensorsTimers[ROTATION_MATRIX].refresh = RotationMatrixReport;
  332. sensorsTimers[HEADING].refresh = HeadingReport;
  333. sensorsTimers[LINEAR_ACCEL].refresh = LinearAccelReport;
  334. return SUCCESS;
  335. }
  336. void disableIMU(void) {
  337. }
  338. int i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t length, uint8_t const *data) {
  339. uint8_t i2cTxBuffer[20]; //Arbitrary value;
  340. if (length > sizeof(i2cTxBuffer) - 1) {
  341. return -1; //This is bad
  342. }
  343. i2cTxBuffer[0] = reg_addr;
  344. memcpy(i2cTxBuffer + 1, data, length);
  345. if (!Chip_I2C_MasterSend(I2C0, slave_addr, i2cTxBuffer, length + 1)) {
  346. return -1; //This is bad
  347. }
  348. return 0;
  349. }
  350. int i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t length, uint8_t *data) {
  351. if (!Chip_I2C_MasterCmdRead(I2C0, slave_addr, reg_addr, data, length)) {
  352. return -1; //This is bad
  353. }
  354. return 0;
  355. }
  356. /**
  357. * Stubs for the MPL library
  358. */
  359. int _MLPrintLog(int priority, const char *tag, const char *fmt, ...) {
  360. return 0;
  361. }
  362. int _MLPrintVaLog(int priority, const char *tag, const char *fmt, va_list args) {
  363. return 0;
  364. }
  365. /* Final implementation of actual writing to a character device */
  366. int _MLWriteLog(const char *buf, int buflen) {
  367. return 0;
  368. }
  369. #endif