1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2021 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_fxos.h"
10 
11 /******************************************************************************
12  * Code
13  ******************************************************************************/
FXOS_Init(fxos_handle_t * fxos_handle,fxos_config_t * config)14 status_t FXOS_Init(fxos_handle_t *fxos_handle, fxos_config_t *config)
15 {
16     assert(fxos_handle);
17     assert(config);
18     assert(config->I2C_SendFunc);
19     assert(config->I2C_ReceiveFunc);
20 
21     uint8_t tmp[1] = {0};
22 
23     /* Initialize the I2C access function. */
24     fxos_handle->I2C_SendFunc    = config->I2C_SendFunc;
25     fxos_handle->I2C_ReceiveFunc = config->I2C_ReceiveFunc;
26     /* Set Slave Address. */
27     fxos_handle->slaveAddress = config->slaveAddress;
28 
29     if (FXOS_ReadReg(fxos_handle, WHO_AM_I_REG, tmp, 1) != kStatus_Success)
30     {
31         return kStatus_Fail;
32     }
33 
34     if (tmp[0] != kFXOS_WHO_AM_I_Device_ID)
35     {
36         return kStatus_Fail;
37     }
38 
39     /* setup auto sleep with FFMT trigger */
40     /* go to standby */
41     if (FXOS_ReadReg(fxos_handle, CTRL_REG1, tmp, 1) != kStatus_Success)
42     {
43         return kStatus_Fail;
44     }
45 
46     if (FXOS_WriteReg(fxos_handle, CTRL_REG1, tmp[0] & (uint8_t)~ACTIVE_MASK) != kStatus_Success)
47     {
48         return kStatus_Fail;
49     }
50 
51     /* Read again to make sure we are in standby mode. */
52     if (FXOS_ReadReg(fxos_handle, CTRL_REG1, tmp, 1) != kStatus_Success)
53     {
54         return kStatus_Fail;
55     }
56     if ((tmp[0] & ACTIVE_MASK) == ACTIVE_MASK)
57     {
58         return kStatus_Fail;
59     }
60 
61     /* Disable the FIFO */
62     if (FXOS_WriteReg(fxos_handle, F_SETUP_REG, F_MODE_DISABLED) != kStatus_Success)
63     {
64         return kStatus_Fail;
65     }
66 
67 #ifdef LPSLEEP_HIRES
68     /* enable auto-sleep, low power in sleep, high res in wake */
69     if (FXOS_WriteReg(fxos_handle, CTRL_REG2, SLPE_MASK | SMOD_LOW_POWER | MOD_HIGH_RES) != kStatus_Success)
70     {
71         return kStatus_Fail;
72     }
73 #else
74     /* enable auto-sleep, low power in sleep, high res in wake */
75     if (FXOS_WriteReg(fxos_handle, CTRL_REG2, MOD_HIGH_RES) != kStatus_Success)
76     {
77         return kStatus_Fail;
78     }
79 
80 #endif
81 
82     /* set up Mag OSR and Hybrid mode using M_CTRL_REG1, use default for Acc */
83     if (FXOS_WriteReg(fxos_handle, M_CTRL_REG1, (M_RST_MASK | M_OSR_MASK | M_HMS_MASK)) != kStatus_Success)
84     {
85         return kStatus_Fail;
86     }
87 
88     /* Enable hyrid mode auto increment using M_CTRL_REG2 */
89     if (FXOS_WriteReg(fxos_handle, M_CTRL_REG2, (M_HYB_AUTOINC_MASK)) != kStatus_Success)
90     {
91         return kStatus_Fail;
92     }
93 
94 #ifdef EN_FFMT
95     /* enable FFMT for motion detect for X and Y axes, latch enable */
96     if (FXOS_WriteReg(fxos_handle, FF_MT_CFG_REG, XEFE_MASK | YEFE_MASK | ELE_MASK | OAE_MASK) != kStatus_Success)
97     {
98         return kStatus_Fail;
99     }
100 #endif
101 
102 #ifdef SET_THRESHOLD
103     /* set threshold to about 0.25g */
104     if (FXOS_WriteReg(fxos_handle, FT_MT_THS_REG, 0x04) != kStatus_Success)
105     {
106         return kStatus_Fail;
107     }
108 #endif
109 
110 #ifdef SET_DEBOUNCE
111     /* set debounce to zero */
112     if (FXOS_WriteReg(fxos_handle, FF_MT_COUNT_REG, 0x00) != kStatus_Success)
113     {
114         return kStatus_Fail;
115     }
116 #endif
117 
118 #ifdef EN_AUTO_SLEEP
119     /* set auto-sleep wait period to 5s (=5/0.64=~8) */
120     if (FXOS_WriteReg(fxos_handle, ASLP_COUNT_REG, 8) != kStatus_Success)
121     {
122         return kStatus_Fail;
123     }
124 #endif
125     /* default set to 4g mode */
126     if (FXOS_WriteReg(fxos_handle, XYZ_DATA_CFG_REG, FULL_SCALE_4G) != kStatus_Success)
127     {
128         return kStatus_Fail;
129     }
130 #ifdef EN_INTERRUPTS
131     /* enable data-ready, auto-sleep and motion detection interrupts */
132     /* FXOS1_WriteRegister(CTRL_REG4, INT_EN_DRDY_MASK | INT_EN_ASLP_MASK | INT_EN_FF_MT_MASK); */
133     if (FXOS_WriteReg(fxos_handle, CTRL_REG4, 0x0) != kStatus_Success)
134     {
135         return kStatus_Fail;
136     }
137     /* route data-ready interrupts to INT1, others INT2 (default) */
138     if (FXOS_WriteReg(fxos_handle, CTRL_REG5, INT_CFG_DRDY_MASK) != kStatus_Success)
139     {
140         return kStatus_Fail;
141     }
142     /* enable ffmt as a wake-up source */
143     if (FXOS_WriteReg(fxos_handle, CTRL_REG3, WAKE_FF_MT_MASK) != kStatus_Success)
144     {
145         return kStatus_Fail;
146     }
147     /* finally activate accel_device with ASLP ODR=0.8Hz, ODR=100Hz, FSR=2g */
148     if (FXOS_WriteReg(fxos_handle, CTRL_REG1, HYB_ASLP_RATE_0_8HZ | HYB_DATA_RATE_100HZ | ACTIVE_MASK) !=
149         kStatus_Success)
150     {
151         return kStatus_Fail;
152     }
153 #else
154     /* Setup the ODR for 50 Hz and activate the accelerometer */
155     if (FXOS_WriteReg(fxos_handle, CTRL_REG1, (HYB_DATA_RATE_200HZ | ACTIVE_MASK)) != kStatus_Success)
156     {
157         return kStatus_Fail;
158     }
159 #endif
160 
161     /* Read Control register again to ensure we are in active mode */
162     if (FXOS_ReadReg(fxos_handle, CTRL_REG1, tmp, 1) != kStatus_Success)
163     {
164         return kStatus_Fail;
165     }
166 
167     if ((tmp[0] & ACTIVE_MASK) != ACTIVE_MASK)
168     {
169         return kStatus_Fail;
170     }
171 
172     return kStatus_Success;
173 }
174 
FXOS_ReadSensorData(fxos_handle_t * fxos_handle,fxos_data_t * sensorData)175 status_t FXOS_ReadSensorData(fxos_handle_t *fxos_handle, fxos_data_t *sensorData)
176 {
177     status_t status     = kStatus_Success;
178     uint8_t tmp_buff[6] = {0};
179     uint8_t i           = 0;
180 
181     if ((FXOS_ReadReg(fxos_handle, OUT_X_MSB_REG, tmp_buff, 6)) != kStatus_Success)
182     {
183         status = kStatus_Fail;
184     }
185 
186     for (i = 0U; i < 6U; i++)
187     {
188         ((uint8_t *)sensorData)[i] = tmp_buff[i];
189     }
190 
191     if ((FXOS_ReadReg(fxos_handle, M_OUT_X_MSB_REG, tmp_buff, 6)) != kStatus_Success)
192     {
193         status = kStatus_Fail;
194     }
195 
196     for (i = 0U; i < 6U; i++)
197     {
198         ((uint8_t *)sensorData)[i + 6U] = tmp_buff[i];
199     }
200 
201     return status;
202 }
203 
FXOS_ReadReg(fxos_handle_t * handle,uint8_t reg,uint8_t * val,uint8_t bytesNumber)204 status_t FXOS_ReadReg(fxos_handle_t *handle, uint8_t reg, uint8_t *val, uint8_t bytesNumber)
205 {
206     assert(handle);
207     assert(val);
208 
209     if ((handle->I2C_ReceiveFunc) == NULL)
210     {
211         return kStatus_Fail;
212     }
213 
214     return handle->I2C_ReceiveFunc(handle->slaveAddress, reg, 1, val, bytesNumber);
215 }
216 
FXOS_WriteReg(fxos_handle_t * handle,uint8_t reg,uint8_t val)217 status_t FXOS_WriteReg(fxos_handle_t *handle, uint8_t reg, uint8_t val)
218 {
219     assert(handle);
220 
221     if ((handle->I2C_SendFunc) == NULL)
222     {
223         return kStatus_Fail;
224     }
225 
226     return handle->I2C_SendFunc(handle->slaveAddress, reg, 1, val);
227 }
228