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, &regVal );
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