2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
28 #ifdef USE_ACCGYRO_BMI270
30 #include "drivers/accgyro/accgyro.h"
31 #include "drivers/accgyro/accgyro_spi_bmi270.h"
32 #include "drivers/bus_spi.h"
33 #include "drivers/exti.h"
34 #include "drivers/io.h"
35 #include "drivers/io_impl.h"
36 #include "drivers/nvic.h"
37 #include "drivers/sensor.h"
38 #include "drivers/system.h"
39 #include "drivers/time.h"
41 #include "sensors/gyro.h"
43 // 10 MHz max SPI frequency
44 #define BMI270_MAX_SPI_CLK_HZ 10000000
46 #define BMI270_FIFO_FRAME_SIZE 6
48 #define BMI270_CONFIG_SIZE 328
50 // Declaration for the device config (microcode) that must be uploaded to the sensor
51 extern const uint8_t bmi270_maximum_fifo_config_file
[BMI270_CONFIG_SIZE
];
53 #define BMI270_CHIP_ID 0x24
55 // BMI270 registers (not the complete list)
57 BMI270_REG_CHIP_ID
= 0x00,
58 BMI270_REG_ERR_REG
= 0x02,
59 BMI270_REG_STATUS
= 0x03,
60 BMI270_REG_ACC_DATA_X_LSB
= 0x0C,
61 BMI270_REG_GYR_DATA_X_LSB
= 0x12,
62 BMI270_REG_SENSORTIME_0
= 0x18,
63 BMI270_REG_SENSORTIME_1
= 0x19,
64 BMI270_REG_SENSORTIME_2
= 0x1A,
65 BMI270_REG_EVENT
= 0x1B,
66 BMI270_REG_INT_STATUS_0
= 0x1C,
67 BMI270_REG_INT_STATUS_1
= 0x1D,
68 BMI270_REG_INTERNAL_STATUS
= 0x21,
69 BMI270_REG_TEMPERATURE_LSB
= 0x22,
70 BMI270_REG_TEMPERATURE_MSB
= 0x23,
71 BMI270_REG_FIFO_LENGTH_LSB
= 0x24,
72 BMI270_REG_FIFO_LENGTH_MSB
= 0x25,
73 BMI270_REG_FIFO_DATA
= 0x26,
74 BMI270_REG_ACC_CONF
= 0x40,
75 BMI270_REG_ACC_RANGE
= 0x41,
76 BMI270_REG_GYRO_CONF
= 0x42,
77 BMI270_REG_GYRO_RANGE
= 0x43,
78 BMI270_REG_AUX_CONF
= 0x44,
79 BMI270_REG_FIFO_DOWNS
= 0x45,
80 BMI270_REG_FIFO_WTM_0
= 0x46,
81 BMI270_REG_FIFO_WTM_1
= 0x47,
82 BMI270_REG_FIFO_CONFIG_0
= 0x48,
83 BMI270_REG_FIFO_CONFIG_1
= 0x49,
84 BMI270_REG_SATURATION
= 0x4A,
85 BMI270_REG_INT1_IO_CTRL
= 0x53,
86 BMI270_REG_INT2_IO_CTRL
= 0x54,
87 BMI270_REG_INT_LATCH
= 0x55,
88 BMI270_REG_INT1_MAP_FEAT
= 0x56,
89 BMI270_REG_INT2_MAP_FEAT
= 0x57,
90 BMI270_REG_INT_MAP_DATA
= 0x58,
91 BMI270_REG_INIT_CTRL
= 0x59,
92 BMI270_REG_INIT_DATA
= 0x5E,
93 BMI270_REG_ACC_SELF_TEST
= 0x6D,
94 BMI270_REG_GYR_SELF_TEST_AXES
= 0x6E,
95 BMI270_REG_PWR_CONF
= 0x7C,
96 BMI270_REG_PWR_CTRL
= 0x7D,
97 BMI270_REG_CMD
= 0x7E,
100 // BMI270 register configuration values
102 BMI270_VAL_CMD_SOFTRESET
= 0xB6,
103 BMI270_VAL_CMD_FIFOFLUSH
= 0xB0,
104 BMI270_VAL_PWR_CTRL
= 0x0E, // enable gyro, acc and temp sensors
105 BMI270_VAL_PWR_CONF
= 0x02, // disable advanced power save, enable FIFO self-wake
106 BMI270_VAL_ACC_CONF_ODR800
= 0x0B, // set acc sample rate to 800hz
107 BMI270_VAL_ACC_CONF_ODR1600
= 0x0C, // set acc sample rate to 1600hz
108 BMI270_VAL_ACC_CONF_BWP
= 0x01, // set acc filter in osr2 mode (only in high performance mode)
109 BMI270_VAL_ACC_CONF_HP
= 0x01, // set acc in high performance mode
110 BMI270_VAL_ACC_RANGE_8G
= 0x02, // set acc to 8G full scale
111 BMI270_VAL_ACC_RANGE_16G
= 0x03, // set acc to 16G full scale
112 BMI270_VAL_GYRO_CONF_ODR3200
= 0x0D, // set gyro sample rate to 3200hz
113 BMI270_VAL_GYRO_CONF_BWP_OSR4
= 0x00, // set gyro filter in OSR4 mode
114 BMI270_VAL_GYRO_CONF_BWP_OSR2
= 0x01, // set gyro filter in OSR2 mode
115 BMI270_VAL_GYRO_CONF_BWP_NORM
= 0x02, // set gyro filter in normal mode
116 BMI270_VAL_GYRO_CONF_NOISE_PERF
= 0x01, // set gyro in high performance noise mode
117 BMI270_VAL_GYRO_CONF_FILTER_PERF
= 0x01, // set gyro in high performance filter mode
119 BMI270_VAL_GYRO_RANGE_2000DPS
= 0x08, // set gyro to 2000dps full scale
120 // for some reason you have to enable the ois_range bit (bit 3) for 2000dps as well
121 // or else the gyro scale will be 250dps when in prefiltered FIFO mode (not documented in datasheet!)
123 BMI270_VAL_INT_MAP_DATA_DRDY_INT1
= 0x04,// enable the data ready interrupt pin 1
124 BMI270_VAL_INT_MAP_FIFO_WM_INT1
= 0x02, // enable the FIFO watermark interrupt pin 1
125 BMI270_VAL_INT1_IO_CTRL_PINMODE
= 0x0A, // active high, push-pull, output enabled, input disabled
126 BMI270_VAL_FIFO_CONFIG_0
= 0x00, // don't stop when full, disable sensortime frame
127 BMI270_VAL_FIFO_CONFIG_1
= 0x80, // only gyro data in FIFO, use headerless mode
128 BMI270_VAL_FIFO_DOWNS
= 0x00, // select unfiltered gyro data with no downsampling (6.4KHz samples)
129 BMI270_VAL_FIFO_WTM_0
= 0x06, // set the FIFO watermark level to 1 gyro sample (6 bytes)
130 BMI270_VAL_FIFO_WTM_1
= 0x00, // FIFO watermark MSB
131 } bmi270ConfigValues_e
;
133 // Need to see at least this many interrupts during initialisation to confirm EXTI connectivity
134 #define GYRO_EXTI_DETECT_THRESHOLD 1000
136 // BMI270 register reads are 16bits with the first byte a "dummy" value 0
137 // that must be ignored. The result is in the second byte.
138 static uint8_t bmi270RegisterRead(const extDevice_t
*dev
, bmi270Register_e registerId
)
140 uint8_t data
[2] = { 0, 0 };
142 if (spiReadRegMskBufRB(dev
, registerId
, data
, 2)) {
149 static void bmi270RegisterWrite(const extDevice_t
*dev
, bmi270Register_e registerId
, uint8_t value
, unsigned delayMs
)
151 spiWriteReg(dev
, registerId
, value
);
157 // Toggle the CS to switch the device into SPI mode.
158 // Device switches initializes as I2C and switches to SPI on a low to high CS transition
159 static void bmi270EnableSPI(const extDevice_t
*dev
)
161 IOLo(dev
->busType_u
.spi
.csnPin
);
163 IOHi(dev
->busType_u
.spi
.csnPin
);
167 uint8_t bmi270Detect(const extDevice_t
*dev
)
169 bmi270EnableSPI(dev
);
171 if (bmi270RegisterRead(dev
, BMI270_REG_CHIP_ID
) == BMI270_CHIP_ID
) {
178 static void bmi270UploadConfig(const extDevice_t
*dev
)
180 bmi270RegisterWrite(dev
, BMI270_REG_PWR_CONF
, 0, 1);
181 bmi270RegisterWrite(dev
, BMI270_REG_INIT_CTRL
, 0, 1);
183 // Transfer the config file
184 spiWriteRegBuf(dev
, BMI270_REG_INIT_DATA
, (uint8_t *)bmi270_maximum_fifo_config_file
, sizeof(bmi270_maximum_fifo_config_file
));
187 bmi270RegisterWrite(dev
, BMI270_REG_INIT_CTRL
, 1, 1);
190 static uint8_t getBmiOsrMode(void)
192 switch(gyroConfig()->gyro_hardware_lpf
) {
193 case GYRO_HARDWARE_LPF_NORMAL
:
194 return BMI270_VAL_GYRO_CONF_BWP_OSR4
;
195 case GYRO_HARDWARE_LPF_OPTION_1
:
196 return BMI270_VAL_GYRO_CONF_BWP_OSR2
;
197 case GYRO_HARDWARE_LPF_OPTION_2
:
198 return BMI270_VAL_GYRO_CONF_BWP_NORM
;
199 #ifdef USE_GYRO_DLPF_EXPERIMENTAL
200 case GYRO_HARDWARE_LPF_EXPERIMENTAL
:
201 return BMI270_VAL_GYRO_CONF_BWP_NORM
;
204 return BMI270_VAL_GYRO_CONF_BWP_OSR4
;
208 static void bmi270Config(gyroDev_t
*gyro
)
210 extDevice_t
*dev
= &gyro
->dev
;
212 // If running in hardware_lpf experimental mode then switch to FIFO-based,
213 // 6.4KHz sampling, unfiltered data vs. the default 3.2KHz with hardware filtering
214 #ifdef USE_GYRO_DLPF_EXPERIMENTAL
215 const bool fifoMode
= (gyro
->hardware_lpf
== GYRO_HARDWARE_LPF_EXPERIMENTAL
);
217 const bool fifoMode
= false;
220 // Perform a soft reset to set all configuration to default
221 // Delay 100ms before continuing configuration
222 bmi270RegisterWrite(dev
, BMI270_REG_CMD
, BMI270_VAL_CMD_SOFTRESET
, 100);
224 // Toggle the chip into SPI mode
225 bmi270EnableSPI(dev
);
227 bmi270UploadConfig(dev
);
229 // Configure the FIFO
231 bmi270RegisterWrite(dev
, BMI270_REG_FIFO_CONFIG_0
, BMI270_VAL_FIFO_CONFIG_0
, 1);
232 bmi270RegisterWrite(dev
, BMI270_REG_FIFO_CONFIG_1
, BMI270_VAL_FIFO_CONFIG_1
, 1);
233 bmi270RegisterWrite(dev
, BMI270_REG_FIFO_DOWNS
, BMI270_VAL_FIFO_DOWNS
, 1);
234 bmi270RegisterWrite(dev
, BMI270_REG_FIFO_WTM_0
, BMI270_VAL_FIFO_WTM_0
, 1);
235 bmi270RegisterWrite(dev
, BMI270_REG_FIFO_WTM_1
, BMI270_VAL_FIFO_WTM_1
, 1);
238 // Configure the accelerometer
239 bmi270RegisterWrite(dev
, BMI270_REG_ACC_CONF
, (BMI270_VAL_ACC_CONF_HP
<< 7) | (BMI270_VAL_ACC_CONF_BWP
<< 4) | BMI270_VAL_ACC_CONF_ODR800
, 1);
241 // Configure the accelerometer full-scale range
242 bmi270RegisterWrite(dev
, BMI270_REG_ACC_RANGE
, BMI270_VAL_ACC_RANGE_16G
, 1);
244 // Configure the gyro
245 bmi270RegisterWrite(dev
, BMI270_REG_GYRO_CONF
, (BMI270_VAL_GYRO_CONF_FILTER_PERF
<< 7) | (BMI270_VAL_GYRO_CONF_NOISE_PERF
<< 6) | (getBmiOsrMode() << 4) | BMI270_VAL_GYRO_CONF_ODR3200
, 1);
247 // Configure the gyro full-range scale
248 bmi270RegisterWrite(dev
, BMI270_REG_GYRO_RANGE
, BMI270_VAL_GYRO_RANGE_2000DPS
, 1);
250 // Configure the gyro data ready interrupt
252 // Interrupt driven by FIFO watermark level
253 bmi270RegisterWrite(dev
, BMI270_REG_INT_MAP_DATA
, BMI270_VAL_INT_MAP_FIFO_WM_INT1
, 1);
255 // Interrupt driven by data ready
256 bmi270RegisterWrite(dev
, BMI270_REG_INT_MAP_DATA
, BMI270_VAL_INT_MAP_DATA_DRDY_INT1
, 1);
259 // Configure the behavior of the INT1 pin
260 bmi270RegisterWrite(dev
, BMI270_REG_INT1_IO_CTRL
, BMI270_VAL_INT1_IO_CTRL_PINMODE
, 1);
262 // Configure the device for performance mode
263 bmi270RegisterWrite(dev
, BMI270_REG_PWR_CONF
, BMI270_VAL_PWR_CONF
, 1);
265 // Enable the gyro, accelerometer and temperature sensor - disable aux interface
266 bmi270RegisterWrite(dev
, BMI270_REG_PWR_CTRL
, BMI270_VAL_PWR_CTRL
, 1);
270 bmi270RegisterWrite(dev
, BMI270_REG_CMD
, BMI270_VAL_CMD_FIFOFLUSH
, 1);
274 extiCallbackRec_t bmi270IntCallbackRec
;
277 * Gyro interrupt service routine
279 // Called in ISR context
280 // Gyro read has just completed
281 busStatus_e
bmi270Intcallback(uint32_t arg
)
283 gyroDev_t
*gyro
= (gyroDev_t
*)arg
;
284 int32_t gyroDmaDuration
= cmpTimeCycles(getCycleCounter(), gyro
->gyroLastEXTI
);
286 if (gyroDmaDuration
> gyro
->gyroDmaMaxDuration
) {
287 gyro
->gyroDmaMaxDuration
= gyroDmaDuration
;
290 gyro
->dataReady
= true;
295 void bmi270ExtiHandler(extiCallbackRec_t
*cb
)
297 gyroDev_t
*gyro
= container_of(cb
, gyroDev_t
, exti
);
298 extDevice_t
*dev
= &gyro
->dev
;
300 // Ideally we'd use a timer to capture such information, but unfortunately the port used for EXTI interrupt does
301 // not have an associated timer
302 uint32_t nowCycles
= getCycleCounter();
303 gyro
->gyroSyncEXTI
= gyro
->gyroLastEXTI
+ gyro
->gyroDmaMaxDuration
;
304 gyro
->gyroLastEXTI
= nowCycles
;
306 if (gyro
->gyroModeSPI
== GYRO_EXTI_INT_DMA
) {
307 spiSequence(dev
, gyro
->segments
);
310 gyro
->detectedEXTI
++;
314 static void bmi270IntExtiInit(gyroDev_t
*gyro
)
316 if (gyro
->mpuIntExtiTag
== IO_TAG_NONE
) {
320 IO_t mpuIntIO
= IOGetByTag(gyro
->mpuIntExtiTag
);
322 IOInit(mpuIntIO
, OWNER_GYRO_EXTI
, 0);
323 EXTIHandlerInit(&gyro
->exti
, bmi270ExtiHandler
);
324 EXTIConfig(mpuIntIO
, &gyro
->exti
, NVIC_PRIO_MPU_INT_EXTI
, IOCFG_IN_FLOATING
, BETAFLIGHT_EXTI_TRIGGER_RISING
);
325 EXTIEnable(mpuIntIO
);
328 static bool bmi270AccRead(accDev_t
*acc
)
330 extDevice_t
*dev
= &acc
->gyro
->dev
;
332 switch (acc
->gyro
->gyroModeSPI
) {
334 case GYRO_EXTI_NO_INT
:
336 dev
->txBuf
[0] = BMI270_REG_ACC_DATA_X_LSB
| 0x80;
338 busSegment_t segments
[] = {
339 {.u
.buffers
= {NULL
, NULL
}, 8, true, NULL
},
340 {.u
.link
= {NULL
, NULL
}, 0, true, NULL
},
342 segments
[0].u
.buffers
.txData
= dev
->txBuf
;
343 segments
[0].u
.buffers
.rxData
= dev
->rxBuf
;
345 spiSequence(&acc
->gyro
->dev
, &segments
[0]);
347 // Wait for completion
348 spiWait(&acc
->gyro
->dev
);
354 case GYRO_EXTI_INT_DMA
:
356 // If read was triggered in interrupt don't bother waiting. The worst that could happen is that we pick
359 // This data was read from the gyro, which is the same SPI device as the acc
360 int16_t *accData
= (int16_t *)dev
->rxBuf
;
361 acc
->ADCRaw
[X
] = accData
[1];
362 acc
->ADCRaw
[Y
] = accData
[2];
363 acc
->ADCRaw
[Z
] = accData
[3];
375 static bool bmi270GyroReadRegister(gyroDev_t
*gyro
)
377 extDevice_t
*dev
= &gyro
->dev
;
378 int16_t *gyroData
= (int16_t *)dev
->rxBuf
;
380 switch (gyro
->gyroModeSPI
) {
383 // Initialise the tx buffer to all 0x00
384 memset(dev
->txBuf
, 0x00, 14);
386 // Check that minimum number of interrupts have been detected
388 // We need some offset from the gyro interrupts to ensure sampling after the interrupt
389 gyro
->gyroDmaMaxDuration
= 5;
390 // Using DMA for gyro access upsets the scheduler on the F4
391 if (gyro
->detectedEXTI
> GYRO_EXTI_DETECT_THRESHOLD
) {
392 if (spiUseDMA(dev
)) {
393 dev
->callbackArg
= (uint32_t)gyro
;
394 dev
->txBuf
[0] = BMI270_REG_ACC_DATA_X_LSB
| 0x80;
395 gyro
->segments
[0].len
= 14;
396 gyro
->segments
[0].callback
= bmi270Intcallback
;
397 gyro
->segments
[0].u
.buffers
.txData
= dev
->txBuf
;
398 gyro
->segments
[0].u
.buffers
.rxData
= dev
->rxBuf
;
399 gyro
->segments
[0].negateCS
= true;
400 gyro
->gyroModeSPI
= GYRO_EXTI_INT_DMA
;
402 // Interrupts are present, but no DMA
403 gyro
->gyroModeSPI
= GYRO_EXTI_INT
;
406 gyro
->gyroModeSPI
= GYRO_EXTI_NO_INT
;
412 case GYRO_EXTI_NO_INT
:
414 dev
->txBuf
[0] = BMI270_REG_GYR_DATA_X_LSB
| 0x80;
416 busSegment_t segments
[] = {
417 {.u
.buffers
= {NULL
, NULL
}, 8, true, NULL
},
418 {.u
.link
= {NULL
, NULL
}, 0, true, NULL
},
420 segments
[0].u
.buffers
.txData
= dev
->txBuf
;
421 segments
[0].u
.buffers
.rxData
= dev
->rxBuf
;
423 spiSequence(dev
, &segments
[0]);
425 // Wait for completion
428 gyro
->gyroADCRaw
[X
] = gyroData
[1];
429 gyro
->gyroADCRaw
[Y
] = gyroData
[2];
430 gyro
->gyroADCRaw
[Z
] = gyroData
[3];
435 case GYRO_EXTI_INT_DMA
:
437 // If read was triggered in interrupt don't bother waiting. The worst that could happen is that we pick
439 gyro
->gyroADCRaw
[X
] = gyroData
[4];
440 gyro
->gyroADCRaw
[Y
] = gyroData
[5];
441 gyro
->gyroADCRaw
[Z
] = gyroData
[6];
452 #ifdef USE_GYRO_DLPF_EXPERIMENTAL
453 static bool bmi270GyroReadFifo(gyroDev_t
*gyro
)
469 bool dataRead
= false;
470 STATIC_DMA_DATA_AUTO
uint8_t bmi270_tx_buf
[BUFFER_SIZE
] = {BMI270_REG_FIFO_LENGTH_LSB
| 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0};
471 STATIC_DMA_DATA_AUTO
uint8_t bmi270_rx_buf
[BUFFER_SIZE
];
473 // Burst read the FIFO length followed by the next 6 bytes containing the gyro axis data for
474 // the first sample in the queue. It's possible for the FIFO to be empty so we need to check the
475 // length before using the sample.
476 spiReadWriteBuf(&gyro
->dev
, (uint8_t *)bmi270_tx_buf
, bmi270_rx_buf
, BUFFER_SIZE
); // receive response
478 int fifoLength
= (uint16_t)((bmi270_rx_buf
[IDX_FIFO_LENGTH_H
] << 8) | bmi270_rx_buf
[IDX_FIFO_LENGTH_L
]);
480 if (fifoLength
>= BMI270_FIFO_FRAME_SIZE
) {
482 const int16_t gyroX
= (int16_t)((bmi270_rx_buf
[IDX_GYRO_XOUT_H
] << 8) | bmi270_rx_buf
[IDX_GYRO_XOUT_L
]);
483 const int16_t gyroY
= (int16_t)((bmi270_rx_buf
[IDX_GYRO_YOUT_H
] << 8) | bmi270_rx_buf
[IDX_GYRO_YOUT_L
]);
484 const int16_t gyroZ
= (int16_t)((bmi270_rx_buf
[IDX_GYRO_ZOUT_H
] << 8) | bmi270_rx_buf
[IDX_GYRO_ZOUT_L
]);
486 // If the FIFO data is invalid then the returned values will be 0x8000 (-32768) (pg. 43 of datasheet).
487 // This shouldn't happen since we're only using the data if the FIFO length indicates
488 // that data is available, but this safeguard is needed to prevent bad things in
489 // case it does happen.
490 if ((gyroX
!= INT16_MIN
) || (gyroY
!= INT16_MIN
) || (gyroZ
!= INT16_MIN
)) {
491 gyro
->gyroADCRaw
[X
] = gyroX
;
492 gyro
->gyroADCRaw
[Y
] = gyroY
;
493 gyro
->gyroADCRaw
[Z
] = gyroZ
;
496 fifoLength
-= BMI270_FIFO_FRAME_SIZE
;
499 // If there are additional samples in the FIFO then we don't use those for now and simply
500 // flush the FIFO. Under normal circumstances we only expect one sample in the FIFO since
501 // the gyro loop is running at the native sample rate of 6.4KHz.
502 // However the way the FIFO works in the sensor is that if a frame is partially read then
503 // it remains in the queue instead of bein removed. So if we ever got into a state where there
504 // was a partial frame or other unexpected data in the FIFO is may never get cleared and we
505 // would end up in a lock state of always re-reading the same partial or invalid sample.
506 if (fifoLength
> 0) {
507 // Partial or additional frames left - flush the FIFO
508 bmi270RegisterWrite(&gyro
->dev
, BMI270_REG_CMD
, BMI270_VAL_CMD_FIFOFLUSH
, 0);
515 static bool bmi270GyroRead(gyroDev_t
*gyro
)
517 #ifdef USE_GYRO_DLPF_EXPERIMENTAL
518 if (gyro
->hardware_lpf
== GYRO_HARDWARE_LPF_EXPERIMENTAL
) {
519 // running in 6.4KHz FIFO mode
520 return bmi270GyroReadFifo(gyro
);
524 // running in 3.2KHz register mode
525 return bmi270GyroReadRegister(gyro
);
529 static void bmi270SpiGyroInit(gyroDev_t
*gyro
)
531 extDevice_t
*dev
= &gyro
->dev
;
535 bmi270IntExtiInit(gyro
);
537 spiSetClkDivisor(dev
, spiCalculateDivider(BMI270_MAX_SPI_CLK_HZ
));
540 static void bmi270SpiAccInit(accDev_t
*acc
)
542 // sensor is configured during gyro init
543 acc
->acc_1G
= 512 * 4; // 16G sensor scale
546 bool bmi270SpiAccDetect(accDev_t
*acc
)
548 if (acc
->mpuDetectionResult
.sensor
!= BMI_270_SPI
) {
552 acc
->initFn
= bmi270SpiAccInit
;
553 acc
->readFn
= bmi270AccRead
;
559 bool bmi270SpiGyroDetect(gyroDev_t
*gyro
)
561 if (gyro
->mpuDetectionResult
.sensor
!= BMI_270_SPI
) {
565 gyro
->initFn
= bmi270SpiGyroInit
;
566 gyro
->readFn
= bmi270GyroRead
;
567 gyro
->scale
= GYRO_SCALE_2000DPS
;
572 // Used to query the status register to determine what event caused the EXTI to fire.
573 // When in 3.2KHz mode the interrupt is mapped to the data ready state. However the data ready
574 // trigger will fire for both gyro and accelerometer. So it's necessary to check this register
575 // to determine which event caused the interrupt.
576 // When in 6.4KHz mode the interrupt is configured to be the FIFO watermark size of 6 bytes.
577 // Since in this mode we only put gyro data in the FIFO it's sufficient to check for the FIFO
578 // watermark reason as an idication of gyro data ready.
579 uint8_t bmi270InterruptStatus(gyroDev_t
*gyro
)
581 return bmi270RegisterRead(&gyro
->dev
, BMI270_REG_INT_STATUS_1
);
583 #endif // USE_ACCGYRO_BMI270