1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 /**
10 * @file fxls8962_drv.c
11 * @brief The fxls8962_drv.c file implements the FXLS8962 sensor driver interfaces.
12 */
13
14 //-----------------------------------------------------------------------
15 // ISSDK Includes
16 //-----------------------------------------------------------------------
17 #include "gpio_driver.h"
18 #include "fxls8962_drv.h"
19 #include "systick_utils.h"
20
21 //-----------------------------------------------------------------------
22 // Global Variables
23 //-----------------------------------------------------------------------
24 uint8_t fxls8962_spiRead_CmdBuffer[FXLS8962_SPI_MAX_MSG_SIZE] = {0};
25 uint8_t fxls8962_spiRead_DataBuffer[FXLS8962_SPI_MAX_MSG_SIZE] = {0};
26 uint8_t fxls8962_spiWrite_CmdDataBuffer[FXLS8962_SPI_MAX_MSG_SIZE] = {0};
27
28 //-----------------------------------------------------------------------
29 // Functions
30 //-----------------------------------------------------------------------
FXLS8962_SPI_ReadPreprocess(void * pCmdOut,uint32_t offset,uint32_t size)31 void FXLS8962_SPI_ReadPreprocess(void *pCmdOut, uint32_t offset, uint32_t size)
32 {
33 spiCmdParams_t *pSlaveCmd = pCmdOut;
34
35 uint8_t *pWBuff = fxls8962_spiRead_CmdBuffer;
36 uint8_t *pRBuff = fxls8962_spiRead_DataBuffer;
37
38 /* Formatting for Read command of FXLS8962 SENSOR. */
39 *(pWBuff) = offset | 0x80; /* offset is the internal register address of the sensor at which write is performed. */
40 *(pWBuff + 1) = 0x00;
41
42 /* Create the slave read command. */
43 pSlaveCmd->size = size + FXLS8962_SPI_CMD_LEN;
44 pSlaveCmd->pWriteBuffer = pWBuff;
45 pSlaveCmd->pReadBuffer = pRBuff;
46 }
47
FXLS8962_SPI_WritePreprocess(void * pCmdOut,uint32_t offset,uint32_t size,void * pWritebuffer)48 void FXLS8962_SPI_WritePreprocess(void *pCmdOut, uint32_t offset, uint32_t size, void *pWritebuffer)
49 {
50 spiCmdParams_t *pSlaveCmd = pCmdOut;
51
52 uint8_t *pWBuff = fxls8962_spiWrite_CmdDataBuffer;
53 uint8_t *pRBuff = fxls8962_spiWrite_CmdDataBuffer + size + FXLS8962_SPI_CMD_LEN;
54
55 /* Formatting for Write command of FXLS8962 SENSOR. */
56 *(pWBuff) = offset & 0x7F; /* offset is the internal register address of the sensor at which write is performed. */
57 *(pWBuff + 1) = 0x00;
58
59 /* Copy the slave write command */
60 memcpy(pWBuff + FXLS8962_SPI_CMD_LEN, pWritebuffer, size);
61
62 /* Create the slave command. */
63 pSlaveCmd->size = size + FXLS8962_SPI_CMD_LEN;
64 pSlaveCmd->pWriteBuffer = pWBuff;
65 pSlaveCmd->pReadBuffer = pRBuff;
66 }
67
FXLS8962_SPI_Initialize(fxls8962_spi_sensorhandle_t * pSensorHandle,ARM_DRIVER_SPI * pBus,uint8_t index,void * pSlaveSelect,uint8_t * whoami)68 int32_t FXLS8962_SPI_Initialize(
69 fxls8962_spi_sensorhandle_t *pSensorHandle, ARM_DRIVER_SPI *pBus, uint8_t index, void *pSlaveSelect, uint8_t *whoami)
70 {
71 int32_t status;
72 uint8_t reg;
73 GENERIC_DRIVER_GPIO *pGPIODriver = &Driver_GPIO_KSDK;
74
75 /*! Check the input parameters. */
76 if ((pSensorHandle == NULL) || (pBus == NULL) || (pSlaveSelect == NULL))
77 {
78 return SENSOR_ERROR_INVALID_PARAM;
79 }
80
81 /*! Initialize the sensor handle. */
82 pSensorHandle->pCommDrv = pBus;
83 pSensorHandle->slaveParams.pReadPreprocessFN = FXLS8962_SPI_ReadPreprocess;
84 pSensorHandle->slaveParams.pWritePreprocessFN = FXLS8962_SPI_WritePreprocess;
85 pSensorHandle->slaveParams.pTargetSlavePinID = pSlaveSelect;
86 pSensorHandle->slaveParams.spiCmdLen = FXLS8962_SPI_CMD_LEN;
87 pSensorHandle->slaveParams.ssActiveValue = FXLS8962_SS_ACTIVE_VALUE;
88
89 pSensorHandle->deviceInfo.deviceInstance = index;
90 pSensorHandle->deviceInfo.functionParam = NULL;
91 pSensorHandle->deviceInfo.idleFunction = NULL;
92
93 /* Initialize the Slave Select Pin. */
94 pGPIODriver->pin_init(pSlaveSelect, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
95 if (pSensorHandle->slaveParams.ssActiveValue == SPI_SS_ACTIVE_LOW)
96 {
97 pGPIODriver->set_pin(pSlaveSelect);
98 }
99 else
100 {
101 pGPIODriver->clr_pin(pSlaveSelect);
102 }
103
104 /*! Read and store the device's WHO_AM_I.*/
105 status = Register_SPI_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
106 FXLS8962_WHO_AM_I, 1, ®);
107 //if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
108 (*whoami) = reg;
109 if (ARM_DRIVER_OK != status)
110 {
111 if ((FXLS8962_WHOAMI_VALUE != reg) || (FXLS8964_WHOAMI_VALUE != reg) || (FXLS8967_WHOAMI_VALUE != reg) || (FXLS8974_WHOAMI_VALUE != reg))
112 {
113 pSensorHandle->isInitialized = false;
114 return SENSOR_ERROR_BAD_ADDRESS;
115 }
116 pSensorHandle->isInitialized = false;
117 return SENSOR_ERROR_INIT;
118 }
119 pSensorHandle->isInitialized = true;
120 return SENSOR_ERROR_NONE;
121 }
122
FXLS8962_SPI_SetIdleTask(fxls8962_spi_sensorhandle_t * pSensorHandle,registeridlefunction_t idleTask,void * userParam)123 void FXLS8962_SPI_SetIdleTask(fxls8962_spi_sensorhandle_t *pSensorHandle,
124 registeridlefunction_t idleTask,
125 void *userParam)
126 {
127 pSensorHandle->deviceInfo.functionParam = userParam;
128 pSensorHandle->deviceInfo.idleFunction = idleTask;
129 }
130
FXLS8962_SPI_Configure(fxls8962_spi_sensorhandle_t * pSensorHandle,const registerwritelist_t * pRegWriteList)131 int32_t FXLS8962_SPI_Configure(fxls8962_spi_sensorhandle_t *pSensorHandle, const registerwritelist_t *pRegWriteList)
132 {
133 int32_t status;
134
135 /*! Validate for the correct handle and register write list.*/
136 if ((pSensorHandle == NULL) || (pRegWriteList == NULL))
137 {
138 return SENSOR_ERROR_INVALID_PARAM;
139 }
140
141 /*! Check whether sensor handle is initialized before applying configuration.*/
142 if (pSensorHandle->isInitialized != true)
143 {
144 return SENSOR_ERROR_INIT;
145 }
146
147 /*! Put the device into standby mode so that configuration can be applied.*/
148 status = Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
149 FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ACTIVE_STANDBY,
150 FXLS8962_SENS_CONFIG1_ACTIVE_MASK);
151 if (ARM_DRIVER_OK != status)
152 {
153 return SENSOR_ERROR_WRITE;
154 }
155
156 /*! Apply the Sensor Configuration based on the Register Write List */
157 status = Sensor_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
158 pRegWriteList);
159 if (ARM_DRIVER_OK != status)
160 {
161 return SENSOR_ERROR_WRITE;
162 }
163
164 /*! Put the device into active mode and ready for reading data.*/
165 status = Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
166 FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ACTIVE_ACTIVE,
167 FXLS8962_SENS_CONFIG1_ACTIVE_MASK);
168 if (ARM_DRIVER_OK != status)
169 {
170 return SENSOR_ERROR_WRITE;
171 }
172
173 return SENSOR_ERROR_NONE;
174 }
175
FXLS8962_SPI_ReadData(fxls8962_spi_sensorhandle_t * pSensorHandle,const registerreadlist_t * pReadList,uint8_t * pBuffer)176 int32_t FXLS8962_SPI_ReadData(fxls8962_spi_sensorhandle_t *pSensorHandle,
177 const registerreadlist_t *pReadList,
178 uint8_t *pBuffer)
179 {
180 int32_t status;
181
182 /*! Validate for the correct handle and register read list.*/
183 if ((pSensorHandle == NULL) || (pReadList == NULL) || (pBuffer == NULL))
184 {
185 return SENSOR_ERROR_INVALID_PARAM;
186 }
187
188 /*! Check whether sensor handle is initialized before reading sensor data.*/
189 if (pSensorHandle->isInitialized != true)
190 {
191 return SENSOR_ERROR_INIT;
192 }
193
194 /*! Parse through the read list and read the data one by one. */
195 status = Sensor_SPI_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
196 pReadList, pBuffer);
197 if (ARM_DRIVER_OK != status)
198 {
199 return SENSOR_ERROR_READ;
200 }
201
202 return SENSOR_ERROR_NONE;
203 }
204
FXLS8962_SPI_Deinit(fxls8962_spi_sensorhandle_t * pSensorHandle)205 int32_t FXLS8962_SPI_Deinit(fxls8962_spi_sensorhandle_t *pSensorHandle)
206 {
207 int32_t status;
208
209 if (pSensorHandle == NULL)
210 {
211 return SENSOR_ERROR_INVALID_PARAM;
212 }
213
214 /*! Check whether sensor handle is initialized before triggering sensor reset.*/
215 if (pSensorHandle->isInitialized != true)
216 {
217 return SENSOR_ERROR_INIT;
218 }
219
220 /*! Trigger sensor device reset.*/
221 status = Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
222 FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_RST_RST, FXLS8962_SENS_CONFIG1_RST_MASK);
223 if (ARM_DRIVER_OK != status)
224 {
225 return SENSOR_ERROR_WRITE;
226 }
227 else
228 {
229 /*! De-initialize sensor handle. */
230 pSensorHandle->isInitialized = false;
231 }
232
233 /* Wait for MAX of TBOOT ms after soft reset command,
234 * to allow enough time for FXLS8962AF to complete its internal boot sequence and be ready for communication. */
235 BOARD_DELAY_ms(FXLS8962_TBOOT_MAX);
236
237 return SENSOR_ERROR_NONE;
238 }
239
FXLS8962_I2C_Initialize(fxls8962_i2c_sensorhandle_t * pSensorHandle,ARM_DRIVER_I2C * pBus,uint8_t index,uint16_t sAddress,uint8_t * whoami)240 int32_t FXLS8962_I2C_Initialize(
241 fxls8962_i2c_sensorhandle_t *pSensorHandle, ARM_DRIVER_I2C *pBus, uint8_t index, uint16_t sAddress, uint8_t *whoami)
242 {
243 int32_t status;
244 uint8_t reg;
245
246 /*! Check the input parameters. */
247 if ((pSensorHandle == NULL) || (pBus == NULL))
248 {
249 return SENSOR_ERROR_INVALID_PARAM;
250 }
251
252 pSensorHandle->deviceInfo.deviceInstance = index;
253 pSensorHandle->deviceInfo.functionParam = NULL;
254 pSensorHandle->deviceInfo.idleFunction = NULL;
255
256 /*! Read and store the device's WHO_AM_I.*/
257 status = Register_I2C_Read(pBus, &pSensorHandle->deviceInfo, sAddress, FXLS8962_WHO_AM_I, 1, ®);
258 //if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
259 (*whoami) = reg;
260 if (ARM_DRIVER_OK != status)
261 {
262 if ((FXLS8962_WHOAMI_VALUE != reg) || (FXLS8964_WHOAMI_VALUE != reg) || (FXLS8967_WHOAMI_VALUE != reg) || (FXLS8974_WHOAMI_VALUE != reg))
263 {
264 pSensorHandle->isInitialized = false;
265 return SENSOR_ERROR_BAD_ADDRESS;
266 }
267 pSensorHandle->isInitialized = false;
268 return SENSOR_ERROR_INIT;
269 }
270
271 /*! Initialize the sensor handle. */
272 pSensorHandle->pCommDrv = pBus;
273 pSensorHandle->slaveAddress = sAddress;
274 pSensorHandle->isInitialized = true;
275 return SENSOR_ERROR_NONE;
276 }
277
FXLS8962_I2C_SetIdleTask(fxls8962_i2c_sensorhandle_t * pSensorHandle,registeridlefunction_t idleTask,void * userParam)278 void FXLS8962_I2C_SetIdleTask(fxls8962_i2c_sensorhandle_t *pSensorHandle,
279 registeridlefunction_t idleTask,
280 void *userParam)
281 {
282 pSensorHandle->deviceInfo.functionParam = userParam;
283 pSensorHandle->deviceInfo.idleFunction = idleTask;
284 }
285
FXLS8962_I2C_Configure(fxls8962_i2c_sensorhandle_t * pSensorHandle,const registerwritelist_t * pRegWriteList)286 int32_t FXLS8962_I2C_Configure(fxls8962_i2c_sensorhandle_t *pSensorHandle, const registerwritelist_t *pRegWriteList)
287 {
288 int32_t status;
289
290 /*! Validate for the correct handle and register write list.*/
291 if ((pSensorHandle == NULL) || (pRegWriteList == NULL))
292 {
293 return SENSOR_ERROR_INVALID_PARAM;
294 }
295
296 /*! Check whether sensor handle is initialized before applying configuration.*/
297 if (pSensorHandle->isInitialized != true)
298 {
299 return SENSOR_ERROR_INIT;
300 }
301
302 /*! Put the device into standby mode so that configuration can be applied.*/
303 status = Register_I2C_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
304 FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ACTIVE_STANDBY,
305 FXLS8962_SENS_CONFIG1_ACTIVE_MASK, false);
306 if (ARM_DRIVER_OK != status)
307 {
308 return SENSOR_ERROR_WRITE;
309 }
310
311 /*! Apply the Sensor Configuration based on the Register Write List */
312 status = Sensor_I2C_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
313 pRegWriteList);
314 if (ARM_DRIVER_OK != status)
315 {
316 return SENSOR_ERROR_WRITE;
317 }
318
319 /*! Put the device into active mode and ready for reading data.*/
320 status = Register_I2C_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
321 FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ACTIVE_ACTIVE,
322 FXLS8962_SENS_CONFIG1_ACTIVE_MASK, false);
323 if (ARM_DRIVER_OK != status)
324 {
325 return SENSOR_ERROR_WRITE;
326 }
327
328 return SENSOR_ERROR_NONE;
329 }
330
FXLS8962_I2C_ReadData(fxls8962_i2c_sensorhandle_t * pSensorHandle,const registerreadlist_t * pReadList,uint8_t * pBuffer)331 int32_t FXLS8962_I2C_ReadData(fxls8962_i2c_sensorhandle_t *pSensorHandle,
332 const registerreadlist_t *pReadList,
333 uint8_t *pBuffer)
334 {
335 int32_t status;
336
337 /*! Validate for the correct handle and register read list.*/
338 if ((pSensorHandle == NULL) || (pReadList == NULL) || (pBuffer == NULL))
339 {
340 return SENSOR_ERROR_INVALID_PARAM;
341 }
342
343 /*! Check whether sensor handle is initialized before reading sensor data.*/
344 if (pSensorHandle->isInitialized != true)
345 {
346 return SENSOR_ERROR_INIT;
347 }
348
349 /*! Parse through the read list and read the data one by one. */
350 status = Sensor_I2C_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
351 pReadList, pBuffer);
352 if (ARM_DRIVER_OK != status)
353 {
354 return SENSOR_ERROR_READ;
355 }
356
357 return SENSOR_ERROR_NONE;
358 }
359
FXLS8962_I2C_DeInit(fxls8962_i2c_sensorhandle_t * pSensorHandle)360 int32_t FXLS8962_I2C_DeInit(fxls8962_i2c_sensorhandle_t *pSensorHandle)
361 {
362 int32_t status;
363
364 if (pSensorHandle == NULL)
365 {
366 return SENSOR_ERROR_INVALID_PARAM;
367 }
368
369 /*! Check whether sensor handle is initialized before triggering sensor reset.*/
370 if (pSensorHandle->isInitialized != true)
371 {
372 return SENSOR_ERROR_INIT;
373 }
374
375 /*! Trigger sensor device reset.*/
376 status =
377 Register_I2C_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
378 FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_RST_RST, FXLS8962_SENS_CONFIG1_RST_MASK, false);
379 if (ARM_DRIVER_OK != status)
380 {
381 return SENSOR_ERROR_WRITE;
382 }
383 else
384 {
385 /*! De-initialize sensor handle. */
386 pSensorHandle->isInitialized = false;
387 }
388
389 /* Wait for MAX of TBOOT ms after soft reset command,
390 * to allow enough time for FXLS8962AF to complete its internal boot sequence and be ready for communication. */
391 BOARD_DELAY_ms(FXLS8962_TBOOT_MAX);
392
393 return SENSOR_ERROR_NONE;
394 }
395