[4.4.2] Remove 15 m/s limit on estimated vario (#12788)
[betaflight.git] / src / main / drivers / accgyro / accgyro_spi_bmi270.c
blobbc6331c3a3fc999c8ec246f0c3dfef915e93e973
1 /*
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)
8 * any later version.
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/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include "platform.h"
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)
56 typedef enum {
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,
98 } bmi270Register_e;
100 // BMI270 register configuration values
101 typedef enum {
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)) {
143 return data[1];
144 } else {
145 return 0;
149 static void bmi270RegisterWrite(const extDevice_t *dev, bmi270Register_e registerId, uint8_t value, unsigned delayMs)
151 spiWriteReg(dev, registerId, value);
152 if (delayMs) {
153 delay(delayMs);
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);
162 delay(1);
163 IOHi(dev->busType_u.spi.csnPin);
164 delay(10);
167 uint8_t bmi270Detect(const extDevice_t *dev)
169 bmi270EnableSPI(dev);
171 if (bmi270RegisterRead(dev, BMI270_REG_CHIP_ID) == BMI270_CHIP_ID) {
172 return BMI_270_SPI;
175 return MPU_NONE;
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));
186 delay(10);
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;
202 #endif
203 default:
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);
216 #else
217 const bool fifoMode = false;
218 #endif
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
230 if (fifoMode) {
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
251 if (fifoMode) {
252 // Interrupt driven by FIFO watermark level
253 bmi270RegisterWrite(dev, BMI270_REG_INT_MAP_DATA, BMI270_VAL_INT_MAP_FIFO_WM_INT1, 1);
254 } else {
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);
268 // Flush the FIFO
269 if (fifoMode) {
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;
292 return BUS_READY;
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) {
317 return;
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) {
333 case GYRO_EXTI_INT:
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);
350 // Fall through
351 FALLTHROUGH;
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
357 // up an old value.
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];
364 break;
367 case GYRO_EXTI_INIT:
368 default:
369 break;
372 return true;
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) {
381 case GYRO_EXTI_INIT:
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;
401 } else {
402 // Interrupts are present, but no DMA
403 gyro->gyroModeSPI = GYRO_EXTI_INT;
405 } else {
406 gyro->gyroModeSPI = GYRO_EXTI_NO_INT;
408 break;
411 case GYRO_EXTI_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
426 spiWait(dev);
428 gyro->gyroADCRaw[X] = gyroData[1];
429 gyro->gyroADCRaw[Y] = gyroData[2];
430 gyro->gyroADCRaw[Z] = gyroData[3];
432 break;
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
438 // up an old value.
439 gyro->gyroADCRaw[X] = gyroData[4];
440 gyro->gyroADCRaw[Y] = gyroData[5];
441 gyro->gyroADCRaw[Z] = gyroData[6];
442 break;
445 default:
446 break;
449 return true;
452 #ifdef USE_GYRO_DLPF_EXPERIMENTAL
453 static bool bmi270GyroReadFifo(gyroDev_t *gyro)
455 enum {
456 IDX_REG = 0,
457 IDX_SKIP,
458 IDX_FIFO_LENGTH_L,
459 IDX_FIFO_LENGTH_H,
460 IDX_GYRO_XOUT_L,
461 IDX_GYRO_XOUT_H,
462 IDX_GYRO_YOUT_L,
463 IDX_GYRO_YOUT_H,
464 IDX_GYRO_ZOUT_L,
465 IDX_GYRO_ZOUT_H,
466 BUFFER_SIZE,
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;
494 dataRead = true;
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);
511 return dataRead;
513 #endif
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);
521 } else
522 #endif
524 // running in 3.2KHz register mode
525 return bmi270GyroReadRegister(gyro);
529 static void bmi270SpiGyroInit(gyroDev_t *gyro)
531 extDevice_t *dev = &gyro->dev;
533 bmi270Config(gyro);
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) {
549 return false;
552 acc->initFn = bmi270SpiAccInit;
553 acc->readFn = bmi270AccRead;
555 return true;
559 bool bmi270SpiGyroDetect(gyroDev_t *gyro)
561 if (gyro->mpuDetectionResult.sensor != BMI_270_SPI) {
562 return false;
565 gyro->initFn = bmi270SpiGyroInit;
566 gyro->readFn = bmi270GyroRead;
567 gyro->scale = GYRO_SCALE_2000DPS;
569 return true;
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