1 /*!
2 * \file mma8451.h
3 *
4 * \brief MMA8451 Accelerometer driver implementation
5 *
6 * \copyright Revised BSD License, see section \ref LICENSE.
7 *
8 * \code
9 * ______ _
10 * / _____) _ | |
11 * ( (____ _____ ____ _| |_ _____ ____| |__
12 * \____ \| ___ | (_ _) ___ |/ ___) _ \
13 * _____) ) ____| | | || |_| ____( (___| | | |
14 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15 * (C)2013-2017 Semtech
16 *
17 * \endcode
18 *
19 * \author Miguel Luis ( Semtech )
20 *
21 * \author Gregory Cristian ( Semtech )
22 */
23 #include <stdbool.h>
24 #include "utilities.h"
25 #include "i2c.h"
26 #include "mma8451.h"
27
28 extern I2c_t I2c;
29
30 static uint8_t I2cDeviceAddr = 0;
31
32 static bool MMA8451Initialized = false;
33
34 /*!
35 * \brief Writes a byte at specified address in the device
36 *
37 * \param [IN]: addr
38 * \param [IN]: data
39 * \retval status [LMN_STATUS_OK, LMN_STATUS_ERROR]
40 */
41 LmnStatus_t MMA8451Write( uint8_t addr, uint8_t data );
42
43 /*!
44 * \brief Writes a buffer at specified address in the device
45 *
46 * \param [IN]: addr
47 * \param [IN]: data
48 * \param [IN]: size
49 * \retval status [LMN_STATUS_OK, LMN_STATUS_ERROR]
50 */
51 LmnStatus_t MMA8451WriteBuffer( uint8_t addr, uint8_t *data, uint8_t size );
52
53 /*!
54 * \brief Reads a byte at specified address in the device
55 *
56 * \param [IN]: addr
57 * \param [OUT]: data
58 * \retval status [LMN_STATUS_OK, LMN_STATUS_ERROR]
59 */
60 LmnStatus_t MMA8451Read( uint8_t addr, uint8_t *data );
61
62 /*!
63 * \brief Reads a buffer at specified address in the device
64 *
65 * \param [IN]: addr
66 * \param [OUT]: data
67 * \param [IN]: size
68 * \retval status [LMN_STATUS_OK, LMN_STATUS_ERROR]
69 */
70 LmnStatus_t MMA8451ReadBuffer( uint8_t addr, uint8_t *data, uint8_t size );
71
72 /*!
73 * \brief Sets the I2C device slave address
74 *
75 * \param [IN]: addr
76 */
77 void MMA8451SetDeviceAddr( uint8_t addr );
78
79 /*!
80 * \brief Gets the I2C device slave address
81 *
82 * \retval: addr Current device slave address
83 */
84 uint8_t MMA8451GetDeviceAddr( void );
85
MMA8451Init(void)86 LmnStatus_t MMA8451Init( void )
87 {
88 uint8_t regVal = 0;
89
90 MMA8451SetDeviceAddr( MMA8451_I2C_ADDRESS );
91
92 if( MMA8451Initialized == false )
93 {
94 MMA8451Initialized = true;
95
96 MMA8451Read( MMA8451_ID, ®Val );
97 if( regVal != 0x1A ) // Fixed Device ID Number = 0x1A
98 {
99 return LMN_STATUS_ERROR;
100 }
101 MMA8451Reset( );
102
103 // INT pins on this chip default to push-pull output
104 // set them to open drain.
105 MMA8451Write( MMA8451_CTRL_REG3, 0x01 );
106 MMA8451OrientDetect( );
107 }
108 return LMN_STATUS_OK;
109 }
110
111
MMA8451Reset()112 LmnStatus_t MMA8451Reset( )
113 {
114 if( MMA8451Write( 0x2B, 0x40 ) == LMN_STATUS_OK ) // Reset the MMA8451 with CTRL_REG2
115 {
116 return LMN_STATUS_OK;
117 }
118 return LMN_STATUS_ERROR;
119 }
120
MMA8451Write(uint8_t addr,uint8_t data)121 LmnStatus_t MMA8451Write( uint8_t addr, uint8_t data )
122 {
123 return MMA8451WriteBuffer( addr, &data, 1 );
124 }
125
MMA8451WriteBuffer(uint8_t addr,uint8_t * data,uint8_t size)126 LmnStatus_t MMA8451WriteBuffer( uint8_t addr, uint8_t *data, uint8_t size )
127 {
128 return I2cWriteMemBuffer( &I2c, I2cDeviceAddr << 1, addr, data, size );
129 }
130
MMA8451Read(uint8_t addr,uint8_t * data)131 LmnStatus_t MMA8451Read( uint8_t addr, uint8_t *data )
132 {
133 return MMA8451ReadBuffer( addr, data, 1 );
134 }
135
MMA8451ReadBuffer(uint8_t addr,uint8_t * data,uint8_t size)136 LmnStatus_t MMA8451ReadBuffer( uint8_t addr, uint8_t *data, uint8_t size )
137 {
138 return I2cReadMemBuffer( &I2c, I2cDeviceAddr << 1, addr, data, size );
139 }
140
MMA8451SetDeviceAddr(uint8_t addr)141 void MMA8451SetDeviceAddr( uint8_t addr )
142 {
143 I2cDeviceAddr = addr;
144 }
145
MMA8451GetDeviceAddr(void)146 uint8_t MMA8451GetDeviceAddr( void )
147 {
148 return I2cDeviceAddr;
149 }
150
MMA8451GetOrientation(void)151 uint8_t MMA8451GetOrientation( void )
152 {
153 uint8_t orientation = 0;
154
155 MMA8451Read( MMA8451_PL_STATUS, &orientation );
156 return orientation;
157 }
158
MMA8451OrientDetect(void)159 void MMA8451OrientDetect( void )
160 {
161 uint8_t ctrlReg1 = 0;
162 uint8_t tmpReg = 0;
163
164 // Set device in standby mode
165 MMA8451Read( MMA8451_CTRL_REG1, &ctrlReg1 );
166 MMA8451Write( MMA8451_CTRL_REG1, ctrlReg1 & 0xFE );
167
168 // Set the data rate to 50 Hz
169 MMA8451Write( MMA8451_CTRL_REG1, ctrlReg1 | 0x20 );
170
171 // Set enable orientation detection.
172 MMA8451Read( MMA8451_PL_CFG, &tmpReg );
173 MMA8451Write( MMA8451_PL_CFG, tmpReg | 0x40 );
174
175 // Enable orientation interrupt
176 MMA8451Write( MMA8451_CTRL_REG4, 0x10 );
177
178 // Select orientation interrupt pin INT1
179 MMA8451Write( MMA8451_CTRL_REG5, 0x10 );
180
181 // Set the debounce counter 5 -> 100 ms at 50 Hz
182 MMA8451Write( MMA8451_PL_COUNT, 0x05 );
183
184 // Set device in active mode
185 MMA8451Read( MMA8451_CTRL_REG1, &ctrlReg1 );
186 MMA8451Write( MMA8451_CTRL_REG1, ctrlReg1 | 0x01 );
187 }
188