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/>.
25 #ifdef USE_MAG_IST8310
27 #include "build/debug.h"
29 #include "common/axis.h"
30 #include "common/maths.h"
32 #include "drivers/time.h"
33 #include "drivers/nvic.h"
34 #include "drivers/io.h"
35 #include "drivers/bus.h"
36 #include "drivers/light_led.h"
38 #include "drivers/sensor.h"
39 #include "drivers/compass/compass.h"
41 #include "drivers/compass/compass_ist8310.h"
43 #define IST8310_ADDRESS 0x0C
45 // Hardware descriptor
46 #if defined(MAG_I2C_BUS)
49 /* ist8310 Slave Address Select : default address 0x0C
50 * CAD1 | CAD0 | Address
51 * ------------------------------
56 * if CAD1 and CAD0 are floating, I2C address will be 0EH
59 * CTRL_REGA: Control Register 1
63 * 3:0 DO2-DO0: Operating mode setting
64 * DO3 | DO2 | DO1 | DO0 | mode
65 * ------------------------------------------------------
66 * 0 | 0 | 0 | 0 | Stand-By mode
67 * 0 | 0 | 0 | 1 | Single measurement mode
70 * CTRL_REGB: Control Register 2
74 * 3 DREN : Data ready enable control:
77 * 2 DRP: DRDY pin polarity control
81 * 0 SRST: Soft reset, perform Power On Reset (POR) routine
83 * 1: start immediately POR routine
84 * This bit will be set to zero after POR routine
87 #define IST8310_REG_DATA 0x03
88 #define IST8310_REG_WHOAMI 0x00
90 // I2C Contorl Register
91 #define IST8310_REG_CNTRL1 0x0A
92 #define IST8310_REG_CNTRL2 0x0B
93 #define IST8310_REG_AVERAGE 0x41
94 #define IST8310_REG_PDCNTL 0x42
97 // ODR = Output Data Rate, we use single measure mode for getting more data.
98 #define IST8310_ODR_SINGLE 0x01
99 #define IST8310_ODR_10_HZ 0x03
100 #define IST8310_ODR_20_HZ 0x05
101 #define IST8310_ODR_50_HZ 0x07
102 #define IST8310_ODR_100_HZ 0x06
104 // Device ID (ist8310 -> 0x10)
105 #define IST8310_CHIP_ID 0x10
106 #define IST8310_AVG_16 0x24
107 #define IST8310_PULSE_DURATION_NORMAL 0xC0
109 #define IST8310_CNTRL2_RESET 0x01
110 #define IST8310_CNTRL2_DRPOL 0x04
111 #define IST8310_CNTRL2_DRENA 0x08
113 static bool ist8310Init(magDev_t
* mag
)
115 busWrite(mag
->busDev
, IST8310_REG_CNTRL1
, IST8310_ODR_50_HZ
);
118 busWrite(mag
->busDev
, IST8310_REG_AVERAGE
, IST8310_AVG_16
);
121 busWrite(mag
->busDev
, IST8310_REG_PDCNTL
, IST8310_PULSE_DURATION_NORMAL
);
127 static bool ist8310Read(magDev_t
* mag
)
130 uint8_t LSB2FSV
= 3; // 3mG - 14 bit
132 // set magData to zero for case of failed read
133 mag
->magADCRaw
[X
] = 0;
134 mag
->magADCRaw
[Y
] = 0;
135 mag
->magADCRaw
[Z
] = 0;
137 bool ack
= busReadBuf(mag
->busDev
, IST8310_REG_DATA
, buf
, 6);
142 // Invert Y axis to co convert from left to right coordinate system
143 mag
->magADCRaw
[X
] = (int16_t)(buf
[1] << 8 | buf
[0]) * LSB2FSV
;
144 mag
->magADCRaw
[Y
] = -(int16_t)(buf
[3] << 8 | buf
[2]) * LSB2FSV
;
145 mag
->magADCRaw
[Z
] = (int16_t)(buf
[5] << 8 | buf
[4]) * LSB2FSV
;
150 #define DETECTION_MAX_RETRY_COUNT 5
151 static bool deviceDetect(magDev_t
* mag
)
153 for (int retryCount
= 0; retryCount
< DETECTION_MAX_RETRY_COUNT
; retryCount
++) {
157 bool ack
= busRead(mag
->busDev
, IST8310_REG_WHOAMI
, &sig
);
159 if (ack
&& sig
== IST8310_CHIP_ID
) {
167 bool ist8310Detect(magDev_t
* mag
)
169 for (uint8_t index
= 0; index
< 2; ++index
) {
170 mag
->busDev
= busDeviceInit(BUSTYPE_ANY
, DEVHW_IST8310_0
+ index
, mag
->magSensorToUse
, OWNER_COMPASS
);
171 if (mag
->busDev
== NULL
) {
175 if (deviceDetect(mag
)) {
176 mag
->init
= ist8310Init
;
177 mag
->read
= ist8310Read
;
180 busDeviceDeInit(mag
->busDev
);