1 /*
2 * Copyright (c) 2015 - 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 fxls8471q_drv.c
11 * @brief The fxls8471q_drv.c file implements the FXLS8471Q sensor driver interfaces.
12 */
13
14 //-----------------------------------------------------------------------
15 // ISSDK Includes
16 //-----------------------------------------------------------------------
17 #include "gpio_driver.h"
18 #include "fxls8471q_drv.h"
19
20 //-----------------------------------------------------------------------
21 // Global Variables
22 //-----------------------------------------------------------------------
23 uint8_t fxls8471q_spiRead_CmdBuffer[FXLS8471Q_SPI_MAX_MSG_SIZE] = {0};
24 uint8_t fxls8471q_spiRead_DataBuffer[FXLS8471Q_SPI_MAX_MSG_SIZE] = {0};
25 uint8_t fxls8471q_spiWrite_CmdDataBuffer[FXLS8471Q_SPI_MAX_MSG_SIZE] = {0};
26
27 //-----------------------------------------------------------------------
28 // Functions
29 //-----------------------------------------------------------------------
FXLS8471Q_SPI_ReadPreprocess(void * pCmdOut,uint32_t offset,uint32_t size)30 void FXLS8471Q_SPI_ReadPreprocess(void *pCmdOut, uint32_t offset, uint32_t size)
31 {
32 spiCmdParams_t *pSlaveCmd = pCmdOut;
33
34 uint8_t *pWBuff = fxls8471q_spiRead_CmdBuffer;
35 uint8_t *pRBuff = fxls8471q_spiRead_DataBuffer;
36
37 /* Formatting for Read command of FXLS8471Q SENSOR. */
38 *(pWBuff) = offset & 0x7F; /* offset is the internal register address of the sensor at which write is performed. */
39 *(pWBuff + 1) = offset & 0x80;
40
41 // Create the slave read command.
42 pSlaveCmd->size = size + FXLS8471Q_SPI_CMD_LEN;
43 pSlaveCmd->pWriteBuffer = pWBuff;
44 pSlaveCmd->pReadBuffer = pRBuff;
45 }
46
FXLS8471Q_SPI_WritePreprocess(void * pCmdOut,uint32_t offset,uint32_t size,void * pWritebuffer)47 void FXLS8471Q_SPI_WritePreprocess(void *pCmdOut, uint32_t offset, uint32_t size, void *pWritebuffer)
48 {
49 spiCmdParams_t *pSlaveCmd = pCmdOut;
50
51 uint8_t *pWBuff = fxls8471q_spiWrite_CmdDataBuffer;
52 uint8_t *pRBuff = fxls8471q_spiWrite_CmdDataBuffer + size + FXLS8471Q_SPI_CMD_LEN;
53
54 /* Formatting for Write command of FXLS8471Q SENSOR. */
55 *(pWBuff) = offset | 0x80; /* offset is the internal register address of the sensor at which write is performed. */
56 *(pWBuff + 1) = offset & 0x80;
57
58 /* Copy the slave write command */
59 memcpy(pWBuff + FXLS8471Q_SPI_CMD_LEN, pWritebuffer, size);
60
61 /* Create the slave command. */
62 pSlaveCmd->size = size + FXLS8471Q_SPI_CMD_LEN;
63 pSlaveCmd->pWriteBuffer = pWBuff;
64 pSlaveCmd->pReadBuffer = pRBuff;
65 }
66
FXLS8471Q_SPI_Initialize(fxls8471q_spi_sensorhandle_t * pSensorHandle,ARM_DRIVER_SPI * pBus,uint8_t index,void * pSlaveSelect,uint8_t whoAmi)67 int32_t FXLS8471Q_SPI_Initialize(fxls8471q_spi_sensorhandle_t *pSensorHandle,
68 ARM_DRIVER_SPI *pBus,
69 uint8_t index,
70 void *pSlaveSelect,
71 uint8_t whoAmi)
72 {
73 int32_t status;
74 uint8_t reg;
75 GENERIC_DRIVER_GPIO *pGPIODriver = &Driver_GPIO_KSDK;
76
77 /*! Check the input parameters. */
78 if ((pSensorHandle == NULL) || (pBus == NULL) || (pSlaveSelect == NULL))
79 {
80 return SENSOR_ERROR_INVALID_PARAM;
81 }
82
83 /*! Initialize the sensor handle. */
84 pSensorHandle->pCommDrv = pBus;
85 pSensorHandle->slaveParams.pReadPreprocessFN = FXLS8471Q_SPI_ReadPreprocess;
86 pSensorHandle->slaveParams.pWritePreprocessFN = FXLS8471Q_SPI_WritePreprocess;
87 pSensorHandle->slaveParams.pTargetSlavePinID = pSlaveSelect;
88 pSensorHandle->slaveParams.spiCmdLen = FXLS8471Q_SPI_CMD_LEN;
89 pSensorHandle->slaveParams.ssActiveValue = FXLS8471Q_SS_ACTIVE_VALUE;
90
91 pSensorHandle->deviceInfo.deviceInstance = index;
92 pSensorHandle->deviceInfo.functionParam = NULL;
93 pSensorHandle->deviceInfo.idleFunction = NULL;
94
95 /* Initialize the Slave Select Pin. */
96 pGPIODriver->pin_init(pSlaveSelect, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
97 if (pSensorHandle->slaveParams.ssActiveValue == SPI_SS_ACTIVE_LOW)
98 {
99 pGPIODriver->set_pin(pSlaveSelect);
100 }
101 else
102 {
103 pGPIODriver->clr_pin(pSlaveSelect);
104 }
105
106 /*! Read and store the device's WHO_AM_I.*/
107 status = Register_SPI_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
108 FXLS8471Q_WHO_AM_I, 1, ®);
109 if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
110 {
111 pSensorHandle->isInitialized = false;
112 return SENSOR_ERROR_INIT;
113 }
114
115 pSensorHandle->isInitialized = true;
116 return SENSOR_ERROR_NONE;
117 }
118
FXLS8471Q_SPI_SetIdleTask(fxls8471q_spi_sensorhandle_t * pSensorHandle,registeridlefunction_t idleTask,void * userParam)119 void FXLS8471Q_SPI_SetIdleTask(fxls8471q_spi_sensorhandle_t *pSensorHandle,
120 registeridlefunction_t idleTask,
121 void *userParam)
122 {
123 pSensorHandle->deviceInfo.functionParam = userParam;
124 pSensorHandle->deviceInfo.idleFunction = idleTask;
125 }
126
FXLS8471Q_SPI_Configure(fxls8471q_spi_sensorhandle_t * pSensorHandle,const registerwritelist_t * pRegWriteList)127 int32_t FXLS8471Q_SPI_Configure(fxls8471q_spi_sensorhandle_t *pSensorHandle, const registerwritelist_t *pRegWriteList)
128 {
129 int32_t status;
130
131 /*! Validate for the correct handle and register write list.*/
132 if ((pSensorHandle == NULL) || (pRegWriteList == NULL))
133 {
134 return SENSOR_ERROR_INVALID_PARAM;
135 }
136
137 /*! Check whether sensor handle is initialized before applying configuration.*/
138 if (pSensorHandle->isInitialized != true)
139 {
140 return SENSOR_ERROR_INIT;
141 }
142
143 /*! Put the device into standby mode so that configuration can be applied.*/
144 status = Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
145 FXLS8471Q_CTRL_REG1, FXLS8471Q_CTRL_REG1_MODE_STANDBY, FXLS8471Q_CTRL_REG1_MODE_MASK);
146 if (ARM_DRIVER_OK != status)
147 {
148 return SENSOR_ERROR_WRITE;
149 }
150
151 /*! Apply the Sensor Configuration based on the Register Write List */
152 status = Sensor_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
153 pRegWriteList);
154 if (ARM_DRIVER_OK != status)
155 {
156 return SENSOR_ERROR_WRITE;
157 }
158
159 /*! Put the device into active mode and ready for reading data.*/
160 status = Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
161 FXLS8471Q_CTRL_REG1, FXLS8471Q_CTRL_REG1_MODE_ACTIVE, FXLS8471Q_CTRL_REG1_MODE_MASK);
162 if (ARM_DRIVER_OK != status)
163 {
164 return SENSOR_ERROR_WRITE;
165 }
166
167 return SENSOR_ERROR_NONE;
168 }
169
FXLS8471Q_SPI_ReadData(fxls8471q_spi_sensorhandle_t * pSensorHandle,const registerreadlist_t * pReadList,uint8_t * pBuffer)170 int32_t FXLS8471Q_SPI_ReadData(fxls8471q_spi_sensorhandle_t *pSensorHandle,
171 const registerreadlist_t *pReadList,
172 uint8_t *pBuffer)
173 {
174 int32_t status;
175
176 /*! Validate for the correct handle and register read list.*/
177 if ((pSensorHandle == NULL) || (pReadList == NULL) || (pBuffer == NULL))
178 {
179 return SENSOR_ERROR_INVALID_PARAM;
180 }
181
182 /*! Check whether sensor handle is initialized before reading sensor data.*/
183 if (pSensorHandle->isInitialized != true)
184 {
185 return SENSOR_ERROR_INIT;
186 }
187
188 /*! Parse through the read list and read the data one by one. */
189 status = Sensor_SPI_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
190 pReadList, pBuffer);
191 if (ARM_DRIVER_OK != status)
192 {
193 return SENSOR_ERROR_READ;
194 }
195
196 return SENSOR_ERROR_NONE;
197 }
198
FXLS8471Q_SPI_Deinit(fxls8471q_spi_sensorhandle_t * pSensorHandle)199 int32_t FXLS8471Q_SPI_Deinit(fxls8471q_spi_sensorhandle_t *pSensorHandle)
200 {
201 if (pSensorHandle == NULL)
202 {
203 return SENSOR_ERROR_INVALID_PARAM;
204 }
205
206 /*! Check whether sensor handle is initialized before triggering sensor reset.*/
207 if (pSensorHandle->isInitialized != true)
208 {
209 return SENSOR_ERROR_INIT;
210 }
211
212 /* Note:
213 * There is a Errata described in the data sheet for soft reset with SPI,
214 * which says device specific paratameters do not get updated correctly from NVM,
215 * causing inaccurate data output once the soft-reset command issued in SPI mode.
216 * The work around is hard reset, which cannot be handled in sensor driver software.
217 * So software reset command wont be issued until this issue is fixed in the silicon.
218 */
219
220 /*! De-initialize sensor handle. */
221 pSensorHandle->isInitialized = false;
222
223 return SENSOR_ERROR_NONE;
224 }
225