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/>.
29 #include "accgyro_mma845x.h"
31 #ifndef MMA8452_I2C_INSTANCE
32 #define MMA8452_I2C_INSTANCE I2CDEV_1
35 // MMA8452QT, Standard address 0x1C
36 // ACC_INT2 routed to PA5
38 #define MMA8452_ADDRESS 0x1C
40 #define MMA8452_DEVICE_SIGNATURE 0x2A
41 #define MMA8451_DEVICE_SIGNATURE 0x1A
43 #define MMA8452_STATUS 0x00
44 #define MMA8452_OUT_X_MSB 0x01
45 #define MMA8452_WHO_AM_I 0x0D
46 #define MMA8452_XYZ_DATA_CFG 0x0E
47 #define MMA8452_HP_FILTER_CUTOFF 0x0F
48 #define MMA8452_CTRL_REG1 0x2A
49 #define MMA8452_CTRL_REG2 0x2B
50 #define MMA8452_CTRL_REG3 0x2C
51 #define MMA8452_CTRL_REG4 0x2D
52 #define MMA8452_CTRL_REG5 0x2E
54 #define MMA8452_FS_RANGE_8G 0x02
55 #define MMA8452_FS_RANGE_4G 0x01
56 #define MMA8452_FS_RANGE_2G 0x00
58 #define MMA8452_HPF_CUTOFF_LV1 0x00
59 #define MMA8452_HPF_CUTOFF_LV2 0x01
60 #define MMA8452_HPF_CUTOFF_LV3 0x02
61 #define MMA8452_HPF_CUTOFF_LV4 0x03
63 #define MMA8452_CTRL_REG2_B7_ST 0x80
64 #define MMA8452_CTRL_REG2_B6_RST 0x40
65 #define MMA8452_CTRL_REG2_B4_SMODS1 0x10
66 #define MMA8452_CTRL_REG2_B3_SMODS0 0x08
67 #define MMA8452_CTRL_REG2_B2_SLPE 0x04
68 #define MMA8452_CTRL_REG2_B1_MODS1 0x02
69 #define MMA8452_CTRL_REG2_B0_MODS0 0x01
71 #define MMA8452_CTRL_REG2_MODS_LP 0x03
72 #define MMA8452_CTRL_REG2_MODS_HR 0x02
73 #define MMA8452_CTRL_REG2_MODS_LNLP 0x01
74 #define MMA8452_CTRL_REG2_MODS_NOR 0x00
76 #define MMA8452_CTRL_REG3_IPOL 0x02
77 #define MMA8452_CTRL_REG4_INT_EN_DRDY 0x01
79 #define MMA8452_CTRL_REG1_LNOISE 0x04
80 #define MMA8452_CTRL_REG1_ACTIVE 0x01
82 static uint8_t device_id
;
84 static inline void mma8451ConfigureInterrupt(void)
86 #ifdef MMA8451_INT_PIN
87 IOInit(IOGetByTag(IO_TAG(MMA8451_INT_PIN
)), OWNER_MPU_EXTI
, 0);
88 // TODO - maybe pullup / pulldown ?
89 IOConfigGPIO(IOGetByTag(IO_TAG(MMA8451_INT_PIN
)), IOCFG_IN_FLOATING
);
92 i2cWrite(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_CTRL_REG3
, MMA8452_CTRL_REG3_IPOL
); // Interrupt polarity (active HIGH)
93 i2cWrite(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_CTRL_REG4
, MMA8452_CTRL_REG4_INT_EN_DRDY
); // Enable DRDY interrupt (unused by this driver)
94 i2cWrite(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_CTRL_REG5
, 0); // DRDY routed to INT2
97 static void mma8452Init(accDev_t
*acc
)
100 i2cWrite(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_CTRL_REG1
, 0); // Put device in standby to configure stuff
101 i2cWrite(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_XYZ_DATA_CFG
, MMA8452_FS_RANGE_8G
);
102 i2cWrite(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_HP_FILTER_CUTOFF
, MMA8452_HPF_CUTOFF_LV4
);
103 i2cWrite(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_CTRL_REG2
, MMA8452_CTRL_REG2_MODS_HR
| MMA8452_CTRL_REG2_MODS_HR
<< 3); // High resolution measurement in both sleep and active modes
105 mma8451ConfigureInterrupt();
107 i2cWrite(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_CTRL_REG1
, MMA8452_CTRL_REG1_LNOISE
| MMA8452_CTRL_REG1_ACTIVE
); // Turn on measurements, low noise at max scale mode, Data Rate 800Hz. LNoise mode makes range +-4G.
112 static bool mma8452Read(accDev_t
*acc
)
116 if (!i2cRead(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_OUT_X_MSB
, 6, buf
)) {
120 acc
->ADCRaw
[0] = ((int16_t)((buf
[0] << 8) | buf
[1]) >> 2) / 4;
121 acc
->ADCRaw
[1] = ((int16_t)((buf
[2] << 8) | buf
[3]) >> 2) / 4;
122 acc
->ADCRaw
[2] = ((int16_t)((buf
[4] << 8) | buf
[5]) >> 2) / 4;
127 bool mma8452Detect(accDev_t
*acc
)
130 bool ack
= i2cRead(MPU_I2C_INSTANCE
, MMA8452_ADDRESS
, MMA8452_WHO_AM_I
, 1, &sig
);
132 if (!ack
|| (sig
!= MMA8452_DEVICE_SIGNATURE
&& sig
!= MMA8451_DEVICE_SIGNATURE
))
135 acc
->init
= mma8452Init
;
136 acc
->read
= mma8452Read
;