diff --git a/make/source.mk b/make/source.mk
index abc8b833d..baa91c8cc 100644
--- a/make/source.mk
+++ b/make/source.mk
@@ -126,6 +126,7 @@ COMMON_SRC = \
sensors/boardalignment.c \
sensors/compass.c \
sensors/gyro.c \
+ sensors/gyro_init.c \
sensors/initialisation.c \
blackbox/blackbox.c \
blackbox/blackbox_encoding.c \
@@ -348,7 +349,8 @@ SIZE_OPTIMISED_SRC := $(SIZE_OPTIMISED_SRC) \
io/spektrum_vtx_control.c \
osd/osd.c \
osd/osd_elements.c \
- rx/rx_bind.c
+ rx/rx_bind.c \
+ sensors/gyro_init.c
# F4 and F7 optimizations
ifneq ($(TARGET),$(filter $(TARGET),$(F3_TARGETS)))
diff --git a/src/main/cli/cli.c b/src/main/cli/cli.c
index cb6c828ff..5d32eb2f2 100644
--- a/src/main/cli/cli.c
+++ b/src/main/cli/cli.c
@@ -164,6 +164,7 @@ bool cliMode = false;
#include "sensors/compass.h"
#include "sensors/esc_sensor.h"
#include "sensors/gyro.h"
+#include "sensors/gyro_init.h"
#include "sensors/sensors.h"
#include "telemetry/frsky_hub.h"
diff --git a/src/main/fc/init.c b/src/main/fc/init.c
index 6d8abc15b..6f8983396 100644
--- a/src/main/fc/init.c
+++ b/src/main/fc/init.c
@@ -164,6 +164,7 @@
#include "sensors/compass.h"
#include "sensors/esc_sensor.h"
#include "sensors/gyro.h"
+#include "sensors/gyro_init.h"
#include "sensors/initialisation.h"
#include "telemetry/telemetry.h"
diff --git a/src/main/msp/msp.c b/src/main/msp/msp.c
index 4518b438f..577031940 100644
--- a/src/main/msp/msp.c
+++ b/src/main/msp/msp.c
@@ -133,6 +133,7 @@
#include "sensors/compass.h"
#include "sensors/esc_sensor.h"
#include "sensors/gyro.h"
+#include "sensors/gyro_init.h"
#include "sensors/rangefinder.h"
#include "telemetry/telemetry.h"
diff --git a/src/main/sensors/acceleration.c b/src/main/sensors/acceleration.c
index 4d912c83e..07f1b447c 100644
--- a/src/main/sensors/acceleration.c
+++ b/src/main/sensors/acceleration.c
@@ -80,6 +80,7 @@
#include "sensors/boardalignment.h"
#include "sensors/gyro.h"
+#include "sensors/gyro_init.h"
#include "sensors/sensors.h"
#include "acceleration.h"
diff --git a/src/main/sensors/compass.c b/src/main/sensors/compass.c
index a63c7f704..2be2970b5 100644
--- a/src/main/sensors/compass.c
+++ b/src/main/sensors/compass.c
@@ -51,6 +51,7 @@
#include "sensors/boardalignment.h"
#include "sensors/gyro.h"
+#include "sensors/gyro_init.h"
#include "sensors/sensors.h"
#include "compass.h"
diff --git a/src/main/sensors/gyro.c b/src/main/sensors/gyro.c
index 53aa348d5..15fc4caa8 100644
--- a/src/main/sensors/gyro.c
+++ b/src/main/sensors/gyro.c
@@ -38,31 +38,6 @@
#include "pg/pg_ids.h"
#include "pg/gyrodev.h"
-#include "drivers/accgyro/accgyro.h"
-#include "drivers/accgyro/accgyro_fake.h"
-#include "drivers/accgyro/accgyro_mpu.h"
-#include "drivers/accgyro/accgyro_mpu3050.h"
-#include "drivers/accgyro/accgyro_mpu6050.h"
-#include "drivers/accgyro/accgyro_mpu6500.h"
-#include "drivers/accgyro/accgyro_spi_bmi160.h"
-#include "drivers/accgyro/accgyro_spi_bmi270.h"
-#include "drivers/accgyro/accgyro_spi_icm20649.h"
-#include "drivers/accgyro/accgyro_spi_icm20689.h"
-#include "drivers/accgyro/accgyro_spi_icm20689.h"
-#include "drivers/accgyro/accgyro_spi_icm42605.h"
-#include "drivers/accgyro/accgyro_spi_mpu6000.h"
-#include "drivers/accgyro/accgyro_spi_mpu6500.h"
-#include "drivers/accgyro/accgyro_spi_mpu9250.h"
-
-#ifdef USE_GYRO_L3GD20
-#include "drivers/accgyro/accgyro_spi_l3gd20.h"
-#endif
-
-#ifdef USE_GYRO_L3G4200D
-#include "drivers/accgyro_legacy/accgyro_l3g4200d.h"
-#endif
-
-#include "drivers/accgyro/gyro_sync.h"
#include "drivers/bus_spi.h"
#include "drivers/io.h"
@@ -81,25 +56,19 @@
#include "sensors/boardalignment.h"
#include "sensors/gyro.h"
-#include "sensors/sensors.h"
+#include "sensors/gyro_init.h"
#if ((TARGET_FLASH_SIZE > 128) && (defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_SPI_MPU6500)))
#define USE_GYRO_SLEW_LIMITER
#endif
FAST_RAM_ZERO_INIT gyro_t gyro;
-static FAST_RAM_ZERO_INIT uint8_t gyroDebugMode;
-static FAST_RAM_ZERO_INIT uint8_t gyroToUse;
static FAST_RAM_ZERO_INIT bool overflowDetected;
#ifdef USE_GYRO_OVERFLOW_CHECK
static FAST_RAM_ZERO_INIT timeUs_t overflowTimeUs;
#endif
-#ifdef USE_GYRO_OVERFLOW_CHECK
-static FAST_RAM_ZERO_INIT uint8_t overflowAxisMask;
-#endif
-
#ifdef USE_YAW_SPIN_RECOVERY
static FAST_RAM_ZERO_INIT bool yawSpinRecoveryEnabled;
static FAST_RAM_ZERO_INIT int yawSpinRecoveryThreshold;
@@ -113,39 +82,15 @@ static FAST_RAM_ZERO_INIT int accumulatedMeasurementCount;
static FAST_RAM_ZERO_INIT int16_t gyroSensorTemperature;
-static bool gyroHasOverflowProtection = true;
-
-static FAST_RAM_ZERO_INIT bool useDualGyroDebugging;
-static FAST_RAM_ZERO_INIT flight_dynamics_index_t gyroDebugAxis;
FAST_RAM uint8_t activePidLoopDenom = 1;
-typedef struct gyroCalibration_s {
- float sum[XYZ_AXIS_COUNT];
- stdev_t var[XYZ_AXIS_COUNT];
- int32_t cyclesRemaining;
-} gyroCalibration_t;
-
static bool firstArmingCalibrationWasStarted = false;
-typedef struct gyroSensor_s {
- gyroDev_t gyroDev;
- gyroCalibration_t calibration;
-} gyroSensor_t;
-
-STATIC_UNIT_TESTED FAST_RAM_ZERO_INIT gyroSensor_t gyroSensor1;
-#ifdef USE_MULTI_GYRO
-STATIC_UNIT_TESTED FAST_RAM_ZERO_INIT gyroSensor_t gyroSensor2;
-#endif
-
-static gyroDetectionFlags_t gyroDetectionFlags = NO_GYROS_DETECTED;
-
#ifdef UNIT_TEST
-STATIC_UNIT_TESTED gyroSensor_t * const gyroSensorPtr = &gyroSensor1;
-STATIC_UNIT_TESTED gyroDev_t * const gyroDevPtr = &gyroSensor1.gyroDev;
+STATIC_UNIT_TESTED gyroSensor_t * const gyroSensorPtr = &gyro.gyroSensor1;
+STATIC_UNIT_TESTED gyroDev_t * const gyroDevPtr = &gyro.gyroSensor1.gyroDev;
#endif
-static void gyroInitSensorFilters(gyroSensor_t *gyroSensor);
-static bool gyroInitLowpassFilterLpf(int slot, int type, uint16_t lpfHz, uint32_t looptime);
#define DEBUG_GYRO_CALIBRATION 3
@@ -158,11 +103,6 @@ PG_REGISTER_WITH_RESET_FN(gyroConfig_t, gyroConfig, PG_GYRO_CONFIG, 8);
#define GYRO_CONFIG_USE_GYRO_DEFAULT GYRO_CONFIG_USE_GYRO_1
#endif
-#ifdef USE_GYRO_DATA_ANALYSE
-#define DYNAMIC_NOTCH_DEFAULT_CENTER_HZ 350
-#define DYNAMIC_NOTCH_DEFAULT_CUTOFF_HZ 300
-#endif
-
void pgResetFn_gyroConfig(gyroConfig_t *gyroConfig)
{
gyroConfig->gyroCalibrationDuration = 125; // 1.25 seconds
@@ -194,624 +134,13 @@ void pgResetFn_gyroConfig(gyroConfig_t *gyroConfig)
gyroConfig->gyro_filter_debug_axis = FD_ROLL;
}
-#ifdef USE_MULTI_GYRO
-#define ACTIVE_GYRO ((gyroToUse == GYRO_CONFIG_USE_GYRO_2) ? &gyroSensor2 : &gyroSensor1)
-#else
-#define ACTIVE_GYRO (&gyroSensor1)
-#endif
-
-const busDevice_t *gyroSensorBus(void)
-{
- return &ACTIVE_GYRO->gyroDev.bus;
-}
-
-#ifdef USE_GYRO_REGISTER_DUMP
-const busDevice_t *gyroSensorBusByDevice(uint8_t whichSensor)
-{
-#ifdef USE_MULTI_GYRO
- if (whichSensor == GYRO_CONFIG_USE_GYRO_2) {
- return &gyroSensor2.gyroDev.bus;
- }
-#else
- UNUSED(whichSensor);
-#endif
- return &gyroSensor1.gyroDev.bus;
-}
-#endif // USE_GYRO_REGISTER_DUMP
-
-const mpuDetectionResult_t *gyroMpuDetectionResult(void)
-{
- return &ACTIVE_GYRO->gyroDev.mpuDetectionResult;
-}
-
-STATIC_UNIT_TESTED gyroHardware_e gyroDetect(gyroDev_t *dev)
-{
- gyroHardware_e gyroHardware = GYRO_DEFAULT;
-
- switch (gyroHardware) {
- case GYRO_DEFAULT:
- FALLTHROUGH;
-
-#ifdef USE_GYRO_MPU6050
- case GYRO_MPU6050:
- if (mpu6050GyroDetect(dev)) {
- gyroHardware = GYRO_MPU6050;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_GYRO_L3G4200D
- case GYRO_L3G4200D:
- if (l3g4200dDetect(dev)) {
- gyroHardware = GYRO_L3G4200D;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_GYRO_MPU3050
- case GYRO_MPU3050:
- if (mpu3050Detect(dev)) {
- gyroHardware = GYRO_MPU3050;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_GYRO_L3GD20
- case GYRO_L3GD20:
- if (l3gd20GyroDetect(dev)) {
- gyroHardware = GYRO_L3GD20;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_GYRO_SPI_MPU6000
- case GYRO_MPU6000:
- if (mpu6000SpiGyroDetect(dev)) {
- gyroHardware = GYRO_MPU6000;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#if defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500)
- case GYRO_MPU6500:
- case GYRO_ICM20601:
- case GYRO_ICM20602:
- case GYRO_ICM20608G:
-#ifdef USE_GYRO_SPI_MPU6500
- if (mpu6500GyroDetect(dev) || mpu6500SpiGyroDetect(dev)) {
-#else
- if (mpu6500GyroDetect(dev)) {
-#endif
- switch (dev->mpuDetectionResult.sensor) {
- case MPU_9250_SPI:
- gyroHardware = GYRO_MPU9250;
- break;
- case ICM_20601_SPI:
- gyroHardware = GYRO_ICM20601;
- break;
- case ICM_20602_SPI:
- gyroHardware = GYRO_ICM20602;
- break;
- case ICM_20608_SPI:
- gyroHardware = GYRO_ICM20608G;
- break;
- default:
- gyroHardware = GYRO_MPU6500;
- }
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_GYRO_SPI_MPU9250
- case GYRO_MPU9250:
- if (mpu9250SpiGyroDetect(dev)) {
- gyroHardware = GYRO_MPU9250;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_GYRO_SPI_ICM20649
- case GYRO_ICM20649:
- if (icm20649SpiGyroDetect(dev)) {
- gyroHardware = GYRO_ICM20649;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_GYRO_SPI_ICM20689
- case GYRO_ICM20689:
- if (icm20689SpiGyroDetect(dev)) {
- gyroHardware = GYRO_ICM20689;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_GYRO_SPI_ICM42605
- case GYRO_ICM42605:
- if (icm42605SpiGyroDetect(dev)) {
- gyroHardware = GYRO_ICM42605;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_ACCGYRO_BMI160
- case GYRO_BMI160:
- if (bmi160SpiGyroDetect(dev)) {
- gyroHardware = GYRO_BMI160;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_ACCGYRO_BMI270
- case GYRO_BMI270:
- if (bmi270SpiGyroDetect(dev)) {
- gyroHardware = GYRO_BMI270;
- break;
- }
- FALLTHROUGH;
-#endif
-
-#ifdef USE_FAKE_GYRO
- case GYRO_FAKE:
- if (fakeGyroDetect(dev)) {
- gyroHardware = GYRO_FAKE;
- break;
- }
- FALLTHROUGH;
-#endif
-
- default:
- gyroHardware = GYRO_NONE;
- }
-
- if (gyroHardware != GYRO_NONE) {
- sensorsSet(SENSOR_GYRO);
- }
-
-
- return gyroHardware;
-}
-
-static void gyroPreInitSensor(const gyroDeviceConfig_t *config)
-{
-#if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \
- || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) \
- || defined(USE_GYRO_SPI_ICM20689) || defined(USE_ACCGYRO_BMI160) || defined(USE_ACCGYRO_BMI270)
- mpuPreInit(config);
-#else
- UNUSED(config);
-#endif
-}
-
-static bool gyroDetectSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config)
-{
-#if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \
- || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) \
- || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_L3GD20) || defined(USE_ACCGYRO_BMI160) || defined(USE_ACCGYRO_BMI270)
-
- bool gyroFound = mpuDetect(&gyroSensor->gyroDev, config);
-
-#if !defined(USE_FAKE_GYRO) // Allow resorting to fake accgyro if defined
- if (!gyroFound) {
- return false;
- }
-#else
- UNUSED(gyroFound);
-#endif
-#else
- UNUSED(config);
-#endif
-
- const gyroHardware_e gyroHardware = gyroDetect(&gyroSensor->gyroDev);
- gyroSensor->gyroDev.gyroHardware = gyroHardware;
-
- return gyroHardware != GYRO_NONE;
-}
-
-static void gyroInitSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config)
-{
- gyroSensor->gyroDev.gyro_high_fsr = gyroConfig()->gyro_high_fsr;
- gyroSensor->gyroDev.gyroAlign = config->alignment;
- buildRotationMatrixFromAlignment(&config->customAlignment, &gyroSensor->gyroDev.rotationMatrix);
- gyroSensor->gyroDev.mpuIntExtiTag = config->extiTag;
- gyroSensor->gyroDev.hardware_lpf = gyroConfig()->gyro_hardware_lpf;
-
- // The targetLooptime gets set later based on the active sensor's gyroSampleRateHz and pid_process_denom
- gyroSensor->gyroDev.gyroSampleRateHz = gyroSetSampleRate(&gyroSensor->gyroDev);
- gyroSensor->gyroDev.initFn(&gyroSensor->gyroDev);
-
- // As new gyros are supported, be sure to add them below based on whether they are subject to the overflow/inversion bug
- // Any gyro not explicitly defined will default to not having built-in overflow protection as a safe alternative.
- switch (gyroSensor->gyroDev.gyroHardware) {
- case GYRO_NONE: // Won't ever actually get here, but included to account for all gyro types
- case GYRO_DEFAULT:
- case GYRO_FAKE:
- case GYRO_MPU6050:
- case GYRO_L3G4200D:
- case GYRO_MPU3050:
- case GYRO_L3GD20:
- case GYRO_BMI160:
- case GYRO_BMI270:
- case GYRO_MPU6000:
- case GYRO_MPU6500:
- case GYRO_MPU9250:
- gyroSensor->gyroDev.gyroHasOverflowProtection = true;
- break;
-
- case GYRO_ICM20601:
- case GYRO_ICM20602:
- case GYRO_ICM20608G:
- case GYRO_ICM20649: // we don't actually know if this is affected, but as there are currently no flight controllers using it we err on the side of caution
- case GYRO_ICM20689:
- gyroSensor->gyroDev.gyroHasOverflowProtection = false;
- break;
-
- default:
- gyroSensor->gyroDev.gyroHasOverflowProtection = false; // default catch for newly added gyros until proven to be unaffected
- break;
- }
-
- gyroInitSensorFilters(gyroSensor);
-
-}
-
-void gyroPreInit(void)
-{
- gyroPreInitSensor(gyroDeviceConfig(0));
-#ifdef USE_MULTI_GYRO
- gyroPreInitSensor(gyroDeviceConfig(1));
-#endif
-}
-
-bool gyroInit(void)
-{
-#ifdef USE_GYRO_OVERFLOW_CHECK
- if (gyroConfig()->checkOverflow == GYRO_OVERFLOW_CHECK_YAW) {
- overflowAxisMask = GYRO_OVERFLOW_Z;
- } else if (gyroConfig()->checkOverflow == GYRO_OVERFLOW_CHECK_ALL_AXES) {
- overflowAxisMask = GYRO_OVERFLOW_X | GYRO_OVERFLOW_Y | GYRO_OVERFLOW_Z;
- } else {
- overflowAxisMask = 0;
- }
-#endif
-
- gyroDebugMode = DEBUG_NONE;
- useDualGyroDebugging = false;
-
- switch (debugMode) {
- case DEBUG_FFT:
- case DEBUG_FFT_FREQ:
- case DEBUG_GYRO_RAW:
- case DEBUG_GYRO_SCALED:
- case DEBUG_GYRO_FILTERED:
- case DEBUG_DYN_LPF:
- case DEBUG_GYRO_SAMPLE:
- gyroDebugMode = debugMode;
- break;
- case DEBUG_DUAL_GYRO_DIFF:
- case DEBUG_DUAL_GYRO_RAW:
- case DEBUG_DUAL_GYRO_SCALED:
- useDualGyroDebugging = true;
- break;
- }
- firstArmingCalibrationWasStarted = false;
-
- gyroDetectionFlags = NO_GYROS_DETECTED;
-
- gyroToUse = gyroConfig()->gyro_to_use;
- gyroDebugAxis = gyroConfig()->gyro_filter_debug_axis;
-
- if (gyroDetectSensor(&gyroSensor1, gyroDeviceConfig(0))) {
- gyroDetectionFlags |= DETECTED_GYRO_1;
- }
-
-#if defined(USE_MULTI_GYRO)
- if (gyroDetectSensor(&gyroSensor2, gyroDeviceConfig(1))) {
- gyroDetectionFlags |= DETECTED_GYRO_2;
- }
-#endif
-
- if (gyroDetectionFlags == NO_GYROS_DETECTED) {
- return false;
- }
-
-#if defined(USE_MULTI_GYRO)
- if ((gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH && !((gyroDetectionFlags & DETECTED_BOTH_GYROS) == DETECTED_BOTH_GYROS))
- || (gyroToUse == GYRO_CONFIG_USE_GYRO_1 && !(gyroDetectionFlags & DETECTED_GYRO_1))
- || (gyroToUse == GYRO_CONFIG_USE_GYRO_2 && !(gyroDetectionFlags & DETECTED_GYRO_2))) {
- if (gyroDetectionFlags & DETECTED_GYRO_1) {
- gyroToUse = GYRO_CONFIG_USE_GYRO_1;
- } else {
- gyroToUse = GYRO_CONFIG_USE_GYRO_2;
- }
-
- gyroConfigMutable()->gyro_to_use = gyroToUse;
- }
-
- // Only allow using both gyros simultaneously if they are the same hardware type.
- if (((gyroDetectionFlags & DETECTED_BOTH_GYROS) == DETECTED_BOTH_GYROS) && gyroSensor1.gyroDev.gyroHardware == gyroSensor2.gyroDev.gyroHardware) {
- gyroDetectionFlags |= DETECTED_DUAL_GYROS;
- } else if (gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
- // If the user selected "BOTH" and they are not the same type, then reset to using only the first gyro.
- gyroToUse = GYRO_CONFIG_USE_GYRO_1;
- gyroConfigMutable()->gyro_to_use = gyroToUse;
- }
-
- if (gyroToUse == GYRO_CONFIG_USE_GYRO_2 || gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
- gyroInitSensor(&gyroSensor2, gyroDeviceConfig(1));
- gyroHasOverflowProtection = gyroHasOverflowProtection && gyroSensor2.gyroDev.gyroHasOverflowProtection;
- detectedSensors[SENSOR_INDEX_GYRO] = gyroSensor2.gyroDev.gyroHardware;
- }
-#endif
-
- if (gyroToUse == GYRO_CONFIG_USE_GYRO_1 || gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
- gyroInitSensor(&gyroSensor1, gyroDeviceConfig(0));
- gyroHasOverflowProtection = gyroHasOverflowProtection && gyroSensor1.gyroDev.gyroHasOverflowProtection;
- detectedSensors[SENSOR_INDEX_GYRO] = gyroSensor1.gyroDev.gyroHardware;
- }
-
- // Copy the sensor's scale to the high-level gyro object. If running in "BOTH" mode
- // then logic above requires both sensors to be the same so we'll use sensor1's scale.
- // This will need to be revised if we ever allow different sensor types to be used simultaneously.
- // Likewise determine the appropriate raw data for use in DEBUG_GYRO_RAW
- gyro.scale = gyroSensor1.gyroDev.scale;
- gyro.rawSensorDev = &gyroSensor1.gyroDev;
-#if defined(USE_MULTI_GYRO)
- if (gyroToUse == GYRO_CONFIG_USE_GYRO_2) {
- gyro.scale = gyroSensor2.gyroDev.scale;
- gyro.rawSensorDev = &gyroSensor2.gyroDev;
- }
-#endif
-
- if (gyro.rawSensorDev) {
- gyro.sampleRateHz = gyro.rawSensorDev->gyroSampleRateHz;
- gyro.accSampleRateHz = gyro.rawSensorDev->accSampleRateHz;
- } else {
- gyro.sampleRateHz = 0;
- gyro.accSampleRateHz = 0;
- }
-
- return true;
-}
-
-gyroDetectionFlags_t getGyroDetectionFlags(void)
-{
- return gyroDetectionFlags;
-}
-
-#ifdef USE_DYN_LPF
-static FAST_RAM uint8_t dynLpfFilter = DYN_LPF_NONE;
-static FAST_RAM_ZERO_INIT uint16_t dynLpfMin;
-static FAST_RAM_ZERO_INIT uint16_t dynLpfMax;
-
-static void dynLpfFilterInit()
-{
- if (gyroConfig()->dyn_lpf_gyro_min_hz > 0) {
- switch (gyroConfig()->gyro_lowpass_type) {
- case FILTER_PT1:
- dynLpfFilter = DYN_LPF_PT1;
- break;
- case FILTER_BIQUAD:
- dynLpfFilter = DYN_LPF_BIQUAD;
- break;
- default:
- dynLpfFilter = DYN_LPF_NONE;
- break;
- }
- } else {
- dynLpfFilter = DYN_LPF_NONE;
- }
- dynLpfMin = gyroConfig()->dyn_lpf_gyro_min_hz;
- dynLpfMax = gyroConfig()->dyn_lpf_gyro_max_hz;
-}
-#endif
-
-bool gyroInitLowpassFilterLpf(int slot, int type, uint16_t lpfHz, uint32_t looptime)
-{
- filterApplyFnPtr *lowpassFilterApplyFn;
- gyroLowpassFilter_t *lowpassFilter = NULL;
-
- switch (slot) {
- case FILTER_LOWPASS:
- lowpassFilterApplyFn = &gyro.lowpassFilterApplyFn;
- lowpassFilter = gyro.lowpassFilter;
- break;
-
- case FILTER_LOWPASS2:
- lowpassFilterApplyFn = &gyro.lowpass2FilterApplyFn;
- lowpassFilter = gyro.lowpass2Filter;
- break;
-
- default:
- return false;
- }
-
- bool ret = false;
-
- // Establish some common constants
- const uint32_t gyroFrequencyNyquist = 1000000 / 2 / looptime;
- const float gyroDt = looptime * 1e-6f;
-
- // Gain could be calculated a little later as it is specific to the pt1/bqrcf2/fkf branches
- const float gain = pt1FilterGain(lpfHz, gyroDt);
-
- // Dereference the pointer to null before checking valid cutoff and filter
- // type. It will be overridden for positive cases.
- *lowpassFilterApplyFn = nullFilterApply;
-
- // If lowpass cutoff has been specified and is less than the Nyquist frequency
- if (lpfHz && lpfHz <= gyroFrequencyNyquist) {
- switch (type) {
- case FILTER_PT1:
- *lowpassFilterApplyFn = (filterApplyFnPtr) pt1FilterApply;
- for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
- pt1FilterInit(&lowpassFilter[axis].pt1FilterState, gain);
- }
- ret = true;
- break;
- case FILTER_BIQUAD:
-#ifdef USE_DYN_LPF
- *lowpassFilterApplyFn = (filterApplyFnPtr) biquadFilterApplyDF1;
-#else
- *lowpassFilterApplyFn = (filterApplyFnPtr) biquadFilterApply;
-#endif
- for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
- biquadFilterInitLPF(&lowpassFilter[axis].biquadFilterState, lpfHz, looptime);
- }
- ret = true;
- break;
- }
- }
- return ret;
-}
-
-static uint16_t calculateNyquistAdjustedNotchHz(uint16_t notchHz, uint16_t notchCutoffHz)
-{
- const uint32_t gyroFrequencyNyquist = 1000000 / 2 / gyro.targetLooptime;
- if (notchHz > gyroFrequencyNyquist) {
- if (notchCutoffHz < gyroFrequencyNyquist) {
- notchHz = gyroFrequencyNyquist;
- } else {
- notchHz = 0;
- }
- }
-
- return notchHz;
-}
-
-#if defined(USE_GYRO_SLEW_LIMITER)
-void gyroInitSlewLimiter(gyroSensor_t *gyroSensor) {
-
- for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
- gyroSensor->gyroDev.gyroADCRawPrevious[axis] = 0;
- }
-}
-#endif
-
-static void gyroInitFilterNotch1(uint16_t notchHz, uint16_t notchCutoffHz)
-{
- gyro.notchFilter1ApplyFn = nullFilterApply;
-
- notchHz = calculateNyquistAdjustedNotchHz(notchHz, notchCutoffHz);
-
- if (notchHz != 0 && notchCutoffHz != 0) {
- gyro.notchFilter1ApplyFn = (filterApplyFnPtr)biquadFilterApply;
- const float notchQ = filterGetNotchQ(notchHz, notchCutoffHz);
- for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
- biquadFilterInit(&gyro.notchFilter1[axis], notchHz, gyro.targetLooptime, notchQ, FILTER_NOTCH);
- }
- }
-}
-
-static void gyroInitFilterNotch2(uint16_t notchHz, uint16_t notchCutoffHz)
-{
- gyro.notchFilter2ApplyFn = nullFilterApply;
-
- notchHz = calculateNyquistAdjustedNotchHz(notchHz, notchCutoffHz);
-
- if (notchHz != 0 && notchCutoffHz != 0) {
- gyro.notchFilter2ApplyFn = (filterApplyFnPtr)biquadFilterApply;
- const float notchQ = filterGetNotchQ(notchHz, notchCutoffHz);
- for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
- biquadFilterInit(&gyro.notchFilter2[axis], notchHz, gyro.targetLooptime, notchQ, FILTER_NOTCH);
- }
- }
-}
-
#ifdef USE_GYRO_DATA_ANALYSE
-static bool isDynamicFilterActive(void)
+bool isDynamicFilterActive(void)
{
return featureIsEnabled(FEATURE_DYNAMIC_FILTER);
}
-
-static void gyroInitFilterDynamicNotch()
-{
- gyro.notchFilterDynApplyFn = nullFilterApply;
- gyro.notchFilterDynApplyFn2 = nullFilterApply;
-
- if (isDynamicFilterActive()) {
- gyro.notchFilterDynApplyFn = (filterApplyFnPtr)biquadFilterApplyDF1; // must be this function, not DF2
- if(gyroConfig()->dyn_notch_width_percent != 0) {
- gyro.notchFilterDynApplyFn2 = (filterApplyFnPtr)biquadFilterApplyDF1; // must be this function, not DF2
- }
- const float notchQ = filterGetNotchQ(DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, DYNAMIC_NOTCH_DEFAULT_CUTOFF_HZ); // any defaults OK here
- for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
- biquadFilterInit(&gyro.notchFilterDyn[axis], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, gyro.targetLooptime, notchQ, FILTER_NOTCH);
- biquadFilterInit(&gyro.notchFilterDyn2[axis], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, gyro.targetLooptime, notchQ, FILTER_NOTCH);
- }
- }
-}
#endif
-static void gyroInitSensorFilters(gyroSensor_t *gyroSensor)
-{
-#if defined(USE_GYRO_SLEW_LIMITER)
- gyroInitSlewLimiter(gyroSensor);
-#else
- UNUSED(gyroSensor);
-#endif
-}
-
-void gyroSetTargetLooptime(uint8_t pidDenom)
-{
- activePidLoopDenom = pidDenom;
- if (gyro.sampleRateHz) {
- gyro.sampleLooptime = 1e6 / gyro.sampleRateHz;
- gyro.targetLooptime = activePidLoopDenom * 1e6 / gyro.sampleRateHz;
- } else {
- gyro.sampleLooptime = 0;
- gyro.targetLooptime = 0;
- }
-}
-
-void gyroInitFilters(void)
-{
- uint16_t gyro_lowpass_hz = gyroConfig()->gyro_lowpass_hz;
-
-#ifdef USE_DYN_LPF
- if (gyroConfig()->dyn_lpf_gyro_min_hz > 0) {
- gyro_lowpass_hz = gyroConfig()->dyn_lpf_gyro_min_hz;
- }
-#endif
-
- gyroInitLowpassFilterLpf(
- FILTER_LOWPASS,
- gyroConfig()->gyro_lowpass_type,
- gyro_lowpass_hz,
- gyro.targetLooptime
- );
-
- gyro.downsampleFilterEnabled = gyroInitLowpassFilterLpf(
- FILTER_LOWPASS2,
- gyroConfig()->gyro_lowpass2_type,
- gyroConfig()->gyro_lowpass2_hz,
- gyro.sampleLooptime
- );
-
- gyroInitFilterNotch1(gyroConfig()->gyro_soft_notch_hz_1, gyroConfig()->gyro_soft_notch_cutoff_1);
- gyroInitFilterNotch2(gyroConfig()->gyro_soft_notch_hz_2, gyroConfig()->gyro_soft_notch_cutoff_2);
-#ifdef USE_GYRO_DATA_ANALYSE
- gyroInitFilterDynamicNotch();
-#endif
-#ifdef USE_DYN_LPF
- dynLpfFilterInit();
-#endif
-#ifdef USE_GYRO_DATA_ANALYSE
- gyroDataAnalyseStateInit(&gyro.gyroAnalyseState, gyro.targetLooptime);
-#endif
-}
-
FAST_CODE bool isGyroSensorCalibrationComplete(const gyroSensor_t *gyroSensor)
{
return gyroSensor->calibration.cyclesRemaining == 0;
@@ -819,17 +148,17 @@ FAST_CODE bool isGyroSensorCalibrationComplete(const gyroSensor_t *gyroSensor)
FAST_CODE bool gyroIsCalibrationComplete(void)
{
- switch (gyroToUse) {
+ switch (gyro.gyroToUse) {
default:
case GYRO_CONFIG_USE_GYRO_1: {
- return isGyroSensorCalibrationComplete(&gyroSensor1);
+ return isGyroSensorCalibrationComplete(&gyro.gyroSensor1);
}
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2: {
- return isGyroSensorCalibrationComplete(&gyroSensor2);
+ return isGyroSensorCalibrationComplete(&gyro.gyroSensor2);
}
case GYRO_CONFIG_USE_GYRO_BOTH: {
- return isGyroSensorCalibrationComplete(&gyroSensor1) && isGyroSensorCalibrationComplete(&gyroSensor2);
+ return isGyroSensorCalibrationComplete(&gyro.gyroSensor1) && isGyroSensorCalibrationComplete(&gyro.gyroSensor2);
}
#endif
}
@@ -867,9 +196,9 @@ void gyroStartCalibration(bool isFirstArmingCalibration)
return;
}
- gyroSetCalibrationCycles(&gyroSensor1);
+ gyroSetCalibrationCycles(&gyro.gyroSensor1);
#ifdef USE_MULTI_GYRO
- gyroSetCalibrationCycles(&gyroSensor2);
+ gyroSetCalibrationCycles(&gyro.gyroSensor2);
#endif
if (isFirstArmingCalibration) {
@@ -933,7 +262,7 @@ STATIC_UNIT_TESTED void performGyroCalibration(gyroSensor_t *gyroSensor, uint8_t
FAST_CODE int32_t gyroSlewLimiter(gyroSensor_t *gyroSensor, int axis)
{
int32_t ret = (int32_t)gyroSensor->gyroDev.gyroADCRaw[axis];
- if (gyroConfig()->checkOverflow || gyroHasOverflowProtection) {
+ if (gyroConfig()->checkOverflow || gyro.gyroHasOverflowProtection) {
// don't use the slew limiter if overflow checking is on or gyro is not subject to overflow bug
return ret;
}
@@ -998,7 +327,7 @@ static FAST_CODE void checkForOverflow(timeUs_t currentTimeUs)
if (fabsf(gyro.gyroADCf[Z]) > gyroOverflowTriggerRate) {
overflowCheck |= GYRO_OVERFLOW_Z;
}
- if (overflowCheck & overflowAxisMask) {
+ if (overflowCheck & gyro.overflowAxisMask) {
overflowDetected = true;
overflowTimeUs = currentTimeUs;
#ifdef USE_YAW_SPIN_RECOVERY
@@ -1081,31 +410,31 @@ static FAST_CODE FAST_CODE_NOINLINE void gyroUpdateSensor(gyroSensor_t *gyroSens
FAST_CODE void gyroUpdate(void)
{
- switch (gyroToUse) {
+ switch (gyro.gyroToUse) {
case GYRO_CONFIG_USE_GYRO_1:
- gyroUpdateSensor(&gyroSensor1);
- if (isGyroSensorCalibrationComplete(&gyroSensor1)) {
- gyro.gyroADC[X] = gyroSensor1.gyroDev.gyroADC[X] * gyroSensor1.gyroDev.scale;
- gyro.gyroADC[Y] = gyroSensor1.gyroDev.gyroADC[Y] * gyroSensor1.gyroDev.scale;
- gyro.gyroADC[Z] = gyroSensor1.gyroDev.gyroADC[Z] * gyroSensor1.gyroDev.scale;
+ gyroUpdateSensor(&gyro.gyroSensor1);
+ if (isGyroSensorCalibrationComplete(&gyro.gyroSensor1)) {
+ gyro.gyroADC[X] = gyro.gyroSensor1.gyroDev.gyroADC[X] * gyro.gyroSensor1.gyroDev.scale;
+ gyro.gyroADC[Y] = gyro.gyroSensor1.gyroDev.gyroADC[Y] * gyro.gyroSensor1.gyroDev.scale;
+ gyro.gyroADC[Z] = gyro.gyroSensor1.gyroDev.gyroADC[Z] * gyro.gyroSensor1.gyroDev.scale;
}
break;
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2:
- gyroUpdateSensor(&gyroSensor2);
- if (isGyroSensorCalibrationComplete(&gyroSensor2)) {
- gyro.gyroADC[X] = gyroSensor2.gyroDev.gyroADC[X] * gyroSensor2.gyroDev.scale;
- gyro.gyroADC[Y] = gyroSensor2.gyroDev.gyroADC[Y] * gyroSensor2.gyroDev.scale;
- gyro.gyroADC[Z] = gyroSensor2.gyroDev.gyroADC[Z] * gyroSensor2.gyroDev.scale;
+ gyroUpdateSensor(&gyro.gyroSensor2);
+ if (isGyroSensorCalibrationComplete(&gyro.gyroSensor2)) {
+ gyro.gyroADC[X] = gyro.gyroSensor2.gyroDev.gyroADC[X] * gyro.gyroSensor2.gyroDev.scale;
+ gyro.gyroADC[Y] = gyro.gyroSensor2.gyroDev.gyroADC[Y] * gyro.gyroSensor2.gyroDev.scale;
+ gyro.gyroADC[Z] = gyro.gyroSensor2.gyroDev.gyroADC[Z] * gyro.gyroSensor2.gyroDev.scale;
}
break;
case GYRO_CONFIG_USE_GYRO_BOTH:
- gyroUpdateSensor(&gyroSensor1);
- gyroUpdateSensor(&gyroSensor2);
- if (isGyroSensorCalibrationComplete(&gyroSensor1) && isGyroSensorCalibrationComplete(&gyroSensor2)) {
- gyro.gyroADC[X] = ((gyroSensor1.gyroDev.gyroADC[X] * gyroSensor1.gyroDev.scale) + (gyroSensor2.gyroDev.gyroADC[X] * gyroSensor2.gyroDev.scale)) / 2.0f;
- gyro.gyroADC[Y] = ((gyroSensor1.gyroDev.gyroADC[Y] * gyroSensor1.gyroDev.scale) + (gyroSensor2.gyroDev.gyroADC[Y] * gyroSensor2.gyroDev.scale)) / 2.0f;
- gyro.gyroADC[Z] = ((gyroSensor1.gyroDev.gyroADC[Z] * gyroSensor1.gyroDev.scale) + (gyroSensor2.gyroDev.gyroADC[Z] * gyroSensor2.gyroDev.scale)) / 2.0f;
+ gyroUpdateSensor(&gyro.gyroSensor1);
+ gyroUpdateSensor(&gyro.gyroSensor2);
+ if (isGyroSensorCalibrationComplete(&gyro.gyroSensor1) && isGyroSensorCalibrationComplete(&gyro.gyroSensor2)) {
+ gyro.gyroADC[X] = ((gyro.gyroSensor1.gyroDev.gyroADC[X] * gyro.gyroSensor1.gyroDev.scale) + (gyro.gyroSensor2.gyroDev.gyroADC[X] * gyro.gyroSensor2.gyroDev.scale)) / 2.0f;
+ gyro.gyroADC[Y] = ((gyro.gyroSensor1.gyroDev.gyroADC[Y] * gyro.gyroSensor1.gyroDev.scale) + (gyro.gyroSensor2.gyroDev.gyroADC[Y] * gyro.gyroSensor2.gyroDev.scale)) / 2.0f;
+ gyro.gyroADC[Z] = ((gyro.gyroSensor1.gyroDev.gyroADC[Z] * gyro.gyroSensor1.gyroDev.scale) + (gyro.gyroSensor2.gyroDev.gyroADC[Z] * gyro.gyroSensor2.gyroDev.scale)) / 2.0f;
}
break;
#endif
@@ -1135,7 +464,7 @@ FAST_CODE void gyroUpdate(void)
#define GYRO_FILTER_FUNCTION_NAME filterGyroDebug
#define GYRO_FILTER_DEBUG_SET DEBUG_SET
-#define GYRO_FILTER_AXIS_DEBUG_SET(axis, mode, index, value) if (axis == (int)gyroDebugAxis) DEBUG_SET(mode, index, value)
+#define GYRO_FILTER_AXIS_DEBUG_SET(axis, mode, index, value) if (axis == (int)gyro.gyroDebugAxis) DEBUG_SET(mode, index, value)
#include "gyro_filter_impl.c"
#undef GYRO_FILTER_FUNCTION_NAME
#undef GYRO_FILTER_DEBUG_SET
@@ -1143,7 +472,7 @@ FAST_CODE void gyroUpdate(void)
FAST_CODE void gyroFiltering(timeUs_t currentTimeUs)
{
- if (gyroDebugMode == DEBUG_NONE) {
+ if (gyro.gyroDebugMode == DEBUG_NONE) {
filterGyro();
} else {
filterGyroDebug();
@@ -1155,42 +484,42 @@ FAST_CODE void gyroFiltering(timeUs_t currentTimeUs)
}
#endif
- if (useDualGyroDebugging) {
- switch (gyroToUse) {
+ if (gyro.useDualGyroDebugging) {
+ switch (gyro.gyroToUse) {
case GYRO_CONFIG_USE_GYRO_1:
- DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 0, gyroSensor1.gyroDev.gyroADCRaw[X]);
- DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 1, gyroSensor1.gyroDev.gyroADCRaw[Y]);
- DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 0, lrintf(gyroSensor1.gyroDev.gyroADC[X] * gyroSensor1.gyroDev.scale));
- DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 1, lrintf(gyroSensor1.gyroDev.gyroADC[Y] * gyroSensor1.gyroDev.scale));
+ DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 0, gyro.gyroSensor1.gyroDev.gyroADCRaw[X]);
+ DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 1, gyro.gyroSensor1.gyroDev.gyroADCRaw[Y]);
+ DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 0, lrintf(gyro.gyroSensor1.gyroDev.gyroADC[X] * gyro.gyroSensor1.gyroDev.scale));
+ DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 1, lrintf(gyro.gyroSensor1.gyroDev.gyroADC[Y] * gyro.gyroSensor1.gyroDev.scale));
break;
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2:
- DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 2, gyroSensor2.gyroDev.gyroADCRaw[X]);
- DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 3, gyroSensor2.gyroDev.gyroADCRaw[Y]);
- DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 2, lrintf(gyroSensor2.gyroDev.gyroADC[X] * gyroSensor2.gyroDev.scale));
- DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 3, lrintf(gyroSensor2.gyroDev.gyroADC[Y] * gyroSensor2.gyroDev.scale));
+ DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 2, gyro.gyroSensor2.gyroDev.gyroADCRaw[X]);
+ DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 3, gyro.gyroSensor2.gyroDev.gyroADCRaw[Y]);
+ DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 2, lrintf(gyro.gyroSensor2.gyroDev.gyroADC[X] * gyro.gyroSensor2.gyroDev.scale));
+ DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 3, lrintf(gyro.gyroSensor2.gyroDev.gyroADC[Y] * gyro.gyroSensor2.gyroDev.scale));
break;
case GYRO_CONFIG_USE_GYRO_BOTH:
- DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 0, gyroSensor1.gyroDev.gyroADCRaw[X]);
- DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 1, gyroSensor1.gyroDev.gyroADCRaw[Y]);
- DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 2, gyroSensor2.gyroDev.gyroADCRaw[X]);
- DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 3, gyroSensor2.gyroDev.gyroADCRaw[Y]);
- DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 0, lrintf(gyroSensor1.gyroDev.gyroADC[X] * gyroSensor1.gyroDev.scale));
- DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 1, lrintf(gyroSensor1.gyroDev.gyroADC[Y] * gyroSensor1.gyroDev.scale));
- DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 2, lrintf(gyroSensor2.gyroDev.gyroADC[X] * gyroSensor2.gyroDev.scale));
- DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 3, lrintf(gyroSensor2.gyroDev.gyroADC[Y] * gyroSensor2.gyroDev.scale));
- DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 0, lrintf((gyroSensor1.gyroDev.gyroADC[X] * gyroSensor1.gyroDev.scale) - (gyroSensor2.gyroDev.gyroADC[X] * gyroSensor2.gyroDev.scale)));
- DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 1, lrintf((gyroSensor1.gyroDev.gyroADC[Y] * gyroSensor1.gyroDev.scale) - (gyroSensor2.gyroDev.gyroADC[Y] * gyroSensor2.gyroDev.scale)));
- DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 2, lrintf((gyroSensor1.gyroDev.gyroADC[Z] * gyroSensor1.gyroDev.scale) - (gyroSensor2.gyroDev.gyroADC[Z] * gyroSensor2.gyroDev.scale)));
+ DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 0, gyro.gyroSensor1.gyroDev.gyroADCRaw[X]);
+ DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 1, gyro.gyroSensor1.gyroDev.gyroADCRaw[Y]);
+ DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 2, gyro.gyroSensor2.gyroDev.gyroADCRaw[X]);
+ DEBUG_SET(DEBUG_DUAL_GYRO_RAW, 3, gyro.gyroSensor2.gyroDev.gyroADCRaw[Y]);
+ DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 0, lrintf(gyro.gyroSensor1.gyroDev.gyroADC[X] * gyro.gyroSensor1.gyroDev.scale));
+ DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 1, lrintf(gyro.gyroSensor1.gyroDev.gyroADC[Y] * gyro.gyroSensor1.gyroDev.scale));
+ DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 2, lrintf(gyro.gyroSensor2.gyroDev.gyroADC[X] * gyro.gyroSensor2.gyroDev.scale));
+ DEBUG_SET(DEBUG_DUAL_GYRO_SCALED, 3, lrintf(gyro.gyroSensor2.gyroDev.gyroADC[Y] * gyro.gyroSensor2.gyroDev.scale));
+ DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 0, lrintf((gyro.gyroSensor1.gyroDev.gyroADC[X] * gyro.gyroSensor1.gyroDev.scale) - (gyro.gyroSensor2.gyroDev.gyroADC[X] * gyro.gyroSensor2.gyroDev.scale)));
+ DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 1, lrintf((gyro.gyroSensor1.gyroDev.gyroADC[Y] * gyro.gyroSensor1.gyroDev.scale) - (gyro.gyroSensor2.gyroDev.gyroADC[Y] * gyro.gyroSensor2.gyroDev.scale)));
+ DEBUG_SET(DEBUG_DUAL_GYRO_DIFF, 2, lrintf((gyro.gyroSensor1.gyroDev.gyroADC[Z] * gyro.gyroSensor1.gyroDev.scale) - (gyro.gyroSensor2.gyroDev.gyroADC[Z] * gyro.gyroSensor2.gyroDev.scale)));
break;
#endif
}
}
#ifdef USE_GYRO_OVERFLOW_CHECK
- if (gyroConfig()->checkOverflow && !gyroHasOverflowProtection) {
+ if (gyroConfig()->checkOverflow && !gyro.gyroHasOverflowProtection) {
checkForOverflow(currentTimeUs);
}
#endif
@@ -1244,18 +573,18 @@ int16_t gyroReadSensorTemperature(gyroSensor_t gyroSensor)
void gyroReadTemperature(void)
{
- switch (gyroToUse) {
+ switch (gyro.gyroToUse) {
case GYRO_CONFIG_USE_GYRO_1:
- gyroSensorTemperature = gyroReadSensorTemperature(gyroSensor1);
+ gyroSensorTemperature = gyroReadSensorTemperature(gyro.gyroSensor1);
break;
#ifdef USE_MULTI_GYRO
case GYRO_CONFIG_USE_GYRO_2:
- gyroSensorTemperature = gyroReadSensorTemperature(gyroSensor2);
+ gyroSensorTemperature = gyroReadSensorTemperature(gyro.gyroSensor2);
break;
case GYRO_CONFIG_USE_GYRO_BOTH:
- gyroSensorTemperature = MAX(gyroReadSensorTemperature(gyroSensor1), gyroReadSensorTemperature(gyroSensor2));
+ gyroSensorTemperature = MAX(gyroReadSensorTemperature(gyro.gyroSensor1), gyroReadSensorTemperature(gyro.gyroSensor2));
break;
#endif // USE_MULTI_GYRO
}
@@ -1266,11 +595,6 @@ int16_t gyroGetTemperature(void)
return gyroSensorTemperature;
}
-int16_t gyroRateDps(int axis)
-{
- return lrintf(gyro.gyroADCf[axis] / ACTIVE_GYRO->gyroDev.scale);
-}
-
bool gyroOverflowDetected(void)
{
#ifdef USE_GYRO_OVERFLOW_CHECK
@@ -1292,13 +616,6 @@ uint16_t gyroAbsRateDps(int axis)
return fabsf(gyro.gyroADCf[axis]);
}
-#ifdef USE_GYRO_REGISTER_DUMP
-uint8_t gyroReadRegister(uint8_t whichSensor, uint8_t reg)
-{
- return mpuGyroReadRegister(gyroSensorBusByDevice(whichSensor), reg);
-}
-#endif // USE_GYRO_REGISTER_DUMP
-
#ifdef USE_DYN_LPF
float dynThrottle(float throttle) {
@@ -1307,16 +624,16 @@ float dynThrottle(float throttle) {
void dynLpfGyroUpdate(float throttle)
{
- if (dynLpfFilter != DYN_LPF_NONE) {
- const unsigned int cutoffFreq = fmax(dynThrottle(throttle) * dynLpfMax, dynLpfMin);
+ if (gyro.dynLpfFilter != DYN_LPF_NONE) {
+ const unsigned int cutoffFreq = fmax(dynThrottle(throttle) * gyro.dynLpfMax, gyro.dynLpfMin);
- if (dynLpfFilter == DYN_LPF_PT1) {
+ if (gyro.dynLpfFilter == DYN_LPF_PT1) {
DEBUG_SET(DEBUG_DYN_LPF, 2, cutoffFreq);
const float gyroDt = gyro.targetLooptime * 1e-6f;
for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
pt1FilterUpdateCutoff(&gyro.lowpassFilter[axis].pt1FilterState, pt1FilterGain(cutoffFreq, gyroDt));
}
- } else if (dynLpfFilter == DYN_LPF_BIQUAD) {
+ } else if (gyro.dynLpfFilter == DYN_LPF_BIQUAD) {
DEBUG_SET(DEBUG_DYN_LPF, 2, cutoffFreq);
for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
biquadFilterUpdateLPF(&gyro.lowpassFilter[axis].biquadFilterState, cutoffFreq, gyro.targetLooptime);
diff --git a/src/main/sensors/gyro.h b/src/main/sensors/gyro.h
index 344763040..43fad15e6 100644
--- a/src/main/sensors/gyro.h
+++ b/src/main/sensors/gyro.h
@@ -48,6 +48,27 @@ typedef union gyroLowpassFilter_u {
biquadFilter_t biquadFilterState;
} gyroLowpassFilter_t;
+typedef enum gyroDetectionFlags_e {
+ NO_GYROS_DETECTED = 0,
+ DETECTED_GYRO_1 = (1 << 0),
+#if defined(USE_MULTI_GYRO)
+ DETECTED_GYRO_2 = (1 << 1),
+ DETECTED_BOTH_GYROS = (DETECTED_GYRO_1 | DETECTED_GYRO_2),
+ DETECTED_DUAL_GYROS = (1 << 7), // All gyros are of the same hardware type
+#endif
+} gyroDetectionFlags_t;
+
+typedef struct gyroCalibration_s {
+ float sum[XYZ_AXIS_COUNT];
+ stdev_t var[XYZ_AXIS_COUNT];
+ int32_t cyclesRemaining;
+} gyroCalibration_t;
+
+typedef struct gyroSensor_s {
+ gyroDev_t gyroDev;
+ gyroCalibration_t calibration;
+} gyroSensor_t;
+
typedef struct gyro_s {
uint16_t sampleRateHz;
uint32_t targetLooptime;
@@ -59,6 +80,11 @@ typedef struct gyro_s {
float sampleSum[XYZ_AXIS_COUNT]; // summed samples used for downsampling
bool downsampleFilterEnabled; // if true then downsample using gyro lowpass 2, otherwise use averaging
+ gyroSensor_t gyroSensor1;
+#ifdef USE_MULTI_GYRO
+ gyroSensor_t gyroSensor2;
+#endif
+
gyroDev_t *rawSensorDev; // pointer to the sensor providing the raw data for DEBUG_GYRO_RAW
// lowpass gyro soft filter
@@ -86,6 +112,22 @@ typedef struct gyro_s {
#endif
uint16_t accSampleRateHz;
+ uint8_t gyroToUse;
+ uint8_t gyroDebugMode;
+ bool gyroHasOverflowProtection;
+ bool useDualGyroDebugging;
+ flight_dynamics_index_t gyroDebugAxis;
+
+#ifdef USE_DYN_LPF
+ uint8_t dynLpfFilter;
+ uint16_t dynLpfMin;
+ uint16_t dynLpfMax;
+#endif
+
+#ifdef USE_GYRO_OVERFLOW_CHECK
+ uint8_t overflowAxisMask;
+#endif
+
} gyro_t;
extern gyro_t gyro;
@@ -118,16 +160,6 @@ enum {
FILTER_LOWPASS2
};
-typedef enum gyroDetectionFlags_e {
- NO_GYROS_DETECTED = 0,
- DETECTED_GYRO_1 = (1 << 0),
-#if defined(USE_MULTI_GYRO)
- DETECTED_GYRO_2 = (1 << 1),
- DETECTED_BOTH_GYROS = (DETECTED_GYRO_1 | DETECTED_GYRO_2),
- DETECTED_DUAL_GYROS = (1 << 7), // All gyros are of the same hardware type
-#endif
-} gyroDetectionFlags_t;
-
typedef struct gyroConfig_s {
uint8_t gyroMovementCalibrationThreshold; // people keep forgetting that moving model while init results in wrong gyro offsets. and then they never reset gyro. so this is now on by default.
uint8_t gyro_hardware_lpf; // gyro DLPF setting
@@ -167,27 +199,17 @@ typedef struct gyroConfig_s {
PG_DECLARE(gyroConfig_t, gyroConfig);
-void gyroPreInit(void);
-bool gyroInit(void);
-void gyroSetTargetLooptime(uint8_t pidDenom);
-void gyroInitFilters(void);
void gyroUpdate(void);
void gyroFiltering(timeUs_t currentTimeUs);
bool gyroGetAccumulationAverage(float *accumulation);
-const busDevice_t *gyroSensorBus(void);
-struct mpuDetectionResult_s;
-const struct mpuDetectionResult_s *gyroMpuDetectionResult(void);
void gyroStartCalibration(bool isFirstArmingCalibration);
bool isFirstArmingGyroCalibrationRunning(void);
bool gyroIsCalibrationComplete(void);
void gyroReadTemperature(void);
int16_t gyroGetTemperature(void);
-int16_t gyroRateDps(int axis);
bool gyroOverflowDetected(void);
bool gyroYawSpinDetected(void);
uint16_t gyroAbsRateDps(int axis);
-uint8_t gyroReadRegister(uint8_t whichSensor, uint8_t reg);
-gyroDetectionFlags_t getGyroDetectionFlags(void);
#ifdef USE_DYN_LPF
float dynThrottle(float throttle);
void dynLpfGyroUpdate(float throttle);
@@ -195,3 +217,6 @@ void dynLpfGyroUpdate(float throttle);
#ifdef USE_YAW_SPIN_RECOVERY
void initYawSpinRecovery(int maxYawRate);
#endif
+#ifdef USE_GYRO_DATA_ANALYSE
+bool isDynamicFilterActive(void);
+#endif
diff --git a/src/main/sensors/gyro_filter_impl.c b/src/main/sensors/gyro_filter_impl.c
index e26209ee9..e9e9917ee 100644
--- a/src/main/sensors/gyro_filter_impl.c
+++ b/src/main/sensors/gyro_filter_impl.c
@@ -51,7 +51,7 @@ static FAST_CODE void GYRO_FILTER_FUNCTION_NAME(void)
#ifdef USE_GYRO_DATA_ANALYSE
if (isDynamicFilterActive()) {
- if (axis == gyroDebugAxis) {
+ if (axis == gyro.gyroDebugAxis) {
GYRO_FILTER_DEBUG_SET(DEBUG_FFT, 0, lrintf(gyroADCf));
GYRO_FILTER_DEBUG_SET(DEBUG_FFT_FREQ, 3, lrintf(gyroADCf));
GYRO_FILTER_DEBUG_SET(DEBUG_DYN_LPF, 0, lrintf(gyroADCf));
@@ -76,7 +76,7 @@ static FAST_CODE void GYRO_FILTER_FUNCTION_NAME(void)
#ifdef USE_GYRO_DATA_ANALYSE
if (isDynamicFilterActive()) {
- if (axis == gyroDebugAxis) {
+ if (axis == gyro.gyroDebugAxis) {
GYRO_FILTER_DEBUG_SET(DEBUG_FFT, 1, lrintf(gyroADCf));
GYRO_FILTER_DEBUG_SET(DEBUG_FFT_FREQ, 2, lrintf(gyroADCf));
GYRO_FILTER_DEBUG_SET(DEBUG_DYN_LPF, 3, lrintf(gyroADCf));
diff --git a/src/main/sensors/gyro_init.c b/src/main/sensors/gyro_init.c
new file mode 100644
index 000000000..393c9a785
--- /dev/null
+++ b/src/main/sensors/gyro_init.c
@@ -0,0 +1,695 @@
+/*
+ * This file is part of Cleanflight and Betaflight.
+ *
+ * Cleanflight and Betaflight are free software. You can redistribute
+ * this software and/or modify this software under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Cleanflight and Betaflight are distributed in the hope that they
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software.
+ *
+ * If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "platform.h"
+
+#include "build/debug.h"
+
+#include "common/axis.h"
+#include "common/maths.h"
+#include "common/filter.h"
+
+#include "drivers/accgyro/accgyro.h"
+#include "drivers/accgyro/accgyro_fake.h"
+#include "drivers/accgyro/accgyro_mpu.h"
+#include "drivers/accgyro/accgyro_mpu3050.h"
+#include "drivers/accgyro/accgyro_mpu6050.h"
+#include "drivers/accgyro/accgyro_mpu6500.h"
+#include "drivers/accgyro/accgyro_spi_bmi160.h"
+#include "drivers/accgyro/accgyro_spi_bmi270.h"
+#include "drivers/accgyro/accgyro_spi_icm20649.h"
+#include "drivers/accgyro/accgyro_spi_icm20689.h"
+#include "drivers/accgyro/accgyro_spi_icm20689.h"
+#include "drivers/accgyro/accgyro_spi_icm42605.h"
+#include "drivers/accgyro/accgyro_spi_mpu6000.h"
+#include "drivers/accgyro/accgyro_spi_mpu6500.h"
+#include "drivers/accgyro/accgyro_spi_mpu9250.h"
+
+#ifdef USE_GYRO_L3GD20
+#include "drivers/accgyro/accgyro_spi_l3gd20.h"
+#endif
+
+#ifdef USE_GYRO_L3G4200D
+#include "drivers/accgyro_legacy/accgyro_l3g4200d.h"
+#endif
+
+#include "drivers/accgyro/gyro_sync.h"
+
+#include "fc/runtime_config.h"
+
+#ifdef USE_GYRO_DATA_ANALYSE
+#include "flight/gyroanalyse.h"
+#endif
+
+#include "pg/gyrodev.h"
+
+#include "sensors/gyro.h"
+#include "sensors/sensors.h"
+
+#ifdef USE_GYRO_DATA_ANALYSE
+#define DYNAMIC_NOTCH_DEFAULT_CENTER_HZ 350
+#define DYNAMIC_NOTCH_DEFAULT_CUTOFF_HZ 300
+#endif
+
+#ifdef USE_MULTI_GYRO
+#define ACTIVE_GYRO ((gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_2) ? &gyro.gyroSensor2 : &gyro.gyroSensor1)
+#else
+#define ACTIVE_GYRO (&gyro.gyroSensor1)
+#endif
+
+static gyroDetectionFlags_t gyroDetectionFlags = NO_GYROS_DETECTED;
+
+static uint16_t calculateNyquistAdjustedNotchHz(uint16_t notchHz, uint16_t notchCutoffHz)
+{
+ const uint32_t gyroFrequencyNyquist = 1000000 / 2 / gyro.targetLooptime;
+ if (notchHz > gyroFrequencyNyquist) {
+ if (notchCutoffHz < gyroFrequencyNyquist) {
+ notchHz = gyroFrequencyNyquist;
+ } else {
+ notchHz = 0;
+ }
+ }
+
+ return notchHz;
+}
+
+static void gyroInitFilterNotch1(uint16_t notchHz, uint16_t notchCutoffHz)
+{
+ gyro.notchFilter1ApplyFn = nullFilterApply;
+
+ notchHz = calculateNyquistAdjustedNotchHz(notchHz, notchCutoffHz);
+
+ if (notchHz != 0 && notchCutoffHz != 0) {
+ gyro.notchFilter1ApplyFn = (filterApplyFnPtr)biquadFilterApply;
+ const float notchQ = filterGetNotchQ(notchHz, notchCutoffHz);
+ for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
+ biquadFilterInit(&gyro.notchFilter1[axis], notchHz, gyro.targetLooptime, notchQ, FILTER_NOTCH);
+ }
+ }
+}
+
+static void gyroInitFilterNotch2(uint16_t notchHz, uint16_t notchCutoffHz)
+{
+ gyro.notchFilter2ApplyFn = nullFilterApply;
+
+ notchHz = calculateNyquistAdjustedNotchHz(notchHz, notchCutoffHz);
+
+ if (notchHz != 0 && notchCutoffHz != 0) {
+ gyro.notchFilter2ApplyFn = (filterApplyFnPtr)biquadFilterApply;
+ const float notchQ = filterGetNotchQ(notchHz, notchCutoffHz);
+ for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
+ biquadFilterInit(&gyro.notchFilter2[axis], notchHz, gyro.targetLooptime, notchQ, FILTER_NOTCH);
+ }
+ }
+}
+
+#ifdef USE_GYRO_DATA_ANALYSE
+static void gyroInitFilterDynamicNotch()
+{
+ gyro.notchFilterDynApplyFn = nullFilterApply;
+ gyro.notchFilterDynApplyFn2 = nullFilterApply;
+
+ if (isDynamicFilterActive()) {
+ gyro.notchFilterDynApplyFn = (filterApplyFnPtr)biquadFilterApplyDF1; // must be this function, not DF2
+ if(gyroConfig()->dyn_notch_width_percent != 0) {
+ gyro.notchFilterDynApplyFn2 = (filterApplyFnPtr)biquadFilterApplyDF1; // must be this function, not DF2
+ }
+ const float notchQ = filterGetNotchQ(DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, DYNAMIC_NOTCH_DEFAULT_CUTOFF_HZ); // any defaults OK here
+ for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
+ biquadFilterInit(&gyro.notchFilterDyn[axis], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, gyro.targetLooptime, notchQ, FILTER_NOTCH);
+ biquadFilterInit(&gyro.notchFilterDyn2[axis], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, gyro.targetLooptime, notchQ, FILTER_NOTCH);
+ }
+ }
+}
+#endif
+
+static bool gyroInitLowpassFilterLpf(int slot, int type, uint16_t lpfHz, uint32_t looptime)
+{
+ filterApplyFnPtr *lowpassFilterApplyFn;
+ gyroLowpassFilter_t *lowpassFilter = NULL;
+
+ switch (slot) {
+ case FILTER_LOWPASS:
+ lowpassFilterApplyFn = &gyro.lowpassFilterApplyFn;
+ lowpassFilter = gyro.lowpassFilter;
+ break;
+
+ case FILTER_LOWPASS2:
+ lowpassFilterApplyFn = &gyro.lowpass2FilterApplyFn;
+ lowpassFilter = gyro.lowpass2Filter;
+ break;
+
+ default:
+ return false;
+ }
+
+ bool ret = false;
+
+ // Establish some common constants
+ const uint32_t gyroFrequencyNyquist = 1000000 / 2 / looptime;
+ const float gyroDt = looptime * 1e-6f;
+
+ // Gain could be calculated a little later as it is specific to the pt1/bqrcf2/fkf branches
+ const float gain = pt1FilterGain(lpfHz, gyroDt);
+
+ // Dereference the pointer to null before checking valid cutoff and filter
+ // type. It will be overridden for positive cases.
+ *lowpassFilterApplyFn = nullFilterApply;
+
+ // If lowpass cutoff has been specified and is less than the Nyquist frequency
+ if (lpfHz && lpfHz <= gyroFrequencyNyquist) {
+ switch (type) {
+ case FILTER_PT1:
+ *lowpassFilterApplyFn = (filterApplyFnPtr) pt1FilterApply;
+ for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
+ pt1FilterInit(&lowpassFilter[axis].pt1FilterState, gain);
+ }
+ ret = true;
+ break;
+ case FILTER_BIQUAD:
+#ifdef USE_DYN_LPF
+ *lowpassFilterApplyFn = (filterApplyFnPtr) biquadFilterApplyDF1;
+#else
+ *lowpassFilterApplyFn = (filterApplyFnPtr) biquadFilterApply;
+#endif
+ for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
+ biquadFilterInitLPF(&lowpassFilter[axis].biquadFilterState, lpfHz, looptime);
+ }
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+}
+
+#ifdef USE_DYN_LPF
+static void dynLpfFilterInit()
+{
+ if (gyroConfig()->dyn_lpf_gyro_min_hz > 0) {
+ switch (gyroConfig()->gyro_lowpass_type) {
+ case FILTER_PT1:
+ gyro.dynLpfFilter = DYN_LPF_PT1;
+ break;
+ case FILTER_BIQUAD:
+ gyro.dynLpfFilter = DYN_LPF_BIQUAD;
+ break;
+ default:
+ gyro.dynLpfFilter = DYN_LPF_NONE;
+ break;
+ }
+ } else {
+ gyro.dynLpfFilter = DYN_LPF_NONE;
+ }
+ gyro.dynLpfMin = gyroConfig()->dyn_lpf_gyro_min_hz;
+ gyro.dynLpfMax = gyroConfig()->dyn_lpf_gyro_max_hz;
+}
+#endif
+
+void gyroInitFilters(void)
+{
+ uint16_t gyro_lowpass_hz = gyroConfig()->gyro_lowpass_hz;
+
+#ifdef USE_DYN_LPF
+ if (gyroConfig()->dyn_lpf_gyro_min_hz > 0) {
+ gyro_lowpass_hz = gyroConfig()->dyn_lpf_gyro_min_hz;
+ }
+#endif
+
+ gyroInitLowpassFilterLpf(
+ FILTER_LOWPASS,
+ gyroConfig()->gyro_lowpass_type,
+ gyro_lowpass_hz,
+ gyro.targetLooptime
+ );
+
+ gyro.downsampleFilterEnabled = gyroInitLowpassFilterLpf(
+ FILTER_LOWPASS2,
+ gyroConfig()->gyro_lowpass2_type,
+ gyroConfig()->gyro_lowpass2_hz,
+ gyro.sampleLooptime
+ );
+
+ gyroInitFilterNotch1(gyroConfig()->gyro_soft_notch_hz_1, gyroConfig()->gyro_soft_notch_cutoff_1);
+ gyroInitFilterNotch2(gyroConfig()->gyro_soft_notch_hz_2, gyroConfig()->gyro_soft_notch_cutoff_2);
+#ifdef USE_GYRO_DATA_ANALYSE
+ gyroInitFilterDynamicNotch();
+#endif
+#ifdef USE_DYN_LPF
+ dynLpfFilterInit();
+#endif
+#ifdef USE_GYRO_DATA_ANALYSE
+ gyroDataAnalyseStateInit(&gyro.gyroAnalyseState, gyro.targetLooptime);
+#endif
+}
+
+#if defined(USE_GYRO_SLEW_LIMITER)
+void gyroInitSlewLimiter(gyroSensor_t *gyroSensor) {
+
+ for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
+ gyroSensor->gyroDev.gyroADCRawPrevious[axis] = 0;
+ }
+}
+#endif
+
+static void gyroInitSensorFilters(gyroSensor_t *gyroSensor)
+{
+#if defined(USE_GYRO_SLEW_LIMITER)
+ gyroInitSlewLimiter(gyroSensor);
+#else
+ UNUSED(gyroSensor);
+#endif
+}
+
+void gyroInitSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config)
+{
+ gyroSensor->gyroDev.gyro_high_fsr = gyroConfig()->gyro_high_fsr;
+ gyroSensor->gyroDev.gyroAlign = config->alignment;
+ buildRotationMatrixFromAlignment(&config->customAlignment, &gyroSensor->gyroDev.rotationMatrix);
+ gyroSensor->gyroDev.mpuIntExtiTag = config->extiTag;
+ gyroSensor->gyroDev.hardware_lpf = gyroConfig()->gyro_hardware_lpf;
+
+ // The targetLooptime gets set later based on the active sensor's gyroSampleRateHz and pid_process_denom
+ gyroSensor->gyroDev.gyroSampleRateHz = gyroSetSampleRate(&gyroSensor->gyroDev);
+ gyroSensor->gyroDev.initFn(&gyroSensor->gyroDev);
+
+ // As new gyros are supported, be sure to add them below based on whether they are subject to the overflow/inversion bug
+ // Any gyro not explicitly defined will default to not having built-in overflow protection as a safe alternative.
+ switch (gyroSensor->gyroDev.gyroHardware) {
+ case GYRO_NONE: // Won't ever actually get here, but included to account for all gyro types
+ case GYRO_DEFAULT:
+ case GYRO_FAKE:
+ case GYRO_MPU6050:
+ case GYRO_L3G4200D:
+ case GYRO_MPU3050:
+ case GYRO_L3GD20:
+ case GYRO_BMI160:
+ case GYRO_BMI270:
+ case GYRO_MPU6000:
+ case GYRO_MPU6500:
+ case GYRO_MPU9250:
+ gyroSensor->gyroDev.gyroHasOverflowProtection = true;
+ break;
+
+ case GYRO_ICM20601:
+ case GYRO_ICM20602:
+ case GYRO_ICM20608G:
+ case GYRO_ICM20649: // we don't actually know if this is affected, but as there are currently no flight controllers using it we err on the side of caution
+ case GYRO_ICM20689:
+ gyroSensor->gyroDev.gyroHasOverflowProtection = false;
+ break;
+
+ default:
+ gyroSensor->gyroDev.gyroHasOverflowProtection = false; // default catch for newly added gyros until proven to be unaffected
+ break;
+ }
+
+ gyroInitSensorFilters(gyroSensor);
+}
+
+STATIC_UNIT_TESTED gyroHardware_e gyroDetect(gyroDev_t *dev)
+{
+ gyroHardware_e gyroHardware = GYRO_DEFAULT;
+
+ switch (gyroHardware) {
+ case GYRO_DEFAULT:
+ FALLTHROUGH;
+
+#ifdef USE_GYRO_MPU6050
+ case GYRO_MPU6050:
+ if (mpu6050GyroDetect(dev)) {
+ gyroHardware = GYRO_MPU6050;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_GYRO_L3G4200D
+ case GYRO_L3G4200D:
+ if (l3g4200dDetect(dev)) {
+ gyroHardware = GYRO_L3G4200D;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_GYRO_MPU3050
+ case GYRO_MPU3050:
+ if (mpu3050Detect(dev)) {
+ gyroHardware = GYRO_MPU3050;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_GYRO_L3GD20
+ case GYRO_L3GD20:
+ if (l3gd20GyroDetect(dev)) {
+ gyroHardware = GYRO_L3GD20;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_GYRO_SPI_MPU6000
+ case GYRO_MPU6000:
+ if (mpu6000SpiGyroDetect(dev)) {
+ gyroHardware = GYRO_MPU6000;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#if defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500)
+ case GYRO_MPU6500:
+ case GYRO_ICM20601:
+ case GYRO_ICM20602:
+ case GYRO_ICM20608G:
+#ifdef USE_GYRO_SPI_MPU6500
+ if (mpu6500GyroDetect(dev) || mpu6500SpiGyroDetect(dev)) {
+#else
+ if (mpu6500GyroDetect(dev)) {
+#endif
+ switch (dev->mpuDetectionResult.sensor) {
+ case MPU_9250_SPI:
+ gyroHardware = GYRO_MPU9250;
+ break;
+ case ICM_20601_SPI:
+ gyroHardware = GYRO_ICM20601;
+ break;
+ case ICM_20602_SPI:
+ gyroHardware = GYRO_ICM20602;
+ break;
+ case ICM_20608_SPI:
+ gyroHardware = GYRO_ICM20608G;
+ break;
+ default:
+ gyroHardware = GYRO_MPU6500;
+ }
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_GYRO_SPI_MPU9250
+ case GYRO_MPU9250:
+ if (mpu9250SpiGyroDetect(dev)) {
+ gyroHardware = GYRO_MPU9250;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_GYRO_SPI_ICM20649
+ case GYRO_ICM20649:
+ if (icm20649SpiGyroDetect(dev)) {
+ gyroHardware = GYRO_ICM20649;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_GYRO_SPI_ICM20689
+ case GYRO_ICM20689:
+ if (icm20689SpiGyroDetect(dev)) {
+ gyroHardware = GYRO_ICM20689;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_GYRO_SPI_ICM42605
+ case GYRO_ICM42605:
+ if (icm42605SpiGyroDetect(dev)) {
+ gyroHardware = GYRO_ICM42605;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_ACCGYRO_BMI160
+ case GYRO_BMI160:
+ if (bmi160SpiGyroDetect(dev)) {
+ gyroHardware = GYRO_BMI160;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_ACCGYRO_BMI270
+ case GYRO_BMI270:
+ if (bmi270SpiGyroDetect(dev)) {
+ gyroHardware = GYRO_BMI270;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+#ifdef USE_FAKE_GYRO
+ case GYRO_FAKE:
+ if (fakeGyroDetect(dev)) {
+ gyroHardware = GYRO_FAKE;
+ break;
+ }
+ FALLTHROUGH;
+#endif
+
+ default:
+ gyroHardware = GYRO_NONE;
+ }
+
+ if (gyroHardware != GYRO_NONE) {
+ sensorsSet(SENSOR_GYRO);
+ }
+
+
+ return gyroHardware;
+}
+
+static bool gyroDetectSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config)
+{
+#if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \
+ || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) \
+ || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_L3GD20) || defined(USE_ACCGYRO_BMI160) || defined(USE_ACCGYRO_BMI270)
+
+ bool gyroFound = mpuDetect(&gyroSensor->gyroDev, config);
+
+#if !defined(USE_FAKE_GYRO) // Allow resorting to fake accgyro if defined
+ if (!gyroFound) {
+ return false;
+ }
+#else
+ UNUSED(gyroFound);
+#endif
+#else
+ UNUSED(config);
+#endif
+
+ const gyroHardware_e gyroHardware = gyroDetect(&gyroSensor->gyroDev);
+ gyroSensor->gyroDev.gyroHardware = gyroHardware;
+
+ return gyroHardware != GYRO_NONE;
+}
+
+static void gyroPreInitSensor(const gyroDeviceConfig_t *config)
+{
+#if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \
+ || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) \
+ || defined(USE_GYRO_SPI_ICM20689) || defined(USE_ACCGYRO_BMI160) || defined(USE_ACCGYRO_BMI270)
+ mpuPreInit(config);
+#else
+ UNUSED(config);
+#endif
+}
+
+void gyroPreInit(void)
+{
+ gyroPreInitSensor(gyroDeviceConfig(0));
+#ifdef USE_MULTI_GYRO
+ gyroPreInitSensor(gyroDeviceConfig(1));
+#endif
+}
+
+bool gyroInit(void)
+{
+#ifdef USE_GYRO_OVERFLOW_CHECK
+ if (gyroConfig()->checkOverflow == GYRO_OVERFLOW_CHECK_YAW) {
+ gyro.overflowAxisMask = GYRO_OVERFLOW_Z;
+ } else if (gyroConfig()->checkOverflow == GYRO_OVERFLOW_CHECK_ALL_AXES) {
+ gyro.overflowAxisMask = GYRO_OVERFLOW_X | GYRO_OVERFLOW_Y | GYRO_OVERFLOW_Z;
+ } else {
+ gyro.overflowAxisMask = 0;
+ }
+#endif
+
+ gyro.gyroDebugMode = DEBUG_NONE;
+ gyro.useDualGyroDebugging = false;
+ gyro.gyroHasOverflowProtection = true;
+
+ switch (debugMode) {
+ case DEBUG_FFT:
+ case DEBUG_FFT_FREQ:
+ case DEBUG_GYRO_RAW:
+ case DEBUG_GYRO_SCALED:
+ case DEBUG_GYRO_FILTERED:
+ case DEBUG_DYN_LPF:
+ case DEBUG_GYRO_SAMPLE:
+ gyro.gyroDebugMode = debugMode;
+ break;
+ case DEBUG_DUAL_GYRO_DIFF:
+ case DEBUG_DUAL_GYRO_RAW:
+ case DEBUG_DUAL_GYRO_SCALED:
+ gyro.useDualGyroDebugging = true;
+ break;
+ }
+
+ gyroDetectionFlags = NO_GYROS_DETECTED;
+
+ gyro.gyroToUse = gyroConfig()->gyro_to_use;
+ gyro.gyroDebugAxis = gyroConfig()->gyro_filter_debug_axis;
+
+ if (gyroDetectSensor(&gyro.gyroSensor1, gyroDeviceConfig(0))) {
+ gyroDetectionFlags |= DETECTED_GYRO_1;
+ }
+
+#if defined(USE_MULTI_GYRO)
+ if (gyroDetectSensor(&gyro.gyroSensor2, gyroDeviceConfig(1))) {
+ gyroDetectionFlags |= DETECTED_GYRO_2;
+ }
+#endif
+
+ if (gyroDetectionFlags == NO_GYROS_DETECTED) {
+ return false;
+ }
+
+#if defined(USE_MULTI_GYRO)
+ if ((gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH && !((gyroDetectionFlags & DETECTED_BOTH_GYROS) == DETECTED_BOTH_GYROS))
+ || (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_1 && !(gyroDetectionFlags & DETECTED_GYRO_1))
+ || (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_2 && !(gyroDetectionFlags & DETECTED_GYRO_2))) {
+ if (gyroDetectionFlags & DETECTED_GYRO_1) {
+ gyro.gyroToUse = GYRO_CONFIG_USE_GYRO_1;
+ } else {
+ gyro.gyroToUse = GYRO_CONFIG_USE_GYRO_2;
+ }
+
+ gyroConfigMutable()->gyro_to_use = gyro.gyroToUse;
+ }
+
+ // Only allow using both gyros simultaneously if they are the same hardware type.
+ if (((gyroDetectionFlags & DETECTED_BOTH_GYROS) == DETECTED_BOTH_GYROS) && gyro.gyroSensor1.gyroDev.gyroHardware == gyro.gyroSensor2.gyroDev.gyroHardware) {
+ gyroDetectionFlags |= DETECTED_DUAL_GYROS;
+ } else if (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
+ // If the user selected "BOTH" and they are not the same type, then reset to using only the first gyro.
+ gyro.gyroToUse = GYRO_CONFIG_USE_GYRO_1;
+ gyroConfigMutable()->gyro_to_use = gyro.gyroToUse;
+ }
+
+ if (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_2 || gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
+ gyroInitSensor(&gyro.gyroSensor2, gyroDeviceConfig(1));
+ gyro.gyroHasOverflowProtection = gyro.gyroHasOverflowProtection && gyro.gyroSensor2.gyroDev.gyroHasOverflowProtection;
+ detectedSensors[SENSOR_INDEX_GYRO] = gyro.gyroSensor2.gyroDev.gyroHardware;
+ }
+#endif
+
+ if (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_1 || gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_BOTH) {
+ gyroInitSensor(&gyro.gyroSensor1, gyroDeviceConfig(0));
+ gyro.gyroHasOverflowProtection = gyro.gyroHasOverflowProtection && gyro.gyroSensor1.gyroDev.gyroHasOverflowProtection;
+ detectedSensors[SENSOR_INDEX_GYRO] = gyro.gyroSensor1.gyroDev.gyroHardware;
+ }
+
+ // Copy the sensor's scale to the high-level gyro object. If running in "BOTH" mode
+ // then logic above requires both sensors to be the same so we'll use sensor1's scale.
+ // This will need to be revised if we ever allow different sensor types to be used simultaneously.
+ // Likewise determine the appropriate raw data for use in DEBUG_GYRO_RAW
+ gyro.scale = gyro.gyroSensor1.gyroDev.scale;
+ gyro.rawSensorDev = &gyro.gyroSensor1.gyroDev;
+#if defined(USE_MULTI_GYRO)
+ if (gyro.gyroToUse == GYRO_CONFIG_USE_GYRO_2) {
+ gyro.scale = gyro.gyroSensor2.gyroDev.scale;
+ gyro.rawSensorDev = &gyro.gyroSensor2.gyroDev;
+ }
+#endif
+
+ if (gyro.rawSensorDev) {
+ gyro.sampleRateHz = gyro.rawSensorDev->gyroSampleRateHz;
+ gyro.accSampleRateHz = gyro.rawSensorDev->accSampleRateHz;
+ } else {
+ gyro.sampleRateHz = 0;
+ gyro.accSampleRateHz = 0;
+ }
+
+ return true;
+}
+
+gyroDetectionFlags_t getGyroDetectionFlags(void)
+{
+ return gyroDetectionFlags;
+}
+
+void gyroSetTargetLooptime(uint8_t pidDenom)
+{
+ activePidLoopDenom = pidDenom;
+ if (gyro.sampleRateHz) {
+ gyro.sampleLooptime = 1e6 / gyro.sampleRateHz;
+ gyro.targetLooptime = activePidLoopDenom * 1e6 / gyro.sampleRateHz;
+ } else {
+ gyro.sampleLooptime = 0;
+ gyro.targetLooptime = 0;
+ }
+}
+
+const busDevice_t *gyroSensorBus(void)
+{
+ return &ACTIVE_GYRO->gyroDev.bus;
+}
+
+const mpuDetectionResult_t *gyroMpuDetectionResult(void)
+{
+ return &ACTIVE_GYRO->gyroDev.mpuDetectionResult;
+}
+
+int16_t gyroRateDps(int axis)
+{
+ return lrintf(gyro.gyroADCf[axis] / ACTIVE_GYRO->gyroDev.scale);
+}
+
+#ifdef USE_GYRO_REGISTER_DUMP
+static const busDevice_t *gyroSensorBusByDevice(uint8_t whichSensor)
+{
+#ifdef USE_MULTI_GYRO
+ if (whichSensor == GYRO_CONFIG_USE_GYRO_2) {
+ return &gyro.gyroSensor2.gyroDev.bus;
+ }
+#else
+ UNUSED(whichSensor);
+#endif
+ return &gyro.gyroSensor1.gyroDev.bus;
+}
+
+uint8_t gyroReadRegister(uint8_t whichSensor, uint8_t reg)
+{
+ return mpuGyroReadRegister(gyroSensorBusByDevice(whichSensor), reg);
+}
+#endif // USE_GYRO_REGISTER_DUMP
diff --git a/src/main/sensors/gyro_init.h b/src/main/sensors/gyro_init.h
new file mode 100644
index 000000000..26d0f7e39
--- /dev/null
+++ b/src/main/sensors/gyro_init.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of Cleanflight and Betaflight.
+ *
+ * Cleanflight and Betaflight are free software. You can redistribute
+ * this software and/or modify this software under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Cleanflight and Betaflight are distributed in the hope that they
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software.
+ *
+ * If not, see .
+ */
+
+#pragma once
+
+#include "pg/gyrodev.h"
+#include "sensors/gyro.h"
+
+void gyroSetTargetLooptime(uint8_t pidDenom);
+void gyroPreInit(void);
+bool gyroInit(void);
+void gyroInitFilters(void);
+void gyroInitSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config);
+gyroDetectionFlags_t getGyroDetectionFlags(void);
+const busDevice_t *gyroSensorBus(void);
+struct mpuDetectionResult_s;
+const struct mpuDetectionResult_s *gyroMpuDetectionResult(void);
+int16_t gyroRateDps(int axis);
+uint8_t gyroReadRegister(uint8_t whichSensor, uint8_t reg);
diff --git a/src/main/sensors/initialisation.c b/src/main/sensors/initialisation.c
index 57c81e2f0..deafc1fc1 100644
--- a/src/main/sensors/initialisation.c
+++ b/src/main/sensors/initialisation.c
@@ -26,23 +26,25 @@
#include "common/utils.h"
-#include "config/feature.h"
-#include "pg/pg.h"
-#include "pg/pg_ids.h"
-
#include "config/config.h"
+#include "config/feature.h"
+
#include "fc/runtime_config.h"
#include "flight/pid.h"
-#include "sensors/sensors.h"
-#include "sensors/adcinternal.h"
+#include "pg/pg.h"
+#include "pg/pg_ids.h"
+
#include "sensors/acceleration.h"
+#include "sensors/adcinternal.h"
#include "sensors/barometer.h"
-#include "sensors/gyro.h"
#include "sensors/compass.h"
-#include "sensors/rangefinder.h"
+#include "sensors/gyro.h"
+#include "sensors/gyro_init.h"
#include "sensors/initialisation.h"
+#include "sensors/rangefinder.h"
+#include "sensors/sensors.h"
// requestedSensors is not actually used
uint8_t requestedSensors[SENSOR_INDEX_COUNT] = { GYRO_NONE, ACC_NONE, BARO_NONE, MAG_NONE, RANGEFINDER_NONE };
diff --git a/src/test/Makefile b/src/test/Makefile
index 4e243a208..f7fa864ee 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -277,6 +277,7 @@ scheduler_unittest_SRC := \
sensor_gyro_unittest_SRC := \
$(USER_DIR)/sensors/gyro.c \
+ $(USER_DIR)/sensors/gyro_init.c \
$(USER_DIR)/sensors/boardalignment.c \
$(USER_DIR)/common/filter.c \
$(USER_DIR)/common/maths.c \
diff --git a/src/test/unit/sensor_gyro_unittest.cc b/src/test/unit/sensor_gyro_unittest.cc
index d9e7c7c04..4f6d78e5c 100644
--- a/src/test/unit/sensor_gyro_unittest.cc
+++ b/src/test/unit/sensor_gyro_unittest.cc
@@ -37,6 +37,7 @@ extern "C" {
#include "pg/pg_ids.h"
#include "scheduler/scheduler.h"
#include "sensors/gyro.h"
+ #include "sensors/gyro_init.h"
#include "sensors/acceleration.h"
#include "sensors/sensors.h"