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