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, ®);
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, ®);
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