dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_mpu.c
Go to the documentation of this file.
1 
12 /*
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  * for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * with this program; if not, see <http://www.gnu.org/licenses/>
25  *
26  * Additional note on redistribution: The copyright and license notices above
27  * must be maintained in each individual source file that is a derivative work
28  * of this source file; otherwise redistribution is prohibited.
29  */
30 
31 #include "openpilot.h"
32 #include "pios.h"
33 
34 #if defined(PIOS_INCLUDE_MPU)
35 
36 #include "pios_semaphore.h"
37 #include "physical_constants.h"
38 
39 #include "pios_mpu_priv.h"
40 
41 #ifndef PIOS_MPU_SPI_HIGH_SPEED
42 #define PIOS_MPU_SPI_HIGH_SPEED 20000000 // should result in 10.5MHz clock on F4 targets like Sparky2
43 #endif // PIOS_MPU_SPI_HIGH_SPEED
44 #define PIOS_MPU_SPI_LOW_SPEED 300000
45 
46 
50 static const uint8_t pios_mpu_whoami[PIOS_MPU_NUM] = {
51  [PIOS_MPU60X0] = 0x68,
52  [PIOS_MPU6500] = 0x70,
53  [PIOS_MPU9150] = 0x68,
54  [PIOS_MPU9250] = 0x71,
55  [PIOS_ICM20608G] = 0xAF,
56  [PIOS_ICM20602] = 0x12,
57  [PIOS_ICM20689] = 0x98,
58 };
59 
63 #if defined(PIOS_INCLUDE_I2C) || defined(__DOXYGEN__)
64 static const uint8_t pios_mpu_i2c_addr[] = {
65  0x68,
66  0x69,
67 };
68 #endif
69 
73 enum pios_mpu_com_driver {
74  PIOS_MPU_COM_I2C,
75  PIOS_MPU_COM_SPI,
76 };
77 
82 enum pios_mpu_dev_magic {
83  PIOS_MPU_DEV_MAGIC = 0xa9dd94b4
84 };
85 
89 struct pios_mpu_dev {
90  const struct pios_mpu_cfg *cfg;
91  enum pios_mpu_type mpu_type;
92  enum pios_mpu_com_driver com_driver_type;
93  pios_spi_t spi_driver_id;
94  pios_i2c_t i2c_driver_id;
95  uint32_t com_slave_addr;
96  struct pios_semaphore *data_ready_sema;
97  enum pios_mpu_gyro_range gyro_range;
98  enum pios_mpu_accel_range accel_range;
99  enum pios_mpu_dev_magic magic;
100  struct pios_sensor_gyro_data gyro_data;
101  struct pios_sensor_accel_data accel_data;
102 #ifdef PIOS_INCLUDE_MPU_MAG
103  bool use_mag;
104  struct pios_sensor_mag_data mag_data;
105  int mag_age;
106  bool do_full_mag;
107 #endif // PIOS_INCLUDE_MPU_MAG
108  volatile uint32_t interrupt_count;
109  volatile uint8_t sensor_ready;
110 };
111 
112 #define SENSOR_ACCEL (1 << 0)
113 #define SENSOR_MAG (1 << 1)
114 
116 static struct pios_mpu_dev *mpu_dev;
117 
119 
122 static struct pios_mpu_dev *PIOS_MPU_Alloc(const struct pios_mpu_cfg *cfg);
123 
124 #ifdef PIOS_INCLUDE_MPU_MAG
125 
128 static int32_t PIOS_MPU_Mag_Probe(void);
129 #endif // PIOS_INCLUDE_MPU_MAG
130 
134 static int32_t PIOS_MPU_Validate(struct pios_mpu_dev *dev);
139 static int32_t PIOS_MPU_Reset();
145 static int32_t PIOS_MPU_Config(struct pios_mpu_cfg const *cfg);
146 static int32_t PIOS_MPU_ReadReg(uint8_t reg);
147 static int32_t PIOS_MPU_WriteReg(uint8_t reg, uint8_t data);
148 
149 #if defined(PIOS_INCLUDE_SPI) || defined(__DOXYGEN__)
150 
155 static int32_t PIOS_MPU_ClaimBus(bool lowspeed);
161 static int32_t PIOS_MPU_ReleaseBus(bool lowspeed);
167 static int32_t PIOS_MPU_SPI_Probe(enum pios_mpu_type *detected_device);
168 #endif // defined(PIOS_INCLUDE_SPI) || defined(__DOXYGEN__)
169 
170 #if defined(PIOS_INCLUDE_I2C) || defined(__DOXYGEN__)
171 
176 static int32_t PIOS_MPU_I2C_Probe(enum pios_mpu_type *detected_device);
177 #endif // defined(PIOS_INCLUDE_I2C) || defined(__DOXYGEN__)
178 
179 static int PIOS_MPU_parse_data(struct pios_mpu_dev *p);
180 
181 static bool PIOS_MPU_callback_gyro(void *ctx, void *output,
182  int ms_to_wait, int *next_call)
183 {
184  struct pios_mpu_dev *dev = (struct pios_mpu_dev *)ctx;
185 
186  PIOS_Assert(dev);
187  PIOS_Assert(output);
188 
189  *next_call = 0; /* Baby you know you can call me anytime */
190 
191  if (PIOS_Semaphore_Take(dev->data_ready_sema, ms_to_wait) != true) {
192  return false;
193  }
194 
195  if (PIOS_MPU_parse_data(dev)) {
196  return false;
197  }
198 
199  memcpy(output, &dev->gyro_data, sizeof(dev->gyro_data));
200 
201  return true;
202 }
203 
204 static bool PIOS_MPU_callback_accel(void *ctx, void *output,
205  int ms_to_wait, int *next_call)
206 {
207  struct pios_mpu_dev *dev = (struct pios_mpu_dev *)ctx;
208 
209  PIOS_Assert(dev);
210  PIOS_Assert(output);
211 
212  *next_call = 0;
213 
214  if (!(dev->sensor_ready & SENSOR_ACCEL)) {
215  return false;
216  }
217 
218  memcpy(output, &dev->accel_data, sizeof(dev->accel_data));
219  dev->sensor_ready &= ~SENSOR_ACCEL;
220 
221  return true;
222 }
223 
224 #if defined(PIOS_INCLUDE_MPU_MAG)
225 static bool PIOS_MPU_callback_mag(void *ctx, void *output,
226  int ms_to_wait, int *next_call)
227 {
228  struct pios_mpu_dev *dev = (struct pios_mpu_dev *)ctx;
229 
230  PIOS_Assert(dev);
231  PIOS_Assert(output);
232 
233  /* TODO: could know this better! */
234  *next_call = 0;
235 
236  if (!(dev->sensor_ready & SENSOR_MAG)) {
237  return false;
238  }
239 
240  memcpy(output, &dev->mag_data, sizeof(dev->mag_data));
241  dev->sensor_ready &= ~SENSOR_MAG;
242 
243  return true;
244 }
245 #endif // PIOS_INCLUDE_MPU_MAG
246 
247 static struct pios_mpu_dev *PIOS_MPU_Alloc(const struct pios_mpu_cfg *cfg)
248 {
249  struct pios_mpu_dev *dev;
250 
251  dev = (struct pios_mpu_dev *)PIOS_malloc(sizeof(*mpu_dev));
252  if (!dev)
253  return NULL;
254 
255  *dev = (struct pios_mpu_dev) {
256  .magic = PIOS_MPU_DEV_MAGIC
257  };
258 
259  dev->data_ready_sema = PIOS_Semaphore_Create();
260  if (dev->data_ready_sema == NULL) {
261  PIOS_free(dev);
262  return NULL;
263  }
264 
265  return dev;
266 }
267 
268 static int32_t PIOS_MPU_Validate(struct pios_mpu_dev *dev)
269 {
270  if (dev == NULL)
271  return -1;
272  if (dev->magic != PIOS_MPU_DEV_MAGIC)
273  return -2;
274  return 0;
275 }
276 
277 static int32_t PIOS_MPU_CheckWhoAmI(enum pios_mpu_type *detected_device)
278 {
279  // mask the reserved bit
280  int32_t retval = PIOS_MPU_ReadReg(PIOS_MPU_WHOAMI);
281 
282  if (retval < 0)
284 
285  for (int i = 0; i < PIOS_MPU_NUM; i++) {
286  if (((uint8_t) retval) == pios_mpu_whoami[i]) {
287  *detected_device = i;
288  return 0;
289  }
290  }
291 
292  return -PIOS_MPU_ERROR_WHOAMI;
293 }
294 
295 static int32_t PIOS_MPU_Reset()
296 {
297  // reset chip
298  if (PIOS_MPU_WriteReg(PIOS_MPU_PWR_MGMT_REG, PIOS_MPU_PWRMGMT_IMU_RST) != 0)
300 
301  // give chip some time to initialize
302  PIOS_DELAY_WaitmS(50);
303 
304  // power management config
305  if (PIOS_MPU_WriteReg(PIOS_MPU_PWR_MGMT_REG, PIOS_MPU_PWRMGMT_PLL_X_CLK) != 0)
307 
308  // user control
309  if (mpu_dev->com_driver_type == PIOS_MPU_COM_SPI) {
312  } else {
313  if (PIOS_MPU_WriteReg(PIOS_MPU_USER_CTRL_REG, PIOS_MPU_USERCTL_I2C_MST_EN) != 0)
315  }
316 
317  return 0;
318 }
319 
320 static int32_t PIOS_MPU_Config(struct pios_mpu_cfg const *cfg)
321 {
322  // Digital low-pass filter and scale
323  // set this before sample rate else sample rate calculation will fail
326 
327  // Sample rate
330 
331  // Set the gyro scale
333 
334  // Set the accel scale
336 
337  // Interrupt configuration
338  PIOS_MPU_WriteReg(PIOS_MPU_INT_CFG_REG, PIOS_MPU_INT_CLR_ANYRD);
339 
340  // Interrupt enable
341  PIOS_MPU_WriteReg(PIOS_MPU_INT_EN_REG, PIOS_MPU_INTEN_DATA_RDY);
342 
343  return 0;
344 }
345 
346 #ifdef PIOS_INCLUDE_MPU_MAG
347 
353 static int32_t PIOS_MPU_Mag_WriteReg(uint8_t reg, uint8_t data)
354 {
355  // we will use I2C SLV4 to manipulate with AK8963 control registers
356  if (PIOS_MPU_WriteReg(PIOS_MPU_SLV4_REG_REG, reg) != 0)
357  return -1;
358  PIOS_MPU_WriteReg(PIOS_MPU_SLV4_REG_REG, reg);
359  PIOS_MPU_WriteReg(PIOS_MPU_SLV4_ADDR_REG, PIOS_MPU_AK89XX_ADDR);
360  PIOS_MPU_WriteReg(PIOS_MPU_SLV4_DO_REG, data);
361  PIOS_MPU_WriteReg(PIOS_MPU_SLV4_CTRL_REG, PIOS_MPU_I2CSLV_EN | 9);
362 
363  // wait for I2C transaction done, use simple safety
364  // escape counter to prevent endless loop in case
365  // MPU is broken
366  uint8_t status = 0;
367  uint32_t timeout = 0;
368  do {
369  if (timeout++ > 50)
370  return -2;
371 
372  status = PIOS_MPU_ReadReg(PIOS_MPU_I2C_MST_STATUS_REG);
373  } while ((status & PIOS_MPU_I2C_MST_SLV4_DONE) == 0);
374 
375  if (status & PIOS_MPU_I2C_MST_SLV4_NACK)
376  return -3;
377 
378  return 0;
379 }
380 
386 static uint8_t PIOS_MPU_Mag_ReadReg(uint8_t reg)
387 {
388  // we will use I2C SLV4 to manipulate with AK8xxx control registers
389  PIOS_MPU_WriteReg(PIOS_MPU_SLV4_REG_REG, reg);
390  PIOS_MPU_WriteReg(PIOS_MPU_SLV4_ADDR_REG, PIOS_MPU_AK89XX_ADDR | 0x80);
391 
392  // The 9 here-- does "slow" transactions at a /10 rate ... or 50Hz when
393  // sampling rate is 500. Only used for 9150 triggering.
394  PIOS_MPU_WriteReg(PIOS_MPU_SLV4_CTRL_REG, PIOS_MPU_I2CSLV_EN | 9);
395 
396  // wait for I2C transaction done, use simple safety
397  // escape counter to prevent endless loop in case
398  // MPU is broken
399  uint8_t status = 0;
400  uint32_t timeout = 0;
401  do {
402  if (timeout++ > 50)
403  return 0;
404 
405  status = PIOS_MPU_ReadReg(PIOS_MPU_I2C_MST_STATUS_REG);
406  } while ((status & PIOS_MPU_I2C_MST_SLV4_DONE) == 0);
407 
408  return PIOS_MPU_ReadReg(PIOS_MPU_SLV4_DI_REG);
409 }
410 
411 static void PIOS_MPU_Mag_Trigger(void)
412 {
413  // set magnetometer sampling rate to 100Hz and 16-bit resolution
414  if (mpu_dev->mpu_type == PIOS_MPU9250) {
416  } else if (mpu_dev->mpu_type == PIOS_MPU9150) {
418  PIOS_MPU_WriteReg(PIOS_MPU_SLV1_ADDR_REG, PIOS_MPU_AK89XX_ADDR);
419  PIOS_MPU_WriteReg(PIOS_MPU_SLV1_DO_REG,
421  PIOS_MPU_WriteReg(PIOS_MPU_SLV1_CTRL_REG, PIOS_MPU_I2CSLV_EN | 1);
422  }
423 }
424 
430 static int32_t PIOS_MPU_Mag_Config(void)
431 {
432  if (mpu_dev->mpu_type == PIOS_MPU9250) {
433  // reset AK8963
434  if (PIOS_MPU_Mag_WriteReg(PIOS_MPU_AK8963_CNTL2_REG, PIOS_MPU_AK8963_CNTL2_SRST) != 0)
435  return -3;
436  }
437 
438  // AK8975 (MPU-9150) doesn't have soft reset function
439 
440  // give chip some time to initialize
442 
443  // Set Slave 1 slow, just in case we're going to use it. and set
444  // I2C regs shadowed.
445  PIOS_MPU_WriteReg(PIOS_MPU_I2C_MST_DELAY_CTRL,
448 
449  PIOS_MPU_Mag_Trigger();
450 
451  // configure mpu to read ak89xx data range from STATUS1 to CTRL at ODR
453  PIOS_MPU_WriteReg(PIOS_MPU_SLV0_ADDR_REG, PIOS_MPU_AK89XX_ADDR | 0x80);
454  PIOS_MPU_WriteReg(PIOS_MPU_SLV0_CTRL_REG, PIOS_MPU_I2CSLV_EN | 8);
455 
456  return 0;
457 }
458 
459 static int32_t PIOS_MPU_Mag_Probe(void)
460 {
461  /* probe for mag whomai */
462  uint8_t id = PIOS_MPU_Mag_ReadReg(PIOS_MPU_AK89XX_WHOAMI_REG);
463  if (id != PIOS_MPU_AK89XX_WHOAMI_ID)
464  return -2;
465 
466  return 0;
467 }
468 #endif // PIOS_INCLUDE_MPU_MAG
469 
470 static int32_t PIOS_MPU_Common_Init(void)
471 {
472  /* Configure the MPU Sensor */
473  if (PIOS_MPU_Reset() != 0)
474  return -PIOS_MPU_ERROR_NOCONFIG;
475 
476 #ifdef PIOS_INCLUDE_MPU_MAG
477  /* Probe for mag */
478  if (mpu_dev->cfg->use_internal_mag) {
479  mpu_dev->use_mag = true;
480  if (PIOS_MPU_Mag_Probe() == 0) {
481  if (mpu_dev->mpu_type == PIOS_MPU60X0)
482  mpu_dev->mpu_type = PIOS_MPU9150;
483 
484  if (PIOS_MPU_Mag_Config() != 0)
485  return -PIOS_MPU_ERROR_MAGFAILED;
486  } else if (mpu_dev->mpu_type == PIOS_MPU9250) {
487  /* we have positively identified 9250 so we can be sure
488  * this is a hardware failure */
489  return -PIOS_MPU_ERROR_MAGFAILED;
490  } else {
491  /* we can't positively identify 9150 so just disable mag
492  * (and some boards can have 6xx0 _or_ 9150 placed...) */
493  mpu_dev->use_mag = false;
494  }
495  } else {
496  mpu_dev->use_mag = false;
497  }
498 #endif // PIOS_INCLUDE_MPU_MAG
499 
500  /* Configure the MPU Sensor */
501  if (PIOS_MPU_Config(mpu_dev->cfg) != 0)
502  return -PIOS_MPU_ERROR_NOCONFIG;
503 
504  /* Set up EXTI line */
505  PIOS_EXTI_Init(mpu_dev->cfg->exti_cfg);
506 
507  /* Wait 20 ms for data ready interrupt and make sure it happens twice */
508  if (!mpu_dev->cfg->skip_startup_irq_check) {
509  for (int i=0; i<2; i++) {
510  uint32_t ref_val = mpu_dev->interrupt_count;
511  uint32_t raw_start = PIOS_DELAY_GetRaw();
512 
513  while (mpu_dev->interrupt_count == ref_val) {
514  if (PIOS_DELAY_DiffuS(raw_start) > 20000) {
515  PIOS_EXTI_DeInit(mpu_dev->cfg->exti_cfg);
516  return -PIOS_MPU_ERROR_NOIRQ;
517  }
518  }
519  }
520  }
521 
522  mpu_dev->accel_range = PIOS_MPU_SCALE_8G;
523  mpu_dev->gyro_range = PIOS_MPU_SCALE_1000_DEG;
524 
526  PIOS_MPU_callback_gyro, mpu_dev);
527 
528  PIOS_Assert(!ret);
529 
531  PIOS_MPU_callback_accel, mpu_dev);
532 
533  PIOS_Assert(!ret);
534 #ifdef PIOS_INCLUDE_MPU_MAG
535  if (mpu_dev->use_mag) {
537  PIOS_MPU_callback_mag, mpu_dev);
538 
539  PIOS_Assert(!ret);
540  }
541 #endif // PIOS_INCLUDE_MPU_MAG
542 
543  return 0;
544 }
545 
551 int32_t PIOS_MPU_SetGyroRange(enum pios_mpu_gyro_range range)
552 {
553  if (PIOS_MPU_WriteReg(PIOS_MPU_GYRO_CFG_REG, range) != 0)
555 
556  switch (range) {
559  break;
562  break;
565  break;
568  break;
569  }
570 
571  mpu_dev->gyro_range = range;
572 
573  return 0;
574 }
575 
582 {
583  if (PIOS_MPU_WriteReg(PIOS_MPU_ACCEL_CFG_REG, range) != 0)
585 
586  mpu_dev->accel_range = range;
587 
588  return 0;
589 }
590 
595 static float PIOS_MPU_GetGyroScale(void)
596 {
597  switch (mpu_dev->gyro_range) {
599  return 1.0f / 131.0f;
601  return 1.0f / 65.5f;
603  return 1.0f / 32.8f;
605  return 1.0f / 16.4f;
606  }
607  return 0;
608 }
609 
614 static float PIOS_MPU_GetAccelScale(void)
615 {
616  switch (mpu_dev->accel_range) {
617  case PIOS_MPU_SCALE_2G:
618  return GRAVITY / 16384.0f;
619  case PIOS_MPU_SCALE_4G:
620  return GRAVITY / 8192.0f;
621  case PIOS_MPU_SCALE_8G:
622  return GRAVITY / 4096.0f;
623  case PIOS_MPU_SCALE_16G:
624  return GRAVITY / 2048.0f;
625  }
626  return 0;
627 }
628 
629 void PIOS_MPU_SetGyroBandwidth(uint16_t bandwidth)
630 {
631  uint8_t filter;
632  // TODO: investigate 250/256 Hz (Fs=8 kHz, aliasing?)
633  if (mpu_dev->mpu_type == PIOS_MPU6500 || mpu_dev->mpu_type == PIOS_MPU9250) {
634  if (bandwidth <= 5)
636  else if (bandwidth <= 10)
638  else if (bandwidth <= 20)
640  else if (bandwidth <= 41)
642  else if (bandwidth <= 92)
644  else
646  } else if ((mpu_dev->mpu_type == PIOS_MPU60X0) || (mpu_dev->mpu_type == PIOS_MPU9150)) {
647  if (bandwidth <= 5)
649  else if (bandwidth <= 10)
651  else if (bandwidth <= 20)
653  else if (bandwidth <= 42)
655  else if (bandwidth <= 98)
657  else
659  } else {
660  if (bandwidth <= 5)
662  else if (bandwidth <= 10)
664  else if (bandwidth <= 20)
666  else if (bandwidth <= 92)
668  else
670 #if 0
671  /* Unsupported/higher sample rates */
672  else if (bandwidth <= 176)
674  else if (bandwidth <= 250)
676  else
678 #endif
679  }
680 
681  PIOS_MPU_WriteReg(PIOS_MPU_DLPF_CFG_REG, filter);
682 }
683 
684 void PIOS_MPU_SetAccelBandwidth(uint16_t bandwidth)
685 {
686  if (mpu_dev->mpu_type != PIOS_MPU6500 &&
687  mpu_dev->mpu_type != PIOS_MPU9250 &&
688  mpu_dev->mpu_type != PIOS_ICM20608G &&
689  mpu_dev->mpu_type != PIOS_ICM20602 &&
690  mpu_dev->mpu_type != PIOS_ICM20689)
691  return;
692 
693  enum pios_mpu6500_accel_filter filter;
694  if (mpu_dev->mpu_type == PIOS_MPU6500 || mpu_dev->mpu_type == PIOS_MPU9250) {
695  if (bandwidth <= 5)
697  else if (bandwidth <= 10)
699  else if (bandwidth <= 20)
701  else if (bandwidth <= 41)
703  else if (bandwidth <= 92)
705  else if (bandwidth <= 184)
707  else
709  } else {
710  if (bandwidth <= 5)
712  else if (bandwidth <= 10)
714  else if (bandwidth <= 21)
716  else if (bandwidth <= 45)
718  else if (bandwidth <= 99)
720  else if (bandwidth <= 218)
722  else
724  }
725 
726  PIOS_MPU_WriteReg(PIOS_MPU_ACCEL_CFG2_REG, filter);
727 }
728 
729 int32_t PIOS_MPU_SetSampleRate(uint16_t samplerate_hz)
730 {
731  // TODO: think about supporting >1 khz, aliasing/noise issues though..
732  uint16_t internal_rate = 1000;
733 
734  // limit samplerate to filter frequency
735  if (samplerate_hz > internal_rate)
736  samplerate_hz = internal_rate;
737 
738  // calculate divisor, round to nearest integer
739  int32_t divisor = (int32_t)(((float)internal_rate / samplerate_hz) + 0.5f) - 1;
740 
741  // limit resulting divisor to register value range
742  if (divisor < 0)
743  divisor = 0;
744 
745  if (divisor > 0xff)
746  divisor = 0xff;
747 
748  // calculate true sample rate
749  samplerate_hz = internal_rate / (1 + divisor);
750 
751  int32_t retval = PIOS_MPU_WriteReg(PIOS_MPU_SMPLRT_DIV_REG, (uint8_t)divisor);
752 
753  if (retval == 0) {
756 #ifdef PIOS_INCLUDE_MPU_MAG
757  if (mpu_dev->use_mag) {
758  if (mpu_dev->mpu_type == PIOS_MPU9150) {
760  samplerate_hz / 10);
761  } else {
763  }
764  }
765 #endif // PIOS_INCLUDE_MPU_MAG
766  }
767 
768  return retval;
769 }
770 
772 {
773  return mpu_dev->mpu_type;
774 }
775 
776 #if defined(PIOS_INCLUDE_I2C)
777 static int32_t PIOS_MPU_I2C_Probe(enum pios_mpu_type *detected_device)
778 {
779  int32_t retval = -1;
780  for (int i = 0; i < NELEMENTS(pios_mpu_i2c_addr); i++) {
781  mpu_dev->com_slave_addr = pios_mpu_i2c_addr[i];
782  retval = PIOS_MPU_CheckWhoAmI(detected_device);
783  if (retval == 0)
784  break;
785  }
786  return retval;
787 }
788 
789 int32_t PIOS_MPU_I2C_Init(pios_mpu_dev_t *dev, pios_i2c_t i2c_id, const struct pios_mpu_cfg *cfg)
790 {
791  if (!*dev) {
792  mpu_dev = PIOS_MPU_Alloc(cfg);
793  if (mpu_dev == NULL)
794  return -1;
795  *dev = mpu_dev;
796  } else {
797  mpu_dev = *dev;
798  }
799 
800  mpu_dev->com_driver_type = PIOS_MPU_COM_I2C;
801  mpu_dev->i2c_driver_id = i2c_id;
802  mpu_dev->cfg = cfg;
803 
804  if (PIOS_MPU_I2C_Probe(&mpu_dev->mpu_type) != 0)
806 
807  return PIOS_MPU_Common_Init();
808 }
809 
810 static int32_t PIOS_MPU_I2C_Read(uint8_t address, uint8_t *buffer, uint8_t len)
811 {
812  uint8_t addr_buffer[] = {
813  address,
814  };
815 
816  const struct pios_i2c_txn txn_list[] = {
817  {
818  .info = __func__,
819  .addr = mpu_dev->com_slave_addr,
820  .rw = PIOS_I2C_TXN_WRITE,
821  .len = sizeof(addr_buffer),
822  .buf = addr_buffer,
823  },
824  {
825  .info = __func__,
826  .addr = mpu_dev->com_slave_addr,
827  .rw = PIOS_I2C_TXN_READ,
828  .len = len,
829  .buf = buffer,
830  }
831  };
832 
833  return PIOS_I2C_Transfer(mpu_dev->i2c_driver_id, txn_list, NELEMENTS(txn_list));
834 }
835 
836 static int32_t PIOS_MPU_I2C_Write(uint8_t address, uint8_t buffer)
837 {
838  uint8_t data[] = {
839  address,
840  buffer,
841  };
842 
843  const struct pios_i2c_txn txn_list[] = {
844  {
845  .info = __func__,
846  .addr = mpu_dev->com_slave_addr,
847  .rw = PIOS_I2C_TXN_WRITE,
848  .len = sizeof(data),
849  .buf = data,
850  },
851  };
852 
853  return PIOS_I2C_Transfer(mpu_dev->i2c_driver_id, txn_list, NELEMENTS(txn_list));
854 }
855 #endif // defined(PIOS_INCLUDE_I2C)
856 
857 #if defined(PIOS_INCLUDE_SPI)
858 int32_t PIOS_MPU_SPI_Init(pios_mpu_dev_t *dev, pios_spi_t spi_id,
859  uint32_t slave_num, const struct pios_mpu_cfg *cfg)
860 {
861  if (!*dev) {
862  mpu_dev = PIOS_MPU_Alloc(cfg);
863  if (mpu_dev == NULL)
864  return -1;
865  *dev = mpu_dev;
866  } else {
867  mpu_dev = *dev;
868  }
869 
870  mpu_dev->com_driver_type = PIOS_MPU_COM_SPI;
871  mpu_dev->spi_driver_id = spi_id;
872  mpu_dev->com_slave_addr = slave_num;
873  mpu_dev->cfg = cfg;
874 
875  int32_t ret = PIOS_MPU_SPI_Probe(&mpu_dev->mpu_type);
876 
877  if (ret) {
878  return ret;
879  }
880 
881  return PIOS_MPU_Common_Init();
882 }
883 
884 static int32_t PIOS_MPU_SPI_Probe(enum pios_mpu_type *detected_device)
885 {
886  int32_t retval = PIOS_MPU_CheckWhoAmI(detected_device);
887  return retval;
888 }
889 
890 static int32_t PIOS_MPU_ClaimBus(bool lowspeed)
891 {
892  if (PIOS_MPU_Validate(mpu_dev) != 0)
893  return -1;
894 
895  if (PIOS_SPI_ClaimBus(mpu_dev->spi_driver_id) != 0)
896  return -2;
897 
898  if (lowspeed)
899  PIOS_SPI_SetClockSpeed(mpu_dev->spi_driver_id, PIOS_MPU_SPI_LOW_SPEED);
900 
901  PIOS_SPI_RC_PinSet(mpu_dev->spi_driver_id, mpu_dev->com_slave_addr, 0);
902 
903  return 0;
904 }
905 
906 static int32_t PIOS_MPU_ReleaseBus(bool lowspeed)
907 {
908  if (PIOS_MPU_Validate(mpu_dev) != 0)
909  return -1;
910 
911  PIOS_SPI_RC_PinSet(mpu_dev->spi_driver_id, mpu_dev->com_slave_addr, 1);
912 
913  if (lowspeed)
914  PIOS_SPI_SetClockSpeed(mpu_dev->spi_driver_id, PIOS_MPU_SPI_HIGH_SPEED);
915 
916  PIOS_SPI_ReleaseBus(mpu_dev->spi_driver_id);
917 
918  return 0;
919 }
920 
921 static int32_t PIOS_MPU_SPI_Read(uint8_t address, uint8_t *buffer)
922 {
923  if (PIOS_MPU_ClaimBus(true) != 0)
924  return -1;
925 
926  PIOS_SPI_TransferByte(mpu_dev->spi_driver_id, 0x80 | address); // request byte
927  *buffer = PIOS_SPI_TransferByte(mpu_dev->spi_driver_id, 0); // receive response
928 
929  PIOS_MPU_ReleaseBus(true);
930 
931  return 0;
932 }
933 
934 static int32_t PIOS_MPU_SPI_Write(uint8_t address, uint8_t buffer)
935 {
936  if (PIOS_MPU_ClaimBus(true) != 0)
937  return -1;
938 
939  PIOS_SPI_TransferByte(mpu_dev->spi_driver_id, 0x7f & address);
940  PIOS_SPI_TransferByte(mpu_dev->spi_driver_id, buffer);
941 
942  PIOS_MPU_ReleaseBus(true);
943 
944  return 0;
945 }
946 #endif // defined(PIOS_INCLUDE_SPI)
947 
948 static int32_t PIOS_MPU_WriteReg(uint8_t reg, uint8_t data)
949 {
950 #if defined(PIOS_INCLUDE_I2C)
951  if (mpu_dev->com_driver_type == PIOS_MPU_COM_I2C)
952  return PIOS_MPU_I2C_Write(reg, data);
953 #endif // defined(PIOS_INCLUDE_I2C)
954 #if defined(PIOS_INCLUDE_SPI)
955  if (mpu_dev->com_driver_type == PIOS_MPU_COM_SPI)
956  return PIOS_MPU_SPI_Write(reg, data);
957 #endif // defined(PIOS_INCLUDE_SPI)
958 
959  return -1;
960 }
961 
962 static int32_t PIOS_MPU_ReadReg(uint8_t reg)
963 {
964  uint8_t data;
965  int32_t retval = -1;
966 
967 #if defined(PIOS_INCLUDE_I2C)
968  if (mpu_dev->com_driver_type == PIOS_MPU_COM_I2C)
969  retval = PIOS_MPU_I2C_Read(reg, &data, sizeof(data));
970 #endif // defined(PIOS_INCLUDE_I2C)
971 #if defined(PIOS_INCLUDE_SPI)
972  if (mpu_dev->com_driver_type == PIOS_MPU_COM_SPI)
973  retval = PIOS_MPU_SPI_Read(reg, &data);
974 #endif // defined(PIOS_INCLUDE_SPI)
975 
976  if (retval != 0)
977  return retval;
978  else
979  return data;
980 }
981 
982 bool PIOS_MPU_IRQHandler(void)
983 {
984  if (PIOS_MPU_Validate(mpu_dev) != 0)
985  return false;
986 
987  bool woken = false;
988 
989  mpu_dev->interrupt_count++;
990 
991  PIOS_Semaphore_Give_FromISR(mpu_dev->data_ready_sema, &woken);
992 
993  return woken;
994 }
995 
1001 static int PIOS_MPU_parse_data(struct pios_mpu_dev *p)
1002 {
1003  enum {
1004  IDX_SPI_DUMMY_BYTE = 0,
1005  IDX_ACCEL_XOUT_H,
1006  IDX_ACCEL_XOUT_L,
1007  IDX_ACCEL_YOUT_H,
1008  IDX_ACCEL_YOUT_L,
1009  IDX_ACCEL_ZOUT_H,
1010  IDX_ACCEL_ZOUT_L,
1011  IDX_TEMP_OUT_H,
1012  IDX_TEMP_OUT_L,
1013  IDX_GYRO_XOUT_H,
1014  IDX_GYRO_XOUT_L,
1015  IDX_GYRO_YOUT_H,
1016  IDX_GYRO_YOUT_L,
1017  IDX_GYRO_ZOUT_H,
1018  IDX_GYRO_ZOUT_L,
1019 #ifdef PIOS_INCLUDE_MPU_MAG
1020  IDX_MAG_ST1,
1021  IDX_MAG_XOUT_L,
1022  IDX_MAG_XOUT_H,
1023  IDX_MAG_YOUT_L,
1024  IDX_MAG_YOUT_H,
1025  IDX_MAG_ZOUT_L,
1026  IDX_MAG_ZOUT_H,
1027  IDX_MAG_ST2,
1028 #endif // PIOS_INCLUDE_MPU_MAG
1029  BUFFER_SIZE
1030  };
1031 
1032  uint8_t mpu_rec_buf[BUFFER_SIZE];
1033 
1034 #ifdef PIOS_INCLUDE_SPI
1035  uint8_t mpu_tx_buf[BUFFER_SIZE] = {PIOS_MPU_ACCEL_X_OUT_MSB | 0x80, };
1036 #endif // PIOS_INCLUDE_SPI
1037 
1038 #ifdef PIOS_INCLUDE_MPU_MAG
1039  mpu_dev->mag_age++;
1040 
1041  uint8_t transfer_size;
1042  /* By default we only transfer the magnetometer status
1043  * information, and leave the actual mag data invalid. If the
1044  * status info says DRDY, then next time around we transfer it
1045  * all.
1046  */
1047  if (mpu_dev->use_mag) {
1048  if (mpu_dev->do_full_mag) {
1049  transfer_size = BUFFER_SIZE;
1050  } else {
1051  /* If mag_age is low, could consider not
1052  * even polling */
1053  transfer_size = IDX_MAG_ST1 + 1;
1054  }
1055  } else {
1056  transfer_size = IDX_GYRO_ZOUT_L + 1;
1057  }
1058 #else
1059  uint8_t transfer_size = BUFFER_SIZE;
1060 #endif // PIOS_INCLUDE_MPU_MAG
1061 
1062 #if defined(PIOS_INCLUDE_SPI)
1063  if (mpu_dev->com_driver_type == PIOS_MPU_COM_SPI) {
1064  // claim bus in high speed mode
1065  if (PIOS_MPU_ClaimBus(false) != 0)
1066  return -1;
1067 
1068  if (PIOS_SPI_TransferBlock(mpu_dev->spi_driver_id, mpu_tx_buf, mpu_rec_buf, transfer_size) < 0) {
1069  PIOS_MPU_ReleaseBus(false);
1070  return -1;
1071  }
1072 
1073  PIOS_MPU_ReleaseBus(false);
1074  }
1075 #endif // defined(PIOS_INCLUDE_SPI)
1076 
1077 #if defined(PIOS_INCLUDE_I2C)
1078  if (mpu_dev->com_driver_type == PIOS_MPU_COM_I2C) {
1079  // we skip the SPI dummy byte at the beginning of the buffer here
1080  if (PIOS_MPU_I2C_Read(PIOS_MPU_ACCEL_X_OUT_MSB, &mpu_rec_buf[IDX_ACCEL_XOUT_H], transfer_size - 1) < 0)
1081  return -1;
1082  }
1083 #endif // defined(PIOS_INCLUDE_I2C)
1084 
1085  float accel_x = (int16_t)(mpu_rec_buf[IDX_ACCEL_XOUT_H] << 8 | mpu_rec_buf[IDX_ACCEL_XOUT_L]);
1086  float accel_y = (int16_t)(mpu_rec_buf[IDX_ACCEL_YOUT_H] << 8 | mpu_rec_buf[IDX_ACCEL_YOUT_L]);
1087  float accel_z = (int16_t)(mpu_rec_buf[IDX_ACCEL_ZOUT_H] << 8 | mpu_rec_buf[IDX_ACCEL_ZOUT_L]);
1088  float gyro_x = (int16_t)(mpu_rec_buf[IDX_GYRO_XOUT_H] << 8 | mpu_rec_buf[IDX_GYRO_XOUT_L]);
1089  float gyro_y = (int16_t)(mpu_rec_buf[IDX_GYRO_YOUT_H] << 8 | mpu_rec_buf[IDX_GYRO_YOUT_L]);
1090  float gyro_z = (int16_t)(mpu_rec_buf[IDX_GYRO_ZOUT_H] << 8 | mpu_rec_buf[IDX_GYRO_ZOUT_L]);
1091 
1092  // Apply sensor scaling
1093  float accel_scale = PIOS_MPU_GetAccelScale();
1094  float gyro_scale = PIOS_MPU_GetGyroScale();
1095 
1096  accel_x *= accel_scale;
1097  accel_y *= accel_scale;
1098  accel_z *= accel_scale;
1099 
1100  gyro_x *= gyro_scale;
1101  gyro_y *= gyro_scale;
1102  gyro_z *= gyro_scale;
1103 
1104 #ifdef PIOS_INCLUDE_MPU_MAG
1105  float mag_x = (int16_t)(mpu_rec_buf[IDX_MAG_XOUT_H] << 8 | mpu_rec_buf[IDX_MAG_XOUT_L]);
1106  float mag_y = (int16_t)(mpu_rec_buf[IDX_MAG_YOUT_H] << 8 | mpu_rec_buf[IDX_MAG_YOUT_L]);
1107  float mag_z = (int16_t)(mpu_rec_buf[IDX_MAG_ZOUT_H] << 8 | mpu_rec_buf[IDX_MAG_ZOUT_L]);
1108 
1109  struct pios_sensor_mag_data *mag_data = &mpu_dev->mag_data;
1110 #endif // PIOS_INCLUDE_MPU_MAG
1111 
1112  struct pios_sensor_gyro_data *gyro_data = &mpu_dev->gyro_data;
1113  struct pios_sensor_accel_data *accel_data = &mpu_dev->accel_data;
1114 
1115  /*
1116  * Rotate the sensor to our convention (x forward, y right, z down).
1117  * Sensor orientation for all supported Invensense variants is
1118  * x right, y forward, z up.
1119  * The embedded AK8xxx magnetometer in MPU9x50 variants matches our convention.
1120  * See flight/Doc/imu_orientation.md for further detail
1121  */
1122  switch (mpu_dev->cfg->orientation) {
1123  case PIOS_MPU_TOP_0DEG:
1124  accel_data->x = accel_y;
1125  accel_data->y = accel_x;
1126  accel_data->z = -accel_z;
1127  gyro_data->x = gyro_y;
1128  gyro_data->y = gyro_x;
1129  gyro_data->z = -gyro_z;
1130 #ifdef PIOS_INCLUDE_MPU_MAG
1131  mag_data->x = mag_x;
1132  mag_data->y = mag_y;
1133  mag_data->z = mag_z;
1134 #endif // PIOS_INCLUDE_MPU_MAG
1135  break;
1136  case PIOS_MPU_TOP_90DEG:
1137  accel_data->x = -accel_x;
1138  accel_data->y = accel_y;
1139  accel_data->z = -accel_z;
1140  gyro_data->x = -gyro_x;
1141  gyro_data->y = gyro_y;
1142  gyro_data->z = -gyro_z;
1143 #ifdef PIOS_INCLUDE_MPU_MAG
1144  mag_data->x = -mag_y;
1145  mag_data->y = mag_x;
1146  mag_data->z = mag_z;
1147 #endif // PIOS_INCLUDE_MPU_MAG
1148  break;
1149  case PIOS_MPU_TOP_180DEG:
1150  accel_data->x = -accel_y;
1151  accel_data->y = -accel_x;
1152  accel_data->z = -accel_z;
1153  gyro_data->x = -gyro_y;
1154  gyro_data->y = -gyro_x;
1155  gyro_data->z = -gyro_z;
1156 #ifdef PIOS_INCLUDE_MPU_MAG
1157  mag_data->x = -mag_x;
1158  mag_data->y = -mag_y;
1159  mag_data->z = mag_z;
1160 #endif // PIOS_INCLUDE_MPU_MAG
1161  break;
1162  case PIOS_MPU_TOP_270DEG:
1163  accel_data->x = accel_x;
1164  accel_data->y = -accel_y;
1165  accel_data->z = -accel_z;
1166  gyro_data->x = gyro_x;
1167  gyro_data->y = -gyro_y;
1168  gyro_data->z = -gyro_z;
1169 #ifdef PIOS_INCLUDE_MPU_MAG
1170  mag_data->x = mag_y;
1171  mag_data->y = -mag_x;
1172  mag_data->z = mag_z;
1173 #endif // PIOS_INCLUDE_MPU_MAG
1174  break;
1175  case PIOS_MPU_BOTTOM_0DEG:
1176  accel_data->x = accel_y;
1177  accel_data->y = -accel_x;
1178  accel_data->z = accel_z;
1179  gyro_data->x = gyro_y;
1180  gyro_data->y = -gyro_x;
1181  gyro_data->z = gyro_z;
1182 #ifdef PIOS_INCLUDE_MPU_MAG
1183  mag_data->x = mag_x;
1184  mag_data->y = -mag_y;
1185  mag_data->z = -mag_z;
1186 #endif // PIOS_INCLUDE_MPU_MAG
1187  break;
1188 
1189  case PIOS_MPU_BOTTOM_90DEG:
1190  accel_data->x = accel_x;
1191  accel_data->y = accel_y;
1192  accel_data->z = accel_z;
1193  gyro_data->x = gyro_x;
1194  gyro_data->y = gyro_y;
1195  gyro_data->z = gyro_z;
1196 #ifdef PIOS_INCLUDE_MPU_MAG
1197  mag_data->x = mag_y;
1198  mag_data->y = mag_x;
1199  mag_data->z = -mag_z;
1200 #endif // PIOS_INCLUDE_MPU_MAG
1201  break;
1202 
1204  accel_data->x = -accel_y;
1205  accel_data->y = accel_x;
1206  accel_data->z = accel_z;
1207  gyro_data->x = -gyro_y;
1208  gyro_data->y = gyro_x;
1209  gyro_data->z = gyro_z;
1210 #ifdef PIOS_INCLUDE_MPU_MAG
1211  mag_data->x = -mag_x;
1212  mag_data->y = mag_y;
1213  mag_data->z = -mag_z;
1214 #endif // PIOS_INCLUDE_MPU_MAG
1215  break;
1216 
1218  accel_data->x = -accel_x;
1219  accel_data->y = -accel_y;
1220  accel_data->z = accel_z;
1221  gyro_data->x = -gyro_x;
1222  gyro_data->y = -gyro_y;
1223  gyro_data->z = gyro_z;
1224 #ifdef PIOS_INCLUDE_MPU_MAG
1225  mag_data->x = -mag_y;
1226  mag_data->y = -mag_x;
1227  mag_data->z = -mag_z;
1228 #endif // PIOS_INCLUDE_MPU_MAG
1229  break;
1230  }
1231 
1232  int16_t raw_temp = (int16_t)(mpu_rec_buf[IDX_TEMP_OUT_H] << 8 | mpu_rec_buf[IDX_TEMP_OUT_L]);
1233  float temperature;
1234  if (mpu_dev->mpu_type == PIOS_MPU6500 || mpu_dev->mpu_type == PIOS_MPU9250)
1235  temperature = 21.0f + ((float)raw_temp) / 333.87f;
1236  else
1237  temperature = 35.0f + ((float)raw_temp + 512.0f) / 340.0f;
1238 
1239  gyro_data->temperature = temperature;
1240  accel_data->temperature = temperature;
1241 
1242  mpu_dev->sensor_ready |= SENSOR_ACCEL;
1243 
1244 #ifdef PIOS_INCLUDE_MPU_MAG
1245  if (mpu_dev->use_mag) {
1246  if (mpu_dev->do_full_mag) {
1247  mpu_dev->mag_age = 0;
1248 
1249  // DRDY will have gotten cleared by the previous
1250  // read cycle, so don't look.
1251 
1252  // check for overflow
1253  bool mag_ok = !(mpu_rec_buf[IDX_MAG_ST2] & PIOS_MPU_AK89XX_ST2_HOFL);
1254 
1255  mag_ok &= (mpu_dev->mpu_type != PIOS_MPU9150) ||
1256  (!(mpu_rec_buf[IDX_MAG_ST2] & PIOS_MPU_AK8975_ST2_DERR));
1257  if (mag_ok) {
1258  float mag_scale;
1259  if (mpu_dev->mpu_type == PIOS_MPU9150)
1260  mag_scale = 3.0f; // 12-bit sampling
1261  else if (mpu_rec_buf[IDX_MAG_ST2] & PIOS_MPU_AK8963_ST2_BITM)
1262  mag_scale = 1.5f; // 16-bit sampling
1263  else
1264  mag_scale = 6.0f; // 14-bit sampling
1265  mag_data->x *= mag_scale;
1266  mag_data->y *= mag_scale;
1267  mag_data->z *= mag_scale;
1268 
1269  mpu_dev->sensor_ready |= SENSOR_MAG;
1270  }
1271 
1272  mpu_dev->do_full_mag = false;
1273  } else {
1274  if (mpu_rec_buf[IDX_MAG_ST1] & PIOS_MPU_AK89XX_ST1_DRDY) {
1275  if (mpu_dev->mag_age > 3) {
1276  mpu_dev->do_full_mag = true;
1277  }
1278  }
1279  }
1280  }
1281 #endif // PIOS_INCLUDE_MPU_MAG
1282  return 0;
1283 }
1284 
1285 #endif // PIOS_INCLUDE_MPU
1286 
int32_t PIOS_MPU_I2C_Init(pios_mpu_dev_t *dev, pios_i2c_t i2c_id, const struct pios_mpu_cfg *cfg)
Initialize the MPU-xxxx 6/9-axis sensor on I2C.
#define PIOS_MPU_AK89XX_ADDR
#define PIOS_MPU_I2CMSTDELAY_ESSHADOW
#define PIOS_MPU_SLV4_DI_REG
Definition: pios_mpu_priv.h:53
#define PIOS_MPU_AK89XX_ST1_DRDY
uint32_t PIOS_DELAY_DiffuS(uint32_t raw)
Subtract raw time from now and convert to us.
Definition: pios_delay.c:159
int32_t PIOS_MPU_SetSampleRate(uint16_t samplerate_hz)
#define PIOS_MPU_I2C_MST_STATUS_REG
Definition: pios_mpu_priv.h:54
#define PIOS_MPU_USERCTL_I2C_MST_EN
void PIOS_SENSORS_SetMaxGyro(int32_t rate)
Set the maximum gyro rate in deg/s.
Definition: pios_sensors.c:162
Main PiOS header to include all the compiled in PiOS options.
#define PIOS_MPU_I2CMSTDELAY_SLV1EN
int32_t PIOS_SPI_RC_PinSet(pios_spi_t spi_dev, uint32_t slave_id, bool pin_value)
#define NELEMENTS(x)
Definition: pios.h:192
enum pios_mpu_type PIOS_MPU_GetType(void)
Which type of MPU was detected?
int32_t PIOS_EXTI_Init(const struct pios_exti_cfg *cfg)
int32_t PIOS_SPI_ClaimBus(pios_spi_t spi_dev)
#define PIOS_MPU_AK89XX_WHOAMI_REG
#define PIOS_MPU_AK89XX_ST2_HOFL
pios_mpu6500_accel_filter
Definition: pios_mpu.h:94
#define PIOS_MPU_ACCEL_X_OUT_MSB
Definition: pios_mpu_priv.h:58
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_Semaphore_Give_FromISR(struct pios_semaphore *sema, bool *woken)
#define PIOS_MPU_ACCEL_CFG2_REG
Definition: pios_mpu_priv.h:40
uint16_t default_samplerate
Definition: pios_mpu.h:142
uint8_t * buf
Definition: pios_i2c.h:45
#define PIOS_MPU_SLV0_REG_REG
Definition: pios_mpu_priv.h:43
struct pios_mpu_dev * pios_mpu_dev_t
Definition: pios_mpu.h:150
#define PIOS_MPU_INT_CFG_REG
Definition: pios_mpu_priv.h:55
#define PIOS_MPU_AK8963_CNTL2_REG
#define PIOS_MPU_PWR_MGMT_REG
Definition: pios_mpu_priv.h:75
uint8_t data[XFER_BYTES_PER_PACKET]
Definition: bl_messages.h:129
void PIOS_EXTI_DeInit(const struct pios_exti_cfg *cfg)
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
int32_t PIOS_MPU_SPI_Init(pios_mpu_dev_t *dev, pios_spi_t spi_id, uint32_t slave_num, const struct pios_mpu_cfg *cfg)
Initialize the MPU-xxxx 6/9-axis sensor on SPI.
int16_t status
Definition: main.c:61
#define PIOS_MPU_AK8963_ST2_BITM
#define PIOS_MPU_SLV0_ADDR_REG
Definition: pios_mpu_priv.h:42
static float gyro_scale[3]
Definition: sensors.c:116
#define PIOS_MPU_INT_EN_REG
Definition: pios_mpu_priv.h:56
int32_t PIOS_MPU_SetAccelRange(enum pios_mpu_accel_range range)
#define PIOS_MPU_INT_CLR_ANYRD
Definition: pios_mpu_priv.h:92
#define PIOS_MPU_SLV4_REG_REG
Definition: pios_mpu_priv.h:50
#define PIOS_MPU_DLPF_CFG_REG
Definition: pios_mpu_priv.h:37
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
#define PIOS_MPU_SLV4_DO_REG
Definition: pios_mpu_priv.h:51
#define PIOS_MPU_I2C_MST_SLV4_NACK
static float accel_scale[3]
Definition: sensors.c:115
#define PIOS_MPU_AK89XX_WHOAMI_ID
Pios sensor structure for generic accel data.
Definition: pios_sensors.h:46
struct pios_i2c_adapter * pios_i2c_t
Definition: pios_i2c.h:48
#define PIOS_MPU_I2CSLV_EN
uint8_t PIOS_SPI_TransferByte(pios_spi_t spi_dev, uint8_t b)
int32_t PIOS_SPI_SetClockSpeed(pios_spi_t spi_dev, uint32_t speed)
int32_t PIOS_SPI_TransferBlock(pios_spi_t spi_dev, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len)
static float mag_scale[3]
Definition: sensors.c:113
pios_mpu_type
Definition: pios_mpu.h:52
uint8_t i
Definition: msp_messages.h:97
#define PIOS_MPU_USERCTL_DIS_I2C
#define PIOS_MPU_PWRMGMT_PLL_X_CLK
#define PIOS_MPU_SLV0_CTRL_REG
Definition: pios_mpu_priv.h:44
int32_t PIOS_I2C_Transfer(pios_i2c_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns)
#define PIOS_MPU_PWRMGMT_IMU_RST
#define PIOS_MPU_SLV4_CTRL_REG
Definition: pios_mpu_priv.h:52
#define PIOS_MPU_SMPLRT_DIV_REG
Definition: pios_mpu_priv.h:36
int32_t PIOS_SENSORS_RegisterCallback(enum pios_sensor_type type, PIOS_SENSOR_Callback_t callback, void *ctx)
Register a callback-based sensor with the PIOS_SENSORS interface.
Definition: pios_sensors.c:68
Pios sensor structure for generic gyro data.
Definition: pios_sensors.h:38
#define PIOS_MPU_AK89XX_ST1_REG
void PIOS_MPU_SetGyroBandwidth(uint16_t bandwidth)
Sets the bandwidth desired from the gyro. The driver will automatically select the lowest bandwidth l...
#define PIOS_MPU_AK8963_CNTL2_SRST
uint32_t magic
#define PIOS_MPU_GYRO_CFG_REG
Definition: pios_mpu_priv.h:38
#define PIOS_MPU_SLV1_ADDR_REG
Definition: pios_mpu_priv.h:45
void PIOS_free(void *buf)
Definition: pios_heap.c:174
#define PIOS_MPU_USER_CTRL_REG
Definition: pios_mpu_priv.h:74
#define PIOS_MPU_WHOAMI
Definition: pios_mpu_priv.h:79
Pios sensor structure for generic mag data.
Definition: pios_sensors.h:54
void PIOS_MPU_SetAccelBandwidth(uint16_t bandwidth)
Sets the bandwidth desired from the accelerometer. The driver will automatically select the lowest ba...
pios_mpu_accel_range
Definition: pios_mpu.h:121
tuple f
Definition: px_mkfw.py:81
#define PIOS_MPU_SLV1_DO_REG
Definition: pios_mpu_priv.h:47
#define PIOS_MPU_ACCEL_CFG_REG
Definition: pios_mpu_priv.h:39
void PIOS_SENSORS_SetSampleRate(enum pios_sensor_type type, uint32_t sample_rate)
Set the sample rate of a sensor (Hz)
Definition: pios_sensors.c:172
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
Takes binary semaphore.
#define PIOS_MPU_SLV1_CTRL_REG
Definition: pios_mpu_priv.h:48
Includes PiOS and core architecture components.
bool PIOS_MPU_IRQHandler(void)
The IMU interrupt handler. Fetches new data from the IMU.
const char * info
Definition: pios_i2c.h:41
pios_mpu_gyro_range
Definition: pios_mpu.h:114
#define PIOS_MPU_AK8975_ST2_DERR
#define PIOS_MPU_SLV4_ADDR_REG
Definition: pios_mpu_priv.h:49
int32_t PIOS_SPI_ReleaseBus(pios_spi_t spi_dev)
#define PIOS_MPU_AK8963_MODE_CONTINUOUS_FAST_16B
#define PIOS_MPU_I2C_MST_DELAY_CTRL
Definition: pios_mpu_priv.h:72
uint32_t len
Definition: pios_i2c.h:44
#define PIOS_MPU_INTEN_DATA_RDY
Definition: pios_mpu_priv.h:96
#define PIOS_MPU_AK8975_MODE_SINGLE_12B
#define PIOS_MPU_AK89XX_CNTL1_REG
uint8_t p
Definition: msp_messages.h:96
#define PIOS_MPU_SLV1_REG_REG
Definition: pios_mpu_priv.h:46
#define PIOS_Assert(test)
Definition: pios_debug.h:52
#define PIOS_MPU_I2C_MST_SLV4_DONE
int32_t PIOS_DELAY_WaitmS(uint32_t mS)
Definition: pios_delay.c:140
int32_t PIOS_MPU_SetGyroRange(enum pios_mpu_gyro_range range)
uint32_t PIOS_DELAY_GetRaw()
Get the raw delay timer, useful for timing.
Definition: pios_delay.c:153