2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
28 #if defined(USE_MAG_LIS3MDL)
31 #include "drivers/time.h"
32 #include "common/axis.h"
34 #define LIS3MDL_MAG_I2C_ADDRESS 0x1E
35 #define LIS3MDL_DEVICE_ID 0x3D
37 #define LIS3MDL_REG_WHO_AM_I 0x0F
39 #define LIS3MDL_REG_CTRL_REG1 0x20
40 #define LIS3MDL_REG_CTRL_REG2 0x21
41 #define LIS3MDL_REG_CTRL_REG3 0x22
42 #define LIS3MDL_REG_CTRL_REG4 0x23
43 #define LIS3MDL_REG_CTRL_REG5 0x24
45 #define LIS3MDL_REG_STATUS_REG 0x27
47 #define LIS3MDL_REG_OUT_X_L 0x28
48 #define LIS3MDL_REG_OUT_X_H 0x29
49 #define LIS3MDL_REG_OUT_Y_L 0x2A
50 #define LIS3MDL_REG_OUT_Y_H 0x2B
51 #define LIS3MDL_REG_OUT_Z_L 0x2C
52 #define LIS3MDL_REG_OUT_Z_H 0x2D
54 #define LIS3MDL_TEMP_OUT_L 0x2E
55 #define LIS3MDL_TEMP_OUT_H 0x2F
57 #define LIS3MDL_INT_CFG 0x30
58 #define LIS3MDL_INT_SRC 0x31
59 #define LIS3MDL_THS_L 0x32
60 #define LIS3MDL_THS_H 0x33
63 #define LIS3MDL_TEMP_EN 0x80 // Default 0
64 #define LIS3MDL_OM_LOW_POWER 0x00 // Default
65 #define LIS3MDL_OM_MED_PROF 0x20
66 #define LIS3MDL_OM_HI_PROF 0x40
67 #define LIS3MDL_OM_ULTRA_HI_PROF 0x60
68 #define LIS3MDL_DO_0_625 0x00
69 #define LIS3MDL_DO_1_25 0x04
70 #define LIS3MDL_DO_2_5 0x08
71 #define LIS3MDL_DO_5 0x0C
72 #define LIS3MDL_DO_10 0x10 // Default
73 #define LIS3MDL_DO_20 0x14
74 #define LIS3MDL_DO_40 0x18
75 #define LIS3MDL_DO_80 0x1C
76 #define LIS3MDL_FAST_ODR 0x02
79 #define LIS3MDL_FS_4GAUSS 0x00 // Default
80 #define LIS3MDL_FS_8GAUSS 0x20
81 #define LIS3MDL_FS_12GAUSS 0x40
82 #define LIS3MDL_FS_16GAUSS 0x60
83 #define LIS3MDL_REBOOT 0x08
84 #define LIS3MDL_SOFT_RST 0x04
87 #define LIS3MDL_LP 0x20 // Default 0
88 #define LIS3MDL_SIM 0x04 // Default 0
89 #define LIS3MDL_MD_CONTINUOUS 0x00 // Default
90 #define LIS3MDL_MD_SINGLE 0x01
91 #define LIS3MDL_MD_POWERDOWN 0x03
94 #define LIS3MDL_ZOM_LP 0x00 // Default
95 #define LIS3MDL_ZOM_MP 0x04
96 #define LIS3MDL_ZOM_HP 0x08
97 #define LIS3MDL_ZOM_UHP 0x0C
98 #define LIS3MDL_BLE 0x02 // Default 0
101 #define LIS3MDL_FAST_READ 0x80 // Default 0
102 #define LIS3MDL_BDU 0x40 // Default 0
104 static bool lis3mdlRead(magDev_t
* mag
, int16_t *magData
)
106 static uint8_t buf
[6];
107 static bool pendingRead
= true;
109 extDevice_t
*dev
= &mag
->dev
;
112 if (busReadRegisterBufferStart(dev
, LIS3MDL_REG_OUT_X_L
, buf
, sizeof(buf
))) {
118 magData
[X
] = (int16_t)(buf
[1] << 8 | buf
[0]) / 4;
119 magData
[Y
] = (int16_t)(buf
[3] << 8 | buf
[2]) / 4;
120 magData
[Z
] = (int16_t)(buf
[5] << 8 | buf
[4]) / 4;
127 static bool lis3mdlInit(magDev_t
*mag
)
129 extDevice_t
*dev
= &mag
->dev
;
131 busDeviceRegister(dev
);
133 busWriteRegister(dev
, LIS3MDL_REG_CTRL_REG2
, LIS3MDL_FS_4GAUSS
);
134 busWriteRegister(dev
, LIS3MDL_REG_CTRL_REG1
, LIS3MDL_TEMP_EN
| LIS3MDL_OM_ULTRA_HI_PROF
| LIS3MDL_DO_80
);
135 busWriteRegister(dev
, LIS3MDL_REG_CTRL_REG5
, LIS3MDL_BDU
);
136 busWriteRegister(dev
, LIS3MDL_REG_CTRL_REG4
, LIS3MDL_ZOM_UHP
);
137 busWriteRegister(dev
, LIS3MDL_REG_CTRL_REG3
, 0x00);
140 mag
->magOdrHz
= 80; // LIS3MDL_DO_80
144 bool lis3mdlDetect(magDev_t
* mag
)
146 extDevice_t
*dev
= &mag
->dev
;
150 if (dev
->bus
->busType
== BUS_TYPE_I2C
&& dev
->busType_u
.i2c
.address
== 0) {
151 dev
->busType_u
.i2c
.address
= LIS3MDL_MAG_I2C_ADDRESS
;
154 bool ack
= busReadRegisterBuffer(&mag
->dev
, LIS3MDL_REG_WHO_AM_I
, &sig
, 1);
156 if (!ack
|| sig
!= LIS3MDL_DEVICE_ID
) {
160 mag
->init
= lis3mdlInit
;
161 mag
->read
= lis3mdlRead
;