37 #if defined(PIOS_INCLUDE_BMI160)
38 #include "physical_constants.h"
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
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
77 enum pios_bmi160_dev_magic {
78 PIOS_BMI160_DEV_MAGIC = 0x76dfa5ba,
87 uint8_t temp_interleave_cnt;
91 enum pios_bmi160_dev_magic
magic;
92 volatile uint8_t sensor_ready;
95 #define SENSOR_ACCEL (1 << 0)
98 static struct bmi160_dev *dev;
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();
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);
123 dev = PIOS_BMI160_alloc(cfg);
127 dev->spi_id = spi_id;
128 dev->slave_num = slave_num;
134 dev->accel_scale = GRAVITY / 16384.f;
137 dev->accel_scale = GRAVITY / 8192.f;
140 dev->accel_scale = GRAVITY / 4096.f;
143 dev->accel_scale = GRAVITY / 2048.f;
149 dev->gyro_scale = 1.f / 262.4f;
153 dev->gyro_scale = 1.f / 131.2f;
157 dev->gyro_scale = 1.f / 65.6f;
161 dev->gyro_scale = 1.f / 32.8f;
165 dev->gyro_scale = 1.f / 16.4f;
171 PIOS_BMI160_ReadReg(0x7F);
175 if (PIOS_BMI160_ReadReg(BMI160_REG_CHIPID) != 0xd1){
180 if (PIOS_BMI160_Config(cfg) != 0){
186 if (PIOS_BMI160_do_foc(cfg) != 0) {
218 if (PIOS_BMI160_WriteReg(BMI160_REG_CMD, BMI160_PMU_CMD_PMU_GYR_NORMAL) != 0){
223 if (PIOS_BMI160_WriteReg(BMI160_REG_CMD, BMI160_PMU_CMD_PMU_ACC_NORMAL) != 0){
229 uint8_t pmu_status = PIOS_BMI160_ReadReg(BMI160_REG_PMU_STAT);
230 if ((pmu_status & 0x3C) != 0x14){
236 if (PIOS_BMI160_WriteReg(BMI160_REG_ACC_CONF, 0x20 | cfg->
odr) != 0){
242 if (PIOS_BMI160_WriteReg(BMI160_REG_GYR_CONF, 0x20 | cfg->
odr) != 0){
247 if (PIOS_BMI160_WriteReg(BMI160_REG_ACC_RANGE, cfg->
acc_range) != 0){
252 if (PIOS_BMI160_WriteReg(BMI160_REG_GYR_RANGE, cfg->
gyro_range) != 0){
258 uint8_t val = PIOS_BMI160_ReadReg(BMI160_REG_OFFSET_0);
259 if (PIOS_BMI160_WriteReg(BMI160_REG_OFFSET_0, val | 0xC0) != 0){
264 if (PIOS_BMI160_WriteReg(BMI160_REG_INT_EN1, BMI160_INT_EN1_DRDY) != 0){
270 if (PIOS_BMI160_WriteReg(BMI160_REG_INT_OUT_CTRL, BMI160_INT_OUT_CTRL_INT1_CONFIG) != 0){
276 if (PIOS_BMI160_WriteReg(BMI160_REG_INT_MAP1, BMI160_REG_INT_MAP1_INT1_DRDY) != 0){
310 if (PIOS_BMI160_WriteReg(BMI160_REG_FOC_CONF, val) != 0) {
315 if (PIOS_BMI160_WriteReg(BMI160_REG_CMD, BMI160_CMD_START_FOC) != 0) {
320 for (
int i=0;
i<50;
i++) {
321 val = PIOS_BMI160_ReadReg(BMI160_REG_STATUS);
322 if (val & BMI160_REG_STATUS_FOC_RDY) {
328 if (!(val & BMI160_REG_STATUS_FOC_RDY)) {
333 val = PIOS_BMI160_ReadReg(BMI160_REG_CONF);
334 if (PIOS_BMI160_WriteReg(BMI160_REG_CONF, val | BMI160_REG_CONF_NVM_PROG_EN) != 0) {
338 if (PIOS_BMI160_WriteReg(BMI160_REG_CMD, BMI160_CMD_PROG_NVM) != 0) {
343 for (
int i=0;
i<50;
i++) {
344 val = PIOS_BMI160_ReadReg(BMI160_REG_STATUS);
345 if (val & BMI160_REG_STATUS_NVM_RDY) {
351 if (!(val & BMI160_REG_STATUS_NVM_RDY)) {
361 static struct bmi160_dev *PIOS_BMI160_alloc(
const struct pios_bmi160_cfg *cfg)
363 struct bmi160_dev *bmi160_dev;
365 bmi160_dev = (
struct bmi160_dev *)
PIOS_malloc(
sizeof(*bmi160_dev));
369 bmi160_dev->magic = PIOS_BMI160_DEV_MAGIC;
372 if (bmi160_dev->accel_data == NULL) {
378 if (bmi160_dev->gyro_data == NULL) {
385 if (bmi160_dev->data_ready_sema == NULL) {
399 static int32_t PIOS_BMI160_Validate(
struct bmi160_dev *dev)
403 if (dev->magic != PIOS_BMI160_DEV_MAGIC)
405 if (dev->spi_id == 0)
414 static int32_t PIOS_BMI160_ClaimBus()
416 if (PIOS_BMI160_Validate(dev) != 0)
432 static int32_t PIOS_BMI160_ReleaseBus()
434 if (PIOS_BMI160_Validate(dev) != 0)
449 static uint8_t PIOS_BMI160_ReadReg(uint8_t reg)
453 PIOS_BMI160_ClaimBus();
458 PIOS_BMI160_ReleaseBus();
469 static int32_t PIOS_BMI160_WriteReg(uint8_t reg, uint8_t
data)
471 if (PIOS_BMI160_ClaimBus() != 0)
477 PIOS_BMI160_ReleaseBus();
487 if (PIOS_BMI160_Validate(dev) != 0)
490 bool need_yield =
false;
501 static int PIOS_BMI160_parse_data(
struct bmi160_dev *dev)
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};
524 if (PIOS_BMI160_ClaimBus() != 0)
528 PIOS_BMI160_ReleaseBus();
532 PIOS_BMI160_ReleaseBus();
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]);
545 accel_x *= dev->accel_scale;
546 accel_y *= dev->accel_scale;
547 accel_z *= dev->accel_scale;
549 gyro_x *= dev->gyro_scale;
550 gyro_y *= dev->gyro_scale;
551 gyro_z *= dev->gyro_scale;
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;
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;
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;
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;
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;
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;
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;
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;
625 dev->sensor_ready |= SENSOR_ACCEL;
630 if (dev->temp_interleave_cnt % dev->cfg->temperature_interleaving == 0){
631 if (PIOS_BMI160_ClaimBus() != 0)
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};
637 PIOS_BMI160_ReleaseBus();
641 PIOS_BMI160_ReleaseBus();
642 float tmp = 23.f + (int16_t)(bmi160_rec_buf[2] << 8 | bmi160_rec_buf[1]) / 512.f;
647 dev->temp_interleave_cnt += 1;
652 static bool PIOS_BMI160_callback_gyro(
void *ctx,
void *output,
653 int ms_to_wait,
int *next_call)
655 struct bmi160_dev *dev = (
struct bmi160_dev *)ctx;
668 if (PIOS_BMI160_parse_data(dev) < -1) {
672 memcpy(output, dev->gyro_data,
sizeof(*dev->gyro_data));
677 static bool PIOS_BMI160_callback_accel(
void *ctx,
void *output,
678 int ms_to_wait,
int *next_call)
680 struct bmi160_dev *dev = (
struct bmi160_dev *)ctx;
687 if (!(dev->sensor_ready & SENSOR_ACCEL)) {
691 memcpy(output, dev->accel_data,
sizeof(*dev->accel_data));
692 dev->sensor_ready &= ~SENSOR_ACCEL;
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.
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)
bool PIOS_Semaphore_Give_FromISR(struct pios_semaphore *sema, bool *woken)
void * PIOS_malloc_no_dma(size_t size)
uint8_t data[XFER_BYTES_PER_PACKET]
void PIOS_WDG_Clear(void)
Clear the watchdog timer.
static struct flyingpicmd_cfg_fa cfg
static float gyro_scale[3]
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
static float accel_scale[3]
Pios sensor structure for generic accel data.
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
bool PIOS_BMI160_IRQHandler(void)
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.
Pios sensor structure for generic gyro data.
enum pios_bmi160_acc_range acc_range
void PIOS_free(void *buf)
void PIOS_SENSORS_SetSampleRate(enum pios_sensor_type type, uint32_t sample_rate)
Set the sample rate of a sensor (Hz)
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
enum pios_bmi160_gyro_range gyro_range
#define PIOS_Assert(test)
int32_t PIOS_DELAY_WaitmS(uint32_t mS)