dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_bmi160.c
Go to the documentation of this file.
1 
15 /*
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24  * for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with this program; if not, see <http://www.gnu.org/licenses/>
28  *
29  * Additional note on redistribution: The copyright and license notices above
30  * must be maintained in each individual source file that is a derivative work
31  * of this source file; otherwise redistribution is prohibited.
32  */
33 
34 /* Project Includes */
35 #include "pios.h"
36 
37 #if defined(PIOS_INCLUDE_BMI160)
38 #include "physical_constants.h"
39 #include "pios_bmi160.h"
40 #include "pios_semaphore.h"
41 #include "pios_thread.h"
42 #include "pios_queue.h"
43 
44 /* Private constants */
45 
46 /* BMI160 Registers */
47 #define BMI160_REG_CHIPID 0x00
48 #define BMI160_REG_PMU_STAT 0x03
49 #define BMI160_REG_GYR_DATA_X_LSB 0x0C
50 #define BMI160_REG_STATUS 0x1B
51 #define BMI160_REG_TEMPERATURE_0 0x20
52 #define BMI160_REG_ACC_CONF 0x40
53 #define BMI160_REG_ACC_RANGE 0x41
54 #define BMI160_REG_GYR_CONF 0x42
55 #define BMI160_REG_GYR_RANGE 0x43
56 #define BMI160_REG_INT_EN1 0x51
57 #define BMI160_REG_INT_OUT_CTRL 0x53
58 #define BMI160_REG_INT_MAP1 0x56
59 #define BMI160_REG_FOC_CONF 0x69
60 #define BMI160_REG_CONF 0x6A
61 #define BMI160_REG_OFFSET_0 0x77
62 #define BMI160_REG_CMD 0x7E
63 
64 /* Register values */
65 #define BMI160_PMU_CMD_PMU_ACC_NORMAL 0x11
66 #define BMI160_PMU_CMD_PMU_GYR_NORMAL 0x15
67 #define BMI160_INT_EN1_DRDY 0x10
68 #define BMI160_INT_OUT_CTRL_INT1_CONFIG 0x0A
69 #define BMI160_REG_INT_MAP1_INT1_DRDY 0x80
70 #define BMI160_CMD_START_FOC 0x03
71 #define BMI160_CMD_PROG_NVM 0xA0
72 #define BMI160_REG_STATUS_NVM_RDY 0x10
73 #define BMI160_REG_STATUS_FOC_RDY 0x08
74 #define BMI160_REG_CONF_NVM_PROG_EN 0x02
75 
76 /* Global Variables */
77 enum pios_bmi160_dev_magic {
78  PIOS_BMI160_DEV_MAGIC = 0x76dfa5ba,
79 };
80 
81 struct bmi160_dev {
82  pios_spi_t spi_id;
83  uint32_t slave_num;
84  const struct pios_bmi160_cfg *cfg;
85  struct pios_sensor_accel_data *accel_data;
86  struct pios_sensor_gyro_data *gyro_data;
87  uint8_t temp_interleave_cnt;
88  struct pios_semaphore *data_ready_sema;
89  float accel_scale;
90  float gyro_scale;
91  enum pios_bmi160_dev_magic magic;
92  volatile uint8_t sensor_ready;
93 };
94 
95 #define SENSOR_ACCEL (1 << 0)
96 
98 static struct bmi160_dev *dev;
99 
101 static int32_t PIOS_BMI160_Config(const struct pios_bmi160_cfg *cfg);
102 static int32_t PIOS_BMI160_do_foc(const struct pios_bmi160_cfg *cfg);
103 static struct bmi160_dev *PIOS_BMI160_alloc(const struct pios_bmi160_cfg *cfg);
104 static int32_t PIOS_BMI160_Validate(struct bmi160_dev *dev);
105 static uint8_t PIOS_BMI160_ReadReg(uint8_t reg);
106 static int32_t PIOS_BMI160_WriteReg(uint8_t reg, uint8_t data);
107 static int32_t PIOS_BMI160_ClaimBus();
108 static int32_t PIOS_BMI160_ReleaseBus();
109 
110 static int PIOS_BMI160_parse_data(struct bmi160_dev *dev);
111 static bool PIOS_BMI160_callback_gyro(void *ctx, void *output,
112  int ms_to_wait, int *next_call);
113 static bool PIOS_BMI160_callback_accel(void *ctx, void *output,
114  int ms_to_wait, int *next_call);
115 
116 
121 int32_t PIOS_BMI160_Init(pios_spi_t spi_id, uint32_t slave_num, const struct pios_bmi160_cfg *cfg, bool do_foc)
122 {
123  dev = PIOS_BMI160_alloc(cfg);
124  if (dev == NULL)
125  return -1;
126 
127  dev->spi_id = spi_id;
128  dev->slave_num = slave_num;
129  dev->cfg = cfg;
130 
131  /* Configure the scales */
132  switch (cfg->acc_range){
134  dev->accel_scale = GRAVITY / 16384.f;
135  break;
137  dev->accel_scale = GRAVITY / 8192.f;
138  break;
140  dev->accel_scale = GRAVITY / 4096.f;
141  break;
143  dev->accel_scale = GRAVITY / 2048.f;
144  break;
145  }
146 
147  switch (cfg->gyro_range){
149  dev->gyro_scale = 1.f / 262.4f;
151  break;
153  dev->gyro_scale = 1.f / 131.2f;
155  break;
157  dev->gyro_scale = 1.f / 65.6f;
159  break;
161  dev->gyro_scale = 1.f / 32.8f;
163  break;
165  dev->gyro_scale = 1.f / 16.4f;
167  break;
168  }
169 
170  /* Read this address to acticate SPI (see p. 84) */
171  PIOS_BMI160_ReadReg(0x7F);
172  PIOS_DELAY_WaitmS(10); // Give SPI some time to start up
173 
174  /* Check the chip ID */
175  if (PIOS_BMI160_ReadReg(BMI160_REG_CHIPID) != 0xd1){
176  return -2;
177  }
178 
179  /* Configure the MPU9250 Sensor */
180  if (PIOS_BMI160_Config(cfg) != 0){
181  return -3;
182  }
183 
184  /* Perform fast offset compensation if requested */
185  if (do_foc) {
186  if (PIOS_BMI160_do_foc(cfg) != 0) {
187  return -4;
188  }
189  }
190 
191  /* Set up EXTI line */
192  PIOS_EXTI_Init(cfg->exti_cfg);
193 
194  // Wait 20 ms for data ready interrupt and make sure it happens
195  // twice
196  if ((PIOS_Semaphore_Take(dev->data_ready_sema, 20) != true) ||
197  (PIOS_Semaphore_Take(dev->data_ready_sema, 20) != true)) {
198  return -10;
199  }
200 
203 
204  PIOS_SENSORS_RegisterCallback(PIOS_SENSOR_ACCEL, PIOS_BMI160_callback_accel, dev);
205  PIOS_SENSORS_RegisterCallback(PIOS_SENSOR_GYRO, PIOS_BMI160_callback_gyro, dev);
206 
207  return 0;
208 }
209 
210 
214 static int32_t PIOS_BMI160_Config(const struct pios_bmi160_cfg *cfg)
215 {
216 
217  // Set normal power mode for gyro and accelerometer
218  if (PIOS_BMI160_WriteReg(BMI160_REG_CMD, BMI160_PMU_CMD_PMU_GYR_NORMAL) != 0){
219  return -1;
220  }
221  PIOS_DELAY_WaitmS(100); // can take up to 80ms
222 
223  if (PIOS_BMI160_WriteReg(BMI160_REG_CMD, BMI160_PMU_CMD_PMU_ACC_NORMAL) != 0){
224  return -2;
225  }
226  PIOS_DELAY_WaitmS(5); // can take up to 3.8ms
227 
228  // Verify that normal power mode was entered
229  uint8_t pmu_status = PIOS_BMI160_ReadReg(BMI160_REG_PMU_STAT);
230  if ((pmu_status & 0x3C) != 0x14){
231  return -3;
232  }
233 
234  // Set odr and ranges
235  // Set acc_us = 0 acc_bwp = 0b010 so only the first filter stage is used
236  if (PIOS_BMI160_WriteReg(BMI160_REG_ACC_CONF, 0x20 | cfg->odr) != 0){
237  return -3;
238  }
240 
241  // Set gyr_bwp = 0b010 so only the first filter stage is used
242  if (PIOS_BMI160_WriteReg(BMI160_REG_GYR_CONF, 0x20 | cfg->odr) != 0){
243  return -4;
244  }
246 
247  if (PIOS_BMI160_WriteReg(BMI160_REG_ACC_RANGE, cfg->acc_range) != 0){
248  return -5;
249  }
251 
252  if (PIOS_BMI160_WriteReg(BMI160_REG_GYR_RANGE, cfg->gyro_range) != 0){
253  return -6;
254  }
256 
257  // Enable offset compensation
258  uint8_t val = PIOS_BMI160_ReadReg(BMI160_REG_OFFSET_0);
259  if (PIOS_BMI160_WriteReg(BMI160_REG_OFFSET_0, val | 0xC0) != 0){
260  return -7;
261  }
262 
263  // Enable data ready interrupt
264  if (PIOS_BMI160_WriteReg(BMI160_REG_INT_EN1, BMI160_INT_EN1_DRDY) != 0){
265  return -8;
266  }
268 
269  // Enable INT1 pin
270  if (PIOS_BMI160_WriteReg(BMI160_REG_INT_OUT_CTRL, BMI160_INT_OUT_CTRL_INT1_CONFIG) != 0){
271  return -9;
272  }
274 
275  // Map data ready interrupt to INT1 pin
276  if (PIOS_BMI160_WriteReg(BMI160_REG_INT_MAP1, BMI160_REG_INT_MAP1_INT1_DRDY) != 0){
277  return -10;
278  }
280 
281  return 0;
282 }
283 
284 
291 static int32_t PIOS_BMI160_do_foc(const struct pios_bmi160_cfg *cfg)
292 {
293  uint8_t val = 0;
294 
295  // Set the orientation: 0G for x and y, +/- 1G for z
296  switch (cfg->orientation) {
301  val = 0x7D;
302  break;
307  val = 0x7E;
308  }
309 
310  if (PIOS_BMI160_WriteReg(BMI160_REG_FOC_CONF, val) != 0) {
311  return -1;
312  }
313 
314  // Start FOC
315  if (PIOS_BMI160_WriteReg(BMI160_REG_CMD, BMI160_CMD_START_FOC) != 0) {
316  return -2;
317  }
318 
319  // Wait for FOC to complete
320  for (int i=0; i<50; i++) {
321  val = PIOS_BMI160_ReadReg(BMI160_REG_STATUS);
322  if (val & BMI160_REG_STATUS_FOC_RDY) {
323  break;
324  }
325  PIOS_DELAY_WaitmS(10);
326  PIOS_WDG_Clear();
327  }
328  if (!(val & BMI160_REG_STATUS_FOC_RDY)) {
329  return -3;
330  }
331 
332  // Program NVM
333  val = PIOS_BMI160_ReadReg(BMI160_REG_CONF);
334  if (PIOS_BMI160_WriteReg(BMI160_REG_CONF, val | BMI160_REG_CONF_NVM_PROG_EN) != 0) {
335  return -4;
336  }
337 
338  if (PIOS_BMI160_WriteReg(BMI160_REG_CMD, BMI160_CMD_PROG_NVM) != 0) {
339  return -5;
340  }
341 
342  // Wait for NVM programming to complete
343  for (int i=0; i<50; i++) {
344  val = PIOS_BMI160_ReadReg(BMI160_REG_STATUS);
345  if (val & BMI160_REG_STATUS_NVM_RDY) {
346  break;
347  }
348  PIOS_DELAY_WaitmS(10);
349  PIOS_WDG_Clear();
350  }
351  if (!(val & BMI160_REG_STATUS_NVM_RDY)) {
352  return -6;
353  }
354 
355  return 0;
356 }
357 
361 static struct bmi160_dev *PIOS_BMI160_alloc(const struct pios_bmi160_cfg *cfg)
362 {
363  struct bmi160_dev *bmi160_dev;
364 
365  bmi160_dev = (struct bmi160_dev *)PIOS_malloc(sizeof(*bmi160_dev));
366  if (!bmi160_dev)
367  return NULL;
368 
369  bmi160_dev->magic = PIOS_BMI160_DEV_MAGIC;
370 
371  bmi160_dev->accel_data = PIOS_malloc_no_dma(sizeof(*bmi160_dev->accel_data));
372  if (bmi160_dev->accel_data == NULL) {
373  PIOS_free(bmi160_dev);
374  return NULL;
375  }
376 
377  bmi160_dev->gyro_data = PIOS_malloc_no_dma(sizeof(*bmi160_dev->gyro_data));
378  if (bmi160_dev->gyro_data == NULL) {
379  PIOS_free(bmi160_dev->accel_data);
380  PIOS_free(bmi160_dev);
381  return NULL;
382  }
383 
384  bmi160_dev->data_ready_sema = PIOS_Semaphore_Create();
385  if (bmi160_dev->data_ready_sema == NULL) {
386  PIOS_free(bmi160_dev->gyro_data);
387  PIOS_free(bmi160_dev->accel_data);
388  PIOS_free(bmi160_dev);
389  return NULL;
390  }
391 
392  return bmi160_dev;
393 }
394 
399 static int32_t PIOS_BMI160_Validate(struct bmi160_dev *dev)
400 {
401  if (dev == NULL)
402  return -1;
403  if (dev->magic != PIOS_BMI160_DEV_MAGIC)
404  return -2;
405  if (dev->spi_id == 0)
406  return -3;
407  return 0;
408 }
409 
414 static int32_t PIOS_BMI160_ClaimBus()
415 {
416  if (PIOS_BMI160_Validate(dev) != 0)
417  return -1;
418 
419  if (PIOS_SPI_ClaimBus(dev->spi_id) != 0)
420  return -2;
421 
422  PIOS_SPI_RC_PinSet(dev->spi_id, dev->slave_num, 0);
423 
424  return 0;
425 }
426 
432 static int32_t PIOS_BMI160_ReleaseBus()
433 {
434  if (PIOS_BMI160_Validate(dev) != 0)
435  return -1;
436 
437  PIOS_SPI_RC_PinSet(dev->spi_id, dev->slave_num, 1);
438 
439  PIOS_SPI_ReleaseBus(dev->spi_id);
440 
441  return 0;
442 }
443 
449 static uint8_t PIOS_BMI160_ReadReg(uint8_t reg)
450 {
451  uint8_t data;
452 
453  PIOS_BMI160_ClaimBus();
454 
455  PIOS_SPI_TransferByte(dev->spi_id, 0x80 | reg); // request byte
456  data = PIOS_SPI_TransferByte(dev->spi_id, 0); // receive response
457 
458  PIOS_BMI160_ReleaseBus();
459 
460  return data;
461 }
462 
469 static int32_t PIOS_BMI160_WriteReg(uint8_t reg, uint8_t data)
470 {
471  if (PIOS_BMI160_ClaimBus() != 0)
472  return -1;
473 
474  PIOS_SPI_TransferByte(dev->spi_id, 0x7f & reg);
475  PIOS_SPI_TransferByte(dev->spi_id, data);
476 
477  PIOS_BMI160_ReleaseBus();
478 
479  return 0;
480 }
481 
485 bool PIOS_BMI160_IRQHandler(void)
486 {
487  if (PIOS_BMI160_Validate(dev) != 0)
488  return false;
489 
490  bool need_yield = false;
491 
492  PIOS_Semaphore_Give_FromISR(dev->data_ready_sema, &need_yield);
493 
494  return need_yield;
495 }
496 
501 static int PIOS_BMI160_parse_data(struct bmi160_dev *dev)
502 {
503  enum {
504  IDX_REG = 0,
505  IDX_GYRO_XOUT_L,
506  IDX_GYRO_XOUT_H,
507  IDX_GYRO_YOUT_L,
508  IDX_GYRO_YOUT_H,
509  IDX_GYRO_ZOUT_L,
510  IDX_GYRO_ZOUT_H,
511  IDX_ACCEL_XOUT_L,
512  IDX_ACCEL_XOUT_H,
513  IDX_ACCEL_YOUT_L,
514  IDX_ACCEL_YOUT_H,
515  IDX_ACCEL_ZOUT_L,
516  IDX_ACCEL_ZOUT_H,
517  BUFFER_SIZE,
518  };
519 
520  uint8_t bmi160_rec_buf[BUFFER_SIZE];
521  uint8_t bmi160_tx_buf[BUFFER_SIZE] = {BMI160_REG_GYR_DATA_X_LSB | 0x80, 0, 0, 0, 0, 0,
522  0, 0, 0, 0, 0, 0, 0};
523 
524  if (PIOS_BMI160_ClaimBus() != 0)
525  return -2;
526 
527  if (PIOS_SPI_TransferBlock(dev->spi_id, bmi160_tx_buf, bmi160_rec_buf, BUFFER_SIZE) < 0) {
528  PIOS_BMI160_ReleaseBus();
529  return -2;
530  }
531 
532  PIOS_BMI160_ReleaseBus();
533 
534  struct pios_sensor_accel_data *accel_data = dev->accel_data;
535  struct pios_sensor_gyro_data *gyro_data = dev->gyro_data;
536 
537  float accel_x = (int16_t)(bmi160_rec_buf[IDX_ACCEL_XOUT_H] << 8 | bmi160_rec_buf[IDX_ACCEL_XOUT_L]);
538  float accel_y = (int16_t)(bmi160_rec_buf[IDX_ACCEL_YOUT_H] << 8 | bmi160_rec_buf[IDX_ACCEL_YOUT_L]);
539  float accel_z = (int16_t)(bmi160_rec_buf[IDX_ACCEL_ZOUT_H] << 8 | bmi160_rec_buf[IDX_ACCEL_ZOUT_L]);
540  float gyro_x = (int16_t)(bmi160_rec_buf[IDX_GYRO_XOUT_H] << 8 | bmi160_rec_buf[IDX_GYRO_XOUT_L]);
541  float gyro_y = (int16_t)(bmi160_rec_buf[IDX_GYRO_YOUT_H] << 8 | bmi160_rec_buf[IDX_GYRO_YOUT_L]);
542  float gyro_z = (int16_t)(bmi160_rec_buf[IDX_GYRO_ZOUT_H] << 8 | bmi160_rec_buf[IDX_GYRO_ZOUT_L]);
543 
544  // Apply sensor scaling
545  accel_x *= dev->accel_scale;
546  accel_y *= dev->accel_scale;
547  accel_z *= dev->accel_scale;
548 
549  gyro_x *= dev->gyro_scale;
550  gyro_y *= dev->gyro_scale;
551  gyro_z *= dev->gyro_scale;
552 
553  /*
554  * Convert from sensor frame (x: forward y: left z: up) to
555  * TL convention (x: forward y: right z: down).
556  * See flight/Doc/imu_orientation.md for more detail
557  */
558  switch (dev->cfg->orientation) {
560  accel_data->x = accel_x;
561  accel_data->y = -accel_y;
562  accel_data->z = -accel_z;
563  gyro_data->x = gyro_x;
564  gyro_data->y = -gyro_y;
565  gyro_data->z = -gyro_z;
566  break;
568  accel_data->x = accel_y;
569  accel_data->y = accel_x;
570  accel_data->z = -accel_z;
571  gyro_data->x = gyro_y;
572  gyro_data->y = gyro_x;
573  gyro_data->z = -gyro_z;
574  break;
576  accel_data->x = -accel_x;
577  accel_data->y = accel_y;
578  accel_data->z = -accel_z;
579  gyro_data->x = -gyro_x;
580  gyro_data->y = gyro_y;
581  gyro_data->z = -gyro_z;
582  break;
584  accel_data->x = -accel_y;
585  accel_data->y = -accel_x;
586  accel_data->z = -accel_z;
587  gyro_data->x = -gyro_y;
588  gyro_data->y = -gyro_x;
589  gyro_data->z = -gyro_z;
590  break;
592  accel_data->x = accel_x;
593  accel_data->y = accel_y;
594  accel_data->z = accel_z;
595  gyro_data->x = gyro_x;
596  gyro_data->y = gyro_y;
597  gyro_data->z = gyro_z;
598  break;
600  accel_data->x = -accel_y;
601  accel_data->y = accel_x;
602  accel_data->z = accel_z;
603  gyro_data->x = -gyro_y;
604  gyro_data->y = gyro_x;
605  gyro_data->z = gyro_z;
606  break;
608  accel_data->x = -accel_x;
609  accel_data->y = -accel_y;
610  accel_data->z = accel_z;
611  gyro_data->x = -gyro_x;
612  gyro_data->y = -gyro_y;
613  gyro_data->z = gyro_z;
614  break;
616  accel_data->x = accel_y;
617  accel_data->y = -accel_x;
618  accel_data->z = accel_z;
619  gyro_data->x = gyro_y;
620  gyro_data->y = -gyro_x;
621  gyro_data->z = gyro_z;
622  break;
623  }
624 
625  dev->sensor_ready |= SENSOR_ACCEL;
626 
627  // Get the temperature
628  // NOTE: We do this down here so the chip-select has some time to go low. Strange things happen
629  // When this is done right after readin the accels / gyros
630  if (dev->temp_interleave_cnt % dev->cfg->temperature_interleaving == 0){
631  if (PIOS_BMI160_ClaimBus() != 0)
632  return -1;
633 
634  uint8_t bmi160_tx_buf[BUFFER_SIZE] = {BMI160_REG_TEMPERATURE_0 | 0x80, 0, 0, 0, 0, 0,
635  0, 0, 0, 0, 0, 0, 0};
636  if (PIOS_SPI_TransferBlock(dev->spi_id, bmi160_tx_buf, bmi160_rec_buf, 3) < 0) {
637  PIOS_BMI160_ReleaseBus();
638  return -1;
639  }
640 
641  PIOS_BMI160_ReleaseBus();
642  float tmp = 23.f + (int16_t)(bmi160_rec_buf[2] << 8 | bmi160_rec_buf[1]) / 512.f;
643  accel_data->temperature = tmp;
644  gyro_data->temperature = tmp;
645  }
646 
647  dev->temp_interleave_cnt += 1;
648 
649  return 0;
650 }
651 
652 static bool PIOS_BMI160_callback_gyro(void *ctx, void *output,
653  int ms_to_wait, int *next_call)
654 {
655  struct bmi160_dev *dev = (struct bmi160_dev *)ctx;
656 
657  PIOS_Assert(dev);
658  PIOS_Assert(output);
659 
660  *next_call = 0; /* Baby you know you can call me anytime */
661 
662  if (PIOS_Semaphore_Take(dev->data_ready_sema, ms_to_wait) != true) {
663  return false;
664  }
665 
666  /* Only fail, if sensor data readout fails (-2). Temperature readouts are assumed
667  to fail intermittently only, if at all, and failures don't taint main sensor data. */
668  if (PIOS_BMI160_parse_data(dev) < -1) {
669  return false;
670  }
671 
672  memcpy(output, dev->gyro_data, sizeof(*dev->gyro_data));
673 
674  return true;
675 }
676 
677 static bool PIOS_BMI160_callback_accel(void *ctx, void *output,
678  int ms_to_wait, int *next_call)
679 {
680  struct bmi160_dev *dev = (struct bmi160_dev *)ctx;
681 
682  PIOS_Assert(dev);
683  PIOS_Assert(output);
684 
685  *next_call = 0;
686 
687  if (!(dev->sensor_ready & SENSOR_ACCEL)) {
688  return false;
689  }
690 
691  memcpy(output, dev->accel_data, sizeof(*dev->accel_data));
692  dev->sensor_ready &= ~SENSOR_ACCEL;
693 
694  return true;
695 }
696 
697 #endif /* PIOS_INCLUDE_BMI160 */
int32_t PIOS_BMI160_Init(pios_spi_t spi_id, uint32_t slave_num, const struct pios_bmi160_cfg *cfg, bool do_foc)
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.
int32_t PIOS_SPI_RC_PinSet(pios_spi_t spi_dev, uint32_t slave_id, bool pin_value)
int32_t PIOS_EXTI_Init(const struct pios_exti_cfg *cfg)
int32_t PIOS_SPI_ClaimBus(pios_spi_t spi_dev)
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_Semaphore_Give_FromISR(struct pios_semaphore *sema, bool *woken)
void * PIOS_malloc_no_dma(size_t size)
Definition: pios_heap.c:166
uint8_t data[XFER_BYTES_PER_PACKET]
Definition: bl_messages.h:129
void PIOS_WDG_Clear(void)
Clear the watchdog timer.
Definition: pios_wdg.c:147
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
static float gyro_scale[3]
Definition: sensors.c:116
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
static float accel_scale[3]
Definition: sensors.c:115
Pios sensor structure for generic accel data.
Definition: pios_sensors.h:46
uint8_t PIOS_SPI_TransferByte(pios_spi_t spi_dev, uint8_t b)
int32_t PIOS_SPI_TransferBlock(pios_spi_t spi_dev, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len)
enum pios_bmi160_orientation orientation
Definition: pios_bmi160.h:71
bool PIOS_BMI160_IRQHandler(void)
uint8_t i
Definition: msp_messages.h:97
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
enum pios_bmi160_acc_range acc_range
Definition: pios_bmi160.h:73
enum pios_bmi160_odr odr
Definition: pios_bmi160.h:72
uint32_t magic
void PIOS_free(void *buf)
Definition: pios_heap.c:174
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.
int32_t PIOS_SPI_ReleaseBus(pios_spi_t spi_dev)
const struct pios_exti_cfg * exti_cfg
Definition: pios_bmi160.h:70
enum pios_bmi160_gyro_range gyro_range
Definition: pios_bmi160.h:74
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t PIOS_DELAY_WaitmS(uint32_t mS)
Definition: pios_delay.c:140