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