1 /*
2  * Copyright 2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_pca6416a.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 typedef enum _pca6416a_reg_ops
15 {
16     kPCA6416A_SetRegBits = 0,
17     kPCA6416A_ClearRegBits,
18     kPCA6416A_ToggleRegBits,
19 } pca6416a_reg_ops_t;
20 
21 /*******************************************************************************
22  * Code
23  ******************************************************************************/
24 /*! @brief Read port registers value. */
PCA6416A_ReadPort(pca6416a_handle_t * handle,uint8_t startReg,uint16_t * value)25 static status_t PCA6416A_ReadPort(pca6416a_handle_t *handle, uint8_t startReg, uint16_t *value)
26 {
27     return handle->I2C_ReceiveFunc(handle->i2cAddr, startReg, 1U, (uint8_t *)value, 2U, 0U);
28 }
29 
30 /*! @brief Write port registers value. */
PCA6416A_WritePort(pca6416a_handle_t * handle,uint8_t startReg,uint16_t value)31 static status_t PCA6416A_WritePort(pca6416a_handle_t *handle, uint8_t startReg, uint16_t value)
32 {
33     return handle->I2C_SendFunc(handle->i2cAddr, startReg, 1U, (uint8_t *)&value, 2U, 0U);
34 }
35 
36 /*! @brief Modify PCA6416A port register bits. */
PCA6416A_ModifyPortRegBits(pca6416a_handle_t * handle,uint8_t startReg,uint16_t bits,pca6416a_reg_ops_t ops)37 static status_t PCA6416A_ModifyPortRegBits(pca6416a_handle_t *handle,
38                                            uint8_t startReg,
39                                            uint16_t bits,
40                                            pca6416a_reg_ops_t ops)
41 {
42     uint16_t regValue;
43     status_t status;
44 
45     status = PCA6416A_ReadPort(handle, startReg, &regValue);
46 
47     if (kStatus_Success == status)
48     {
49         if (kPCA6416A_SetRegBits == ops)
50         {
51             regValue |= bits;
52         }
53         else if (kPCA6416A_ClearRegBits == ops)
54         {
55             regValue &= ~bits;
56         }
57         else if (kPCA6416A_ToggleRegBits == ops)
58         {
59             regValue ^= bits;
60         }
61         else
62         {
63             /* Add for MISRA 15.7 */
64         }
65 
66         status = PCA6416A_WritePort(handle, startReg, regValue);
67     }
68 
69     return status;
70 }
71 
72 /*
73  * brief Initializes the PCA6416A driver handle.
74  *
75  * param handle Pointer to the PCA6416A handle.
76  * param config Pointer to the PCA6416A configuration structure.
77  */
PCA6416A_Init(pca6416a_handle_t * handle,const pca6416a_config_t * config)78 void PCA6416A_Init(pca6416a_handle_t *handle, const pca6416a_config_t *config)
79 {
80     assert(NULL != handle);
81     assert(NULL != config);
82 
83     handle->i2cAddr         = config->i2cAddr;
84     handle->I2C_SendFunc    = config->I2C_SendFunc;
85     handle->I2C_ReceiveFunc = config->I2C_ReceiveFunc;
86 }
87 
88 /*
89  * brief Set PCA6416A pins direction.
90  *
91  * This function sets multiple pins direction, the pins to modify are passed in
92  * as a bit OR'ed value.
93  *
94  * For example, the following code set pin2 and pin3 to output:
95  *
96  * code
97    PCA6416A_SetDirection(handle, (1<<2) | (1<<3), pkPCA6416A_Output);
98    endcode
99  *
100  * param handle Pointer to the PCA6416A handle.
101  * param pins The pins to change, for example: (1<<2) | (1<<3) means pin 2 and pin 3.
102  * param dir Pin direction.
103  * return Return ref kStatus_Success if successed, otherwise returns error code.
104  */
PCA6416A_SetDirection(pca6416a_handle_t * handle,uint16_t pins,pca6416a_dir_t dir)105 status_t PCA6416A_SetDirection(pca6416a_handle_t *handle, uint16_t pins, pca6416a_dir_t dir)
106 {
107     return PCA6416A_ModifyPortRegBits(handle, PCA6416A_CFG_PORT_0, pins,
108                                       (kPCA6416A_Input == dir) ? kPCA6416A_SetRegBits : kPCA6416A_ClearRegBits);
109 }
110 
111 /*
112  * brief Inverse PCA6416A pins polarity.
113  *
114  * This function changes multiple pins polarity, the pins to modify are passed in
115  * as a bit OR'ed value.
116  *
117  * For example, the following code set pin2 and pin3 to NOT inverse:
118  *
119  * code
120    PCA6416A_InversePolarity(handle, (1<<2) | (1<<3), false);
121    endcode
122  *
123  * param handle Pointer to the PCA6416A handle.
124  * param pins The pins to change, for example: (1<<2) | (1<<3) means pin 2 and pin 3.
125  * param inverse Use true to inverse, false to not inverse.
126  * return Return ref kStatus_Success if successed, otherwise returns error code.
127  */
PCA6416A_InversePolarity(pca6416a_handle_t * handle,uint16_t pins,bool inverse)128 status_t PCA6416A_InversePolarity(pca6416a_handle_t *handle, uint16_t pins, bool inverse)
129 {
130     return PCA6416A_ModifyPortRegBits(handle, PCA6416A_POL_INV_PORT_0, pins,
131                                       inverse ? kPCA6416A_SetRegBits : kPCA6416A_ClearRegBits);
132 }
133 
134 /*
135  * brief Read PCA6416A pins value.
136  *
137  * param handle Pointer to the PCA6416A handle.
138  * param pinsValue Variable to save the read out pin values.
139  * return Return ref kStatus_Success if successed, otherwise returns error code.
140  */
PCA6416A_ReadPins(pca6416a_handle_t * handle,uint16_t * pinsValue)141 status_t PCA6416A_ReadPins(pca6416a_handle_t *handle, uint16_t *pinsValue)
142 {
143     return PCA6416A_ReadPort(handle, PCA6416A_INPUT_PORT_0, pinsValue);
144 }
145 
146 /*
147  * brief Set PCA6416A pins output value to 1.
148  *
149  * This function changes multiple pins, the pins to modify are passed in as
150  * a bit OR'ed value.
151  *
152  * For example, the following code set pin2 and pin3 output value to 1.
153  *
154  * code
155    PCA6416A_SetPins(handle, (1<<2) | (1<<3));
156    endcode
157  *
158  * param handle Pointer to the PCA6416A handle.
159  * param pins The pins to change, for example: (1<<2) | (1<<3) means pin 2 and pin 3.
160  * return Return ref kStatus_Success if successed, otherwise returns error code.
161  */
PCA6416A_SetPins(pca6416a_handle_t * handle,uint16_t pins)162 status_t PCA6416A_SetPins(pca6416a_handle_t *handle, uint16_t pins)
163 {
164     return PCA6416A_ModifyPortRegBits(handle, PCA6416A_OUTPUT_PORT_0, pins, kPCA6416A_SetRegBits);
165 }
166 
167 /*
168  * brief Set PCA6416A pins output value to 0.
169  *
170  * This function changes multiple pins, the pins to modify are passed in as
171  * a bit OR'ed value.
172  *
173  * For example, the following code set pin2 and pin3 output value to 0.
174  *
175  * code
176    PCA6416A_ClearPins(handle, (1<<2) | (1<<3));
177    endcode
178  *
179  * param handle Pointer to the PCA6416A handle.
180  * param pins The pins to change, for example: (1<<2) | (1<<3) means pin 2 and pin 3.
181  * return Return ref kStatus_Success if successed, otherwise returns error code.
182  */
PCA6416A_ClearPins(pca6416a_handle_t * handle,uint16_t pins)183 status_t PCA6416A_ClearPins(pca6416a_handle_t *handle, uint16_t pins)
184 {
185     return PCA6416A_ModifyPortRegBits(handle, PCA6416A_OUTPUT_PORT_0, pins, kPCA6416A_ClearRegBits);
186 }
187 
188 /*
189  * brief Toggle PCA6416A pins output value.
190  *
191  * This function changes multiple pins, the pins to modify are passed in as
192  * a bit OR'ed value.
193  *
194  * For example, the following code toggle pin2 and pin3 output value.
195  *
196  * code
197    PCA6416A_ClearPins(handle, (1<<2) | (1<<3));
198    endcode
199  *
200  * param handle Pointer to the PCA6416A handle.
201  * param pins The pins to change, for example: (1<<2) | (1<<3) means pin 2 and pin 3.
202  * return Return ref kStatus_Success if successed, otherwise returns error code.
203  */
PCA6416A_TogglePins(pca6416a_handle_t * handle,uint16_t pins)204 status_t PCA6416A_TogglePins(pca6416a_handle_t *handle, uint16_t pins)
205 {
206     return PCA6416A_ModifyPortRegBits(handle, PCA6416A_OUTPUT_PORT_0, pins, kPCA6416A_ToggleRegBits);
207 }
208