2 * This file is part of INAV.
4 * INAV 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 * INAV 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 INAV. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef USE_MAG_MLX90393
27 #include "build/debug.h"
29 #include "common/axis.h"
30 #include "common/maths.h"
31 #include "common/utils.h"
33 #include "drivers/time.h"
34 #include "drivers/io.h"
35 #include "drivers/bus.h"
37 #include "drivers/sensor.h"
38 #include "drivers/compass/compass.h"
40 #define MLX90393_MEASURE_3D 0b00001110
42 #define MLX90393_NOP 0b00000000
43 #define MLX90393_START_BURST_MODE 0b00010000 //uses with zyxt flags
44 #define MLX90393_START_WAKE_UP_ON_CHANGE_MODE 0b00100000 //uses with zyxt flags
45 #define MLX90393_START_SINGLE_MEASUREMENT_MODE 0b00110000 //uses with zyxt flags
46 #define MLX90393_READ_MEASUREMENT 0b01000000 //uses with zyxt flags
47 #define MLX90393_READ_REGISTER 0b01010000
48 #define MLX90393_WRITE_REGISTER 0b01100000
49 #define MLX90393_EXIT_MODE 0b10000000
50 #define MLX90393_MEMORY_RECALL 0b11010000
51 #define MLX90393_MEMORY_STORE 0b11100000
52 #define MLX90393_RESET 0b11110000
54 #define MLX90393_BURST_MODE_FLAG 0b10000000
55 #define MLX90393_WAKE_UP_ON_CHANGE_MODE_FLAG 0b01000000
56 #define MLX90393_SINGLE_MEASUREMENT_MODE_FLAG 0b00100000
57 #define MLX90393_ERROR_FLAG 0b00010000
58 #define MLX90393_SINGLE_ERROR_DETECTION_FLAG 0b00001000
59 #define MLX90393_RESET_FLAG 0b00000100
60 #define MLX90393_D1_FLAG 0b00000010
61 #define MLX90393_D0_FLAG 0b00000001
63 #define DETECTION_MAX_RETRY_COUNT 5
68 #define GAIN_SEL_HALLCONF_REG 0x0 //from datasheet 0x0 << 2 = 0x0
71 #define GAIN_SEL_HALLCONF_REG_VALUE 0x007C
73 #define TCMP_EN_REG 0x4 //from datasheet 0x1 << 2 = 0x4
74 // Burst Data Rate 0b000100
75 #define TCMP_EN_REG_VALUE 0x62C4
77 #define RES_XYZ_OSR_FLT_REG 0x8 //from datasheet 0x2 << 2 = 0x8
80 #define RES_XYZ_OSR_FLT_REG_VALUE 0x001D
83 static void mlx90393WriteRegister(magDev_t
* mag
, uint8_t reg_val
, uint16_t value
) {
85 uint8_t buf
[REG_BUF_LEN
] = {0};
87 buf
[0] = (value
>> 8) & 0xFF;
88 buf
[1] = (value
>> 0) & 0xFF;
91 busWriteBuf(mag
->busDev
, MLX90393_WRITE_REGISTER
, buf
, REG_BUF_LEN
);
95 // To skip ACK FLAG of Write
97 busRead(mag
->busDev
, MLX90393_NOP
, &sig
);
102 // =======================================================================================
103 static bool mlx90393Read(magDev_t
* mag
)
106 uint8_t buf
[7] = {0};
108 busReadBuf(mag
->busDev
, MLX90393_READ_MEASUREMENT
| MLX90393_MEASURE_3D
, buf
, 7);
110 mag
->magADCRaw
[X
] = ((short)(buf
[1] << 8 | buf
[2]));
111 mag
->magADCRaw
[Y
] = ((short)(buf
[3] << 8 | buf
[4]));
112 mag
->magADCRaw
[Z
] = ((short)(buf
[5] << 8 | buf
[6]));
118 static bool deviceDetect(magDev_t
* mag
)
120 for (int retryCount
= 0; retryCount
< DETECTION_MAX_RETRY_COUNT
; retryCount
++) {
123 bool ack
= busRead(mag
->busDev
, MLX90393_RESET
, &sig
);
126 if (ack
&& ((sig
& MLX90393_RESET_FLAG
) == MLX90393_RESET_FLAG
)) { // Check Reset Flag -> MLX90393
133 //--------------------------------------------------
134 static bool mlx90393Init(magDev_t
* mag
)
140 busRead(mag
->busDev
, MLX90393_NOP
, &sig
);
141 // Exit if already in burst mode. (For example when external i2c source power the bus.)
142 busRead(mag
->busDev
, MLX90393_EXIT_MODE
, &sig
);
145 mlx90393WriteRegister(mag
, GAIN_SEL_HALLCONF_REG
, GAIN_SEL_HALLCONF_REG_VALUE
);
146 mlx90393WriteRegister(mag
, TCMP_EN_REG
, TCMP_EN_REG_VALUE
);
147 mlx90393WriteRegister(mag
, RES_XYZ_OSR_FLT_REG
, RES_XYZ_OSR_FLT_REG_VALUE
);
150 busRead(mag
->busDev
, MLX90393_START_BURST_MODE
| MLX90393_MEASURE_3D
, &sig
);
155 // ==========================================================================
157 bool mlx90393Detect(magDev_t
* mag
)
159 mag
->busDev
= busDeviceInit(BUSTYPE_ANY
, DEVHW_MLX90393
, mag
->magSensorToUse
, OWNER_COMPASS
);
160 if (mag
->busDev
== NULL
) {
164 if (!deviceDetect(mag
)) {
165 busDeviceDeInit(mag
->busDev
);
169 mag
->init
= mlx90393Init
;
170 mag
->read
= mlx90393Read
;