2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
23 #include "build_config.h"
25 #include "common/axis.h"
27 #include "drivers/gpio.h"
28 #include "drivers/system.h"
29 #include "drivers/exti.h"
31 #include "drivers/sensor.h"
33 #include "drivers/accgyro.h"
34 #include "drivers/accgyro_adxl345.h"
35 #include "drivers/accgyro_bma280.h"
36 #include "drivers/accgyro_l3g4200d.h"
37 #include "drivers/accgyro_mma845x.h"
38 #include "drivers/accgyro_mpu.h"
39 #include "drivers/accgyro_mpu3050.h"
40 #include "drivers/accgyro_mpu6050.h"
41 #include "drivers/accgyro_mpu6500.h"
42 #include "drivers/accgyro_l3gd20.h"
43 #include "drivers/accgyro_lsm303dlhc.h"
45 #include "drivers/bus_spi.h"
46 #include "drivers/accgyro_spi_mpu6000.h"
47 #include "drivers/accgyro_spi_mpu6500.h"
48 #include "drivers/gyro_sync.h"
50 #include "drivers/barometer.h"
51 #include "drivers/barometer_bmp085.h"
52 #include "drivers/barometer_bmp280.h"
53 #include "drivers/barometer_ms5611.h"
55 #include "drivers/compass.h"
56 #include "drivers/compass_hmc5883l.h"
57 #include "drivers/compass_ak8975.h"
58 #include "drivers/compass_mag3110.h"
60 #include "drivers/sonar_hcsr04.h"
61 #include "drivers/sonar_srf10.h"
63 #include "config/runtime_config.h"
64 #include "config/config.h"
66 #include "sensors/sensors.h"
67 #include "sensors/acceleration.h"
68 #include "sensors/barometer.h"
69 #include "sensors/gyro.h"
70 #include "sensors/compass.h"
71 #include "sensors/rangefinder.h"
72 #include "sensors/initialisation.h"
75 #include "hardware_revision.h"
79 extern bool gpsMagDetect(mag_t
*mag
);
82 extern float magneticDeclination
;
88 uint8_t detectedSensors
[SENSOR_INDEX_COUNT
] = { GYRO_NONE
, ACC_NONE
, BARO_NONE
, MAG_NONE
, RANGEFINDER_NONE
};
91 const extiConfig_t
*selectMPUIntExtiConfig(void)
94 // MPU_INT output on rev4 PB13
95 static const extiConfig_t nazeRev4MPUIntExtiConfig
= {
96 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOB
,
99 .exti_port_source
= GPIO_PortSourceGPIOB
,
100 .exti_line
= EXTI_Line13
,
101 .exti_pin_source
= GPIO_PinSource13
,
102 .exti_irqn
= EXTI15_10_IRQn
104 // MPU_INT output on rev5 hardware PC13
105 static const extiConfig_t nazeRev5MPUIntExtiConfig
= {
106 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOC
,
109 .exti_port_source
= GPIO_PortSourceGPIOC
,
110 .exti_line
= EXTI_Line13
,
111 .exti_pin_source
= GPIO_PinSource13
,
112 .exti_irqn
= EXTI15_10_IRQn
115 if (hardwareRevision
< NAZE32_REV5
) {
116 return &nazeRev4MPUIntExtiConfig
;
118 return &nazeRev5MPUIntExtiConfig
;
122 #if defined(SPRACINGF3)
123 static const extiConfig_t spRacingF3MPUIntExtiConfig
= {
124 .gpioAHBPeripherals
= RCC_AHBPeriph_GPIOC
,
127 .exti_port_source
= EXTI_PortSourceGPIOC
,
128 .exti_pin_source
= EXTI_PinSource13
,
129 .exti_line
= EXTI_Line13
,
130 .exti_irqn
= EXTI15_10_IRQn
132 return &spRacingF3MPUIntExtiConfig
;
136 static const extiConfig_t cc3dMPUIntExtiConfig
= {
137 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOA
,
140 .exti_port_source
= GPIO_PortSourceGPIOA
,
141 .exti_pin_source
= GPIO_PinSource3
,
142 .exti_line
= EXTI_Line3
,
143 .exti_irqn
= EXTI3_IRQn
145 return &cc3dMPUIntExtiConfig
;
149 static const extiConfig_t MotolabF3MPUIntExtiConfig
= {
150 .gpioAHBPeripherals
= RCC_AHBPeriph_GPIOA
,
153 .exti_port_source
= EXTI_PortSourceGPIOA
,
154 .exti_pin_source
= EXTI_PinSource15
,
155 .exti_line
= EXTI_Line15
,
156 .exti_irqn
= EXTI15_10_IRQn
158 return &MotolabF3MPUIntExtiConfig
;
161 #if defined(COLIBRI_RACE) || defined(LUX_RACE)
162 static const extiConfig_t colibriRaceMPUIntExtiConfig
= {
163 .gpioAHBPeripherals
= RCC_AHBPeriph_GPIOA
,
166 .exti_port_source
= EXTI_PortSourceGPIOA
,
167 .exti_pin_source
= EXTI_PinSource5
,
168 .exti_line
= EXTI_Line5
,
169 .exti_irqn
= EXTI9_5_IRQn
171 return &colibriRaceMPUIntExtiConfig
;
178 static void fakeGyroInit(uint8_t lpf
)
183 static bool fakeGyroRead(int16_t *gyroADC
)
185 memset(gyroADC
, 0, sizeof(int16_t[XYZ_AXIS_COUNT
]));
189 static bool fakeGyroReadTemp(int16_t *tempData
)
195 bool fakeGyroDetect(gyro_t
*gyro
)
197 gyro
->init
= fakeGyroInit
;
198 gyro
->read
= fakeGyroRead
;
199 gyro
->temperature
= fakeGyroReadTemp
;
205 static void fakeAccInit(acc_t
*acc
) {UNUSED(acc
);}
206 static bool fakeAccRead(int16_t *accData
) {
207 memset(accData
, 0, sizeof(int16_t[XYZ_AXIS_COUNT
]));
211 bool fakeAccDetect(acc_t
*acc
)
213 acc
->init
= fakeAccInit
;
214 acc
->read
= fakeAccRead
;
215 acc
->revisionCode
= 0;
221 static void fakeBaroStartGet(void)
225 static void fakeBaroCalculate(int32_t *pressure
, int32_t *temperature
)
228 *pressure
= 101325; // pressure in Pa (0m MSL)
230 *temperature
= 2500; // temperature in 0.01 C = 25 deg
233 bool fakeBaroDetect(baro_t
*baro
)
235 // these are dummy as temperature is measured as part of pressure
236 baro
->ut_delay
= 10000;
237 baro
->get_ut
= fakeBaroStartGet
;
238 baro
->start_ut
= fakeBaroStartGet
;
240 // only _up part is executed, and gets both temperature and pressure
241 baro
->up_delay
= 10000;
242 baro
->start_up
= fakeBaroStartGet
;
243 baro
->get_up
= fakeBaroStartGet
;
244 baro
->calculate
= fakeBaroCalculate
;
251 static void fakeMagInit(void)
255 static bool fakeMagRead(int16_t *magData
)
257 // Always pointint North
264 static bool fakeMagDetect(mag_t
*mag
)
266 mag
->init
= fakeMagInit
;
267 mag
->read
= fakeMagRead
;
273 bool detectGyro(void)
275 gyroSensor_e gyroHardware
= GYRO_DEFAULT
;
277 gyroAlign
= ALIGN_DEFAULT
;
279 switch(gyroHardware
) {
283 #ifdef USE_GYRO_MPU6050
284 if (mpu6050GyroDetect(&gyro
)) {
285 #ifdef GYRO_MPU6050_ALIGN
286 gyroHardware
= GYRO_MPU6050
;
287 gyroAlign
= GYRO_MPU6050_ALIGN
;
294 #ifdef USE_GYRO_L3G4200D
295 if (l3g4200dDetect(&gyro
)) {
296 #ifdef GYRO_L3G4200D_ALIGN
297 gyroHardware
= GYRO_L3G4200D
;
298 gyroAlign
= GYRO_L3G4200D_ALIGN
;
306 #ifdef USE_GYRO_MPU3050
307 if (mpu3050Detect(&gyro
)) {
308 #ifdef GYRO_MPU3050_ALIGN
309 gyroHardware
= GYRO_MPU3050
;
310 gyroAlign
= GYRO_MPU3050_ALIGN
;
318 #ifdef USE_GYRO_L3GD20
319 if (l3gd20Detect(&gyro
)) {
320 #ifdef GYRO_L3GD20_ALIGN
321 gyroHardware
= GYRO_L3GD20
;
322 gyroAlign
= GYRO_L3GD20_ALIGN
;
330 #ifdef USE_GYRO_SPI_MPU6000
331 if (mpu6000SpiGyroDetect(&gyro
)) {
332 #ifdef GYRO_MPU6000_ALIGN
333 gyroHardware
= GYRO_MPU6000
;
334 gyroAlign
= GYRO_MPU6000_ALIGN
;
342 #ifdef USE_GYRO_MPU6500
343 #ifdef USE_GYRO_SPI_MPU6500
344 if (mpu6500GyroDetect(&gyro
) || mpu6500SpiGyroDetect(&gyro
))
346 if (mpu6500GyroDetect(&gyro
))
349 gyroHardware
= GYRO_MPU6500
;
350 #ifdef GYRO_MPU6500_ALIGN
351 gyroAlign
= GYRO_MPU6500_ALIGN
;
361 if (fakeGyroDetect(&gyro
)) {
362 gyroHardware
= GYRO_FAKE
;
368 gyroHardware
= GYRO_NONE
;
371 if (gyroHardware
== GYRO_NONE
) {
375 detectedSensors
[SENSOR_INDEX_GYRO
] = gyroHardware
;
376 sensorsSet(SENSOR_GYRO
);
381 static void detectAcc(accelerationSensor_e accHardwareToUse
)
383 accelerationSensor_e accHardware
;
385 #ifdef USE_ACC_ADXL345
386 drv_adxl345_config_t acc_params
;
390 accAlign
= ALIGN_DEFAULT
;
392 switch (accHardwareToUse
) {
395 case ACC_ADXL345
: // ADXL345
396 #ifdef USE_ACC_ADXL345
397 acc_params
.useFifo
= false;
398 acc_params
.dataRate
= 800; // unused currently
400 if (hardwareRevision
< NAZE32_REV5
&& adxl345Detect(&acc_params
, &acc
)) {
402 if (adxl345Detect(&acc_params
, &acc
)) {
404 #ifdef ACC_ADXL345_ALIGN
405 accAlign
= ACC_ADXL345_ALIGN
;
407 accHardware
= ACC_ADXL345
;
413 #ifdef USE_ACC_LSM303DLHC
414 if (lsm303dlhcAccDetect(&acc
)) {
415 #ifdef ACC_LSM303DLHC_ALIGN
416 accAlign
= ACC_LSM303DLHC_ALIGN
;
418 accHardware
= ACC_LSM303DLHC
;
423 case ACC_MPU6050
: // MPU6050
424 #ifdef USE_ACC_MPU6050
425 if (mpu6050AccDetect(&acc
)) {
426 #ifdef ACC_MPU6050_ALIGN
427 accAlign
= ACC_MPU6050_ALIGN
;
429 accHardware
= ACC_MPU6050
;
434 case ACC_MMA8452
: // MMA8452
435 #ifdef USE_ACC_MMA8452
437 // Not supported with this frequency
438 if (hardwareRevision
< NAZE32_REV5
&& mma8452Detect(&acc
)) {
440 if (mma8452Detect(&acc
)) {
442 #ifdef ACC_MMA8452_ALIGN
443 accAlign
= ACC_MMA8452_ALIGN
;
445 accHardware
= ACC_MMA8452
;
450 case ACC_BMA280
: // BMA280
451 #ifdef USE_ACC_BMA280
452 if (bma280Detect(&acc
)) {
453 #ifdef ACC_BMA280_ALIGN
454 accAlign
= ACC_BMA280_ALIGN
;
456 accHardware
= ACC_BMA280
;
462 #ifdef USE_ACC_SPI_MPU6000
463 if (mpu6000SpiAccDetect(&acc
)) {
464 #ifdef ACC_MPU6000_ALIGN
465 accAlign
= ACC_MPU6000_ALIGN
;
467 accHardware
= ACC_MPU6000
;
473 #ifdef USE_ACC_MPU6500
474 #ifdef USE_ACC_SPI_MPU6500
475 if (mpu6500AccDetect(&acc
) || mpu6500SpiAccDetect(&acc
))
477 if (mpu6500AccDetect(&acc
))
480 #ifdef ACC_MPU6500_ALIGN
481 accAlign
= ACC_MPU6500_ALIGN
;
483 accHardware
= ACC_MPU6500
;
490 if (fakeAccDetect(&acc
)) {
491 accHardware
= ACC_FAKE
;
496 case ACC_NONE
: // disable ACC
497 accHardware
= ACC_NONE
;
502 // Found anything? Check if error or ACC is really missing.
503 if (accHardware
== ACC_NONE
&& accHardwareToUse
!= ACC_DEFAULT
&& accHardwareToUse
!= ACC_NONE
) {
504 // Nothing was found and we have a forced sensor that isn't present.
505 accHardwareToUse
= ACC_DEFAULT
;
510 if (accHardware
== ACC_NONE
) {
514 detectedSensors
[SENSOR_INDEX_ACC
] = accHardware
;
515 sensorsSet(SENSOR_ACC
);
518 static void detectBaro(baroSensor_e baroHardwareToUse
)
521 UNUSED(baroHardwareToUse
);
523 // Detect what pressure sensors are available. baro->update() is set to sensor-specific update function
525 baroSensor_e baroHardware
= baroHardwareToUse
;
527 #ifdef USE_BARO_BMP085
529 const bmp085Config_t
*bmp085Config
= NULL
;
531 #if defined(BARO_XCLR_GPIO) && defined(BARO_EOC_GPIO)
532 static const bmp085Config_t defaultBMP085Config
= {
533 .gpioAPB2Peripherals
= BARO_APB2_PERIPHERALS
,
534 .xclrGpioPin
= BARO_XCLR_PIN
,
535 .xclrGpioPort
= BARO_XCLR_GPIO
,
536 .eocGpioPin
= BARO_EOC_PIN
,
537 .eocGpioPort
= BARO_EOC_GPIO
539 bmp085Config
= &defaultBMP085Config
;
543 if (hardwareRevision
== NAZE32
) {
544 bmp085Disable(bmp085Config
);
550 switch (baroHardware
) {
555 #ifdef USE_BARO_MS5611
556 if (ms5611Detect(&baro
)) {
557 baroHardware
= BARO_MS5611
;
563 #ifdef USE_BARO_BMP085
564 if (bmp085Detect(bmp085Config
, &baro
)) {
565 baroHardware
= BARO_BMP085
;
571 #ifdef USE_BARO_BMP280
572 if (bmp280Detect(&baro
)) {
573 baroHardware
= BARO_BMP280
;
580 if (fakeBaroDetect(&baro
)) {
581 baroHardware
= BARO_FAKE
;
587 baroHardware
= BARO_NONE
;
591 if (baroHardware
== BARO_NONE
) {
595 detectedSensors
[SENSOR_INDEX_BARO
] = baroHardware
;
596 sensorsSet(SENSOR_BARO
);
600 static void detectMag(magSensor_e magHardwareToUse
)
602 magSensor_e magHardware
;
604 #ifdef USE_MAG_HMC5883
605 const hmc5883Config_t
*hmc5883Config
= 0;
608 static const hmc5883Config_t nazeHmc5883Config_v1_v4
= {
609 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOB
,
613 /* Disabled for v4 needs more work.
614 .exti_port_source = GPIO_PortSourceGPIOB,
615 .exti_pin_source = GPIO_PinSource12,
616 .exti_line = EXTI_Line12,
617 .exti_irqn = EXTI15_10_IRQn
620 static const hmc5883Config_t nazeHmc5883Config_v5
= {
621 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOC
,
624 .exti_port_source
= GPIO_PortSourceGPIOC
,
625 .exti_line
= EXTI_Line14
,
626 .exti_pin_source
= GPIO_PinSource14
,
627 .exti_irqn
= EXTI15_10_IRQn
629 if (hardwareRevision
< NAZE32_REV5
) {
630 hmc5883Config
= &nazeHmc5883Config_v1_v4
;
632 hmc5883Config
= &nazeHmc5883Config_v5
;
637 static const hmc5883Config_t spRacingF3Hmc5883Config
= {
638 .gpioAHBPeripherals
= RCC_AHBPeriph_GPIOC
,
641 .exti_port_source
= EXTI_PortSourceGPIOC
,
642 .exti_pin_source
= EXTI_PinSource14
,
643 .exti_line
= EXTI_Line14
,
644 .exti_irqn
= EXTI15_10_IRQn
647 hmc5883Config
= &spRacingF3Hmc5883Config
;
654 magAlign
= ALIGN_DEFAULT
;
656 switch(magHardwareToUse
) {
661 #ifdef USE_MAG_HMC5883
662 if (hmc5883lDetect(&mag
, hmc5883Config
)) {
663 #ifdef MAG_HMC5883_ALIGN
664 magAlign
= MAG_HMC5883_ALIGN
;
666 magHardware
= MAG_HMC5883
;
673 #ifdef USE_MAG_AK8975
674 if (ak8975detect(&mag
)) {
675 #ifdef MAG_AK8975_ALIGN
676 magAlign
= MAG_AK8975_ALIGN
;
678 magHardware
= MAG_AK8975
;
686 if (gpsMagDetect(&mag
)) {
688 magAlign
= MAG_GPS_ALIGN
;
690 magHardware
= MAG_GPS
;
697 #ifdef USE_MAG_MAG3110
698 if (mag3110detect(&mag
)) {
699 #ifdef MAG_MAG3110_ALIGN
700 magAlign
= MAG_MAG3110_ALIGN
;
702 magHardware
= MAG_MAG3110
;
710 if (fakeMagDetect(&mag
)) {
711 magHardware
= MAG_FAKE
;
718 magHardware
= MAG_NONE
;
722 if (magHardware
== MAG_NONE
&& magHardwareToUse
!= MAG_DEFAULT
&& magHardwareToUse
!= MAG_NONE
) {
723 // Nothing was found and we have a forced sensor that isn't present.
724 magHardwareToUse
= MAG_DEFAULT
;
728 if (magHardware
== MAG_NONE
) {
732 detectedSensors
[SENSOR_INDEX_MAG
] = magHardware
;
733 sensorsSet(SENSOR_MAG
);
738 * Detect which rangefinder is present
740 static rangefinderType_e
detectRangefinder(void)
742 rangefinderType_e rangefinderType
= RANGEFINDER_NONE
;
743 if (feature(FEATURE_SONAR
)) {
744 // the user has set the sonar feature, so assume they have an HC-SR04 plugged in,
745 // since there is no way to detect it
746 rangefinderType
= RANGEFINDER_HCSR04
;
748 #ifdef USE_SONAR_SRF10
749 if (srf10_detect()) {
750 // if an SFR10 sonar rangefinder is detected then use it in preference to the assumed HC-SR04
751 rangefinderType
= RANGEFINDER_SRF10
;
754 detectedSensors
[SENSOR_INDEX_RANGEFINDER
] = rangefinderType
;
756 if (rangefinderType
!= RANGEFINDER_NONE
) {
757 sensorsSet(SENSOR_SONAR
);
760 return rangefinderType
;
764 static void reconfigureAlignment(const sensorAlignmentConfig_t
*sensorAlignmentConfig
)
766 if (sensorAlignmentConfig
->gyro_align
!= ALIGN_DEFAULT
) {
767 gyroAlign
= sensorAlignmentConfig
->gyro_align
;
769 if (sensorAlignmentConfig
->acc_align
!= ALIGN_DEFAULT
) {
770 accAlign
= sensorAlignmentConfig
->acc_align
;
772 if (sensorAlignmentConfig
->mag_align
!= ALIGN_DEFAULT
) {
773 magAlign
= sensorAlignmentConfig
->mag_align
;
777 bool sensorsAutodetect(sensorAlignmentConfig_t
*sensorAlignmentConfig
, uint8_t gyroLpf
, uint8_t accHardwareToUse
, uint8_t magHardwareToUse
, uint8_t baroHardwareToUse
,
778 int16_t magDeclinationFromConfig
) {
780 memset(&acc
, 0, sizeof(acc
));
781 memset(&gyro
, 0, sizeof(gyro
));
783 #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)
784 const extiConfig_t
*mpuExtiConfig
= selectMPUIntExtiConfig();
785 detectMpu(mpuExtiConfig
);
791 detectAcc(accHardwareToUse
);
792 detectBaro(baroHardwareToUse
);
795 // Now time to init things, acc first
796 if (sensors(SENSOR_ACC
)) {
802 detectMag(magHardwareToUse
);
804 reconfigureAlignment(sensorAlignmentConfig
);
806 // FIXME extract to a method to reduce dependencies, maybe move to sensors_compass.c
807 if (sensors(SENSOR_MAG
)) {
808 // calculate magnetic declination
809 const int deg
= magDeclinationFromConfig
/ 100;
810 const int min
= magDeclinationFromConfig
% 100;
811 magneticDeclination
= (deg
+ ((float)min
* (1.0f
/ 60.0f
))) * 10; // heading is in 0.1deg units
813 magneticDeclination
= 0.0f
; // TODO investigate if this is actually needed if there is no mag sensor or if the value stored in the config should be used.
817 const rangefinderType_e rangefinderType
= detectRangefinder();
818 rangefinderInit(rangefinderType
);