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 sensor_io_i2c.c
11  * @brief The sensor_io_i2c.c file contains definitions for low-level interface functions
12  *  for reading and writing data from/to sensor.
13  */
14 
15 #include "Driver_I2C.h"
16 #include "sensor_drv.h"
17 #include "systick_utils.h"
18 #include "sensor_io_i2c.h"
19 
20 /*******************************************************************************
21  * Code
22  ******************************************************************************/
23 /*! The interface function to block write commands to a sensor. */
Sensor_I2C_BlockWrite(ARM_DRIVER_I2C * pCommDrv,registerDeviceInfo_t * devInfo,uint16_t slaveAddress,const registercommandlist_t * pCommandList,uint8_t error_mask)24 int32_t Sensor_I2C_BlockWrite(ARM_DRIVER_I2C *pCommDrv,
25                               registerDeviceInfo_t *devInfo,
26                               uint16_t slaveAddress,
27                               const registercommandlist_t *pCommandList,
28                               uint8_t error_mask)
29 {
30     int32_t status;
31     bool commandComplete;
32     uint8_t cocoBuffer[2] = {0};
33 
34     /*! Validate for the correct handle.*/
35     if ((pCommDrv == NULL) || (pCommandList == NULL))
36     {
37         return SENSOR_ERROR_BAD_ADDRESS;
38     }
39 
40     const registercommandlist_t *pCmd = pCommandList;
41     /*! Update register values based on register write list unless the next Cmd is the list terminator */
42     do
43     { /*! Write the command based on the values in the command and value pair.*/
44         status =
45             Register_I2C_BlockWrite(pCommDrv, devInfo, slaveAddress, pCmd->writeTo, pCmd->pWriteBuffer, pCmd->numBytes);
46         if (ARM_DRIVER_OK != status)
47         {
48             return SENSOR_ERROR_WRITE;
49         }
50 
51         do
52         { /*! Wait for Command Completion. */
53             BOARD_DELAY_ms(1);
54             status = Register_I2C_Read(pCommDrv, devInfo, slaveAddress, 0, sizeof(cocoBuffer), cocoBuffer);
55             if (ARM_DRIVER_OK != status)
56             {
57                 return SENSOR_ERROR_READ;
58             }
59             commandComplete = cocoBuffer[1] & 0x80;
60             if (commandComplete && cocoBuffer[1] & error_mask)
61             {
62                 return SENSOR_ERROR_WRITE;
63             }
64         } while (!commandComplete);
65     } while ((++pCmd)->writeTo != 0xFFFF);
66 
67     return SENSOR_ERROR_NONE;
68 }
69 
70 /*! The interface function to write register data to a sensor. */
Sensor_I2C_Write(ARM_DRIVER_I2C * pCommDrv,registerDeviceInfo_t * devInfo,uint16_t slaveAddress,const registerwritelist_t * pRegWriteList)71 int32_t Sensor_I2C_Write(ARM_DRIVER_I2C *pCommDrv,
72                          registerDeviceInfo_t *devInfo,
73                          uint16_t slaveAddress,
74                          const registerwritelist_t *pRegWriteList)
75 {
76     int32_t status;
77     bool repeatedStart;
78 
79     /*! Validate for the correct handle.*/
80     if ((pCommDrv == NULL) || (pRegWriteList == NULL))
81     {
82         return SENSOR_ERROR_BAD_ADDRESS;
83     }
84 
85     const registerwritelist_t *pCmd = pRegWriteList;
86 
87     /*! Update register values based on register write list unless the next Cmd is the list terminator */
88     do
89     {
90         repeatedStart = (pCmd + 1)->writeTo != 0xFFFF;
91         /*! Set the register based on the values in the register value pair.*/
92         status =
93             Register_I2C_Write(pCommDrv, devInfo, slaveAddress, pCmd->writeTo, pCmd->value, pCmd->mask, repeatedStart);
94         if (ARM_DRIVER_OK != status)
95         {
96             return SENSOR_ERROR_WRITE;
97         }
98         ++pCmd;
99     } while (repeatedStart);
100 
101     return SENSOR_ERROR_NONE;
102 }
103 
104 /*! The interface function to read register data from a sensor. */
Sensor_I2C_Read(ARM_DRIVER_I2C * pCommDrv,registerDeviceInfo_t * devInfo,uint16_t slaveAddress,const registerreadlist_t * pReadList,uint8_t * pOutBuffer)105 int32_t Sensor_I2C_Read(ARM_DRIVER_I2C *pCommDrv,
106                         registerDeviceInfo_t *devInfo,
107                         uint16_t slaveAddress,
108                         const registerreadlist_t *pReadList,
109                         uint8_t *pOutBuffer)
110 {
111     int32_t status;
112     uint8_t *pBuf;
113 
114     /*! Validate for the correct handle.*/
115     if (pCommDrv == NULL || pReadList == NULL || pOutBuffer == NULL)
116     {
117         return SENSOR_ERROR_BAD_ADDRESS;
118     }
119     const registerreadlist_t *pCmd = pReadList;
120 
121     /*! Traverse the read list and read the registers one by one unless the register read list numBytes is zero*/
122     for (pBuf = pOutBuffer; pCmd->numBytes != 0; pCmd++)
123     {
124         status = Register_I2C_Read(pCommDrv, devInfo, slaveAddress, pCmd->readFrom, pCmd->numBytes, pBuf);
125         if (ARM_DRIVER_OK != status)
126         {
127             return SENSOR_ERROR_READ;
128         }
129         pBuf += pCmd->numBytes;
130     }
131     return SENSOR_ERROR_NONE;
132 }
133