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